在 Node.js 中,日志格式的定义通常取决于你使用的日志库、业务需求以及运行环境(本地 / 容器 / 云)。下面从通用原则 → 常见格式 → 示例 → 推荐实践来说明。
一个合理的日志格式通常包含:
| 字段 | 说明 |
|---|---|
| timestamp | 时间戳(ISO 8601 推荐) |
| level | 日志级别(info / warn / error) |
| message | 日志内容 |
| context | 业务上下文(userId、requestId、module) |
| stack | 错误堆栈(仅 error) |
| meta | 额外结构化数据 |
2026-01-21 10:32:11 [info] 用户登录成功 userId=123
✅ 可读性好
❌ 不利于机器解析
{
"timestamp": "2026-01-21T10:32:11.123Z",
"level": "info",
"message": "用户登录成功",
"userId": 123,
"requestId": "req-abc"
}
✅ 适合 ELK / Loki / Datadog
✅ 易检索、易分析
✅ 云原生标准
[2026-01-21T10:32:11.123Z] INFO [req-abc] 用户登录成功 userId=123
npm install winston
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
transports: [
new winston.transports.Console()
]
});
logger.info('用户登录成功', {
userId: 123,
requestId: 'req-abc'
});
输出:
{
"level": "info",
"message": "用户登录成功",
"userId": 123,
"requestId": "req-abc",
"timestamp": "2026-01-21T10:32:11.123Z"
}
winston.format.printf(({ timestamp, level, message, ...meta }) => {
return `${timestamp} [${level.toUpperCase()}] ${message} ${JSON.stringify(meta)}`;
})
npm install pino
const pino = require('pino');
const logger = pino({
level: 'info',
timestamp: pino.stdTimeFunctions.isoTime
});
logger.info({ userId: 123 }, '用户登录成功');
输出:
{"level":30,"time":"2026-01-21T10:32:11.123Z","msg":"用户登录成功","userId":123}
✅ 性能极高
✅ 云环境首选
{
"timestamp": "...",
"level": "info",
"method": "GET",
"url": "/api/user",
"status": 200,
"duration": 34,
"requestId": "req-abc",
"ip": "127.0.0.1"
}
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
logger.info('HTTP 请求', {
method: req.method,
url: req.url,
status: res.statusCode,
duration: Date.now() - start
});
});
next();
});
| 环境 | 推荐格式 |
|---|---|
| 本地开发 | 彩色文本 |
| 测试环境 | JSON |
| 生产环境 | JSON + 日志平台 |
| Docker / K8s | JSON(stdout) |
Node.js 日志格式定义 = 结构化 JSON + 时间戳 + 日志级别 + 业务上下文
如果你愿意,我可以帮你:
你现在的项目是哪种?