import { isDebug, ITrace, ITraceWith, memoize, Supplier } from '@emprespresso/pengueno'; import { ILogger, isLogLevel, LogLevel, logLevelOrder, PrettyJsonConsoleLogger } from './index.js'; export type LogTraceSupplier = ITraceWith> | ITraceWith; export class LogTrace implements ITrace { constructor( private readonly logger: ILogger = new PrettyJsonConsoleLogger(), private readonly traces: Array = [defaultTrace], private readonly defaultLevel: LogLevel = LogLevel.INFO, private readonly allowedLevels: Supplier> = defaultAllowedLevelsSupplier, ) {} public traceScope(trace: LogTraceSupplier): ITrace { return new LogTrace(this.logger, this.traces.concat(trace), this.defaultLevel, this.allowedLevels); } public trace(trace: LogTraceSupplier) { const { traces, level: _level } = this.foldTraces(this.traces.concat(trace)); if (!this.allowedLevels().has(_level)) return; const level = _level === LogLevel.UNKNOWN ? this.defaultLevel : _level; this.logger.log(level, ...traces); } private foldTraces(_traces: Array) { const _logTraces = _traces.map((trace) => (typeof trace === 'function' ? trace() : trace)); const _level = _logTraces .filter((trace) => isLogLevel(trace)) .reduce((acc, level) => Math.max(logLevelOrder.indexOf(level), acc), -1); const level = logLevelOrder[_level] ?? LogLevel.UNKNOWN; const traces = _logTraces .filter((trace) => !isLogLevel(trace)) .map((trace) => { if (typeof trace === 'object') { return `TracedException.Name = ${trace.name}, TracedException.Message = ${trace.message}, TracedException.Stack = ${trace.stack}`; } return trace; }); return { level, traces, }; } } const defaultTrace = () => `TimeStamp = ${new Date().toISOString()}`; const defaultAllowedLevels = memoize( (isDebug: boolean) => new Set([ LogLevel.UNKNOWN, ...(isDebug ? [LogLevel.DEBUG] : []), LogLevel.INFO, LogLevel.WARN, LogLevel.ERROR, LogLevel.SYS, ]), ); const defaultAllowedLevelsSupplier = () => defaultAllowedLevels(isDebug());