# 功能-日志
# winston
winston (opens new window) 是一个通用的 node 日志库,支持灵活的配置和多种传输方式(如控制台输出、文件存储、HTTP 传输等)。它适用于记录应用程序的各种日志,包括信息日志、错误日志、调试日志等。
# 概念
Logger: 在winston中,日志记录器(Logger)是核心组件,负责创建和管理日志记录。每个日志记录器可以配置多个传输方式,并可以设置不同的日志级别。Levels: 定义了日志的级别,例如error、warn、info、debug等。不同级别的日志可以输出到不同的 Transport。Transports: 传输方式,定义了日志的输出目标,例如控制台、文件、数据库等。winston内置了多种Transport,也支持自定义。Format: 格式化器, 定义了日志的格式,例如JSON、文本、颜色等。winston 提供了多种内置格式,也支持自定义。
示例:
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [new winston.transports.Console()],
});
# 日志级别
winston 默认支持的日志级别(从高到低)如下:
| 级别 | 说明 |
|---|---|
| error | 错误信息,表示严重的故障或问题。 |
| warn | 警告信息,表示潜在的问题或异常。 |
| info | 一般信息,用于记录应用程序的运行状态。 |
| verbose | 详细信息,提供比 info 更详细的日志。 |
| debug | 调试信息,用于开发和调试阶段。 |
| silly | 最详细的日志信息,通常用于极端调试场景。 |
日志Levels 可以在 winston 的 Logger 中配置,也可以在 Transport 中配置,如:
// 在 Logger 中配置
const logger = winston.createLogger({
level: 'info',
transports: [new winston.transports.Console()],
});
// 在 Transport 中配置
const logger = winston.createLogger({
level: 'info',
transports: [new winston.transports.Console()],
});
# 自定义日志级别
日志Levels 可以自定义,如我们自定义下面的日志级别并设置颜色:
const customLevels = {
levels: {
critical: 0, // 自定义 严重错误
error: 1,
warning: 2,
notice: 3,
info: 4,
debug: 5
},
colors: {
critical: 'red',
error: 'orange',
warning: 'yellow',
notice: 'blue',
info: 'green',
debug: 'gray'
}
};
const logger = createLogger({
levels: customLevels.levels,
transports: [new transports.Console()]
});
logger.critical('This is a critical message');
logger.notice('This is a notice message');
在logger中设置级别颜色
const { format, transports } = require('winston');
// 引入combine、colorize、printf格式
const { combine, colorize, printf } = format;
// 自定义格式
const customFormat = printf(({ level, message }) => {
return `${level}: ${message}`;
});
const logger = createLogger({
levels: customLevels.levels,
// 设置日志格式
format: combine(colorize(), customFormat),
// 设置日志输出位置
transports: [new transports.Console()]
});
// 执行
logger.critical('This is a critical message');
logger.notice('This is a notice message');
# Format
Format 是 winston 中用于定义日志格式的核心概念。每个 Format 负责将日志转换为特定的格式,例如 JSON、文本、颜色等。以下是 Format 的详细介绍和使用方法。
| Format | 说明 |
|---|---|
| format.json() | 将日志格式化为 JSON。 |
| format.simple() | 将日志格式化为简单文本。 |
| format.combine() | 组合多个格式。 |
| format.timestamp() | 添加时间戳。 |
| format.colorize() | 为日志添加颜色。 |
| format.printf() | 自定义日志格式。 |
| format.prettyPrint() | 将日志格式化为易读的 JSON。 |
| format.label() | 为日志添加标签。 |
| format.metadata() | 添加元数据。 |
除此之外我们还可以自定义格式,如:
const customFormat = format.printf(({ level, message, timestamp }) => {
return `${timestamp} [${level}]: ${message}`;
});
const logger = createLogger({
format: format.combine(
format.timestamp(),
customFormat
),
transports: [new transports.Console()]
});
logger.info('This is an info message');
# Transports
Transports 是 winston 中用于定义日志输出目标的核心概念。每个 Transport 负责将日志发送到特定的目标,例如控制台、文件、数据库等。以下是 Transports 的详细介绍和使用方法。
| Transport | 说明 |
|---|---|
transports.Console | 将日志输出到控制台。 |
transports.File | 将日志输出到文件。 |
transports.Http | 将日志发送到 HTTP 服务器。 |
transports.Stream | 将日志输出到流。 |
例如:使用transports.Console 在开发环境下将日志输出到控制台
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [new winston.transports.Console()],
});
在生产环境下使用transports.File 将日志输出到文件
// 自定义日志格式
const logFormat = winston.format.printf(({ level, message, timestamp }) => {
return `${timestamp} [${level}]: ${JSON.stringify(message)}`;
});
// 设置北京时间的格式化函数
const beijingTime = winston.format((info) => {
info.timestamp = new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai', hour12: false });
return info;
});
new winston.transports.File({
filename: path.join(logDir, `${date}-${type}.log`), // 日志文件名,使用日期和类型拼接
level: type, // 日志级别,使用类型作为级别
maxAge: 1000 * 60 * 60 * 24 * 30, // 日志保留时间30天
maxFiles: 10, // 最大文件数,最多保留10个日志文件
maxsize: 10000000, // 10MB,单个日志文件最大大小为10MB
tailable: true, // 是否跟随日志文件,如果为true,则可以实时读取日志文件的新内容
zippedArchive: true, // 是否压缩日志文件,如果为true,则将日志文件压缩存储
format: winston.format.combine( // 日志格式
beijingTime(), // 使用北京时间,默认使用UTC时间
winston.format.timestamp(), // 添加时间戳
winston.format.colorize(), // 添加颜色
logFormat // 自定义日志格式
)
})
# 详细代码
在logs目录下创建一个index.js文件,并添加以下代码:
const winston = require('winston');
const fs = require('fs');
const path = require('path');
// 创建日志目录
const logDir = path.join(__dirname, './logs');
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir);
}
// 自定义日志格式
const logFormat = winston.format.printf(({ level, message, timestamp }) => {
return `${timestamp} [${level}]: ${JSON.stringify(message)}`;
});
// 设置北京时间的格式化函数
const beijingTime = winston.format((info) => {
info.timestamp = new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai', hour12: false });
return info;
});
// 根据环境配置日志传输器
const transports = [];
if (process.env.NODE_ENV === 'production') {
const types = ['error', 'info'];
const date = new Date().toLocaleString().split(' ')[0];
types.forEach(type => {
transports.push(
new winston.transports.File({
filename: path.join(logDir, `${date}-${type}.log`), // 日志文件名,使用日期和类型拼接
level: type, // 日志级别
maxFiles: 10, // 最大文件数
maxsize: 10000000, // 10MB,最大文件大小
tailable: true, // 是否跟随日志文件
zippedArchive: true, // 是否压缩归档
format: winston.format.combine( // 日志格式
beijingTime(), // 北京时间
winston.format.timestamp(), // 时间戳
logFormat // 自定义日志格式
)
})
)
})
}else {
// 开发环境下,输出到控制台
transports.push(
new winston.transports.Console({
format: winston.format.combine(
// 获取北京时间
beijingTime(),
// 格式化日志输出
winston.format.colorize(),
// 添加时间戳
winston.format.timestamp(),
// 自定义日志格式
logFormat
)
})
)
}
// 创建日志记录器
const logger = winston.createLogger({
level: 'info',
transports,
});
module.exports = logger;
在app.js中使用
const logger = require('./logs');
// 中间件:记录所有请求的日志
app.use((req, res, next) => {
logger.info({
method: req.method,
ip: req.ip,
url: req.originalUrl,
data: req.body
});
next();
});
// 全局错误处理中间件
app.use((err, req, res, next) => {
logger.error({
method: req.method,
ip: req.ip,
url: req.originalUrl,
error: err.message,
stack: err.stack
});
res.status(500).json({ message: 'Internal Server Error' });
});
# 其它日志
Morgan(opens new window) 作为一款专为Node.js设计的 HTTP 请求记录中间件,它的出现极大地简化了开发者在调试和性能优化过程中对于 HTTP 请求日志的处理工作。- logs4js (opens new window) 是一个基于
log4js的Node.js日志库,它提供了灵活的日志记录功能,支持多种日志格式和传输方式。