Ubuntu Node.js日志如何进行性能监控
导读:Ubuntu 下基于日志的 Node.js 性能监控实战 一 日志与指标打点 使用结构化日志库输出关键性能字段:选择 Winston 或 Pino,以 JSON 格式记录,便于检索与聚合。示例要点:为每条请求输出 method、url、s...
Ubuntu 下基于日志的 Node.js 性能监控实战
一 日志与指标打点
- 使用结构化日志库输出关键性能字段:选择 Winston 或 Pino,以 JSON 格式记录,便于检索与聚合。示例要点:为每条请求输出 method、url、status、responseTimeMs、route、traceId 等字段,错误日志单独输出并携带 stack。
- 在 Express 中记录响应时间:使用 morgan 的响应时间标记或自定义中间件,在 res.finish 时计算耗时并写入日志;对关键业务片段使用 console.time / console.timeEnd 或 process.hrtime 做细粒度埋点。
- 采集运行时资源指标:在定时任务中记录 process.memoryUsage()、process.cpuUsage(),必要时补充 event loop lag 等自定义指标,用于关联日志定位瓶颈。
- 日志轮转与保留:避免单文件过大,使用 winston-daily-rotate-file 或在系统层面配置 logrotate,按 日/周 轮转并压缩归档,保留 7–30 天 便于回溯。
二 实时查看与命令行分析
- 实时查看:开发/排障时用 tail -f 跟踪日志;系统服务日志用 journalctl -u your-app.service -f;多实例集中查看可用 PM2 logs。
- 快速检索与统计:用 grep 过滤错误与慢请求,用 awk 做聚合统计,如按路由统计平均耗时、P95/P99、Top N 慢路径、错误率等。示例:统计某路由平均响应时间、按状态码分布、按内存字段找峰值。
- 建议做法:将常用分析命令写成 Shell/Node 脚本,固化阈值与输出格式,便于值班与告警联动。
三 指标化与可视化
- 指标暴露:在应用内集成 prom-client,定义 Histogram 记录 HTTP 请求时延,暴露 /metrics 端点供 Prometheus 抓取;按需增加 Gauge 记录内存、CPU、事件循环延迟等。
- 可视化与告警:用 Grafana 构建仪表盘,展示 请求率、P50/P95/P99、错误率、内存 RSS/堆、CPU 使用率 等;在 Prometheus 配置告警规则(如 P95 超过阈值、5xx 突增、内存持续增长)。
- 进程与应用双视角:用 PM2 的 monit 与内置监控查看进程级 CPU/内存,与日志/指标联动排查,形成“进程—应用—业务”的三层可观测性。
四 深度诊断与 APM
- 交互式调试:使用 node --inspect 配合 Chrome DevTools 做 CPU/内存热点定位;对生产问题可先短暂采样,避免长时停机。
- 生产级 APM:接入 New Relic / Datadog 等 APM,获得 调用链追踪、数据库/外部依赖耗时、错误堆栈聚合、部署前后对比 等能力,与日志字段(如 traceId)关联,实现端到端可观测。
- 系统级瓶颈排查:结合 top/htop、vmstat、iostat、free、df 等工具,甄别 CPU 饱和、内存不足、I/O 阻塞 等系统层问题,避免只盯应用日志造成误判。
五 落地配置示例
- 结构化日志与中间件(Express + Winston + 响应时间)
// 安装: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 }
));
- Prometheus 指标端点(prom-client)
// 安装: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
- 日志轮转(系统级 logrotate,/etc/logrotate.d/nodejs)
/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
}
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: Ubuntu Node.js日志如何进行性能监控
本文地址: https://pptw.com/jishu/749809.html
