监控与分析 #
监控概述 #
有效的监控是保证应用稳定运行的关键。Heroku 提供了多种监控工具来帮助开发者了解应用状态。
监控层次 #
text
┌─────────────────────────────────────────────────────┐
│ 监控层次 │
├─────────────────────────────────────────────────────┤
│ │
│ 应用层 │
│ ├── 错误追踪 (Sentry) │
│ ├── APM (New Relic) │
│ └── 自定义指标 │
│ │
│ 基础设施层 │
│ ├── Dyno 监控 (Heroku Metrics) │
│ ├── 数据库监控 (Heroku Postgres Metrics) │
│ └── Redis 监控 │
│ │
│ 日志层 │
│ ├── 应用日志 (Papertrail) │
│ ├── 访问日志 (Router Logs) │
│ └── 系统日志 │
│ │
│ 告警层 │
│ ├── 性能告警 │
│ ├── 错误告警 │
│ └── 可用性告警 │
│ │
└─────────────────────────────────────────────────────┘
New Relic APM #
安装配置 #
bash
# 安装 New Relic
heroku addons:create newrelic:wayne
# 查看配置
heroku config | grep NEW_RELIC
Node.js 集成 #
bash
# 安装依赖
npm install newrelic
javascript
// newrelic.js
exports.config = {
app_name: [process.env.NEW_RELIC_APP_NAME || 'My App'],
license_key: process.env.NEW_RELIC_LICENSE_KEY,
logging: {
level: 'info'
},
error_collector: {
enabled: true
},
transaction_tracer: {
enabled: true,
record_sql: 'obfuscated'
}
};
// 在应用入口最顶部引入
require('newrelic');
const express = require('express');
// ...
Python 集成 #
bash
# 安装依赖
pip install newrelic
python
# newrelic.ini
[newrelic]
app_name = My App
license_key = YOUR_LICENSE_KEY
# 在应用入口
import newrelic.agent
newrelic.agent.initialize('newrelic.ini')
监控指标 #
| 指标 | 说明 |
|---|---|
| Response Time | 响应时间 |
| Throughput | 吞吐量 |
| Error Rate | 错误率 |
| Apdex | 应用性能指数 |
| Database | 数据库查询时间 |
| External | 外部服务调用时间 |
自定义监控 #
javascript
// 自定义事务
const newrelic = require('newrelic');
newrelic.startSegment('customOperation', true, async () => {
await performCustomOperation();
});
// 自定义指标
newrelic.recordMetric('Custom/MyMetric', 42);
// 自定义事件
newrelic.recordCustomEvent('MyEvent', {
key1: 'value1',
key2: 'value2'
});
Papertrail 日志 #
安装配置 #
bash
# 安装 Papertrail
heroku addons:create papertrail:choklad
# 打开控制台
heroku addons:open papertrail
日志搜索 #
text
# Papertrail 搜索语法
# 搜索关键词
error
# 排除关键词
-error
# 精确匹配
"connection refused"
# 组合搜索
error AND database
# 通配符
err*
# 正则表达式
/error:\s+\d{3}/
告警配置 #
text
┌─────────────────────────────────────────────────────┐
│ Papertrail 告警配置 │
├─────────────────────────────────────────────────────┤
│ │
│ 告警类型: │
│ ├── 邮件通知 │
│ ├── Slack 集成 │
│ ├── PagerDuty 集成 │
│ └── Webhook │
│ │
│ 告警规则示例: │
│ ├── "error" 出现 → 发送邮件 │
│ ├── "FATAL" 出现 → Slack 通知 │
│ └── 5xx 错误 > 10次/分钟 → PagerDuty │
│ │
└─────────────────────────────────────────────────────┘
日志分析 #
bash
# 统计错误数量
heroku logs -n 1000 | grep -c "Error"
# 分析慢请求
heroku logs -n 1000 | grep "service=" | awk -F'service=' '{print $2}' | sort -n
# 统计 HTTP 状态码
heroku logs -n 1000 | grep "status=" | grep -oP 'status=\K\d+' | sort | uniq -c
Librato 指标 #
安装配置 #
bash
# 安装 Librato
heroku addons:create librato:meter
# 打开控制台
heroku addons:open librato
自定义指标 #
javascript
const librato = require('librato-node');
librato.configure({
email: process.env.LIBRATO_EMAIL,
token: process.env.LIBRATO_TOKEN
});
librato.start();
// 记录指标
librato.increment('api.requests');
librato.measure('api.response_time', responseTime);
librato.timing('api.db_query', () => {
return db.query();
});
// 进程退出时停止
process.on('exit', () => librato.stop());
仪表板配置 #
text
┌─────────────────────────────────────────────────────┐
│ Librato 仪表板配置 │
├─────────────────────────────────────────────────────┤
│ │
│ 推荐指标: │
│ ├── heroku.dyno.memory │
│ ├── heroku.dyno.cpu │
│ ├── heroku.router.request.status │
│ ├── heroku.router.request.time │
│ └── 自定义业务指标 │
│ │
│ 告警规则: │
│ ├── 内存使用 > 80% → 告警 │
│ ├── 响应时间 > 500ms → 告警 │
│ └── 错误率 > 5% → 告警 │
│ │
└─────────────────────────────────────────────────────┘
Sentry 错误追踪 #
安装配置 #
bash
# 安装 Sentry
heroku addons:create sentry:developer
# 查看 DSN
heroku config:get SENTRY_DSN
Node.js 集成 #
bash
npm install @sentry/node
javascript
const Sentry = require('@sentry/node');
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 0.1
});
// Express 中间件
app.use(Sentry.Handlers.requestHandler());
// 路由
app.get('/', (req, res) => {
res.send('Hello');
});
// 错误处理
app.use(Sentry.Handlers.errorHandler());
Python 集成 #
bash
pip install sentry-sdk
python
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
sentry_sdk.init(
dsn=os.environ.get('SENTRY_DSN'),
integrations=[FlaskIntegration()],
traces_sample_rate=0.1
)
错误分析 #
javascript
// 添加上下文
Sentry.setUser({ id: userId, email: userEmail });
Sentry.setTag('page', 'checkout');
Sentry.setExtra('order', orderData);
// 手动捕获错误
try {
await riskyOperation();
} catch (error) {
Sentry.captureException(error);
}
// 捕获消息
Sentry.captureMessage('Something went wrong', 'warning');
Heroku Metrics #
内置指标 #
bash
# 查看 Dyno 指标
heroku ps
# 查看数据库指标
heroku pg:info
# 查看 Redis 指标
heroku redis:info
Metrics Dashboard #
在 Heroku Dashboard 中可以查看:
| 指标 | 说明 |
|---|---|
| Response Time | 响应时间分布 |
| Throughput | 请求吞吐量 |
| Memory Usage | 内存使用情况 |
| CPU Usage | CPU 使用情况 |
| Errors | 错误率 |
命令行监控 #
bash
# 实时日志
heroku logs --tail
# 实时指标
heroku logs --tail --source heroku
# 数据库连接
heroku pg:connections
# Redis 连接
heroku redis:connections
告警配置 #
告警策略 #
text
┌─────────────────────────────────────────────────────┐
│ 告警策略 │
├─────────────────────────────────────────────────────┤
│ │
│ 紧急告警 (立即响应) │
│ ├── 应用完全不可用 │
│ ├── 数据库连接失败 │
│ └── 错误率 > 50% │
│ │
│ 重要告警 (1小时内响应) │
│ ├── 响应时间 > 2s │
│ ├── 内存使用 > 90% │
│ └── 错误率 > 10% │
│ │
│ 警告告警 (当天处理) │
│ ├── 响应时间 > 500ms │
│ ├── 内存使用 > 80% │
│ └── 错误率 > 5% │
│ │
└─────────────────────────────────────────────────────┘
Webhook 告警 #
javascript
// 告警 Webhook 处理
app.post('/alerts', (req, res) => {
const alert = req.body;
console.log('Alert received:', alert);
// 发送到 Slack
sendToSlack(alert);
// 发送邮件
sendEmail(alert);
res.status(200).send('OK');
});
性能分析 #
慢查询分析 #
bash
# PostgreSQL 慢查询
heroku pg:psql -c "SELECT * FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 10"
# Redis 慢查询
heroku redis:cli SLOWLOG GET 10
内存分析 #
javascript
// Node.js 内存分析
const used = process.memoryUsage();
console.log({
rss: `${Math.round(used.rss / 1024 / 1024)}MB`,
heapTotal: `${Math.round(used.heapTotal / 1024 / 1024)}MB`,
heapUsed: `${Math.round(used.heapUsed / 1024 / 1024)}MB`,
external: `${Math.round(used.external / 1024 / 1024)}MB`
});
// 堆快照
const v8 = require('v8');
const snapshot = v8.writeHeapSnapshot();
console.log(`Heap snapshot saved: ${snapshot}`);
请求追踪 #
javascript
// 请求追踪中间件
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
console.log({
method: req.method,
path: req.path,
status: res.statusCode,
duration: `${duration}ms`
});
// 发送到监控系统
librato.measure('request.duration', duration);
});
next();
});
最佳实践 #
1. 监控覆盖 #
markdown
## 监控检查清单
- [ ] APM 已配置 (New Relic)
- [ ] 日志收集已配置 (Papertrail)
- [ ] 错误追踪已配置 (Sentry)
- [ ] 告警规则已配置
- [ ] 仪表板已创建
- [ ] 团队通知已设置
2. 日志规范 #
javascript
// 结构化日志
const logger = {
info: (message, meta = {}) => {
console.log(JSON.stringify({
level: 'info',
message,
timestamp: new Date().toISOString(),
...meta
}));
},
error: (message, error, meta = {}) => {
console.error(JSON.stringify({
level: 'error',
message,
error: error.message,
stack: error.stack,
timestamp: new Date().toISOString(),
...meta
}));
}
};
3. 告警分级 #
javascript
// 告警分级处理
function handleAlert(alert) {
switch (alert.severity) {
case 'critical':
// 立即通知 + 自动处理
notifyOnCall(alert);
attemptAutoRecovery(alert);
break;
case 'warning':
// 工作时间通知
if (isBusinessHours()) {
notifyTeam(alert);
}
break;
default:
// 记录日志
logAlert(alert);
}
}
下一步 #
监控与分析掌握后,接下来学习 邮件服务 了解邮件发送配置!
最后更新:2026-03-28