import { isString, Logger, LoggingConfig, LogLevel, TaggedLogger, } from "./types"; import moment from "moment"; export type LoggingFunction = (...args: unknown[]) => void; // noinspection JSUnusedLocalSymbols const noopTaggedLogger: TaggedLogger = { // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function log(level: LogLevel, ...args: unknown[]): void {}, // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function debug(...args: unknown[]): void {}, // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function info(...args: unknown[]): void {}, // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function warn(...args: unknown[]): void {}, // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function error(...args: unknown[]): void {}, // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function profile(...args: unknown[]): void {}, }; export interface ActivatableLogger extends Logger { init(config: LoggingConfig, loggingFunction?: LoggingFunction): void; } /** * TODO: Check if LoggingConfig.debug and LoggingConfig.profile are handled. */ export class ActivatableLoggerImpl implements ActivatableLogger { private config: LoggingConfig = new LoggingConfig(false, false, false); private loggingFunction: LoggingFunction = console.info; init(config: LoggingConfig, loggingFunction?: LoggingFunction): void { this.config = config; this.loggingFunction = loggingFunction || console.info; } tag(...tags: string[]): TaggedLogger { if (this.config.enabled) { const debug = this.config.debug; const profile = this.config.profile; const loggingFunction = this.loggingFunction; return { log(level: LogLevel, ...args: unknown[]): void { const timeStr = moment().format("YYYY-MM-DD HH:mm:ss"); const levelStr = level.toUpperCase(); const tagsStr = tags ? "[" + tags.join(", ") + "]" : ""; const messagePrefix = `${timeStr} ${levelStr} - ${tagsStr}`; // Make sure to only replace %s, etc. in real log message // but not in tags. const escapedMessagePrefix = messagePrefix.replace( /%/g, "%%" ); let message = ""; if (args && isString(args[0])) { message = args[0]; args.shift(); } const logStr = message ? `${escapedMessagePrefix} ${message}` : escapedMessagePrefix; loggingFunction(logStr, ...args); }, debug(...args: unknown[]): void { if (debug) { this.log("debug", ...args); } }, info(...args: unknown[]): void { this.log("info", ...args); }, warn(...args: unknown[]): void { this.log("warn", ...args); }, error(...args: unknown[]): void { this.log("error", ...args); }, profile(...args: unknown[]): void { if (profile) { this.log("profile", ...args); } }, }; } else { return noopTaggedLogger; } } } export default new ActivatableLoggerImpl() as ActivatableLogger;