jiraCloud/lib/logger.js
jmcqueen 0b056739e9 Add modular Jira-to-Webex approvals service with Docker deployment.
Stabilize logging, correlation IDs, service-account Jira auth, and direct approver reminder DMs while splitting the monolith into focused modules with Compose-based deployment.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-17 08:34:47 -04:00

88 lines
3 KiB
JavaScript

import fs from 'fs';
import path from 'path';
import { createCorrelationId, getCorrelationId, runWithCorrelationId } from './correlation.js';
const LOG_LEVELS = { error: 0, warn: 1, info: 2, debug: 3 };
export function createLogger(config) {
const currentLogLevel = LOG_LEVELS[config.logLevel?.toLowerCase()] ?? LOG_LEVELS.info;
function formatError(error) {
if (!error) return 'Unknown error';
if (typeof error === 'string') return error;
if (error.response?.data) {
return `${error.message || 'Request failed'}: ${JSON.stringify(error.response.data)}`;
}
return error.stack || error.message || String(error);
}
function correlationPrefix() {
const correlationId = getCorrelationId();
return correlationId ? `[${correlationId}] ` : '';
}
function writeLog(level, activeFunction, message) {
if (LOG_LEVELS[level] > currentLogLevel) return;
const line = `${new Date().toISOString()} [${level.toUpperCase()}] ${correlationPrefix()}${activeFunction}: ${message}`;
if (level === 'error') console.error(line);
else if (level === 'warn') console.warn(line);
else console.log(line);
}
function logger(activeFunction, logLine) {
writeLog('info', activeFunction, logLine);
}
function logWarn(activeFunction, logLine) {
writeLog('warn', activeFunction, logLine);
}
function logError(activeFunction, logLine, error) {
const detail = error !== undefined ? ` ${formatError(error)}` : '';
writeLog('error', activeFunction, `${logLine}${detail}`);
}
function logDebug(activeFunction, logLine) {
writeLog('debug', activeFunction, logLine);
}
function safeProcess(context, fn, meta = {}) {
const correlationId = meta.correlationId || createCorrelationId(meta);
runWithCorrelationId(correlationId, () => {
Promise.resolve()
.then(fn)
.catch(error => logError(context, 'Unhandled error during async processing', error));
});
}
function logFile(provider, jsonData) {
const d = new Date();
const year = d.getFullYear();
const month = (d.getMonth() + 1).toString().padStart(2, '0');
const day = d.getDate().toString().padStart(2, '0');
const logFilePath = path.join(`./logs/${provider}-${year}${month}${day}.log`);
const correlationId = getCorrelationId();
const correlationLine = correlationId ? ` [${correlationId}]` : '';
const content = `${d.toISOString()}${correlationLine}\n${JSON.stringify(jsonData)}\n`;
fs.appendFile(logFilePath, content, (error) => {
if (error) {
logError('logFile', `Failed to write ${provider} webhook log`, error);
}
});
}
return {
logger,
logWarn,
logError,
logDebug,
safeProcess,
logFile,
writeLog,
formatError,
runWithCorrelationId,
createCorrelationId,
getCorrelationId,
};
}