From 745e486e1c20a388a2b6f94fb34502a0499d99c6 Mon Sep 17 00:00:00 2001 From: Matthew Blythe Date: Sun, 3 Mar 2024 01:19:21 -0700 Subject: [PATCH] Add logging elision Allow for anonymous functions in logging calls. The function is only called if the message is logged. (e.g. if the verbosity is turned up high enough.) This allows for expensive operations to be avoided in cases where the logging won't happen. The idea is that this provides a performance benefit. I don't know how "expensive" an operation must be to actually realize a performance benefit, though. I added an example in server.ts... It's probably "expensive" to dump the configuration to JSON, then stringify that JSON for logging. --- src/backend/Logger.ts | 36 +++++++++++++++++++++--------------- src/backend/server.ts | 4 ++-- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/backend/Logger.ts b/src/backend/Logger.ts index 7d860178..3cb26270 100644 --- a/src/backend/Logger.ts +++ b/src/backend/Logger.ts @@ -1,7 +1,7 @@ import {Config} from '../common/config/private/Config'; import {LogLevel} from '../common/config/private/PrivateConfig'; -export type logFN = (...args: (string | number)[]) => void; +export type logFN = (...args: (string | number | (() => string))[]) => void; const forcedDebug = process.env['NODE_ENV'] === 'debug'; @@ -11,7 +11,8 @@ if (forcedDebug === true) { ); } -export type LoggerFunction = (...args: (string | number)[]) => void; +export type LoggerArgs = (string | number | (() => string)) +export type LoggerFunction = (...args: LoggerArgs[]) => void; export interface ILogger { silly: LoggerFunction; @@ -23,67 +24,67 @@ export interface ILogger { } export const createLoggerWrapper = (TAG: string): ILogger => ({ - silly: (...args: (string | number)[]) => { + silly: (...args: LoggerArgs[]) => { Logger.silly(TAG, ...args); }, - debug: (...args: (string | number)[]) => { + debug: (...args: LoggerArgs[]) => { Logger.debug(TAG, ...args); }, - verbose: (...args: (string | number)[]) => { + verbose: (...args: LoggerArgs[]) => { Logger.verbose(TAG, ...args); }, - info: (...args: (string | number)[]) => { + info: (...args: LoggerArgs[]) => { Logger.info(TAG, ...args); }, - warn: (...args: (string | number)[]) => { + warn: (...args: LoggerArgs[]) => { Logger.warn(TAG, ...args); }, - error: (...args: (string | number)[]) => { + error: (...args: LoggerArgs[]) => { Logger.error(TAG, ...args); } }); export class Logger { - public static silly(...args: (string | number)[]): void { + public static silly(...args: LoggerArgs[]): void { if (!forcedDebug && Config.Server.Log.level < LogLevel.silly) { return; } Logger.log(`[\x1b[35mSILLY\x1b[0m]`, ...args); } - public static debug(...args: (string | number)[]): void { + public static debug(...args: LoggerArgs[]): void { if (!forcedDebug && Config.Server.Log.level < LogLevel.debug) { return; } Logger.log(`[\x1b[34mDEBUG\x1b[0m]`, ...args); } - public static verbose(...args: (string | number)[]): void { + public static verbose(...args: LoggerArgs[]): void { if (!forcedDebug && Config.Server.Log.level < LogLevel.verbose) { return; } Logger.log(`[\x1b[36mVERBS\x1b[0m]`, ...args); } - public static info(...args: (string | number)[]): void { + public static info(...args: LoggerArgs[]): void { if (!forcedDebug && Config.Server.Log.level < LogLevel.info) { return; } Logger.log(`[\x1b[32mINFO_\x1b[0m]`, ...args); } - public static warn(...args: (string | number)[]): void { + public static warn(...args: LoggerArgs[]): void { if (!forcedDebug && Config.Server.Log.level < LogLevel.warn) { return; } Logger.log(`[\x1b[33mWARN_\x1b[0m]`, ...args); } - public static error(...args: (string | number)[]): void { + public static error(...args: LoggerArgs[]): void { Logger.log(`[\x1b[31mERROR\x1b[0m]`, ...args); } - private static log(tag: string, ...args: (string | number)[]): void { + private static log(tag: string, ...args: LoggerArgs[]): void { const date = new Date().toLocaleString(); let LOG_TAG = ''; if ( @@ -95,6 +96,11 @@ export class Logger { LOG_TAG = args[0]; args.shift(); } + args.forEach((element:LoggerArgs, index:number) => { + if(typeof element === "function"){ + args[index] = element(); //execute function, put resulting string in the array + } + }); console.log(date + tag + LOG_TAG, ...args); } } diff --git a/src/backend/server.ts b/src/backend/server.ts index f77c132e..a34b3643 100644 --- a/src/backend/server.ts +++ b/src/backend/server.ts @@ -67,14 +67,14 @@ export class Server { await ConfigDiagnostics.runDiagnostics(); Logger.verbose( LOG_TAG, - 'using config from ' + + () => 'using config from ' + ( ConfigClassBuilder.attachPrivateInterface(Config) .__options as ConfigClassOptions ).configPath + ':' ); - Logger.verbose(LOG_TAG, JSON.stringify(Config.toJSON({attachDescription: false}), (k, v) => { + Logger.verbose(LOG_TAG, () => JSON.stringify(Config.toJSON({attachDescription: false}), (k, v) => { const MAX_LENGTH = 80; if (typeof v === 'string' && v.length > MAX_LENGTH) { v = v.slice(0, MAX_LENGTH - 3) + '...';