Files
Checkmate/server/src/utils/logger.js
T

151 lines
4.0 KiB
JavaScript
Raw Normal View History

2025-04-20 11:29:53 -07:00
import { createLogger, format, transports } from "winston";
import dotenv from "dotenv";
dotenv.config();
2025-04-20 11:29:53 -07:00
2025-07-25 10:16:29 -07:00
const SERVICE_NAME = "Logger";
2025-04-20 11:29:53 -07:00
class Logger {
2025-07-25 10:16:29 -07:00
static SERVICE_NAME = SERVICE_NAME;
2025-04-20 11:29:53 -07:00
constructor() {
2025-06-23 11:25:42 +08:00
this.logCache = [];
2025-06-23 12:19:52 +08:00
this.maxCacheSize = 1000;
2025-07-21 10:34:16 -07:00
const consoleFormat = format.printf(({ level, message, service, method, details, timestamp, stack }) => {
if (message instanceof Object) {
message = JSON.stringify(message, null, 2);
}
2025-04-20 11:29:53 -07:00
2025-07-21 10:34:16 -07:00
if (details instanceof Object) {
details = JSON.stringify(details, null, 2);
}
let msg = `${timestamp} ${level}:`;
service && (msg += ` [${service}]`);
method && (msg += `(${method})`);
message && (msg += ` ${message}`);
details && (msg += ` (details: ${details})`);
2025-04-20 11:29:53 -07:00
2025-07-21 10:34:16 -07:00
if (typeof stack !== "undefined") {
const stackTrace = stack
?.split("\n")
.slice(1) // Remove first line (error message)
.map((line) => {
const match = line.match(/at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)/);
if (match) {
return {
function: match[1],
file: match[2],
line: parseInt(match[3]),
column: parseInt(match[4]),
};
}
return line.trim();
});
stack && (msg += ` (stack: ${JSON.stringify(stackTrace, null, 2)})`);
2025-04-20 11:29:53 -07:00
}
2025-07-21 10:34:16 -07:00
return msg;
});
2025-04-20 11:29:53 -07:00
const logLevel = process.env.LOG_LEVEL || "info";
2025-04-20 11:29:53 -07:00
this.logger = createLogger({
level: logLevel,
2025-04-20 11:29:53 -07:00
format: format.combine(format.timestamp()),
transports: [
new transports.Console({
2025-07-21 10:34:16 -07:00
format: format.combine(format.colorize(), format.prettyPrint(), format.json(), consoleFormat),
2025-04-20 11:29:53 -07:00
}),
new transports.File({
format: format.combine(format.json()),
filename: "app.log",
}),
],
});
}
2025-07-25 15:15:14 -07:00
get serviceName() {
return Logger.SERVICE_NAME;
}
2025-04-20 11:29:53 -07:00
/**
* Logs an informational message.
* @param {Object} config - The configuration object.
* @param {string} config.message - The message to log.
* @param {string} config.service - The service name.
* @param {string} config.method - The method name.
* @param {Object} config.details - Additional details.
*/
info(config) {
2025-06-23 13:19:18 +08:00
const logEntry = this.buildLogEntry("info", config);
2025-06-23 11:25:42 +08:00
this.cacheLog(logEntry);
2025-06-25 09:35:41 +08:00
this.logger.info(logEntry);
2025-04-20 11:29:53 -07:00
}
/**
* Logs a warning message.
* @param {Object} config - The configuration object.
* @param {string} config.message - The message to log.
* @param {string} config.service - The service name.
* @param {string} config.method - The method name.
* @param {Object} config.details - Additional details.
*/
warn(config) {
2025-06-23 13:19:18 +08:00
const logEntry = this.buildLogEntry("warn", config);
2025-06-23 11:25:42 +08:00
this.cacheLog(logEntry);
2025-06-25 09:35:41 +08:00
this.logger.warn(logEntry);
2025-04-20 11:29:53 -07:00
}
/**
* Logs an error message.
* @param {Object} config - The configuration object.
* @param {string} config.message - The message to log.
* @param {string} config.service - The service name.
* @param {string} config.method - The method name.
* @param {Object} config.details - Additional details.
*/
error(config) {
2025-06-23 13:19:18 +08:00
const logEntry = this.buildLogEntry("error", config);
2025-06-23 11:25:42 +08:00
this.cacheLog(logEntry);
2025-06-25 09:35:41 +08:00
this.logger.error(logEntry);
2025-04-20 11:29:53 -07:00
}
/**
* Logs a debug message.
* @param {Object} config - The configuration object.
* @param {string} config.message - The message to log.
* @param {string} config.service - The service name.
* @param {string} config.method - The method name.
* @param {Object} config.details - Additional details.
*/
debug(config) {
2025-06-23 13:19:18 +08:00
const logEntry = this.buildLogEntry("debug", config);
2025-06-23 11:25:42 +08:00
this.cacheLog(logEntry);
2025-06-25 09:35:41 +08:00
this.logger.debug(logEntry);
2025-06-23 11:25:42 +08:00
}
cacheLog(entry) {
this.logCache.push(entry);
if (this.logCache.length > this.maxCacheSize) {
this.logCache.shift();
}
}
getLogs() {
return this.logCache;
}
2025-06-23 13:19:18 +08:00
buildLogEntry(level, config) {
return {
level,
message: config.message,
service: config.service,
method: config.method,
details: config.details,
2025-06-23 13:22:53 +08:00
stack: config.stack,
2025-06-23 13:19:18 +08:00
timestamp: new Date().toISOString(),
};
}
2025-04-20 11:29:53 -07:00
}
const logger = new Logger();
export { Logger };
export default logger;