From 83f9d12106248b1f6e701a5d94fa1666676fd7a2 Mon Sep 17 00:00:00 2001 From: Egor Kartashov Date: Wed, 3 Jan 2024 14:23:59 +0600 Subject: [PATCH] fix(logger): options --- .../replace-nest-logger-bootstrap/src/main.ts | 18 ++++++---- .../transports/console/console.transport.ts | 26 +++++++++----- .../adapters/winston/winston.adapter.ts | 36 +++++++++++++------ .../interfaces/logger.interfaces.ts | 31 ++++++++++++---- src/modules/logger/logger.adapter.ts | 9 +++-- src/modules/logger/logger.service.ts | 12 +++++-- 6 files changed, 97 insertions(+), 35 deletions(-) diff --git a/examples/replace-nest-logger-bootstrap/src/main.ts b/examples/replace-nest-logger-bootstrap/src/main.ts index 8eb09f8..aa08d27 100644 --- a/examples/replace-nest-logger-bootstrap/src/main.ts +++ b/examples/replace-nest-logger-bootstrap/src/main.ts @@ -1,19 +1,25 @@ import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; -import { LoggerAdapter } from '@wildegor/nestjs-prologger/modules/modules/logger/logger.adapter'; -import { LoggerConstants } from '@wildegor/nestjs-prologger/modules/modules/logger/logger.constants'; +import { LogLevels } from '@wildegor/nestjs-prologger/modules/infrastructure/interfaces/logger.interfaces'; +import { LoggerAdapter } from '../../../src/modules/logger/logger.adapter'; async function bootstrap() { - const app = await NestFactory.create(AppModule); + const app = await NestFactory.create(AppModule, { + bufferLogs: true, + }); - const logger = app.get(LoggerConstants.logger); + const logger = app.get(LoggerAdapter); + logger.setLogLevels([ + LogLevels.Debug, + LogLevels.Log, + LogLevels.Warn, + LogLevels.Verbose, + ]); app.useLogger(logger); logger.error('Error message'); - throw Error('Error message'); - await app.listen(3001); } bootstrap(); diff --git a/src/infrastructure/adapters/winston/transports/console/console.transport.ts b/src/infrastructure/adapters/winston/transports/console/console.transport.ts index 11a921f..cf7691a 100644 --- a/src/infrastructure/adapters/winston/transports/console/console.transport.ts +++ b/src/infrastructure/adapters/winston/transports/console/console.transport.ts @@ -1,35 +1,43 @@ import * as winston from 'winston'; -import { LogColors, LogLevels } from '../../../../interfaces/logger.interfaces'; +import { IConsoleTransportOpts, LogColors, LogLevels } from '../../../../interfaces/logger.interfaces'; export class ConsoleTransport { - public static create(): winston.transports.ConsoleTransportInstance { + public static create(opts?: IConsoleTransportOpts): winston.transports.ConsoleTransportInstance { + if (opts?.format && 'json' === opts.format) { + return new winston.transports.Console({ + format: winston.format.json({ + deterministic: true, + }), + }); + } + return new winston.transports.Console({ format: winston.format.combine( - winston.format.printf((log) => { + winston.format.printf(log => { const color = this._mapLogLevelColor(log.level as LogLevels); - const prefix = `${log?.data?.label ? `[${log.data.label}]` : ''}`; + const prefix = `${log.data?.label ? `[${log.data.label}]` : ''}`; return `${this._colorize(color, `${prefix} -`)} ${log.timestamp} ${ - log?.data?.correlationId + log.data?.correlationId ? `(${this._colorize(LogColors.cyan, log.data.correlationId)})` : '' } ${this._colorize(color, log.level.toUpperCase())} ${ - log?.data?.source + log.data?.source ? `${this._colorize(LogColors.cyan, `[${log.data.source}]`)}` : '' } ${this._colorize( color, `${log.message} - ${log.data.error ? log.data.error : ''}`, )}${ - typeof log?.data?.durationMs !== 'undefined' + typeof log.data?.durationMs !== 'undefined' ? this._colorize(color, ` +${log.data.durationMs}ms`) : '' }${ - log?.data?.stack ? this._colorize(color, ` - ${log.data.stack}`) : '' + log.data?.stack ? this._colorize(color, ` - ${log.data.stack}`) : '' }${ - log?.data?.props + log.data?.props ? `\n - Props: ${JSON.stringify(log.data.props, null, 4)}` : '' }`; diff --git a/src/infrastructure/adapters/winston/winston.adapter.ts b/src/infrastructure/adapters/winston/winston.adapter.ts index e00c6a9..7ad06e9 100644 --- a/src/infrastructure/adapters/winston/winston.adapter.ts +++ b/src/infrastructure/adapters/winston/winston.adapter.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; import * as winston from 'winston'; -import { LoggerOptions } from 'winston'; +import { LogEntry, LoggerOptions } from 'winston'; import { InjectLoggerOpts } from '../../../modules/logger/logger.decorators'; import { ILogPayload, @@ -51,12 +51,16 @@ export class WinstonAdapter implements ILoggerPort { let cont = 0; // Set all levels - if (!levels) { + if ('undefined' === typeof levels) { for (const level of Object.values(LogLevels)) { if (level === LogLevels.Silent) { continue; } + if (level === LogLevels.Log) { + this._logLevels.add(LogLevels.Info); + } + this._logLevels.add(level); this._defaultLevels[level] = cont; cont += 1; @@ -66,6 +70,10 @@ export class WinstonAdapter implements ILoggerPort { } for (const level of levels) { + if (level === LogLevels.Log) { + this._logLevels.add(LogLevels.Info); + } + this._logLevels.add(level); this._defaultLevels[level] = cont; cont += 1; @@ -79,34 +87,42 @@ export class WinstonAdapter implements ILoggerPort { } public verbose(message: string | Error, data?: ILogPayload | undefined, profile?: string | undefined): void { - this.log(LogLevels.Verbose, message, data, profile); + return this.print(LogLevels.Verbose, message, data, profile); } public debug(message: string, data?: ILogPayload, profile?: string): void { - this.log(LogLevels.Debug, message, data, profile); + return this.print(LogLevels.Debug, message, data, profile); } public info(message: string, data?: ILogPayload, profile?: string): void { - this.log(LogLevels.Info, message, data, profile); + return this.print(LogLevels.Info, message, data, profile); } public warn(message: string | Error, data?: ILogPayload, profile?: string): void { - this.log(LogLevels.Warn, message, data, profile); + return this.print(LogLevels.Warn, message, data, profile); } public error(message: string | Error, data?: ILogPayload, profile?: string): void { - this.log(LogLevels.Error, message, data, profile); + return this.print(LogLevels.Error, message, data, profile); } public emergency(message: string | Error, data?: ILogPayload, profile?: string): void { - this.log(LogLevels.Emergency, message, data, profile); + return this.print(LogLevels.Emergency, message, data, profile); } public fatal(message: string | Error, data?: ILogPayload, profile?: string): void { - this.log(LogLevels.Emergency, message, data, profile); + return this.print(LogLevels.Emergency, message, data, profile); } public log( + message: string | Error, + data?: ILogPayload, + profile?: string, + ): void { + return this.print(LogLevels.Info, message, data, profile); + } + + public print( level: LogLevels, message: string | Error, data?: ILogPayload, @@ -116,7 +132,7 @@ export class WinstonAdapter implements ILoggerPort { return; } - const logData = { + const logData: LogEntry = { level, message: message instanceof Error ? message.message : message, error: message instanceof Error ? message : undefined, diff --git a/src/infrastructure/interfaces/logger.interfaces.ts b/src/infrastructure/interfaces/logger.interfaces.ts index 2573647..5746624 100644 --- a/src/infrastructure/interfaces/logger.interfaces.ts +++ b/src/infrastructure/interfaces/logger.interfaces.ts @@ -3,6 +3,10 @@ export interface IFileTransportOpts { period: string; } +export interface IConsoleTransportOpts { + format: 'json' | 'pretty'; +} + export interface ITelegramFormatOptions { context: string; timestamp: string; @@ -38,13 +42,16 @@ export interface ITelegramTransportOpts { batchingSeparator?: string; } +export interface ILoggerMetaOptions { + organization?: string; + context?: string; + app?: string; +} + export interface ILoggerOptions { hideTrace?: boolean; - meta?: { - organization?: string; - context?: string; - app?: string; - }, + meta?: ILoggerMetaOptions; + console?: IConsoleTransportOpts; file?: IFileTransportOpts; telegram?: ITelegramTransportOpts; } @@ -117,13 +124,25 @@ export interface ILoggerPort { * @param data * @param profile */ - log( + print( level: LogLevel, message: string | Error, data?: ILogPayload, profile?: string, ): void; + /** + * @description Log a message with level `log` + * @param message + * @param data + * @param profile + */ + log( + message: string | Error, + data?: ILogPayload, + profile?: string, + ): void; + /** * @description Log a message with level `debug` and color `blue` * @param message diff --git a/src/modules/logger/logger.adapter.ts b/src/modules/logger/logger.adapter.ts index d1afe84..15f7a4a 100644 --- a/src/modules/logger/logger.adapter.ts +++ b/src/modules/logger/logger.adapter.ts @@ -1,6 +1,6 @@ import { ConsoleLogger } from '@nestjs/common'; import { LoggerService } from '@nestjs/common/services/logger.service'; -import { ILoggerPort, ILogPayload } from '../../infrastructure/interfaces/logger.interfaces'; +import { ILoggerPort, ILogPayload, LogLevel } from '../../infrastructure/interfaces/logger.interfaces'; export class LoggerAdapter extends ConsoleLogger @@ -10,6 +10,10 @@ export class LoggerAdapter super(); } + public setLogLevels(levels: LogLevel[]): void { + this.logger.setLogLevels(levels); + } + public log(message: any, ...optionalParams: any[]): void { return this.logger.info(message, this.getLogData(optionalParams)); } @@ -31,8 +35,9 @@ export class LoggerAdapter } private getLogData(...optionalParams: any[]): ILogPayload { + const source = optionalParams[0]?.length ? optionalParams[0] : this.context; return { - source: optionalParams[0] ? optionalParams[0] : undefined, + source, }; } diff --git a/src/modules/logger/logger.service.ts b/src/modules/logger/logger.service.ts index ae58dd5..bcffaac 100644 --- a/src/modules/logger/logger.service.ts +++ b/src/modules/logger/logger.service.ts @@ -34,6 +34,14 @@ export class LoggerService implements ILoggerPort { this._contextRepository = contextRepository; } + public log(message: string | Error, data?: ILogPayload | undefined, profile?: string | undefined): void { + if (message instanceof Error) { + return this._logger.info(message.message, this._extractLogPayload(data), profile); + } + + this._logger.info(message, this._extractLogPayload(data), profile); + } + public startProfile(id: string): void { this._logger.startProfile(id); } @@ -70,13 +78,13 @@ export class LoggerService implements ILoggerPort { return this._logger.fatal(message, this._extractLogPayload(data), profile); } - public log( + public print( level: LogLevel, message: string | Error, data?: ILogPayload, profile?: string, ): void { - return this._logger.log(level, message, this._extractLogPayload(data), profile); + return this._logger.print(level, message, this._extractLogPayload(data), profile); } private _extractLogPayload(data?: ILogPayload): ILogPayload {