|
|
import winston from 'winston'; |
|
|
import DailyRotateFile from 'winston-daily-rotate-file'; |
|
|
import chalk from 'chalk'; |
|
|
|
|
|
const { combine, timestamp, printf, colorize, errors, json } = winston.format; |
|
|
|
|
|
|
|
|
const levels = { |
|
|
error: 0, |
|
|
warn: 1, |
|
|
info: 2, |
|
|
http: 3, |
|
|
debug: 4, |
|
|
}; |
|
|
|
|
|
|
|
|
const colors = { |
|
|
error: 'red', |
|
|
warn: 'yellow', |
|
|
info: 'green', |
|
|
http: 'magenta', |
|
|
debug: 'white', |
|
|
}; |
|
|
|
|
|
|
|
|
winston.addColors(colors); |
|
|
|
|
|
|
|
|
const consoleFormat = printf(({ level, message, timestamp, stack, label }) => { |
|
|
let color; |
|
|
switch (level) { |
|
|
case 'error': color = chalk.red.bold; break; |
|
|
case 'warn': color = chalk.yellow; break; |
|
|
case 'info': color = chalk.green; break; |
|
|
case 'http': color = chalk.magenta; break; |
|
|
case 'debug': color = chalk.blue; break; |
|
|
default: color = chalk.white; |
|
|
} |
|
|
|
|
|
let logMessage = `${chalk.gray(timestamp)} ${color(`[${level.toUpperCase()}]`)}`; |
|
|
|
|
|
if (label) { |
|
|
logMessage += ` ${chalk.cyan(`(${label})`)}`; |
|
|
} |
|
|
|
|
|
logMessage += `: ${message}`; |
|
|
|
|
|
if (stack) { |
|
|
logMessage += `\n${chalk.red(stack)}`; |
|
|
} |
|
|
|
|
|
return logMessage; |
|
|
}); |
|
|
|
|
|
|
|
|
const fileFormat = combine( |
|
|
errors({ stack: true }), |
|
|
timestamp(), |
|
|
json() |
|
|
); |
|
|
|
|
|
|
|
|
const transports = [ |
|
|
new winston.transports.Console({ |
|
|
format: combine( |
|
|
colorize({ level: true }), |
|
|
timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), |
|
|
errors({ stack: true }), |
|
|
consoleFormat |
|
|
), |
|
|
}), |
|
|
new DailyRotateFile({ |
|
|
filename: 'logs/error-%DATE%.log', |
|
|
datePattern: 'YYYY-MM-DD', |
|
|
zippedArchive: true, |
|
|
maxSize: '20m', |
|
|
maxFiles: '14d', |
|
|
level: 'error', |
|
|
format: fileFormat, |
|
|
}), |
|
|
new DailyRotateFile({ |
|
|
filename: 'logs/combined-%DATE%.log', |
|
|
datePattern: 'YYYY-MM-DD', |
|
|
zippedArchive: true, |
|
|
maxSize: '20m', |
|
|
maxFiles: '14d', |
|
|
format: fileFormat, |
|
|
}), |
|
|
]; |
|
|
|
|
|
|
|
|
const logger = winston.createLogger({ |
|
|
level: process.env.LOG_LEVEL || 'info', |
|
|
levels, |
|
|
format: combine( |
|
|
timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), |
|
|
errors({ stack: true }) |
|
|
), |
|
|
transports, |
|
|
exitOnError: false, |
|
|
}); |
|
|
|
|
|
|
|
|
export const createLogger = (label: string) => { |
|
|
return logger.child({ label }); |
|
|
}; |
|
|
|
|
|
|
|
|
export const httpLogStream = { |
|
|
write: (message: string) => { |
|
|
logger.http(message.trim()); |
|
|
}, |
|
|
}; |
|
|
|
|
|
export default logger; |