属于我们的Performance & Scalability系列
阅读完整指南生产监控和警报:完整的设置指南
生产事故平均每分钟停机成本为 5,600 美元。 拥有成熟监控的公司可在 5 分钟内检测到问题,而那些没有监控的公司平均需要 197 分钟才能检测到——这就是小问题和客户流失灾难之间的区别。
本指南涵盖端到端生产监控设置:测量什么、如何收集、在何处可视化以及何时发出警报。
要点
- 可观察性的三大支柱(指标、日志、跟踪)服务于不同的目的,而这三者都是必要的
- 对症状(错误率、延迟)而非原因(CPU 使用率)发出警报,将噪音降低 80%
- 每个警报附带的操作手册可确保一致的事件响应,无论谁在值班
- 从 5 个基本警报开始,仅在您了解基线后才进行扩展
可观察性的三大支柱
指标
随着时间的推移采样的数值测量值。指标回答“现在发生了什么?”
应用指标:
- 请求率(每秒请求数)
- 错误率(每秒 5xx 响应)
- 延迟分布(P50、P95、P99)
- 活动会话/并发用户
基础设施指标:
- 每个服务的CPU利用率
- 内存使用和垃圾收集
- 磁盘 I/O 和可用空间
- 网络吞吐量
业务指标:
- 每分钟订单数
- 购物车放弃率
- 每小时收入
- 通过端点进行API调用
日志
离散事件的带时间戳的结构化记录。日志回答“为什么会发生?”
{
"timestamp": "2026-03-16T14:32:01.234Z",
"level": "error",
"service": "api",
"requestId": "req_abc123",
"userId": "usr_456",
"message": "Payment processing failed",
"error": "Stripe API timeout after 30000ms",
"endpoint": "POST /billing/checkout",
"duration": 30142
}
记录最佳实践:
- 使用结构化 JSON 日志记录,而不是纯文本
- 包括跨服务的关联 ID (
requestId) - 以适当的级别记录(错误表示失败,警告表示降级,信息表示关键事件)
- 切勿记录敏感数据(密码、令牌、完整信用卡号)
痕迹
通过分布式系统的端到端请求路径。 Traces回答“瓶颈在哪里?”
单个用户对电子商务结帐的请求可能会涉及:
- Nginx (2ms) 到 Next.js 前端 (50ms) 到 NestJS API (120ms) 到 PostgreSQL (45ms) 到 Stripe API (800ms) 到电子邮件服务 (200ms)
如果没有跟踪,您会看到“结账需要 1.2 秒”。通过跟踪,您会看到“Stripe API 占结帐延迟的 67%”。
监控堆栈设置
Prometheus + Grafana(自托管)
# docker-compose.monitoring.yml
services:
prometheus:
image: prom/prometheus:v2.50.0
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
ports:
- "9090:9090"
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.retention.time=30d'
- '--web.enable-lifecycle'
grafana:
image: grafana/grafana:10.3.0
volumes:
- grafana-data:/var/lib/grafana
ports:
- "3030:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
- GF_USERS_ALLOW_SIGN_UP=false
loki:
image: grafana/loki:2.9.0
volumes:
- loki-data:/loki
ports:
- "3100:3100"
alertmanager:
image: prom/alertmanager:v0.27.0
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
ports:
- "9093:9093"
volumes:
prometheus-data:
grafana-data:
loki-data:
普罗米修斯配置
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "alerts/*.yml"
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:9093"]
scrape_configs:
- job_name: "api"
metrics_path: /metrics
static_configs:
- targets: ["api:3001"]
- job_name: "node-exporter"
static_configs:
- targets: ["node-exporter:9100"]
- job_name: "postgres"
static_configs:
- targets: ["postgres-exporter:9187"]
- job_name: "redis"
static_configs:
- targets: ["redis-exporter:9121"]
NestJS 应用指标
暴露 Prometheus 指标
// metrics.module.ts
import { Module } from '@nestjs/common';
import { PrometheusModule } from '@willsoto/nestjs-prometheus';
import {
makeCounterProvider,
makeHistogramProvider,
makeGaugeProvider,
} from '@willsoto/nestjs-prometheus';
@Module({
imports: [
PrometheusModule.register({
path: '/metrics',
defaultMetrics: { enabled: true },
}),
],
providers: [
makeCounterProvider({
name: 'http_requests_total',
help: 'Total HTTP requests',
labelNames: ['method', 'path', 'status'],
}),
makeHistogramProvider({
name: 'http_request_duration_seconds',
help: 'HTTP request duration in seconds',
labelNames: ['method', 'path'],
buckets: [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],
}),
makeGaugeProvider({
name: 'active_connections',
help: 'Number of active connections',
}),
],
exports: [PrometheusModule],
})
export class MetricsModule {}
警报配置
五个基本警报
每个生产系统从第一天起就需要这些警报:
# alerts/essential.yml
groups:
- name: essential
rules:
- alert: ServiceDown
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Service {{ $labels.job }} is down"
runbook: "https://wiki.example.com/runbooks/service-down"
- alert: HighErrorRate
expr: |
rate(http_requests_total{status=~"5.."}[5m])
/ rate(http_requests_total[5m]) > 0.01
for: 5m
labels:
severity: critical
annotations:
summary: "Error rate above 1% for 5 minutes"
runbook: "https://wiki.example.com/runbooks/high-error-rate"
- alert: HighLatency
expr: |
histogram_quantile(0.95,
rate(http_request_duration_seconds_bucket[5m])
) > 2
for: 5m
labels:
severity: warning
annotations:
summary: "P95 latency above 2 seconds"
- alert: DiskSpaceLow
expr: |
node_filesystem_avail_bytes{mountpoint="/"}
/ node_filesystem_size_bytes{mountpoint="/"} < 0.2
for: 10m
labels:
severity: warning
annotations:
summary: "Disk space below 20% on {{ $labels.instance }}"
- alert: SSLCertExpiringSoon
expr: |
probe_ssl_earliest_cert_expiry - time() < 14 * 24 * 3600
labels:
severity: warning
annotations:
summary: "SSL certificate expires within 14 days"
警报路由
# alertmanager.yml
global:
slack_api_url: "${SLACK_WEBHOOK_URL}"
route:
group_by: ['alertname', 'severity']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'default'
routes:
- match:
severity: critical
receiver: 'pagerduty'
repeat_interval: 15m
- match:
severity: warning
receiver: 'slack'
receivers:
- name: 'default'
slack_configs:
- channel: '#alerts'
title: '{{ .GroupLabels.alertname }}'
text: '{{ .CommonAnnotations.summary }}'
- name: 'pagerduty'
pagerduty_configs:
- routing_key: "${PAGERDUTY_KEY}"
severity: '{{ .GroupLabels.severity }}'
- name: 'slack'
slack_configs:
- channel: '#alerts-warnings'
title: '{{ .GroupLabels.alertname }}'
警报质量规则
| 实践 | 为什么 |
|---|---|
| 警惕症状,而非原因 | “错误率高”是可操作的; “CPU 达到 80%”可能不是 |
| 每个警报都有一个操作手册 | 值班工程师不需要在凌晨 3 点思考 |
| 警报必须具有可操作性 | 如果没有人能够采取行动,那就是噪音,而不是警报 |
| 两周后调整阈值 | 初始阈值是猜测;根据基线进行调整 |
| 每月检查警报疲劳 | 如果每天触发警报但没有采取任何行动,请提高阈值或将其删除 |
Grafana 仪表板
仪表板层次结构
- 概览仪表板:所有服务的高级运行状况。这是发生事件时任何人看到的第一个屏幕。
- 服务仪表板:每个服务(API、Web、工作人员)的详细指标。
- 基础设施仪表板:节点级指标(CPU、内存、磁盘、网络)。
- 业务仪表板:收入、订单、用户活动。
服务仪表板的 RED 方法
对于每项服务,显示:
- Rate:每秒请求数
- Eerrors:错误率百分比
- Duration:延迟分布(P50、P95、P99)
这提供了对服务运行状况的即时可见性,而无需认知过载。
使用 Sentry 进行错误跟踪
// sentry.config.ts
import * as Sentry from '@sentry/nestjs';
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 0.1,
profilesSampleRate: 0.1,
integrations: [
Sentry.postgresIntegration(),
],
beforeSend(event) {
// Strip sensitive data
if (event.request?.headers) {
delete event.request.headers['authorization'];
delete event.request.headers['cookie'];
}
return event;
},
});
哨兵提供:
- 自动错误分组和重复数据删除
- 带有源映射的堆栈跟踪
- 发布跟踪(哪个部署引入了错误)
- 性能监控(交易痕迹)
常见问题
监控堆栈的成本是多少?
自托管(Prometheus + Grafana + Loki):托管资源约为每月 50-100 美元。托管替代方案:Datadog 基础设施起价为 15 美元/主机/月,日志费用为 0.10 美元/GB。 Sentry Cloud 团队计划的价格为 26 美元/月。小型企业合理的起始预算总计为 100-200 美元/月。
What is the difference between monitoring and observability?
监控会在出现问题时告诉您。可观察性告诉你原因。监控是针对已知故障模式的预定义仪表板和警报。可观察性是指使用指标、日志和跟踪来询问有关系统行为的任意问题的能力。两者都需要,但监控是基础。
我们如何避免警觉疲劳?
三个规则:(1) 每个警报都必须需要人工操作,(2) 根据实际基线而不是理论理想设置阈值,(3) 每月检查和调整警报。如果警报每周触发一次以上且无需采取措施,请解决根本问题或提高阈值。遭受警报疲劳的团队会忽略所有警报,包括关键警报。
我们应该以不同的方式监控我们的 ERP 系统吗?
ERP 系统具有独特的监控要求。除了标准 Web 指标之外,还可以监控:数据库连接池使用情况、后台作业队列深度、集成同步状态(Shopify、支付网关)、计划的报告执行时间以及按模块的用户会话计数。 ECOSIRE 提供托管 Odoo 监控 作为我们支持包的一部分。
接下来会发生什么
监控是生产基础设施的眼睛和耳朵。将其与 CI/CD 自动化 配对以提高部署信心,并与 灾难恢复规划 配对以提高弹性。有关全面的 DevOps 路线图,请参阅我们的小型企业 DevOps 指南。
联系 ECOSIRE 以监控设置和托管基础设施服务。
由 ECOSIRE 发布——帮助企业了解生产中的重要因素。
作者
ECOSIRE Research and Development Team
在 ECOSIRE 构建企业级数字产品。分享关于 Odoo 集成、电商自动化和 AI 驱动商业解决方案的洞见。
相关文章
更多来自Performance & Scalability
AI 代理性能优化:速度、准确性和成本效率
利用经过验证的快速工程、缓存、模型选择和监控技术,在响应时间、准确性和成本方面优化 AI 代理性能。
测试和监控人工智能代理:自治系统的可靠性工程
测试和监控 AI 代理的完整指南,涵盖单元测试、集成测试、行为测试、可观察性和生产监控策略。
CDN 性能优化:更快的全球交付完整指南
通过缓存策略、边缘计算、图像优化和多 CDN 架构优化 CDN 性能,以实现更快的全球内容交付。
Web 应用程序的负载测试策略:在用户之前找到突破点
使用 k6、Artillery 和 Locust 对 Web 应用程序进行负载测试。涵盖测试设计、流量建模、性能基线和结果解释策略。
电子商务移动 SEO:2026 年完整优化指南
电子商务网站的移动 SEO 指南。涵盖移动优先索引、核心网络生命、结构化数据、页面速度优化和移动搜索排名因素。
API 性能:速率限制、分页和异步处理
使用速率限制算法、基于游标的分页、异步作业队列和响应压缩最佳实践构建高性能 API。