Ubuntu 上 JS 应用监控实操指南
一 监控目标与总体架构
二 快速落地步骤
sudo npm i -g pm2;启动 pm2 start app.js -n my-app --log /var/log/my-app/app.log;实时查看 pm2 logs my-app -f;资源监控 pm2 monit;设置开机自启 pm2 startup && pm2 save。/etc/systemd/system/my-app.service,设置 ExecStart=/usr/bin/node /path/app.js、Restart=always,然后用 sudo systemctl start my-app、sudo journalctl -u my-app -f 查看日志。tail -f /var/log/my-app/app.log;定期查看:watch -n 5 cat /var/log/my-app/app.log。三 关键配置示例
sudo npm i -g pm2
pm2 start app.js -n my-app --log /var/log/my-app/app.log
pm2 logs my-app -f
pm2 monit
pm2 startup && pm2 save
sudo tee /etc/systemd/system/my-app.service >/dev/null <<'EOF'
[Unit]
Description=Node.js App
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/opt/my-app
ExecStart=/usr/bin/node /opt/my-app/app.js
Restart=always
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now my-app
sudo journalctl -u my-app -f
npm i winston
// logger.js
const { createLogger, format, transports } = require('winston');
const logger = createLogger({
level: 'info',
format: format.combine(format.timestamp(), format.json()),
transports: [
new transports.File({ filename: 'error.log', level: 'error' }),
new transports.File({ filename: 'combined.log' }),
new transports.Console({ format: format.simple() })
]
});
module.exports = logger;
npm i @sentry/node
// app.js
const Sentry = require('@sentry/node');
Sentry.init({ dsn: process.env.SENTRY_DSN, environment: 'production' });
// 全局异常兜底
process.on('unhandledRejection', e => Sentry.captureException(e));
process.on('uncaughtException', e => { Sentry.captureException(e); process.exit(1); });
npm i prom-client
// metrics.js
const client = require('prom-client');
const http = require('http');
const register = client.register;
const httpReqDur = new client.Histogram({
name: 'http_request_duration_ms',
help: 'Duration of HTTP requests in ms',
labelNames: ['method', 'route', 'code'],
buckets: [5, 15, 50, 100, 200, 300, 400, 500]
});
const server = http.createServer((req, res) => {
const end = httpReqDur.startTimer();
res.on('finish', () => {
end({ method: req.method, route: req.url, code: res.statusCode });
});
res.end('OK');
});
server.listen(3000, () => console.log('Metrics on :3000/metrics'));
// Prometheus 抓取目标示例:scrape_configs: job_name: 'nodejs' static_configs: targets: ['localhost:3000']
sudo tee /etc/logrotate.d/my-app >/dev/null <<'EOF'
/var/log/my-app/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0644 ubuntu ubuntu
sharedscripts
postrotate
systemctl reload my-app >/dev/null 2>&1 || true
endscript
}
EOF
四 可视化与告警
五 排障与优化建议
chrome://inspect 进行 CPU/内存采样与火焰图分析;配合 autocannon/wrk/Artillery 做负载与稳定性压测。