From 4c7caf734cf86dd24de7d87326001528ea354d20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Mon, 7 Oct 2024 16:57:06 +0200 Subject: [PATCH] chore(core): Better debug logs for local dev (#11096) --- packages/cli/src/logging/logger.service.ts | 65 ++++++++++++++++----- packages/workflow/src/ErrorReporterProxy.ts | 6 +- 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/packages/cli/src/logging/logger.service.ts b/packages/cli/src/logging/logger.service.ts index 9a1b804859..c294645d61 100644 --- a/packages/cli/src/logging/logger.service.ts +++ b/packages/cli/src/logging/logger.service.ts @@ -3,9 +3,11 @@ import callsites from 'callsites'; import { InstanceSettings } from 'n8n-core'; import { LoggerProxy, LOG_LEVELS } from 'n8n-workflow'; import path, { basename } from 'node:path'; +import pc from 'picocolors'; import { Service } from 'typedi'; import winston from 'winston'; +import { inDevelopment, inProduction } from '@/constants'; import { isObjectLiteral } from '@/utils'; import { noOp } from './constants'; @@ -61,8 +63,7 @@ export class Logger { for (const logLevel of LOG_LEVELS) { if (levels[logLevel] > levels[this.level]) { - // winston defines `{ error: 0, warn: 1, info: 2, debug: 5 }` - // so numerically higher (less severe) log levels become no-op + // numerically higher (less severe) log levels become no-op // to prevent overhead from `callsites` calls Object.defineProperty(this, logLevel, { value: noOp }); } @@ -71,24 +72,60 @@ export class Logger { private setConsoleTransport() { const format = - this.level === 'debug' - ? winston.format.combine( - winston.format.metadata(), - winston.format.timestamp(), - winston.format.colorize({ all: true }), - winston.format.printf(({ level, message, timestamp, metadata }) => { - const _metadata = this.toPrintable(metadata); - return `${timestamp} | ${level.padEnd(18)} | ${message}${_metadata}`; - }), - ) - : winston.format.printf(({ message }: { message: string }) => message); + this.level === 'debug' && inDevelopment + ? this.debugDevConsoleFormat() + : this.level === 'debug' && inProduction + ? this.debugProdConsoleFormat() + : winston.format.printf(({ message }: { message: string }) => message); this.internalLogger.add(new winston.transports.Console({ format })); } + private debugDevConsoleFormat() { + return winston.format.combine( + winston.format.metadata(), + winston.format.timestamp({ format: () => this.devTsFormat() }), + winston.format.colorize({ all: true }), + winston.format.printf(({ level: _level, message, timestamp, metadata: _metadata }) => { + const SEPARATOR = ' '.repeat(3); + const LOG_LEVEL_COLUMN_WIDTH = 15; // 5 columns + ANSI color codes + const level = _level.toLowerCase().padEnd(LOG_LEVEL_COLUMN_WIDTH, ' '); + const metadata = this.toPrintable(_metadata); + return [timestamp, level, message + ' ' + pc.dim(metadata)].join(SEPARATOR); + }), + ); + } + + private debugProdConsoleFormat() { + return winston.format.combine( + winston.format.metadata(), + winston.format.timestamp(), + winston.format.printf(({ level, message, timestamp, metadata }) => { + const _metadata = this.toPrintable(metadata); + return `${timestamp} | ${level.padEnd(5)} | ${message}${_metadata ? ' ' + _metadata : ''}`; + }), + ); + } + + private devTsFormat() { + const now = new Date(); + const pad = (num: number, digits: number = 2) => num.toString().padStart(digits, '0'); + const hours = pad(now.getHours()); + const minutes = pad(now.getMinutes()); + const seconds = pad(now.getSeconds()); + const milliseconds = pad(now.getMilliseconds(), 3); + return `${hours}:${minutes}:${seconds}.${milliseconds}`; + } + private toPrintable(metadata: unknown) { if (isObjectLiteral(metadata) && Object.keys(metadata).length > 0) { - return ' ' + JSON.stringify(metadata); + return inProduction + ? JSON.stringify(metadata) + : JSON.stringify(metadata) + .replace(/{"/g, '{ "') + .replace(/,"/g, ', "') + .replace(/:/g, ': ') + .replace(/}/g, ' }'); // spacing for readability } return ''; diff --git a/packages/workflow/src/ErrorReporterProxy.ts b/packages/workflow/src/ErrorReporterProxy.ts index 8a6d568d24..7d715d08b5 100644 --- a/packages/workflow/src/ErrorReporterProxy.ts +++ b/packages/workflow/src/ErrorReporterProxy.ts @@ -5,17 +5,13 @@ interface ErrorReporter { report: (error: Error | string, options?: ReportingOptions) => void; } -const { NODE_ENV } = process.env; -const inDevelopment = !NODE_ENV || NODE_ENV === 'development'; - const instance: ErrorReporter = { report: (error) => { if (error instanceof Error) { let e = error; do { const meta = e instanceof ApplicationError ? e.extra : undefined; - if (inDevelopment) console.log(e, meta); - else Logger.error(`${e.constructor.name}: ${e.message}`, meta); + Logger.error(`${e.constructor.name}: ${e.message}`, meta); e = e.cause as Error; } while (e); }