feat: debug logger with levels (#1165)

This commit is contained in:
Peng Xiao
2023-02-21 19:23:53 +08:00
committed by GitHub
parent 11ade8aeaf
commit 86346b284e
21 changed files with 155 additions and 75 deletions

View File

@@ -1,7 +1,7 @@
import { DebugLogger } from '@affine/debug';
import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store';
import assert from 'assert';
import { getLogger } from './logger';
import { MessageCenter } from './message';
import { AffineProvider } from './provider';
import type {
@@ -23,7 +23,7 @@ import { WorkspaceUnitCollection } from './workspace-unit-collection';
export class DataCenter {
private readonly _workspaceUnitCollection = new WorkspaceUnitCollection();
private readonly _logger = getLogger('dc');
private readonly _logger = new DebugLogger('datacenter');
private _workspaceInstances: Map<string, BlocksuiteWorkspace> = new Map();
private _messageCenter = MessageCenter.getInstance();
@@ -33,19 +33,12 @@ export class DataCenter {
private _mainProvider?: BaseProvider;
providerMap: Map<string, BaseProvider> = new Map();
private constructor(debug: boolean) {
this._logger.enabled = debug;
}
static initEmpty() {
return new DataCenter(false);
return new DataCenter();
}
static async init(
debug: boolean,
exclude: 'affine'[] = []
): Promise<DataCenter> {
const dc = new DataCenter(debug);
static async init(exclude: 'affine'[] = []): Promise<DataCenter> {
const dc = new DataCenter();
const getInitParams = () => {
return {
logger: dc._logger,
@@ -182,7 +175,10 @@ export class DataCenter {
}
const provider = this.providerMap.get(workspaceUnit.provider);
assert(provider, `provide '${workspaceUnit.provider}' is not registered`);
this._logger(`Loading ${workspaceUnit.provider} workspace: `, workspaceId);
this._logger.debug(
`Loading ${workspaceUnit.provider} workspace: `,
workspaceId
);
const workspace = this._getBlocksuiteWorkspace(workspaceId);
this._workspaceInstances.set(workspaceId, workspace);
@@ -350,7 +346,7 @@ export class DataCenter {
providerId = 'affine'
) {
if (workspaceUnit.provider === providerId) {
this._logger('Workspace provider is same');
this._logger.error('Workspace provider is same');
return;
}
const provider = this.providerMap.get(providerId);

View File

@@ -3,9 +3,9 @@ import { DataCenter } from './datacenter';
const _initializeDataCenter = () => {
let _dataCenterInstance: Promise<DataCenter>;
return (debug = true) => {
return () => {
if (!_dataCenterInstance) {
_dataCenterInstance = DataCenter.init(debug);
_dataCenterInstance = DataCenter.init();
}
return _dataCenterInstance;
@@ -15,7 +15,6 @@ const _initializeDataCenter = () => {
export const getDataCenter = _initializeDataCenter();
export { DataCenter };
export { getLogger } from './logger';
export * from './message';
export { AffineProvider } from './provider/affine';
export * from './provider/affine/apis';

View File

@@ -1,7 +0,0 @@
import debug from 'debug';
export function getLogger(namespace: string) {
const logger = debug(namespace);
logger.log = console.log.bind(console);
return logger;
}

View File

@@ -86,7 +86,6 @@ export class AffineProvider extends BaseProvider {
`${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${
window.location.host
}/api/global/sync/`,
this._logger,
this._apis.auth,
{
params: {
@@ -115,7 +114,7 @@ export class AffineProvider extends BaseProvider {
ws_details,
metadata,
}: ChannelMessage) {
this._logger('receive server message');
this._logger.debug('receive server message');
const newlyCreatedWorkspaces: WorkspaceUnit[] = [];
const currentWorkspaceIds = this._workspaces.list().map(w => w.id);
const newlyRemovedWorkspaceIds = currentWorkspaceIds;
@@ -331,7 +330,7 @@ export class AffineProvider extends BaseProvider {
await this.deleteWorkspace(w.id);
this._workspaces.remove(w.id);
} catch (e) {
this._logger('has a problem of delete workspace ', e);
this._logger.error('has a problem of delete workspace ', e);
}
}
}

View File

@@ -1,3 +1,4 @@
import { DebugLogger } from '@affine/debug';
import { initializeApp } from 'firebase/app';
import type { User } from 'firebase/auth';
import {
@@ -10,7 +11,6 @@ import {
import { decode } from 'js-base64';
import { KyInstance } from 'ky/distribution/types/ky';
import { getLogger } from '../../../logger';
import { storage } from '../storage';
export interface AccessTokenMessage {
@@ -58,7 +58,7 @@ export class GoogleAuth {
private readonly _doLogin: ReturnType<typeof createDoLogin>;
constructor(bareClient: KyInstance) {
this._logger = getLogger('token');
this._logger = new DebugLogger('token');
this._logger.enabled = true;
this._doLogin = createDoLogin(bareClient);
@@ -93,7 +93,7 @@ export class GoogleAuth {
const login: LoginResponse = JSON.parse(loginStr);
this.setLogin(login);
} catch (err) {
this._logger('Failed to parse login info', err);
this._logger.warn('Failed to parse login info', err);
}
}
@@ -118,7 +118,7 @@ export class GoogleAuth {
}
return true;
} catch {
this._logger('Failed to refresh token');
this._logger.warn('Failed to refresh token');
} finally {
// clear on settled
this._padding = undefined;
@@ -191,7 +191,7 @@ export function createGoogleAuth(bareAuth: KyInstance): GoogleAuth {
export const getAuthorizer = (googleAuth: GoogleAuth) => {
let _firebaseAuth: FirebaseAuth | null = null;
const logger = getLogger('authorizer');
const logger = new DebugLogger('authorizer');
// getAuth will send requests on calling thus we can lazy init it
const getAuth = () => {
@@ -211,7 +211,7 @@ export const getAuthorizer = (googleAuth: GoogleAuth) => {
}
return _firebaseAuth;
} catch (error) {
logger(error);
logger.error('Failed to initialize firebase', error);
return null;
}
};

View File

@@ -1,7 +1,7 @@
import { DebugLogger } from '@affine/debug';
import * as url from 'lib0/url';
import * as websocket from 'lib0/websocket';
import { Logger } from '../../types';
import { GoogleAuth } from './apis/google';
const RECONNECT_INTERVAL_TIME = 500;
@@ -9,12 +9,11 @@ const MAX_RECONNECT_TIMES = 50;
export class WebsocketClient extends websocket.WebsocketClient {
public shouldReconnect = false;
private _logger: Logger;
private _retryTimes = 0;
private _auth: GoogleAuth;
private _logger = new DebugLogger('affine:channel');
constructor(
serverUrl: string,
logger: Logger,
auth: GoogleAuth,
options?: ConstructorParameters<typeof websocket.WebsocketClient>[1] & {
params: Record<string, string>;
@@ -30,13 +29,12 @@ export class WebsocketClient extends websocket.WebsocketClient {
serverUrl + '/' + (encodedParams.length === 0 ? '' : '?' + encodedParams);
super(newUrl, options);
this._auth = auth;
this._logger = logger;
this._setupChannel();
}
private _setupChannel() {
this.on('connect', () => {
this._logger('Affine channel connected');
this._logger.debug('Affine channel connected');
this.shouldReconnect = true;
this._retryTimes = 0;
});
@@ -49,15 +47,17 @@ export class WebsocketClient extends websocket.WebsocketClient {
setTimeout(() => {
if (this._retryTimes <= MAX_RECONNECT_TIMES) {
this.connect();
this._logger(
this._logger.info(
`try reconnect channel ${++this._retryTimes} times`
);
} else {
this._logger('reconnect failed, max reconnect times reached');
this._logger.error(
'reconnect failed, max reconnect times reached'
);
}
}, RECONNECT_INTERVAL_TIME);
} catch (e) {
this._logger('reconnect failed', e);
this._logger.error('reconnect failed', e);
}
}
}

View File

@@ -1,18 +1,14 @@
import { DebugLogger } from '@affine/debug';
import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store';
import { MessageCenter } from '../message';
import { Logger, User } from '../types';
import { User } from '../types';
import type { WorkspaceUnit, WorkspaceUnitCtorParams } from '../workspace-unit';
import type { WorkspaceUnitCollectionScope } from '../workspace-unit-collection';
import { Member } from './affine/apis';
import { Permission } from './affine/apis/workspace';
const defaultLogger = () => {
return;
};
export interface ProviderConstructorParams {
logger?: Logger;
workspaces: WorkspaceUnitCollectionScope;
messageCenter: MessageCenter;
}
@@ -23,25 +19,21 @@ export type UpdateWorkspaceMetaParams = Partial<
Pick<WorkspaceUnitCtorParams, 'name' | 'avatar'>
>;
export class BaseProvider {
export abstract class BaseProvider {
/** provider id */
public readonly id: string = 'base';
/** workspace unit collection */
protected _workspaces!: WorkspaceUnitCollectionScope;
protected _logger!: Logger;
protected _logger: DebugLogger;
/** send message with message center */
protected _sendMessage!: ReturnType<
InstanceType<typeof MessageCenter>['getMessageSender']
>;
public constructor({
logger,
workspaces,
messageCenter,
}: ProviderConstructorParams) {
this._logger = (logger || defaultLogger) as Logger;
public constructor({ workspaces, messageCenter }: ProviderConstructorParams) {
this._workspaces = workspaces;
this._sendMessage = messageCenter.getMessageSender(this.id);
this._logger = new DebugLogger(`provider:${this.id}`);
}
/**

View File

@@ -42,7 +42,7 @@ export class LocalProvider extends BaseProvider {
idb = new IndexedDBProvider(workspace.room, workspace.doc);
}
this._idbMap.set(workspace, idb);
this._logger('Local data loaded');
this._logger.debug('Local data loaded');
return workspace;
}
@@ -68,7 +68,7 @@ export class LocalProvider extends BaseProvider {
this._workspaces.add(workspaceUnits);
return workspaceUnits;
} catch (error) {
this._logger(`Failed to parse workspaces from storage`);
this._logger.error(`Failed to parse workspaces from storage`);
}
}
return [];
@@ -84,7 +84,7 @@ export class LocalProvider extends BaseProvider {
this._idbMap.delete(workspace.blocksuiteWorkspace);
}
} else {
this._logger(`Failed to delete workspace ${id}`);
this._logger.error(`Failed to delete workspace ${id}`);
}
}

View File

@@ -21,6 +21,7 @@ import { createWorkspaceUnit } from './utils';
export class TauriIPCProvider extends LocalProvider {
public id = 'tauri-ipc';
static defaultUserEmail = 'xxx@xx.xx';
/**
* // TODO: We only have one user in this version of app client. But may support switch user later.
*/
@@ -79,7 +80,7 @@ export class TauriIPCProvider extends LocalProvider {
workspaceID: string,
blocksuiteWorkspace: BlocksuiteWorkspace
) {
this._logger(`Loading ${workspaceID}...`);
this._logger.debug(`Loading ${workspaceID}...`);
const result = await this.#ipc?.getYDocument({ id: workspaceID });
if (result) {
const updates = result.updates.map(
@@ -88,7 +89,7 @@ export class TauriIPCProvider extends LocalProvider {
const mergedUpdate = Y.mergeUpdates(updates);
await applyUpdate(blocksuiteWorkspace, mergedUpdate);
this._logger(`Loaded: ${workspaceID}`);
this._logger.debug(`Loaded: ${workspaceID}`);
}
}
@@ -96,7 +97,7 @@ export class TauriIPCProvider extends LocalProvider {
workspaceID: string,
blocksuiteWorkspace: BlocksuiteWorkspace
) {
this._logger(`Connecting yDoc for ${workspaceID}...`);
this._logger.debug(`Connecting yDoc for ${workspaceID}...`);
blocksuiteWorkspace.doc.on('update', async (update: Uint8Array) => {
try {
const binary = Y.encodeStateAsUpdate(blocksuiteWorkspace.doc);
@@ -109,7 +110,7 @@ export class TauriIPCProvider extends LocalProvider {
}
} catch (error) {
// TODO: write error log to disk, and add button to open them in settings panel
console.error("#yDocument.on('update'", error);
this._logger.error("#yDocument.on('update'", error);
}
});
}
@@ -134,7 +135,7 @@ export class TauriIPCProvider extends LocalProvider {
public override async createWorkspace(
meta: CreateWorkspaceInfoParams
): Promise<WorkspaceUnit | undefined> {
this._logger('Creating client app workspace');
this._logger.debug('Creating client app workspace');
assert(this.#ipc);
assert(this.#userID);
const { id } = await this.#ipc.createWorkspace({

View File

@@ -1,5 +1,3 @@
import { getLogger } from '../logger';
// export type WorkspaceInfo = {
// name: string;
// id: string;
@@ -27,7 +25,7 @@ export type User = {
// export type WorkspaceMeta = Pick<WorkspaceInfo, 'name' | 'avatar'>;
export type Logger = ReturnType<typeof getLogger>;
export type Logger = typeof import('@affine/debug').DebugLogger;
export type Message = {
code: number;