为什么需要日志中间件?
- 追踪请求流程: 记录每个请求的详细信息,包括请求方法、URL、请求头、请求体等,让你了解请求的完整路径。
- 监控应用状态: 记录应用的运行状态,例如错误信息、警告信息、性能指标等,让你及时发现潜在问题。
- 调试和排错: 当应用出现问题时,通过分析日志,你可以快速定位问题,并找到解决方案。
- 安全审计: 记录用户的操作行为,例如登录、修改数据等,为安全审计提供依据。
选择合适的日志库
Node.js 社区提供了丰富的日志库,常见的选择包括:
console.log
(内置): 最简单的日志记录方式,但功能有限,不适合生产环境。morgan
: 专门用于记录 HTTP 请求日志的中间件,配置简单,功能强大。winston
: 功能强大的日志库,支持多种日志级别、输出目标和格式化选项。pino
: 高性能的 JSON 日志库,适合对性能有较高要求的应用。bunyan
: 结构化 JSON 日志库,方便分析和查询。
本文将以 morgan
和 winston
为例,介绍如何在 Express 应用中使用日志中间件。
使用 morgan
记录 HTTP 请求日志
morgan
是一个轻量级的 HTTP 请求日志中间件,可以方便地记录请求的详细信息。
-
安装
morgan
:bashnpm install morgan
-
在 Express 应用中使用
morgan
:javascriptconst express = require('express'); const morgan = require('morgan'); const app = express(); // 使用 'dev' 格式记录日志 app.use(morgan('dev')); // 或者使用自定义格式 morgan.token('body', (req, res) => { return JSON.stringify(req.body); }); app.use(morgan(':method :url :status :res[content-length] - :response-time ms :body')); app.get('/', (req, res) => { res.send('Hello World!'); }); app.post('/data', (req, res) => { res.send('Data received!'); }); app.listen(3000, () => { console.log('Server listening on port 3000'); });
morgan
提供了多种预定义的日志格式,例如dev
、combined
、common
等。你也可以自定义日志格式,以满足不同的需求。
使用 winston
进行更高级的日志记录
winston
提供了更强大的日志记录功能,例如支持多种日志级别、输出目标和格式化选项。
-
安装
winston
:bashnpm install winston
-
配置
winston
:javascriptconst winston = require('winston'); const logger = winston.createLogger({ level: 'info', format: winston.format.combine( winston.format.timestamp(), winston.format.json() ), transports: [ new winston.transports.File({ filename: 'error.log', level: 'error' }), new winston.transports.File({ filename: 'combined.log' }), ], }); if (process.env.NODE_ENV !== 'production') { logger.add(new winston.transports.Console({ format: winston.format.simple() })); } module.exports = logger;
在上面的代码中,我们创建了一个
winston
logger 实例,配置了日志级别、格式和输出目标。日志级别包括error
、warn
、info
、verbose
、debug
、silly
等。输出目标可以是控制台、文件、数据库等。 -
在 Express 应用中使用
winston
:javascriptconst express = require('express'); const logger = require('./logger'); const app = express(); // 使用中间件记录请求日志 app.use((req, res, next) => { logger.info({ message: 'Incoming request', method: req.method, url: req.url, headers: req.headers, body: req.body, }); next(); }); app.get('/', (req, res) => { logger.info('Hello World route accessed'); res.send('Hello World!'); }); app.use((err, req, res, next) => { logger.error({ message: 'Error occurred', error: err.message, stack: err.stack, }); res.status(500).send('Something went wrong!'); }); app.listen(3000, () => { logger.info('Server listening on port 3000'); });
在上面的代码中,我们使用中间件记录每个请求的详细信息,包括请求方法、URL、请求头、请求体等。我们还使用
winston
记录错误信息,方便调试和排错。