Files
apxtri/utils/logger.js
T
2026-05-11 11:16:47 +02:00

96 lines
2.9 KiB
JavaScript
Executable File

const path = require('path');
const chalk = require('chalk');
const levels = {
error: 0,
warn: 1,
info: 2,
debug: 3,
};
// Color mapping
const colors = {
error: chalk.red,
warn: chalk.yellow,
info: chalk.blue,
debug: chalk.gray,
};
// Get the set of active modules from the ACTIVELOG environment variable
const activeLogModules = new Set((process.env.ACTIVELOG || '').split(',').map(m => m.trim()).filter(Boolean));
// The filter is active only if the environment variable is explicitly defined.
const isModuleFilteringActive = process.env.ACTIVELOG !== undefined;
const getCallingInfo = () => {
const originalFunc = Error.prepareStackTrace;
let callerfile;
let callerlinenumber;
try {
const err = new Error();
Error.prepareStackTrace = (err, stack) => stack;
// The first call site is this file, the second is the logger function, the third is the actual caller.
const currentfile = err.stack[0].getFileName();
let i = 1;
while (i < err.stack.length) {
callerfile = err.stack[i].getFileName();
callerlinenumber = err.stack[i].getLineNumber();
if (callerfile !== currentfile) {
break;
}
i++;
}
} catch (e) {
// Fallback
}
Error.prepareStackTrace = originalFunc;
return {
fileName: callerfile ? path.relative(process.cwd(), callerfile) : 'unknown',
lineNumber: callerlinenumber || '?'
};
};
const logLevel = process.env.LOG_LEVEL || 'info';
const currentLevel = levels[logLevel.toLowerCase()] ?? levels.info;
const log = (level, message, ...args) => {
// 1. Check log level first
if (levels[level] > currentLevel) {
return;
}
const { fileName, lineNumber } = getCallingInfo();
const moduleFilterName = path.basename(fileName, '.js');
// 2. For 'info' and 'debug', check if the module is in the ACTIVELOG allow-list.
// 'error' and 'warn' messages will always be displayed regardless of the filter.
if (level === 'info' || level === 'debug') {
if (isModuleFilteringActive && !activeLogModules.has(moduleFilterName)) {
return;
}
}
// 3. Format and print the log message
const timestamp = new Date().toISOString();
const colorizer = colors[level] || (text => text); // Fallback to no color
const formattedMessage = colorizer(`${timestamp} [${level.toUpperCase()}] [${fileName}:${lineNumber}] - ${message}`);
if (level === 'error') {
console.error(formattedMessage, ...args.map(arg => colorizer(arg)));
} else if (level === 'warn') {
console.warn(formattedMessage, ...args.map(arg => colorizer(arg)));
} else {
console.log(formattedMessage, ...args);
}
};
const logger = {
error: (message, ...args) => log('error', message, ...args),
warn: (message, ...args) => log('warn', message, ...args),
info: (message, ...args) => log('info', message, ...args),
debug: (message, ...args) => log('debug', message, ...args),
};
module.exports = logger;