import pino from 'pino'; const isProduction = process.env.NODE_ENV === 'production'; // Initialize the base pino instance const baseLogger = pino({ level: process.env.LOG_LEVEL || (isProduction ? 'info' : 'debug'), base: { env: process.env.NODE_ENV, service: 'api-gateway' }, transport: { targets: [ { target: 'pino-pretty', level: isProduction ? 'info' : 'debug', options: { colorize: true, ignore: 'pid,hostname', translateTime: 'SYS:standard', } }, ...(process.env.LOGTAIL_TOKEN ? [{ target: '@logtail/pino', level: 'info', options: { sourceToken: process.env.LOGTAIL_TOKEN } }] : []) ] } }); type LogFn = (arg1: Record | string, arg2?: unknown, ...args: unknown[]) => void; export interface AppLogger { info: LogFn; error: LogFn; warn: LogFn; debug: LogFn; child: (bindings: pino.Bindings) => pino.Logger; pino: pino.Logger; } // Bridges (msg, data) call pattern to pino's ({data}, msg) convention. const wrap = (level: 'info' | 'error' | 'warn' | 'debug'): LogFn => (arg1: Record | string, arg2?: unknown, ...args: unknown[]) => { if (typeof arg1 === 'string' && arg2 !== undefined) { return baseLogger[level]({ err: arg2, data: args.length > 0 ? args : undefined }, arg1); } return baseLogger[level](arg1 as Record, arg2 as string); }; export const logger: AppLogger = { info: wrap('info'), error: wrap('error'), warn: wrap('warn'), debug: wrap('debug'), child: (bindings: pino.Bindings) => baseLogger.child(bindings), pino: baseLogger }; export const log = logger;