import { trace } from '@opentelemetry/api'; enum LogLevel { TRACE = 'trace', DEBUG = 'debug', INFO = 'info', WARN = 'warn', ERROR = 'error', FATAL = 'fatal', SILENT = 'silent' } const LOG_LEVELS = new Map([ ['trace', 10], ['debug', 20], ['info', 30], ['warn', 40], ['error', 50], ['fatal', 60], ['silent', 1000] ]); interface LoggerFn { (message: string, payload?: any): void; } interface Message { message: string; level?: LogLevel; payload?: any; details?: any; } const LOG_COLORS = new Map([ [LogLevel.TRACE, '\x1b[45m'], [LogLevel.DEBUG, '\x1b[44m'], [LogLevel.INFO, '\x1b[42m'], [LogLevel.WARN, '\x1b[43m'], [LogLevel.ERROR, '\x1b[41m'], [LogLevel.FATAL, '\x1b[41m'] ]); let LOG_LEVEL = LOG_LEVELS.get(LogLevel.INFO); if (process.env.NODE_ENV === 'development') { LOG_LEVEL = LOG_LEVELS.get(process.env.LOG_LEVEL_DEV ?? LogLevel.INFO); } if (process.env.NODE_ENV === 'production') { LOG_LEVEL = LOG_LEVELS.get(process.env.LOG_LEVEL ?? LogLevel.INFO); } const writeMsg = ({ level, message, payload }: Message) => { if (LOG_LEVELS.get(level) < LOG_LEVEL) { return; } let log: Message | string = { message }; if (payload) { log.details = payload; } if (process.env.NODE_ENV === 'production') { log.level = level; log = `PZ LOG ----${level.toUpperCase()}---- ${JSON.stringify(log)}`; } if (process.env.NODE_ENV === 'development') { console.log( '\n\n' + LOG_COLORS.get(level), `▼ PZ ${level.toUpperCase()}${ message.length < 250 ? ` ━━ ${message}` : '' } \x1b[0m\n`, log, '\n\n' ); } else { console.log(log); } }; function createCustomSpan({ level, message, payload }: Message) { const tracer = trace.getTracer('pz-next-app'); const span = tracer.startSpan('custom-operation-log'); span.setAttributes({ level, message, payload }); span.end(); } const createLogAndSpan = (level: LogLevel, message: string, payload?: any) => { const content = { level, message, payload: JSON.stringify(payload) }; writeMsg(content); createCustomSpan(content); }; const logger: Record = { trace: (message, payload) => createLogAndSpan(LogLevel.TRACE, message, payload), debug: (message, payload) => createLogAndSpan(LogLevel.DEBUG, message, payload), info: (message, payload) => createLogAndSpan(LogLevel.INFO, message, payload), warn: (message, payload) => createLogAndSpan(LogLevel.WARN, message, payload), error: (message, payload) => createLogAndSpan(LogLevel.ERROR, message, payload), fatal: (message, payload) => createLogAndSpan(LogLevel.FATAL, message, payload), silent: () => {} }; export default logger;