温馨提示×

Node.js应用在Ubuntu上的性能日志分析

小樊
40
2026-01-08 08:34:55
栏目: 编程语言

Node.js 应用在 Ubuntu 上的性能日志分析实操指南

一 目标与总体流程

  • 明确目标:定位响应变慢错误率上升内存泄漏事件循环阻塞等性能问题。
  • 采集高质量日志:使用结构化日志(如JSON),为每次请求生成traceId,记录duration/statusCode等关键字段。
  • 稳定输出与轮转:避免日志过大影响磁盘与 I/O,使用logrotate或日志库的按日轮转能力。
  • 聚合与可视化:将日志送入ELK/Graylog/LokiPrometheus+Grafana,构建P95/P99 延迟、吞吐、错误率等仪表盘并设置告警。
  • 深度排查:必要时结合CPU/内存剖析异步链路追踪确认根因。

二 日志采集与结构化

  • 日志库选型与结构化输出:优先使用Winston、Pino、Bunyan、Log4js等,统一timestamp、level、msg、traceId、method、url、statusCode、durationMs、userId等字段,便于检索与聚合。
  • 请求级计时与追踪:在中间件或路由层记录开始/结束时间,计算durationMs;为请求生成traceId贯穿链路,便于串联日志定位慢请求与异常。
  • 示例(Winston + 简单计时中间件):
    • 安装:npm i winston
    • 配置与中间件:
      // logger.js
      const winston = require('winston');
      const { createLogger, format, transports } = winston;
      const { combine, timestamp, json } = format;
      
      const logger = createLogger({
        level: 'info',
        format: combine(timestamp(), json()),
        transports: [
          new transports.File({ filename: 'error.log', level: 'error' }),
          new transports.File({ filename: 'combined.log' })
        ]
      });
      
      function withTiming(req, res, next) {
        const start = process.hrtime.bigint();
        const traceId = req.headers['x-trace-id'] || require('crypto').randomUUID();
        req.traceId = traceId;
        res.setHeader('x-trace-id', traceId);
      
        res.on('finish', () => {
          const end = process.hrtime.bigint();
          const durationMs = Number(end - start) / 1e6;
          logger.info('http_request', {
            traceId, method: req.method, url: req.url,
            statusCode: res.statusCode, durationMs, userAgent: req.headers['user-agent']
          });
        });
        next();
      }
      
      module.exports = { logger, withTiming };
      
    • 说明:使用process.hrtime.bigint()获取高精度耗时,输出到combined.log/error.log便于后续分析。

三 系统级与 APM 监控

  • 进程与资源监控:使用PM2快速查看CPU、内存、重启次数等,配合日志定位异常波动。
    • 启动与监控:pm2 start app.js --name api && pm2 monit
  • 深度剖析与调试:
    • CPU 剖析node --prof app.js,生成v8.log,再用node --prof-process分析热点函数。
    • 调试node --inspect app.js,通过Chrome DevTools进行采样与火焰图分析。
  • APM 与可观测性:接入New Relic、Datadog、Elastic APM等,获取事务追踪、依赖调用、错误聚合、数据库慢查询等,与日志traceId关联实现端到端观测。

四 日志分析与可视化

  • 命令行快速洞察(适用于 JSON 行日志,字段名可按需调整):
    • Top 10 慢请求
      jq -r 'select(.msg=="http_request") | [.url, .durationMs] | @tsv' combined.log \
        | sort -k2 -nr | head -10
      
    • 错误率与错误 Top N
      # 错误率(按行计数)
      wc -l combined.log | awk '{total=$1} END {print "total:", total}'
      grep -c '"level":"error"' combined.log | awk '{err=$1; getline total < "total.tmp"; printf "error_rate: %.2f%%\n", err/total*100}'
      
      # Top 5 URL 错误
      jq -r 'select(.level=="error" and .msg=="http_request") | .url' combined.log \
        | sort | uniq -c | sort -nr | head -5
      
    • 指定时间窗口(示例:2025-04-01)
      awk '/"timestamp":"2025-04-01T[0-9]{2}:[0-9]{2}:[0-9]{2}/' combined.log > day.log
      
  • 集中化与可视化:
    • ELK/Graylog/Loki:将日志采集、解析(如Grok)、索引与可视化,构建P50/P95/P99 延迟、吞吐、错误率等仪表盘,并设置阈值告警。
    • Prometheus + Grafana:暴露**/metrics**,用Histogram记录durationMs,在 Grafana 绘制延迟分布与趋势

五 日志轮转与维护

  • 使用logrotate按日轮转,控制保留份数与压缩,避免磁盘被撑满:
    • 新建配置:sudo nano /etc/logrotate.d/nodejs
    • 示例内容:
      /var/log/nodejs/*.log {
        daily
        rotate 7
        missingok
        notifempty
        compress
        delaycompress
        sharedscripts
        postrotate
          systemctl reload my-node-app >/dev/null 2>&1 || true
        endscript
      }
      
    • 说明:按日轮转、保留7天、压缩旧日志,并在轮转后reload应用以重新打开文件句柄。

0