| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- const winston = require('winston');
- const path = require('path');
- // Define log levels
- const logLevels = {
- error: 0,
- warn: 1,
- info: 2,
- http: 3,
- debug: 4,
- };
- // Define log colors
- const logColors = {
- error: 'red',
- warn: 'yellow',
- info: 'green',
- http: 'magenta',
- debug: 'white',
- };
- winston.addColors(logColors);
- // Create logs directory if it doesn't exist
- const fs = require('fs');
- const logDir = path.join(__dirname, '../logs');
- if (!fs.existsSync(logDir)) {
- fs.mkdirSync(logDir, { recursive: true });
- }
- // Define log format
- const logFormat = winston.format.combine(
- winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
- winston.format.errors({ stack: true }),
- winston.format.json(),
- winston.format.printf(({ timestamp, level, message, stack, ...meta }) => {
- let log = `${timestamp} [${level.toUpperCase()}]: ${message}`;
- if (Object.keys(meta).length > 0) {
- log += ` | ${JSON.stringify(meta)}`;
- }
- if (stack) {
- log += `\n${stack}`;
- }
- return log;
- })
- );
- // Create console format for development
- const consoleFormat = winston.format.combine(
- winston.format.colorize({ all: true }),
- winston.format.timestamp({ format: 'HH:mm:ss' }),
- winston.format.printf(({ timestamp, level, message, ...meta }) => {
- let log = `${timestamp} [${level}]: ${message}`;
- if (Object.keys(meta).length > 0) {
- log += ` | ${JSON.stringify(meta)}`;
- }
- return log;
- })
- );
- // Create the logger instance
- const logger = winston.createLogger({
- level: process.env.LOG_LEVEL || 'info',
- levels: logLevels,
- format: logFormat,
- defaultMeta: { service: 'financial-data-server' },
- transports: [
- // Write all logs with importance level of `error` or less to `error.log`
- new winston.transports.File({
- filename: path.join(logDir, 'error.log'),
- level: 'error',
- maxsize: 5242880, // 5MB
- maxFiles: 5,
- }),
- // Write all logs with importance level of `info` or less to `combined.log`
- new winston.transports.File({
- filename: path.join(logDir, 'combined.log'),
- maxsize: 5242880, // 5MB
- maxFiles: 5,
- }),
- ],
- });
- // If we're not in production, log to the console as well
- if (process.env.NODE_ENV !== 'production') {
- logger.add(new winston.transports.Console({
- format: consoleFormat,
- level: process.env.LOG_LEVEL || 'debug',
- }));
- }
- // Create a stream object for Morgan HTTP logger
- const stream = {
- write: (message) => {
- logger.http(message.trim());
- },
- };
- // Handle uncaught exceptions and unhandled rejections
- logger.exceptions.handle(
- new winston.transports.File({
- filename: path.join(logDir, 'exceptions.log')
- })
- );
- logger.rejections.handle(
- new winston.transports.File({
- filename: path.join(logDir, 'rejections.log')
- })
- );
- // Graceful shutdown
- process.on('SIGTERM', () => {
- logger.info('SIGTERM received, shutting down gracefully');
- logger.end(() => {
- process.exit(0);
- });
- });
- process.on('SIGINT', () => {
- logger.info('SIGINT received, shutting down gracefully');
- logger.end(() => {
- process.exit(0);
- });
- });
- module.exports = {
- logger,
- stream
- };
|