import { context, trace } from '@opentelemetry/api'; import moment from 'moment'; import path from 'path'; import winston from 'winston'; import { getTraceInfoHeader } from "./tracing"; import { B3_INFO_KEY, B3_TRACE_ID_LENGTH_KEY } from "./UoaB3Propagator"; import { UoaLogger } from "./UoaLogger"; const defaultLogPattern = '%date [%thread] %level %class - [[[%traceId,%spanId,%info]]] %message' const uoaLogLevels = { error: 0, warn: 1, audit: 2, info: 3, debug: 4 } const uoaLoggingFormat = function (callingModule: NodeJS.Module) { return winston.format.printf((logInfo: any) => { let logPattern = process.env.loggingPattern ? process.env.loggingPattern : defaultLogPattern; const logReplacements = getLogReplacementValues(callingModule, logInfo); logReplacements.forEach((value, key) => { logPattern = logPattern.replace(key, value); }); return logPattern; }); } function getLogReplacementValues(callingModule: NodeJS.Module, logInfo: any): Map { const parts = callingModule.filename.substring(0, callingModule.filename.lastIndexOf('.js')).split(path.sep); const moduleParts = parts.slice(parts.indexOf('src')); let traceId = '-'; let spanId = '-'; const currentContext = trace.getSpanContext(context.active()); if (currentContext) { traceId = currentContext.traceId; spanId = currentContext.spanId; } let info = '-'; const infoHeader = context.active().getValue(B3_INFO_KEY); if (getTraceInfoHeader()) { info = getTraceInfoHeader(); } else if (infoHeader) { info = infoHeader.toString(); } let message = '-'; if (logInfo.message != null) { message = logInfo.message; } const traceIdLength: number = context.active().getValue(B3_TRACE_ID_LENGTH_KEY); let logReplacements: Map = new Map(); logReplacements.set('%date', moment().toISOString()); logReplacements.set('%thread', '-'); logReplacements.set('%level', logInfo.level.toUpperCase()); logReplacements.set('%class', moduleParts.join('.')); logReplacements.set('%traceId', traceId.slice(traceId.length - traceIdLength)); logReplacements.set('%spanId', spanId); logReplacements.set('%info', info); logReplacements.set('%message', message.replace(/\n/g, '')); return logReplacements; } module.exports = function (callingModule: NodeJS.Module) { return new UoaLogger({ levels: uoaLogLevels, transports: [ new winston.transports.Console({ level: process.env.loggingLevel ? process.env.loggingLevel.toLowerCase() : 'info' }) ], format: uoaLoggingFormat(callingModule) }); }