import { OpenTelemetryTransportV3 } from "@opentelemetry/winston-transport"; import { settings } from "@pkg/settings"; import type { Err } from "@pkg/result"; import winston from "winston"; import util from "util"; process.on("warning", (warning) => { const msg = String(warning?.message || ""); const name = String((warning as any)?.name || ""); if ( name === "TimeoutNegativeWarning" || msg.includes("TimeoutNegativeWarning") || msg.includes("Timeout duration was set to 1") ) { return; } console.warn(warning); }); const levels = { error: 0, warn: 1, info: 2, http: 3, debug: 4, } as const; const colors = { error: "red", warn: "yellow", info: "green", http: "magenta", debug: "white", }; const level = () => { const envLevel = process.env.LOG_LEVEL?.toLowerCase(); if (envLevel && Object.prototype.hasOwnProperty.call(levels, envLevel)) { return envLevel as keyof typeof levels; } return settings.isDevelopment ? "debug" : "warn"; }; const consoleFormat = winston.format.combine( winston.format.errors({ stack: true }), winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss:ms" }), winston.format.colorize({ all: true }), winston.format.printf((info) => { const { level, message, timestamp, ...extra } = info; const formattedMessage = message instanceof Error ? message.stack || message.message : typeof message === "object" ? util.inspect(message, { depth: null, colors: true }) : String(message); const formattedExtra = Object.keys(extra).length > 0 ? `\n${util.inspect(extra, { depth: null, colors: true })}` : ""; return `[${level}] ${timestamp}: ${formattedMessage}${formattedExtra}`; }), ); winston.addColors(colors); const logger = winston.createLogger({ level: level(), levels, format: consoleFormat, transports: [ new winston.transports.Console({ format: consoleFormat }), new OpenTelemetryTransportV3(), ], exceptionHandlers: [new winston.transports.Console({ format: consoleFormat })], rejectionHandlers: [new winston.transports.Console({ format: consoleFormat })], }); const stream = { write: (message: string) => logger.http(message.trim()) }; function getError(payload: Err, error?: any) { logger.error(JSON.stringify({ payload, error }, null, 2)); console.error(error); return { code: payload.code, message: payload.message, description: payload.description, detail: payload.detail, error: error instanceof Error ? error.message : error, actionable: payload.actionable, } as Err; } export { getError, logger, stream };