From 0780ad75761e3f46a5fac36130aaf281c2a3ad7c Mon Sep 17 00:00:00 2001 From: Harish V Date: Thu, 22 Feb 2024 16:14:19 +0800 Subject: [PATCH] test: struc logs --- src/logger/cloudwatch.logger.ts | 8 +++- src/logger/console.logger.ts | 10 ++-- src/logger/logger.ts | 83 +++++++++++++-------------------- 3 files changed, 44 insertions(+), 57 deletions(-) diff --git a/src/logger/cloudwatch.logger.ts b/src/logger/cloudwatch.logger.ts index 7206f28a0..91f6df9f2 100644 --- a/src/logger/cloudwatch.logger.ts +++ b/src/logger/cloudwatch.logger.ts @@ -8,6 +8,8 @@ import { config } from "@config/config" import { consoleLogger } from "./console.logger" import { LogMethod, Loggable } from "./logger.types" +const { combine, timestamp, json, errors } = winston.format + const withConsoleError = (logFn: LogMethod) => (message: Loggable): void => { try { logFn(message) @@ -47,7 +49,11 @@ export default class CloudWatchLogger { _logger: winston.Logger constructor() { - this._logger = winston.createLogger() + this._logger = winston.createLogger({ + level: "info", + format: combine(errors({ stack: true }), timestamp(), json()), + transports: [new winston.transports.Console()], + }) this.init() } diff --git a/src/logger/console.logger.ts b/src/logger/console.logger.ts index 149de6b5b..fd490691e 100644 --- a/src/logger/console.logger.ts +++ b/src/logger/console.logger.ts @@ -21,18 +21,18 @@ const COLORS = { export const consoleLogger: ExtendedLogger = { info: (message: string | Record): void => { // NOTE: This adds RGB to our console logs - console.log(COLORS.FOREGROUND.GREEN, `[INFO]: ${message}`) + console.log(COLORS.FOREGROUND.GREEN, `[INFO]: ${JSON.stringify(message)}`) }, warn: (message: string | Record): void => { - console.warn(COLORS.FOREGROUND.YELLOW, `[WARN]: ${message}`) + console.warn(COLORS.FOREGROUND.YELLOW, `[WARN]: ${JSON.stringify(message)}`) }, error: (message: string | Record): void => { - console.error(COLORS.FOREGROUND.RED, `[ERROR]: ${message}`) + console.error(COLORS.FOREGROUND.RED, `[ERROR]: ${JSON.stringify(message)}`) }, debug: (message: string | Record): void => { - console.debug(COLORS.FOREGROUND.BLUE, `[DEBUG]: ${message}`) + console.debug(COLORS.FOREGROUND.BLUE, `[DEBUG]: ${JSON.stringify(message)}`) }, fatal: (message: string | Record): void => { - console.error(COLORS.BACKGROUND.RED, `[FATAL]: ${message}`) + console.error(COLORS.BACKGROUND.RED, `[FATAL]: ${JSON.stringify(message)}`) }, } diff --git a/src/logger/logger.ts b/src/logger/logger.ts index 244930fa2..84fa96cbe 100644 --- a/src/logger/logger.ts +++ b/src/logger/logger.ts @@ -5,13 +5,11 @@ import { config } from "@root/config/config" import CloudWatchLogger from "./cloudwatch.logger" import { consoleLogger } from "./console.logger" import { - Formatter, Loggable, ExtendedLogger, LogMethod, - Logger, - WithDebug, LoggerVariants, + WithDebug, WithFatal, } from "./logger.types" @@ -23,85 +21,68 @@ const useConsoleLogger = !(NODE_ENV === "test") const timestampGenerator = () => moment().tz("Asia/Singapore").format("YYYY-MM-DD HH:mm:ss") -const hasDebug = (logger: LoggerVariants): logger is WithDebug => - (logger as WithDebug).debug !== undefined - -const hasFatal = (logger: LoggerVariants): logger is WithFatal => - (logger as WithFatal).fatal !== undefined - export class IsomerLogger implements ExtendedLogger { private loggers: LoggerVariants[] - private formatters: Formatter[] - constructor() { this.loggers = [] - this.formatters = [] } private getStructuredMessage = ( level: string, message: Loggable, additionalData?: object - ): string => { - const baseMessage = { - timestamp: timestampGenerator(), + ): object => ({ + timestamp: timestampGenerator(), + level, + message: typeof message === "string" ? message : JSON.stringify(message), + ...additionalData, + }) + + private emitLog( + level: string, + message: Loggable, + additionalData?: object + ): void { + const structuredMessage = this.getStructuredMessage( level, - message: typeof message === "string" ? message : JSON.stringify(message), - ...additionalData, // Spread additional data into the log entry - } - return JSON.stringify(baseMessage) // Convert the log entry to a JSON string + message, + additionalData + ) + this.loggers.forEach((logger: any) => { + if (typeof logger[level] === "function") { + logger[level](structuredMessage) + } + }) } - info: LogMethod = (message: Loggable, additionalData?: object): void => { - this.loggers.forEach((logger) => - logger.info(this.getStructuredMessage("info", message, additionalData)) - ) + info = (message: Loggable, additionalData?: object): void => { + this.emitLog("info", message, additionalData) } - warn: LogMethod = (message: Loggable, additionalData?: object): void => { - this.loggers.forEach((logger) => - logger.warn(this.getStructuredMessage("warn", message, additionalData)) - ) + warn = (message: Loggable, additionalData?: object): void => { + this.emitLog("warn", message, additionalData) } - error: LogMethod = (message: Loggable, additionalData?: object): void => { - this.loggers.forEach((logger) => - logger.error(this.getStructuredMessage("error", message, additionalData)) - ) + error = (message: Loggable, additionalData?: object): void => { + this.emitLog("error", message, additionalData) } - debug: LogMethod = (message: Loggable, additionalData?: object): void => { - this.loggers.forEach((logger) => { - if (hasDebug(logger)) - logger.debug( - this.getStructuredMessage("debug", message, additionalData) - ) - }) + debug = (message: Loggable, additionalData?: object): void => { + this.emitLog("debug", message, additionalData) } - fatal: LogMethod = (message: Loggable, additionalData?: object): void => { - this.loggers.forEach((logger) => { - if (hasFatal(logger)) - logger.fatal( - this.getStructuredMessage("fatal", message, additionalData) - ) - }) + fatal = (message: Loggable, additionalData?: object): void => { + this.emitLog("fatal", message, additionalData) } use(logger: LoggerVariants) { this.loggers.push(logger) } - - useFormatter(formatter: Formatter) { - this.formatters.push(formatter) // Note: You might want to adjust formatter logic to work with structured logs - } } const logger = new IsomerLogger() if (useConsoleLogger) logger.use(consoleLogger) if (useCloudwatchLogger) logger.use(new CloudWatchLogger()) -// Example formatter usage may need to be adjusted for structured logging -// logger.useFormatter((message) => `${timestampGenerator()}: ${message}`); export default logger