Ubuntu 环境下用 JS 日志做性能分析的可落地方案
一 目标与总体思路
二 日志采集与结构化
三 从日志中提取性能指标的实操方法
四 与系统级工具联动定位根因
五 最小可行配置与命令示例
// logger.js
const winston = require('winston');
const { combine, timestamp, json, errors } = winston.format;
const logger = winston.createLogger({
level: 'info',
format: combine(timestamp(), errors({ stack: true }), json()),
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
],
exitOnError: false
});
module.exports = logger;
// 伪代码:记录开始时间
app.use((req, res, next) => {
req._start = Date.now();
res.on('finish', () => {
const durationMs = Date.now() - req._start;
logger.info('http_request', {
method: req.method, url: req.url, statusCode: res.statusCode,
durationMs, userAgent: req.get('user-agent'), ip: req.ip
});
});
next();
});
# 统计 95/99 分位响应时间(单位 ms)
tail -n 100000 app.log | \
jq -r 'select(.msg=="http_request") | .durationMs' | \
sort -n | \
awk '{
a[NR]=$1; sum+=$1; if(NR==1){min=$1} else if($1<min){min=$1}
if($1>max){max=$1}
} END {
n=NR; asort(a);
p95=a[int(n*0.95)]; p99=a[int(n*0.99)];
printf "count=%d min=%.2f max=%.2f mean=%.2f p95=%.2f p99=%.2f\n",
n, min, max, sum/n, p95, p99
}'
# 实时查看错误与慢请求
tail -f app.log | jq 'select(.level=="error" or .durationMs > 1000)'
# 按路由统计平均时延
tail -n 100000 app.log | \
jq -r 'select(.msg=="http_request") | "\(.route) \(.durationMs)"' | \
awk '{sum[$1]+=$2; cnt[$1]++} END {for(r in sum) printf "%s %.2f\n", r, sum[r]/cnt[r]}'
# 查看服务日志
journalctl -u your-app.service -f
# 资源与 I/O 快速巡检
top -b -d 1 -n 20
vmstat 1 20
iostat -x 1 20
free -m
df -h
# CPU 剖析
node --prof app.js
# 生成可读报告(Linux)
node --prof-process isolate-*.log > profile.txt
# 远程调试
node --inspect-brk app.js
# 打开 Chrome:chrome://inspect -> 连接并采集 Performance/Memory