提升 Debian 上 Node.js 日志质量的可落地方案
一 核心原则
二 推荐技术选型与最小可用配置
// npm i winston
const winston = require('winston');
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }),
winston.format.errors({ stack: true }),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
new winston.transports.File({ filename: 'logs/combined.log' })
]
});
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(),
winston.format.simple()
)
}));
}
// 使用示例
logger.info({ msg: 'user login', userId: 42 }, 'login success');
logger.error({ err: new Error('boom') }, 'operation failed');
// npm i morgan
const express = require('express');
const morgan = require('morgan');
const app = express();
app.use(morgan('combined', {
skip: (req, res) => res.statusCode < 400
}));
// npm i pino pino-pretty
const pino = require('pino');
const logger = pino({
level: process.env.LOG_LEVEL || 'info',
transport: process.env.NODE_ENV !== 'production'
? { target: 'pino-pretty', options: { colorize: true } }
: undefined
});
// npm i winston-daily-rotate-file
const DailyRotateFile = require('winston-daily-rotate-file');
const rotateTransport = new DailyRotateFile({
filename: 'logs/app-%DATE%.log',
datePattern: 'YYYY-MM-DD',
zippedArchive: true,
maxSize: '20m',
maxFiles: '14d'
});
LOG_LEVEL=debug node app.js
# 部分库也支持库级变量:WINSTON_LEVEL、PINO_LEVEL
以上做法覆盖库选型、级别控制、结构化输出、异步与轮转等关键要点。
三 系统与运维实践
sudo apt-get install logrotate/etc/logrotate.d/myapp/path/to/your/nodejs/app/logs/*.log {
daily
missingok
rotate 7
compress
notifempty
create 0640 root adm
sharedscripts
postrotate
# 若你的进程支持信号重载,例如使用 SIGUSR1 触发重新打开日志
if [ -f /var/run/myapp.pid ]; then
kill -USR1 $(cat /var/run/myapp.pid)
fi
endscript
}
四 集中式日志与监控告警
// npm i winston-elasticsearch
const { ElasticsearchTransport } = require('winston-elasticsearch');
const esTransport = new ElasticsearchTransport({
client: new require('@elastic/elasticsearch').Client({ node: 'http://localhost:9200' }),
index: 'nodejs-logs-%DATE%'
});
logger.add(esTransport);
五 落地检查清单
| 检查项 | 目标 | 建议 |
|---|---|---|
| 日志格式 | 可机器解析 | 统一用 JSON,含 timestamp、level、pid、msg、trace_id |
| 日志级别 | 降噪与排障平衡 | 生产 info/warn,错误单独落盘,开发 debug |
| 多目标输出 | 本地与远程兼顾 | 控制台 + 文件 +(可选)远程 |
| 异步与非阻塞 | 降低性能影响 | 采用异步写入与批量/缓冲策略 |
| 轮转与压缩 | 控盘与可追溯 | 按天/大小轮转、压缩、保留 7–14 天 |
| 请求日志 | 快速定位 HTTP 问题 | morgan 记录请求,错误码单独输出 |
| 错误与堆栈 | 快速根因定位 | 记录 err.stack 与关键上下文 |
| 集中式与告警 | 统一观测与响应 | 接入 ELK/Graylog,配合 Prometheus/Grafana 告警 |
| 可运维性 | 动态生效 | 通过 环境变量/配置 调整级别与输出 |
| 审计与合规 | 可追溯 | 关键业务操作与权限变更必记审计字段 |
以上清单覆盖格式、级别、输出、轮转、聚合、告警与可运维性,可直接用于上线前自检与日常巡检。