diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 3b2842ad..7d015262 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -17,10 +17,10 @@ limitations under the License. import {LogItem} from "./LogItem"; import {LogLevel, LogFilter} from "./LogFilter"; -import type {FilterCreator, LabelOrValues, LogCallback, ILogItem} from "./LogItem"; +import type {ILogger, ILogExport, FilterCreator, LabelOrValues, LogCallback, ILogItem} from "./types"; import type {Platform} from "../platform/web/Platform.js"; -export abstract class BaseLogger { +export abstract class BaseLogger implements ILogger { protected _openItems: Set = new Set(); protected _platform: Platform; @@ -141,7 +141,7 @@ export abstract class BaseLogger { abstract _persistItem(item: ILogItem, filter?: LogFilter, forced?: boolean): void; - abstract export(): void; + abstract export(): Promise; // expose log level without needing get level(): typeof LogLevel { diff --git a/src/logging/ConsoleLogger.ts b/src/logging/ConsoleLogger.ts index d8693e38..20fdf6a6 100644 --- a/src/logging/ConsoleLogger.ts +++ b/src/logging/ConsoleLogger.ts @@ -14,15 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ import {BaseLogger} from "./BaseLogger"; -import type {ILogItem, LogItemValues} from "./LogItem"; +import type {ILogItem, LogItemValues, ILogExport} from "./types"; export class ConsoleLogger extends BaseLogger { _persistItem(item: ILogItem): void { printToConsole(item); } - export(): void { - throw new Error("Cannot export from ConsoleLogger"); + async export(): Promise { + return undefined; } } diff --git a/src/logging/IDBLogger.ts b/src/logging/IDBLogger.ts index ebcf2249..621359dc 100644 --- a/src/logging/IDBLogger.ts +++ b/src/logging/IDBLogger.ts @@ -26,7 +26,7 @@ import {BaseLogger} from "./BaseLogger"; import type {Interval} from "../platform/web/dom/Clock"; import type {Platform} from "../platform/web/Platform.js"; import type {BlobHandle} from "../platform/web/dom/BlobHandle.js"; -import type {ILogItem} from "./LogItem"; +import type {ILogItem, ILogExport} from "./types"; import type {LogFilter} from "./LogFilter"; type QueuedItem = { @@ -131,7 +131,7 @@ export class IDBLogger extends BaseLogger { } } - async export(): Promise { + async export(): Promise { const db = await this._openDB(); try { const txn = db.transaction(["logs"], "readonly"); @@ -171,7 +171,7 @@ export class IDBLogger extends BaseLogger { } } -class IDBLogExport { +class IDBLogExport implements ILogExport { private readonly _items: QueuedItem[]; private readonly _logger: IDBLogger; private readonly _platform: Platform; diff --git a/src/logging/LogFilter.ts b/src/logging/LogFilter.ts index d0189631..8611d5f3 100644 --- a/src/logging/LogFilter.ts +++ b/src/logging/LogFilter.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import type {ILogItem, ISerializedItem} from "./LogItem"; +import type {ILogItem, ISerializedItem} from "./types"; export enum LogLevel { All = 1, diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 9521b67b..7774dd41 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -17,58 +17,7 @@ limitations under the License. import {LogLevel, LogFilter} from "./LogFilter"; import type {BaseLogger} from "./BaseLogger"; - -export interface ISerializedItem { - s: number; - d?: number; - v: LogItemValues; - l: LogLevel; - e?: { - stack?: string; - name: string; - message: string; - }; - f?: boolean; - c?: Array; -}; - -export interface ILogItem { - logger: any; - level: typeof LogLevel; - duration?: number; - end?: number; - start?: number; - logLevel: LogLevel; - children?: Array; - values: LogItemValues; - error?: Error; - wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T; - log(labelOrValues: LabelOrValues, logLevel?: LogLevel): void; - set(key: string | object, value: unknown): void; - run(callback: LogCallback): T; - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; - wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): void; - refDetached(logItem: ILogItem, logLevel?: LogLevel): void; - ensureRefId(): void; - catch(err: Error): Error; - finish(): void; - child(labelOrValues: LabelOrValues, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; - serialize(filter: LogFilter, parentStartTime: number | undefined, forced: boolean): ISerializedItem | undefined; -} - -export type LogItemValues = { - l?: string; - t?: string; - id?: unknown; - status?: string | number; - refId?: number; - ref?: number; - [key: string]: any -} - -export type LabelOrValues = string | LogItemValues; -export type FilterCreator = ((filter: LogFilter, item: ILogItem) => LogFilter); -export type LogCallback = (item: ILogItem) => T; +import type {ISerializedItem, ILogItem, LogItemValues, LabelOrValues, FilterCreator, LogCallback} from "./types"; export class LogItem implements ILogItem { public readonly start: number; diff --git a/src/logging/NullLogger.ts b/src/logging/NullLogger.ts index eba453e6..ed12cd78 100644 --- a/src/logging/NullLogger.ts +++ b/src/logging/NullLogger.ts @@ -14,20 +14,20 @@ See the License for the specific language governing permissions and limitations under the License. */ import {LogLevel} from "./LogFilter"; -import type {ILogItem, LabelOrValues, LogCallback, LogItemValues} from "./LogItem"; +import type {ILogger, ILogExport, ILogItem, LabelOrValues, LogCallback, LogItemValues} from "./types"; function noop (): void {} -export class NullLogger { +export class NullLogger implements ILogger { public readonly item: ILogItem = new NullLogItem(this); log(): void {} - run(_, callback: LogCallback): T | Promise { + run(_, callback: LogCallback): T { return callback(this.item); } - wrapOrRun(item: ILogItem, _, callback: LogCallback): T | Promise { + wrapOrRun(item: ILogItem | undefined, _, callback: LogCallback): T { if (item) { return item.wrap(_, callback); } else { @@ -35,12 +35,13 @@ export class NullLogger { } } - runDetached(_, callback) { + runDetached(_, callback): ILogItem { new Promise(r => r(callback(this.item))).then(noop, noop); + return this.item; } - async export(): Promise { - return null; + async export(): Promise { + return undefined; } get level(): typeof LogLevel { diff --git a/src/logging/types.ts b/src/logging/types.ts new file mode 100644 index 00000000..6a29a7a2 --- /dev/null +++ b/src/logging/types.ts @@ -0,0 +1,87 @@ +/* +Copyright 2020 Bruno Windels +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import {LogLevel, LogFilter} from "./LogFilter"; +import type {BaseLogger} from "./BaseLogger"; +import type {BlobHandle} from "../platform/web/dom/BlobHandle.js"; + +export interface ISerializedItem { + s: number; + d?: number; + v: LogItemValues; + l: LogLevel; + e?: { + stack?: string; + name: string; + message: string; + }; + f?: boolean; + c?: Array; +}; + +export interface ILogItem { + logger: any; + level: typeof LogLevel; + duration?: number; + end?: number; + start?: number; + logLevel: LogLevel; + children?: Array; + values: LogItemValues; + error?: Error; + wrap(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T; + log(labelOrValues: LabelOrValues, logLevel?: LogLevel): void; + set(key: string | object, value: unknown): void; + run(callback: LogCallback): T; + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; + wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): void; + refDetached(logItem: ILogItem, logLevel?: LogLevel): void; + ensureRefId(): void; + catch(err: Error): Error; + finish(): void; + child(labelOrValues: LabelOrValues, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; + serialize(filter: LogFilter, parentStartTime: number | undefined, forced: boolean): ISerializedItem | undefined; +} + +export interface ILogger { + log(labelOrValues: LabelOrValues, logLevel?: LogLevel): void; + wrapOrRun(item: ILogItem | undefined, labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T; + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): ILogItem; + run(labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T; + export(): Promise; + get level(): typeof LogLevel; +} + +export interface ILogExport { + get count(): number; + removeFromStore(): Promise; + asBlob(): BlobHandle; +} + +export type LogItemValues = { + l?: string; + t?: string; + id?: unknown; + status?: string | number; + refId?: number; + ref?: number; + [key: string]: any +} + +export type LabelOrValues = string | LogItemValues; +export type FilterCreator = ((filter: LogFilter, item: ILogItem) => LogFilter); +export type LogCallback = (item: ILogItem) => T; diff --git a/src/logging/utils.ts b/src/logging/utils.ts index 61cbce80..2b32454d 100644 --- a/src/logging/utils.ts +++ b/src/logging/utils.ts @@ -2,7 +2,7 @@ // if you know you always have a log item, better to use the methods on the log item than these utility functions. import {Instance as NullLoggerInstance} from "./NullLogger"; -import type {FilterCreator, ILogItem, LabelOrValues, LogCallback} from "./LogItem"; +import type {FilterCreator, ILogItem, LabelOrValues, LogCallback} from "./types"; import {LogLevel} from "./LogFilter"; export function wrapOrRunNullLogger(logItem: ILogItem | undefined, labelOrValues: LabelOrValues, callback: LogCallback, logLevel?: LogLevel, filterCreator?: FilterCreator): T | Promise { diff --git a/src/matrix/e2ee/megolm/Decryption.ts b/src/matrix/e2ee/megolm/Decryption.ts index ee96eca1..e139e8c9 100644 --- a/src/matrix/e2ee/megolm/Decryption.ts +++ b/src/matrix/e2ee/megolm/Decryption.ts @@ -26,7 +26,7 @@ import type {OlmWorker} from "../OlmWorker"; import type {Transaction} from "../../storage/idb/Transaction"; import type {TimelineEvent} from "../../storage/types"; import type {DecryptionResult} from "../DecryptionResult"; -import type {ILogItem} from "../../../logging/LogItem"; +import type {ILogItem} from "../../../logging/types"; export class Decryption { private keyLoader: KeyLoader; diff --git a/src/matrix/storage/idb/QueryTarget.ts b/src/matrix/storage/idb/QueryTarget.ts index 7519beac..5bea1139 100644 --- a/src/matrix/storage/idb/QueryTarget.ts +++ b/src/matrix/storage/idb/QueryTarget.ts @@ -16,7 +16,7 @@ limitations under the License. import {iterateCursor, DONE, NOT_DONE, reqAsPromise} from "./utils"; import {StorageError} from "../common"; -import {ILogItem} from "../../../logging/LogItem"; +import {ILogItem} from "../../../logging/types"; import {IDBKey} from "./Transaction"; // this is the part of the Transaction class API that is used here and in the Store subclass, diff --git a/src/matrix/storage/idb/Storage.ts b/src/matrix/storage/idb/Storage.ts index 728d4fca..6f3ed8ad 100644 --- a/src/matrix/storage/idb/Storage.ts +++ b/src/matrix/storage/idb/Storage.ts @@ -18,7 +18,7 @@ import {IDOMStorage} from "./types"; import {Transaction} from "./Transaction"; import { STORE_NAMES, StoreNames, StorageError } from "../common"; import { reqAsPromise } from "./utils"; -import { BaseLogger } from "../../../logging/BaseLogger"; +import { ILogger } from "../../../logging/types"; const WEBKITEARLYCLOSETXNBUG_BOGUS_KEY = "782rh281re38-boguskey"; @@ -26,13 +26,13 @@ export class Storage { private _db: IDBDatabase; private _hasWebkitEarlyCloseTxnBug: boolean; - readonly logger: BaseLogger; + readonly logger: ILogger; readonly idbFactory: IDBFactory readonly IDBKeyRange: typeof IDBKeyRange; readonly storeNames: typeof StoreNames; readonly localStorage: IDOMStorage; - constructor(idbDatabase: IDBDatabase, idbFactory: IDBFactory, _IDBKeyRange: typeof IDBKeyRange, hasWebkitEarlyCloseTxnBug: boolean, localStorage: IDOMStorage, logger: BaseLogger) { + constructor(idbDatabase: IDBDatabase, idbFactory: IDBFactory, _IDBKeyRange: typeof IDBKeyRange, hasWebkitEarlyCloseTxnBug: boolean, localStorage: IDOMStorage, logger: ILogger) { this._db = idbDatabase; this.idbFactory = idbFactory; this.IDBKeyRange = _IDBKeyRange; diff --git a/src/matrix/storage/idb/StorageFactory.ts b/src/matrix/storage/idb/StorageFactory.ts index 3c7e0e40..5cb1b6e5 100644 --- a/src/matrix/storage/idb/StorageFactory.ts +++ b/src/matrix/storage/idb/StorageFactory.ts @@ -20,8 +20,7 @@ import { openDatabase, reqAsPromise } from "./utils"; import { exportSession, importSession, Export } from "./export"; import { schema } from "./schema"; import { detectWebkitEarlyCloseTxnBug } from "./quirks"; -import { BaseLogger } from "../../../logging/BaseLogger"; -import { ILogItem } from "../../../logging/LogItem"; +import { ILogItem } from "../../../logging/types"; const sessionName = (sessionId: string) => `hydrogen_session_${sessionId}`; const openDatabaseWithSessionId = function(sessionId: string, idbFactory: IDBFactory, localStorage: IDOMStorage, log: ILogItem) { diff --git a/src/matrix/storage/idb/Store.ts b/src/matrix/storage/idb/Store.ts index 5a2a9abc..07cc90b0 100644 --- a/src/matrix/storage/idb/Store.ts +++ b/src/matrix/storage/idb/Store.ts @@ -18,7 +18,7 @@ import {QueryTarget, IDBQuery, ITransaction} from "./QueryTarget"; import {IDBRequestError, IDBRequestAttemptError} from "./error"; import {reqAsPromise} from "./utils"; import {Transaction, IDBKey} from "./Transaction"; -import {ILogItem} from "../../../logging/LogItem"; +import {ILogItem} from "../../../logging/types"; const LOG_REQUESTS = false; diff --git a/src/matrix/storage/idb/Transaction.ts b/src/matrix/storage/idb/Transaction.ts index 4c3d2b5c..80894105 100644 --- a/src/matrix/storage/idb/Transaction.ts +++ b/src/matrix/storage/idb/Transaction.ts @@ -36,8 +36,7 @@ import {OutboundGroupSessionStore} from "./stores/OutboundGroupSessionStore"; import {GroupSessionDecryptionStore} from "./stores/GroupSessionDecryptionStore"; import {OperationStore} from "./stores/OperationStore"; import {AccountDataStore} from "./stores/AccountDataStore"; -import {ILogItem} from "../../../logging/LogItem"; -import {BaseLogger} from "../../../logging/BaseLogger"; +import type {ILogger, ILogItem} from "../../../logging/types"; export type IDBKey = IDBValidKey | IDBKeyRange; @@ -77,7 +76,7 @@ export class Transaction { return this._storage.databaseName; } - get logger(): BaseLogger { + get logger(): ILogger { return this._storage.logger; } diff --git a/src/matrix/storage/idb/schema.ts b/src/matrix/storage/idb/schema.ts index 6250980d..ad3e5896 100644 --- a/src/matrix/storage/idb/schema.ts +++ b/src/matrix/storage/idb/schema.ts @@ -11,7 +11,7 @@ import {SessionStore} from "./stores/SessionStore"; import {Store} from "./Store"; import {encodeScopeTypeKey} from "./stores/OperationStore"; import {MAX_UNICODE} from "./stores/common"; -import {ILogItem} from "../../../logging/LogItem"; +import {ILogItem} from "../../../logging/types"; export type MigrationFunc = (db: IDBDatabase, txn: IDBTransaction, localStorage: IDOMStorage, log: ILogItem) => Promise | void; diff --git a/src/matrix/storage/idb/stores/SessionStore.ts b/src/matrix/storage/idb/stores/SessionStore.ts index dd133b45..7faedc41 100644 --- a/src/matrix/storage/idb/stores/SessionStore.ts +++ b/src/matrix/storage/idb/stores/SessionStore.ts @@ -16,8 +16,8 @@ limitations under the License. import {Store} from "../Store"; import {IDOMStorage} from "../types"; import {SESSION_E2EE_KEY_PREFIX} from "../../../e2ee/common.js"; -import {ILogItem} from "../../../../logging/LogItem"; import {parse, stringify} from "../../../../utils/typedJSON"; +import type {ILogItem} from "../../../../logging/types"; export interface SessionEntry { key: string; diff --git a/src/matrix/storage/idb/stores/TimelineEventStore.ts b/src/matrix/storage/idb/stores/TimelineEventStore.ts index b3663c29..bb6f652f 100644 --- a/src/matrix/storage/idb/stores/TimelineEventStore.ts +++ b/src/matrix/storage/idb/stores/TimelineEventStore.ts @@ -20,7 +20,7 @@ import { encodeUint32, decodeUint32 } from "../utils"; import {KeyLimits} from "../../common"; import {Store} from "../Store"; import {TimelineEvent, StateEvent} from "../../types"; -import {ILogItem} from "../../../../logging/LogItem"; +import {ILogItem} from "../../../../logging/types"; interface Annotation { count: number;