From 0763410aa1fd204f6b3d5cf61292c7afcc77f849 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 12 Feb 2021 14:05:51 +0100 Subject: [PATCH] filter output when serializing by loglevel --- src/logging/BaseLogger.js | 29 +++++++++++++++++--- src/logging/IDBLogger.js | 12 +++----- src/logging/LogItem.js | 58 ++++++++++++++++++++++++++++----------- src/logging/LogLevel.js | 25 +++++++++++++++++ 4 files changed, 96 insertions(+), 28 deletions(-) create mode 100644 src/logging/LogLevel.js diff --git a/src/logging/BaseLogger.js b/src/logging/BaseLogger.js index 64405279..772b2c62 100644 --- a/src/logging/BaseLogger.js +++ b/src/logging/BaseLogger.js @@ -15,18 +15,23 @@ limitations under the License. */ import {LogItem} from "./LogItem.js"; +import {LogLevel} from "./LogLevel.js"; export class BaseLogger { - constructor(platform) { + constructor(platform, baseLogLevel) { this._openItems = new Set(); this._platform = platform; + this._baseLogLevel = baseLogLevel; } - wrapLog(labelOrValues, callback, logLevel) { + wrapLog(labelOrValues, callback, logLevel = this._baseLogLevel) { const item = new LogItem(labelOrValues, logLevel, this._platform); const finishItem = () => { - this._persistItem(item); + const serialized = item.serialize(this._baseLogLevel); + if (serialized) { + this._persistItem(serialized); + } this._openItems.remove(item); }; @@ -50,11 +55,27 @@ export class BaseLogger { } } - _persistItem(item) { + _finishOpenItems() { + for (const openItem of this._openItems) { + openItem.finish(); + const serialized = openItem.serialize(this._baseLogLevel); + if (serialized) { + this._persistItem(serialized); + } + } + this._openItems.clear(); + } + + _persistItem() { throw new Error("not implemented"); } async export() { throw new Error("not implemented"); } + + // expose log level without needing + get level() { + return LogLevel; + } } diff --git a/src/logging/IDBLogger.js b/src/logging/IDBLogger.js index 672df9e7..c3a2ac1f 100644 --- a/src/logging/IDBLogger.js +++ b/src/logging/IDBLogger.js @@ -80,11 +80,7 @@ export class IDBLogger extends BaseLogger { } _finishAllAndFlush() { - for (const openItem of this._openItems) { - openItem.finish(); - this._persistItem(openItem); - } - this._openItems.clear(); + this._finishOpenItems(); this._persistQueuedItems(this._queuedItems); } @@ -104,11 +100,11 @@ export class IDBLogger extends BaseLogger { return openDatabase(this._name, db => db.createObjectStore("logs", {keyPath: "id"}), 1); } - _persistItem(item) { + _persistItem(serializedItem) { this._itemCounter += 1; this._queuedItems.push({ - id: `${encodeUint64(item.start)}:${this._itemCounter}`, - tree: item.serialize() + id: `${encodeUint64(serializedItem.start)}:${this._itemCounter}`, + tree: serializedItem }); } diff --git a/src/logging/LogItem.js b/src/logging/LogItem.js index 2d875fe2..7fb659ee 100644 --- a/src/logging/LogItem.js +++ b/src/logging/LogItem.js @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +import {LogLevel} from "./LogLevel.js"; + export class LogItem { constructor(labelOrValues, logLevel, platform) { this._platform = platform; @@ -58,8 +60,22 @@ export class LogItem { return this._platform.base64.encode(buffer); } - serialize() { - let error; + serialize(logLevel) { + const children = this._children.reduce((array, c) => { + const s = c.serialize(logLevel); + if (s) { + array = array || []; + array.push(s); + } + return array; + }, null); + + // neither our children or us have a loglevel high enough, bail out. + if (!children && this._logLevel < logLevel) { + return null; + } + + let error = null; if (this._error) { error = { message: this._error.message, @@ -71,7 +87,7 @@ export class LogItem { end: this._end, values: this._values, error, - children: this._children.map(c => c.serialize()), + children, logLevel: this._logLevel }; } @@ -98,26 +114,45 @@ export class LogItem { result = callback(this); if (result instanceof Promise) { return result.then(promiseResult => { - this._finish(); + this.finish(); return promiseResult; }, err => { this._catch(err); - this._finish(); + this.finish(); throw err; }); } else { - this._finish(); + this.finish(); return result; } } catch (err) { this._catch(err); - this._finish(); + this.finish(); throw err; } } + /** + * finished the item, recording the end time. After finishing, an item can't be modified anymore as it will be persisted. + * @internal shouldn't typically be called by hand. allows to force finish if a promise is still running when closing the app + */ + finish() { + if (this._end === null) { + for(const c of this._children) { + c.finish(); + } + this._end = this._platform.clock.now(); + } + } + + // expose log level without needing + get level() { + return LogLevel; + } + _catch(err) { this._error = err; + this._logLevel = LogLevel.Error; console.error(`log item ${this.values.label} failed: ${err.message}:\n${err.stack}`); } @@ -129,13 +164,4 @@ export class LogItem { this._children.push(item); return item; } - - _finish() { - if (this._end === null) { - for(const c of this._children) { - c._finish(); - } - this._end = this._platform.clock.now(); - } - } } diff --git a/src/logging/LogLevel.js b/src/logging/LogLevel.js new file mode 100644 index 00000000..3580a5de --- /dev/null +++ b/src/logging/LogLevel.js @@ -0,0 +1,25 @@ +/* +Copyright 2020 Bruno Windels + +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. +*/ + +export const LogLevel = { + All: 1, + Debug: 2, + Info: 3, + Warn: 4, + Error: 5, + Fatal: 6, + Off: 7, +}