在 Ubuntu 环境里,很多 JS 应用的性能线索并不在单独的监控平台上,而是分散在应用日志、systemd 日志和系统资源输出里。真正有效的排查方式,不是只搜几条报错,而是按“先定位日志、再提取关键指标、随后结合系统与应用分析、最后补上监控告警”这条路径推进。看完这篇,你可以判断日志该从哪里找、哪些指标值得优先统计,以及该在什么阶段引入 DevTools、clinic.js、Grafana 或 ELK。
先确认日志在哪里,别一上来就盲查
在 Ubuntu 下分析 JS 性能,第一步不是上工具,而是先确认日志落点。不同部署方式下,日志位置并不一样,找错位置,后面的筛选和统计都无从谈起。

常见日志位置
- 系统级 JS 应用:通常写入
/var/log/,例如/var/log/syslog,或者应用自己的日志文件,如/var/log/node-app.log。 - Node.js 应用:如果项目用了
winston、morgan这类日志库,路径往往配置在项目根目录下的logs/,例如./logs/app.log。 - 由 systemd 托管的服务:这类应用通常不必直接翻文件,可以优先用
journalctl查看服务日志,例如journalctl -u your-node-service。
这一步的目标很明确:先把应用日志、系统日志和服务日志分开。后续做响应时间、错误率或资源占用关联时,才不会把不同来源的数据混在一起。
用命令行先筛出性能字段,再处理日志膨胀
日志量一大,直接人工翻看基本没有效率。更实用的做法,是先用命令行工具把与性能相关的字段捞出来,再考虑进一步统计。
几个足够高频的基础命令
grep:适合先按关键词筛出异常样本,比如搜索error、slow、timeout,例如grep "ERROR" /var/log/node-app.log。awk:适合提取字段并做简单聚合,例如提取第一列后排序统计:awk '{print $1}' /path/to/logfile.log | sort | uniq -c。sed:适合先清掉干扰项,例如删除所有DEBUG行:sed '/DEBUG/d' /path/to/logfile.log。journalctl:如果服务由 systemd 管理,可以直接按级别和服务名过滤,例如journalctl -u your-service-name -p err。
这类命令的意义,不是做完整分析,而是快速回答几个常见问题:异常是否集中在某个时间段、是否由某类请求触发、是否存在明显的超时或报错峰值。先把样本缩小,后面再谈趋势和瓶颈才更稳。
别忽视日志轮转
日志分析之前,还要确认日志本身有没有失控增长。文件无限膨胀,既影响检索效率,也可能直接把磁盘空间吃满,最终反过来放大性能问题。

- 查看全局轮转配置:
cat /etc/logrotate.conf - 查看某个服务的专属配置:
cat /etc/logrotate.d/your-service-name
常见参数包括:
maxsize 100M:单个日志文件最大 100MB;rotate 5:保留 5 个历史备份。
如果你发现线上日志越来越难查,先确认问题是不是出在日志管理本身。轮转策略合理,后续无论是 grep 还是导入 ELK,成本都会低很多。
优先提取四类指标,才能看出瓶颈方向
真正能帮助定位性能问题的,不是“日志很多”,而是能从日志中稳定拿到关键性能指标。对大多数 JS 或 Node.js 服务来说,至少应优先关注下面四类数据。

