136 lines
4.0 KiB
TypeScript
136 lines
4.0 KiB
TypeScript
import * as winston from 'winston';
|
||
import * as DailyRotateFile from 'winston-daily-rotate-file';
|
||
import { WinstonModule } from 'nest-winston';
|
||
import * as path from 'path';
|
||
|
||
// 日志目录
|
||
const LOG_DIR = path.join(process.cwd(), 'logs');
|
||
|
||
// 日志格式
|
||
const logFormat = winston.format.combine(
|
||
winston.format.timestamp({
|
||
format: 'YYYY-MM-DD HH:mm:ss',
|
||
}),
|
||
winston.format.errors({ stack: true }),
|
||
winston.format.printf((info) => {
|
||
const { timestamp, level, message, context, stack, ...meta } = info;
|
||
const contextStr = context ? `[${context}] ` : '';
|
||
const stackStr = stack ? `\n${stack}` : '';
|
||
|
||
// 如果有额外的元数据,将其格式化为JSON字符串
|
||
const metaStr = Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta, null, 2)}` : '';
|
||
|
||
return `${timestamp} [${level.toUpperCase()}] ${contextStr}${message}${metaStr}${stackStr}`;
|
||
}),
|
||
);
|
||
|
||
// 控制台格式(带颜色)
|
||
const consoleFormat = winston.format.combine(
|
||
winston.format.colorize(),
|
||
winston.format.timestamp({
|
||
format: 'YYYY-MM-DD HH:mm:ss',
|
||
}),
|
||
winston.format.printf((info) => {
|
||
const { timestamp, level, message, context, stack, ...meta } = info;
|
||
const contextStr = context ? `[${context}] ` : '';
|
||
const stackStr = stack ? `\n${stack}` : '';
|
||
|
||
// 如果有额外的元数据,将其格式化为JSON字符串
|
||
const metaStr = Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta, null, 2)}` : '';
|
||
|
||
return `${timestamp} ${level} ${contextStr}${message}${metaStr}${stackStr}`;
|
||
}),
|
||
);
|
||
|
||
// 创建日志传输器
|
||
const createTransports = () => {
|
||
const transports: winston.transport[] = [];
|
||
|
||
// 控制台输出
|
||
transports.push(
|
||
new winston.transports.Console({
|
||
format: consoleFormat,
|
||
level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
|
||
}),
|
||
);
|
||
|
||
// 错误日志文件(按日期滚动,保留7天)
|
||
transports.push(
|
||
new DailyRotateFile({
|
||
filename: path.join(LOG_DIR, 'error-%DATE%.log'),
|
||
datePattern: 'YYYY-MM-DD',
|
||
level: 'error',
|
||
format: logFormat,
|
||
maxFiles: '7d', // 保留7天
|
||
maxSize: '20m', // 单个文件最大20MB
|
||
auditFile: path.join(LOG_DIR, '.audit-error.json'),
|
||
}),
|
||
);
|
||
|
||
// 应用日志文件(按日期滚动,保留7天)
|
||
transports.push(
|
||
new DailyRotateFile({
|
||
filename: path.join(LOG_DIR, 'app-%DATE%.log'),
|
||
datePattern: 'YYYY-MM-DD',
|
||
level: 'info',
|
||
format: logFormat,
|
||
maxFiles: '7d', // 保留7天
|
||
maxSize: '20m', // 单个文件最大20MB
|
||
auditFile: path.join(LOG_DIR, '.audit-app.json'),
|
||
}),
|
||
);
|
||
|
||
// 调试日志文件(仅在开发环境)
|
||
if (process.env.NODE_ENV !== 'production') {
|
||
transports.push(
|
||
new DailyRotateFile({
|
||
filename: path.join(LOG_DIR, 'debug-%DATE%.log'),
|
||
datePattern: 'YYYY-MM-DD',
|
||
level: 'debug',
|
||
format: logFormat,
|
||
maxFiles: '7d', // 保留7天
|
||
maxSize: '20m', // 单个文件最大20MB
|
||
auditFile: path.join(LOG_DIR, '.audit-debug.json'),
|
||
}),
|
||
);
|
||
}
|
||
|
||
return transports;
|
||
};
|
||
|
||
// Winston配置
|
||
export const winstonConfig = {
|
||
level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
|
||
format: logFormat,
|
||
transports: createTransports(),
|
||
// 处理未捕获的异常
|
||
exceptionHandlers: [
|
||
new DailyRotateFile({
|
||
filename: path.join(LOG_DIR, 'exceptions-%DATE%.log'),
|
||
datePattern: 'YYYY-MM-DD',
|
||
format: logFormat,
|
||
maxFiles: '7d',
|
||
maxSize: '20m',
|
||
auditFile: path.join(LOG_DIR, '.audit-exceptions.json'),
|
||
}),
|
||
],
|
||
// 处理未处理的Promise拒绝
|
||
rejectionHandlers: [
|
||
new DailyRotateFile({
|
||
filename: path.join(LOG_DIR, 'rejections-%DATE%.log'),
|
||
datePattern: 'YYYY-MM-DD',
|
||
format: logFormat,
|
||
maxFiles: '7d',
|
||
maxSize: '20m',
|
||
auditFile: path.join(LOG_DIR, '.audit-rejections.json'),
|
||
}),
|
||
],
|
||
};
|
||
|
||
// 创建Winston Logger实例
|
||
export const createWinstonLogger = () => {
|
||
return WinstonModule.createLogger(winstonConfig);
|
||
};
|
||
|
||
// 导出winston实例供直接使用
|
||
export const logger = winston.createLogger(winstonConfig); |