simplify log filtering, while also adding depth based filtering
This commit is contained in:
parent
78805f0a65
commit
4defbe1322
4 changed files with 97 additions and 117 deletions
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import {LogItem} from "./LogItem.js";
|
||||
import {LogLevel} from "./LogFilter.js";
|
||||
import {LogLevel, LogFilter} from "./LogFilter.js";
|
||||
|
||||
export class BaseLogger {
|
||||
constructor({platform}) {
|
||||
|
@ -33,13 +33,19 @@ export class BaseLogger {
|
|||
this._platform.settingsStorage.setBool("anonymize", this._anonymize);
|
||||
}
|
||||
|
||||
run(labelOrValues, callback, logFilterDef) {
|
||||
const item = new LogItem(labelOrValues, logFilterDef, this._platform, this._anonymize);
|
||||
run(labelOrValues, callback, logLevel = LogLevel.Info, filterCreator = null) {
|
||||
const item = new LogItem(labelOrValues, logLevel, null, this._platform, this._anonymize);
|
||||
this._openItems.add(item);
|
||||
|
||||
const finishItem = () => {
|
||||
const serialized = item.serialize(null);
|
||||
console.log("serialized log item", item, serialized);
|
||||
let filter = new LogFilter();
|
||||
if (filterCreator) {
|
||||
filter = filterCreator(filter, this);
|
||||
} else {
|
||||
// if not filter is specified, filter out anything lower than the initial log level
|
||||
filter = filter.minLevel(logLevel);
|
||||
}
|
||||
const serialized = item.serialize(filter, 0);
|
||||
if (serialized) {
|
||||
this._persistItem(serialized);
|
||||
}
|
||||
|
|
|
@ -24,74 +24,37 @@ export const LogLevel = {
|
|||
Off: 7,
|
||||
}
|
||||
|
||||
export function wrapLogFilterSource(logFilterDef) {
|
||||
if (typeof logFilterDef === "function") {
|
||||
return new DeferredFilterCreator(logFilterDef);
|
||||
} else if (typeof logFilterDef === "number") {
|
||||
return new SimpleFilterCreator(logFilterDef);
|
||||
}
|
||||
return null;
|
||||
export class LogFilter {
|
||||
constructor(parentFilter) {
|
||||
this._parentFilter = parentFilter;
|
||||
this._min = null;
|
||||
this._maxDepth = null;
|
||||
}
|
||||
|
||||
class LogFilter {
|
||||
constructor(parentFilter) {
|
||||
this._default = parentFilter ? parentFilter._default : null;
|
||||
this._min = parentFilter ? parentFilter._min : null;
|
||||
filter(item, children, depth) {
|
||||
if (this._parentFilter) {
|
||||
if (!this._parentFilter.filter(item, children, depth)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// neither our children or us have a loglevel high enough, filter out.
|
||||
if (this._min !== null && children === null && item.logLevel < this._min) {
|
||||
return false;
|
||||
} if (this._maxDepth !== null && depth > this._maxDepth) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* methods to build the filter */
|
||||
min(logLevel) {
|
||||
minLevel(logLevel) {
|
||||
this._min = logLevel;
|
||||
if (this._default === null) {
|
||||
this._default = logLevel;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
default(logLevel) {
|
||||
this._default = logLevel;
|
||||
if (this._min === null) {
|
||||
this._min = logLevel;
|
||||
}
|
||||
maxDepth(depth) {
|
||||
this._maxDepth = depth;
|
||||
return this;
|
||||
}
|
||||
|
||||
/* methods to use the filter */
|
||||
/** determine log level for item */
|
||||
itemLevel(item) {
|
||||
if (item._error) {
|
||||
return LogLevel.Error;
|
||||
}
|
||||
return this._default;
|
||||
}
|
||||
|
||||
/** determines whether an item should be persisted */
|
||||
includeItem(item, logLevel, children) {
|
||||
// neither our children or us have a loglevel high enough, bail out.
|
||||
return logLevel >= this._min || children;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to determine the log level of an item after it has finished.
|
||||
* So we can set the log level on the item duration for example.
|
||||
*/
|
||||
class DeferredFilterCreator {
|
||||
constructor(fn) {
|
||||
this._fn = fn;
|
||||
}
|
||||
|
||||
createFilter(item, parentFilter) {
|
||||
return this._fn(new LogFilter(parentFilter), item);
|
||||
}
|
||||
}
|
||||
|
||||
class SimpleFilterCreator {
|
||||
constructor(logLevel) {
|
||||
this._logLevel = logLevel;
|
||||
}
|
||||
|
||||
createFilter(item, parentFilter) {
|
||||
return new LogFilter(parentFilter).default(this._logLevel);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,29 +14,30 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {LogLevel, wrapLogFilterSource} from "./LogFilter.js";
|
||||
import {LogLevel, LogFilter} from "./LogFilter.js";
|
||||
|
||||
export class LogItem {
|
||||
constructor(labelOrValues, logFilterDef, platform, anonymize) {
|
||||
constructor(labelOrValues, logLevel, filterCreator, platform, anonymize) {
|
||||
this._platform = platform;
|
||||
this._anonymize = anonymize;
|
||||
this._start = platform.clock.now();
|
||||
this._end = null;
|
||||
this._values = typeof labelOrValues === "string" ? {label: labelOrValues} : labelOrValues;
|
||||
this._error = null;
|
||||
this._children = [];
|
||||
this._logFilterSource = wrapLogFilterSource(logFilterDef);
|
||||
this._values = typeof labelOrValues === "string" ? {l: labelOrValues} : labelOrValues;
|
||||
this.error = null;
|
||||
this.logLevel = logLevel;
|
||||
this._children = null;
|
||||
this._filterCreator = filterCreator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new child item and runs it in `callback`.
|
||||
*/
|
||||
wrap(labelOrValues, callback, logFilterDef = null) {
|
||||
const item = this.child(labelOrValues, logFilterDef);
|
||||
wrap(labelOrValues, callback, logLevel = LogLevel.Info, filterCreator = null) {
|
||||
const item = this.child(labelOrValues, logLevel, filterCreator);
|
||||
return item.run(callback);
|
||||
}
|
||||
|
||||
duration() {
|
||||
get duration() {
|
||||
if (this._end) {
|
||||
return this._end - this._start;
|
||||
} else {
|
||||
|
@ -50,8 +51,8 @@ export class LogItem {
|
|||
*
|
||||
* Hence, the child item is not returned.
|
||||
*/
|
||||
log(labelOrValues, logFilterDef = null) {
|
||||
const item = this.child(labelOrValues, logFilterDef);
|
||||
log(labelOrValues, logLevel = LogLevel.Info) {
|
||||
const item = this.child(labelOrValues, logLevel, null);
|
||||
item.end = item.start;
|
||||
}
|
||||
|
||||
|
@ -73,41 +74,45 @@ export class LogItem {
|
|||
}
|
||||
}
|
||||
|
||||
serialize(parentFilter) {
|
||||
const filter = this._logFilterSource ? this._logFilterSource.createFilter(this, parentFilter) : parentFilter;
|
||||
const logLevel = filter.itemLevel(this);
|
||||
console.log("logLevel for item", logLevel);
|
||||
const children = this._children.reduce((array, c) => {
|
||||
const s = c.serialize(filter);
|
||||
serialize(filter, depth) {
|
||||
if (this._filterCreator) {
|
||||
filter = this._filterCreator(new LogFilter(filter), this);
|
||||
}
|
||||
let children;
|
||||
if (this._children !== null) {
|
||||
children = this._children.reduce((array, c) => {
|
||||
const s = c.serialize(filter, depth + 1);
|
||||
if (s) {
|
||||
array = array || [];
|
||||
if (array === null) {
|
||||
array = [];
|
||||
}
|
||||
array.push(s);
|
||||
}
|
||||
return array;
|
||||
}, null);
|
||||
|
||||
if (!filter.includeItem(this, logLevel, children)) {
|
||||
console.log("excluding log item", logLevel, children, this);
|
||||
}
|
||||
if (!filter.filter(this, children, depth)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let error = null;
|
||||
if (this._error) {
|
||||
error = {
|
||||
stack: this._error.stack,
|
||||
name: this._error.name
|
||||
};
|
||||
}
|
||||
const item = {
|
||||
// (s)tart
|
||||
s: this._start,
|
||||
e: this._end,
|
||||
// (d)uration
|
||||
d: this.duration,
|
||||
// (v)alues
|
||||
v: this._values,
|
||||
l: logLevel
|
||||
// (l)evel
|
||||
l: this.logLevel
|
||||
};
|
||||
if (this.error) {
|
||||
// (e)rror
|
||||
item.e = {
|
||||
stack: this.error.stack,
|
||||
name: this.error.name
|
||||
};
|
||||
if (error) {
|
||||
item.err = error;
|
||||
}
|
||||
if (children) {
|
||||
// (c)hildren
|
||||
item.c = children;
|
||||
}
|
||||
return item;
|
||||
|
@ -155,9 +160,11 @@ export class LogItem {
|
|||
*/
|
||||
finish() {
|
||||
if (this._end === null) {
|
||||
if (this._children !== null) {
|
||||
for(const c of this._children) {
|
||||
c.finish();
|
||||
}
|
||||
}
|
||||
this._end = this._platform.clock.now();
|
||||
}
|
||||
}
|
||||
|
@ -168,16 +175,20 @@ export class LogItem {
|
|||
}
|
||||
|
||||
catch(err) {
|
||||
this._error = err;
|
||||
this.error = err;
|
||||
this.logLevel = LogLevel.Error;
|
||||
this.finish();
|
||||
return err;
|
||||
}
|
||||
|
||||
child(labelOrValues, logFilterDef = null) {
|
||||
child(labelOrValues, logLevel, filterCreator) {
|
||||
if (this._end !== null) {
|
||||
console.trace("log item is finished, additional logs will likely not be recorded");
|
||||
}
|
||||
const item = new LogItem(labelOrValues, logFilterDef, this._platform, this._anonymize);
|
||||
const item = new LogItem(labelOrValues, logLevel, filterCreator, this._platform, this._anonymize);
|
||||
if (this._children === null) {
|
||||
this._children = [];
|
||||
}
|
||||
this._children.push(item);
|
||||
return item;
|
||||
}
|
||||
|
|
|
@ -111,13 +111,14 @@ export class Sync {
|
|||
const timeout = this._status.get() === SyncStatus.Syncing ? INCREMENTAL_TIMEOUT : 0;
|
||||
const syncResult = await this._logger.run("sync",
|
||||
log => this._syncRequest(syncToken, timeout, log),
|
||||
this._logger.level.Info,
|
||||
(filter, log) => {
|
||||
if (log.duration >= 2000) {
|
||||
return filter.min(log.level.Info).default(log.level.Warn);
|
||||
} if (this._status.get() === SyncStatus.CatchupSync) {
|
||||
return filter.min(log.level.Info).default(log.level.Info);
|
||||
if (log.duration >= 2000 || this._status.get() === SyncStatus.CatchupSync) {
|
||||
return filter.minLevel(log.level.Info);
|
||||
} else if (log.error) {
|
||||
return filter.minLevel(log.level.Error);
|
||||
} else {
|
||||
return filter.min(log.level.Error);
|
||||
return filter.maxDepth(0);
|
||||
}
|
||||
});
|
||||
syncToken = syncResult.syncToken;
|
||||
|
@ -192,7 +193,6 @@ export class Sync {
|
|||
|
||||
const isInitialSync = !syncToken;
|
||||
syncToken = response.next_batch;
|
||||
log.set("isInitialSync", isInitialSync);
|
||||
log.set("syncToken", log.anonymize(syncToken));
|
||||
log.set("status", this._status.get());
|
||||
|
||||
|
|
Reference in a new issue