1. 响应时间
响应时间是最直接的用户体验指标。例如日志中的:
[2025-09-26T10:00:00] GET /api/user 200 150ms
这里的 150ms 就是可统计的延迟数据。实际分析时,不要只看平均值,最好同时统计平均响应时间以及 P90、P99 延迟。平均值容易掩盖长尾,P90/P99 更容易暴露高并发或特定接口下的慢请求。
2. 错误率
性能问题未必都表现为“慢”,也可能表现为错误率抬升。最基础的做法是先统计错误日志数量,例如:
grep "ERROR" /path/to/logfile.log | wc -l
再结合总请求数计算占比,才能得出更有判断意义的错误率。如果某个时间段响应时间和错误率同时上升,通常说明问题已经影响到服务稳定性,而不是单纯的局部抖动。
3. 资源使用
仅看应用日志还不够,需要把 CPU 和内存数据一起拉进来。比如结合 top 输出观察 CPU 高峰,结合 free -m 观察内存紧张时段,再去对照同一时间段的应用日志,判断是高并发请求、内存泄漏还是某段任务集中执行导致资源被吃满。
4. 慢查询
如果应用连着数据库,慢查询往往是最容易被低估的瓶颈来源。例如日志中出现:
SELECT * FROM users WHERE id = 1; -- 120ms
其中 120ms 就是可以进一步筛选和聚合的慢查询耗时。应用层延迟高,不一定是 Node.js 自身慢,也可能是数据库查询、索引缺失,或外部依赖拖慢了整个请求链路。
把趋势可视化,再做系统级与应用级深挖
当你已经能稳定提取响应时间、错误率和资源数据后,下一步就不是继续手工翻日志,而是把趋势图做出来,同时配合系统和应用级工具精确定位。
可视化平台适合解决什么问题
- ELK Stack(Elasticsearch + Logstash + Kibana):适合把日志解析后集中存储,再基于日志做检索、聚合和仪表盘,常见面板包括响应时间趋势、错误率热力图。
- Grafana:适合接入 Prometheus 或 Elasticsearch,统一展示 CPU、内存、响应时间等实时和历史指标。
- Kibana:如果日志已经在 Elasticsearch 中,Kibana 很适合快速制作“响应时间分布”“错误率 Top10”一类面板,帮助你先判断异常范围,再决定是否继续深挖代码层。
这一层的价值,在于把“单条日志”转成“时间趋势”和“分布变化”。很多性能问题不是某一条日志能说明白的,而是高峰时段、接口维度、错误类型之间的组合关系。
系统级排查:先确认是不是资源瓶颈
如果趋势图已经显示异常,接下来先看系统层。这样做的好处是,可以先排除或确认 CPU、内存、磁盘 I/O 是否已经成为上游限制。
top/htop:实时查看 CPU、内存占用。使用htop时,可以按F6排序,直接找出最吃资源的 Node.js 进程。vmstat:例如vmstat 1,每秒输出一次,可观察 CPU 空闲率、swap、上下文切换和磁盘等待情况。iostat:例如iostat -x 1,适合分析磁盘读写延迟和吞吐量,判断瓶颈是不是落在存储侧。
如果系统指标已经明显异常,再继续盯应用代码意义不大;先确定瓶颈落在哪一层,排查路径才不会绕远。
应用级排查:再确认问题是不是出在代码路径
- Chrome DevTools:适用于前端 JS 或 Node.js。通过
node --inspect启动应用后,连接 DevTools 的 Performance 面板,查看函数调用栈、CPU 占用和内存分配,通常能较快找到执行时间过长的函数。 - Node.js 内置能力:可用
process.memoryUsage()查看堆内存、RSS 等信息,用process.cpuUsage()查看 CPU 时间,并把这些数据按周期写入日志,为后续关联分析提供依据。 - 第三方 APM 工具:如 New Relic、Datadog、AppDynamics,可自动追踪请求链路、数据库查询和第三方 API 调用,适合复杂服务做慢请求追踪或内存泄漏排查。
clinic.js:这是专门面向 Node.js 的性能分析工具包,直接执行clinic doctor就能生成带火焰图和时间线的性能报告,CPU 与内存问题会更直观。
可以把这一层理解为“从日志怀疑,走向证据确认”。日志告诉你哪里可能有问题,Profiler、APM 和 Node.js 运行时指标则负责证明问题到底出在哪段调用链上。
最后补上自动化分析和告警,避免重复救火
如果每次都等到用户反馈变慢再去查日志,说明分析体系还停留在事后排障阶段。更实用的做法,是把已经验证有效的指标沉淀成自动分析与预警机制。
- 自动化分析脚本:可以用 Python 或 JavaScript 定期解析日志中的响应时间均值、错误率等指标,再通过邮件或 Slack 通知;如果在 Node.js 里实现,可用
nodemailer发送提醒。 - 实时监控与警报:例如用 Prometheus + Grafana 设置阈值告警,响应时间超过
500ms时触发通知;或者在 ELK Stack 中使用 Watcher,在错误率超过1%时发出告警。 - 代码审查与回归优化:对日志里反复出现的慢查询、内存泄漏或高频超时问题做定期回顾,针对性优化循环、数组处理、缓存策略和数据库访问逻辑,往往比一次性大改更有效。
一套完整的方法,应该能回答三个问题:问题是不是正在发生、它首先出现在什么指标上、以及改动之后是否真的改善。做到这一步,日志分析才算从“查问题”走向“持续治理”。













