use winstonlog
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
"pg": "^8.14.0",
|
||||
"redis": "^4.7.0",
|
||||
"uuid": "^11.1.0",
|
||||
"winston": "^3.17.0",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,71 +1,79 @@
|
||||
import winston from 'winston';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import config from '../config';
|
||||
|
||||
/**
|
||||
* Logger levels
|
||||
*/
|
||||
export enum LogLevel {
|
||||
DEBUG = 'DEBUG',
|
||||
INFO = 'INFO',
|
||||
WARN = 'WARN',
|
||||
ERROR = 'ERROR'
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility class for logging messages to console and file
|
||||
*/
|
||||
class Logger {
|
||||
private logDir: string;
|
||||
private logFile: string;
|
||||
private debugEnabled: boolean;
|
||||
|
||||
constructor() {
|
||||
// Set up log directory
|
||||
this.logDir = path.join(process.cwd(), 'logs');
|
||||
// Define log levels matching existing implementation
|
||||
const levels = {
|
||||
error: 0,
|
||||
warn: 1,
|
||||
info: 2,
|
||||
debug: 3
|
||||
};
|
||||
|
||||
// Create logs directory if it doesn't exist
|
||||
if (!fs.existsSync(this.logDir)) {
|
||||
fs.mkdirSync(this.logDir, { recursive: true });
|
||||
const logDir = path.join(process.cwd(), 'logs');
|
||||
if (!fs.existsSync(logDir)) {
|
||||
fs.mkdirSync(logDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Set log file path with date in filename
|
||||
const now = new Date();
|
||||
const dateStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
|
||||
this.logFile = path.join(this.logDir, `app-${dateStr}.log`);
|
||||
const logFile = path.join(logDir, `app-${dateStr}.log`);
|
||||
|
||||
// Enable debug logs based on environment (NODE_ENV)
|
||||
this.debugEnabled = process.env.NODE_ENV !== 'production';
|
||||
}
|
||||
// Define log format
|
||||
const logFormat = winston.format.printf(({ timestamp, level, message, ...metadata }) => {
|
||||
let logMessage = `[${timestamp}] [${level.toUpperCase()}] ${message}`;
|
||||
|
||||
/**
|
||||
* Format log message with timestamp and level
|
||||
*/
|
||||
private formatMessage(level: LogLevel, message: string, data?: any): string {
|
||||
const timestamp = new Date().toISOString();
|
||||
let formattedMessage = `[${timestamp}] [${level}] ${message}`;
|
||||
|
||||
if (data) {
|
||||
if (typeof data === 'object') {
|
||||
// Add metadata if exists and is not empty
|
||||
if (metadata && Object.keys(metadata).length > 0) {
|
||||
try {
|
||||
const dataStr = JSON.stringify(data);
|
||||
formattedMessage += ` - ${dataStr}`;
|
||||
logMessage += ` - ${JSON.stringify(metadata)}`;
|
||||
} catch (error) {
|
||||
formattedMessage += ` - [Object cannot be stringified]`;
|
||||
}
|
||||
} else {
|
||||
formattedMessage += ` - ${data}`;
|
||||
logMessage += ` - [Object cannot be stringified]`;
|
||||
}
|
||||
}
|
||||
|
||||
return formattedMessage;
|
||||
}
|
||||
return logMessage;
|
||||
});
|
||||
|
||||
// Create Winston logger
|
||||
const winstonLogger = winston.createLogger({
|
||||
levels,
|
||||
level: process.env.NODE_ENV !== 'production' ? 'debug' : 'info',
|
||||
format: winston.format.combine(
|
||||
winston.format.timestamp(),
|
||||
winston.format.errors({ stack: true }),
|
||||
logFormat
|
||||
),
|
||||
transports: [
|
||||
// Console transport
|
||||
new winston.transports.Console({
|
||||
format: winston.format.combine(
|
||||
winston.format.colorize(),
|
||||
winston.format.timestamp(),
|
||||
logFormat
|
||||
)
|
||||
}),
|
||||
// File transport
|
||||
new winston.transports.File({
|
||||
filename: logFile
|
||||
})
|
||||
],
|
||||
exitOnError: false
|
||||
});
|
||||
|
||||
/**
|
||||
* Write log to file
|
||||
* Logger interface that matches the previous implementation
|
||||
*/
|
||||
private writeToFile(message: string): void {
|
||||
fs.appendFileSync(this.logFile, message + '\n');
|
||||
class Logger {
|
||||
private logFile: string;
|
||||
private debugEnabled: boolean;
|
||||
|
||||
constructor() {
|
||||
this.logFile = logFile;
|
||||
this.debugEnabled = process.env.NODE_ENV !== 'production';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,27 +82,33 @@ class Logger {
|
||||
debug(message: string, data?: any): void {
|
||||
if (!this.debugEnabled) return;
|
||||
|
||||
const formattedMessage = this.formatMessage(LogLevel.DEBUG, message, data);
|
||||
console.debug(formattedMessage);
|
||||
this.writeToFile(formattedMessage);
|
||||
if (data) {
|
||||
winstonLogger.debug(message, data);
|
||||
} else {
|
||||
winstonLogger.debug(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Info level log
|
||||
*/
|
||||
info(message: string, data?: any): void {
|
||||
const formattedMessage = this.formatMessage(LogLevel.INFO, message, data);
|
||||
console.info(formattedMessage);
|
||||
this.writeToFile(formattedMessage);
|
||||
if (data) {
|
||||
winstonLogger.info(message, data);
|
||||
} else {
|
||||
winstonLogger.info(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Warning level log
|
||||
*/
|
||||
warn(message: string, data?: any): void {
|
||||
const formattedMessage = this.formatMessage(LogLevel.WARN, message, data);
|
||||
console.warn(formattedMessage);
|
||||
this.writeToFile(formattedMessage);
|
||||
if (data) {
|
||||
winstonLogger.warn(message, data);
|
||||
} else {
|
||||
winstonLogger.warn(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,9 +126,11 @@ class Logger {
|
||||
};
|
||||
}
|
||||
|
||||
const formattedMessage = this.formatMessage(LogLevel.ERROR, message, errorData);
|
||||
console.error(formattedMessage);
|
||||
this.writeToFile(formattedMessage);
|
||||
if (errorData) {
|
||||
winstonLogger.error(message, errorData);
|
||||
} else {
|
||||
winstonLogger.error(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user