export type LogLevel = 'debug' | 'info' | 'warn' | 'error'; export type LogDepth = 'normal' | 'verbose' | 'profiling'; export type LogType = 'http' | 'app' | 'auth' | 'profiling'; export interface LogHeader { timestamp: string; level: LogLevel; depth: LogDepth; type: LogType; // 'http', 'app', 'db', etc. user_id?: number; } export interface LogPayload { message?: string; // short human-friendly description data?: Record; // type-specific rich data } // Environment defaults const CURRENT_DEPTH: LogDepth = (process.env.LOG_DEPTH as LogDepth) || 'normal'; const DEPTH_ORDER: Record = { normal: 0, verbose: 1, profiling: 2 }; function shouldLog(depth: LogDepth) { let should = DEPTH_ORDER[depth] <= DEPTH_ORDER[CURRENT_DEPTH] return should; } function emitLog(header: LogHeader, payload: LogPayload = {}) { if (!shouldLog(header.depth)) return; const logLine = { ...header, ...payload }; if (header.level === 'error') console.error(JSON.stringify(logLine)) else console.log(JSON.stringify(logLine)); } export const logger = { log(level: LogLevel, type: LogType, message: string, data?: Record, depth: LogDepth = 'normal', context?: Partial) { const header: LogHeader = { timestamp: new Date().toISOString(), level, depth, type, ...context, }; const payload: LogPayload = { message, data, }; emitLog(header, payload); }, info(type: LogType, message: string, data?: Record, depth: LogDepth = 'normal', context?: Partial) { this.log('info', type, message, data, depth, context); }, debug(type: LogType, message: string, data?: Record, depth: LogDepth = 'normal', context?: Partial) { this.log('debug', type, message, data, depth, context); }, warn(type: LogType, message: string, data?: Record, depth: LogDepth = 'normal', context?: Partial) { this.log('warn', type, message, data, depth, context); }, error(type: LogType, message: string, data?: Record, depth: LogDepth = 'normal', context?: Partial) { this.log('error', type, message, data, depth, context); }, }