监控与分析 #

监控概述 #

有效的监控是保证应用稳定运行的关键。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