Ubuntu 下基于日志的 Node.js 性能监控实战
一 日志与指标打点
二 实时查看与命令行分析
三 指标化与可视化
四 深度诊断与 APM
五 落地配置示例
// 安装:npm i winston morgan
const express = require('express');
const winston = require('winston');
const morgan = require('morgan');
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
new winston.transports.File({ filename: 'logs/combined.log' })
]
});
const app = express();
app.use(morgan('combined')); // 可替换为 JSON 格式
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
logger.info({
event: 'http_request',
method: req.method,
url: req.url,
status: res.statusCode,
responseTimeMs: duration,
route: req.route?.path || 'unknown',
userAgent: req.get('user-agent'),
traceId: req.headers['x-request-id'] || '-'
});
});
next();
});
app.get('/health', (req, res) => res.json({ status: 'ok' }));
app.listen(3000, () => logger.info({ event: 'server_start', port: 3000 }));
// 安装:npm i prom-client
const client = require('prom-client');
const httpRequestDuration = new client.Histogram({
name: 'http_request_duration_seconds',
help: 'Duration of HTTP requests in seconds',
labelNames: ['method', 'route', 'status']
});
app.use((req, res, next) => {
const end = httpRequestDuration.startTimer();
res.on('finish', () => {
end({ method: req.method, route: req.route?.path || 'unknown', status: res.statusCode });
});
next();
});
app.get('/metrics', async (req, res) => {
res.set('Content-Type', client.register.contentType);
res.end(await client.register.metrics());
});
# 实时查看
tail -f logs/combined.log
journalctl -u node-app.service -f
# Top N 慢请求(按响应时间字段 responseTimeMs 降序)
awk '$NF ~ /ms/ {gsub("ms","",$NF); dur[$7] += $NF; cnt[$7]++}
END {for (r in dur) printf "%.2fms\t%s\t%d\n", dur[r]/cnt[r], r, cnt[r] | "sort -nr | head"' logs/combined.log
# 5xx 错误率(按分钟)
awk '$9 ~ /^5/ {ts=int($1" "$2); m=ts/60; err[m]++; total[m]++}
END {for (t in total) printf "%s\t%.2f%%\n", strftime("%H:%M",t*60), err[t]/total[t]*100}' logs/combined.log
/path/to/your/nodejs/logs/*.log {
daily
rotate 7
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
systemctl reload node-app.service >/dev/null 2>&1 || true
endscript
}