Skip to content

Commit

Permalink
test: struc logs
Browse files Browse the repository at this point in the history
  • Loading branch information
harishv7 committed Feb 22, 2024
1 parent 7ad1c9c commit 0780ad7
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 57 deletions.
8 changes: 7 additions & 1 deletion src/logger/cloudwatch.logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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()
}

Expand Down
10 changes: 5 additions & 5 deletions src/logger/console.logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@ const COLORS = {
export const consoleLogger: ExtendedLogger = {
info: (message: string | Record<string, unknown>): 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<string, unknown>): void => {
console.warn(COLORS.FOREGROUND.YELLOW, `[WARN]: ${message}`)
console.warn(COLORS.FOREGROUND.YELLOW, `[WARN]: ${JSON.stringify(message)}`)
},
error: (message: string | Record<string, unknown>): void => {
console.error(COLORS.FOREGROUND.RED, `[ERROR]: ${message}`)
console.error(COLORS.FOREGROUND.RED, `[ERROR]: ${JSON.stringify(message)}`)
},
debug: (message: string | Record<string, unknown>): void => {
console.debug(COLORS.FOREGROUND.BLUE, `[DEBUG]: ${message}`)
console.debug(COLORS.FOREGROUND.BLUE, `[DEBUG]: ${JSON.stringify(message)}`)
},
fatal: (message: string | Record<string, unknown>): void => {
console.error(COLORS.BACKGROUND.RED, `[FATAL]: ${message}`)
console.error(COLORS.BACKGROUND.RED, `[FATAL]: ${JSON.stringify(message)}`)
},
}
83 changes: 32 additions & 51 deletions src/logger/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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> =>
(logger as WithDebug<Logger>).debug !== undefined

const hasFatal = (logger: LoggerVariants): logger is WithFatal<Logger> =>
(logger as WithFatal<Logger>).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

0 comments on commit 0780ad7

Please sign in to comment.