結論先講
很多團隊的「監控」是這樣的:裝了 Grafana,有幾個 dashboard,偶爾有人上去看一眼。出事了才發現沒有告警、或者告警太多沒人理。
告警不等於監控。 好的監控系統需要回答三個問題:系統現在健不健康(Metrics)、剛才發生了什麼事(Logs)、問題發生在哪裡(Traces)。然後在問題影響使用者之前,用適當的方式通知適當的人。
體檢清單
1. 可觀測性三根支柱
┌─────────────────────────────────────┐
│ Observability │
│ │
│ ┌─────────┐ ┌──────┐ ┌──────────┐ │
│ │ Metrics │ │ Logs │ │ Traces │ │
│ │ 數值指標 │ │ 事件 │ │ 請求追蹤 │ │
│ └─────────┘ └──────┘ └──────────┘ │
└─────────────────────────────────────┘
| 支柱 | 回答的問題 | 範例 | 工具 |
|---|---|---|---|
| Metrics | 現在怎樣?趨勢如何? | CPU 80%、QPS 500、P99 200ms | Prometheus、Datadog |
| Logs | 發生了什麼?為什麼? | Error: Connection refused | ELK、Loki、CloudWatch |
| Traces | 請求經過了哪些服務? | UserAPI → OrderService → PaymentGW (350ms) | Jaeger、Tempo |
# OpenTelemetry 設定(統一三根支柱)
# otel-collector-config.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
exporters:
prometheus:
endpoint: 0.0.0.0:8889
loki:
endpoint: http://loki:3100/loki/api/v1/push
otlp/tempo:
endpoint: tempo:4317
service:
pipelines:
metrics:
receivers: [otlp]
exporters: [prometheus]
logs:
receivers: [otlp]
exporters: [loki]
traces:
receivers: [otlp]
exporters: [otlp/tempo]- 三根支柱都有覆蓋
- 資料之間可以關聯(trace ID 串起 metrics 和 logs)
- 使用 OpenTelemetry 做統一的 instrumentation
2. SLI / SLO / SLA
先搞清楚這三個東西:
| 概念 | 全稱 | 是什麼 | 範例 |
|---|---|---|---|
| SLI | Service Level Indicator | 衡量指標 | 99.5% 的請求在 200ms 內回應 |
| SLO | Service Level Objective | 內部目標 | 每月 SLI 達到 99.9% |
| SLA | Service Level Agreement | 對外合約 | 低於 99.9% 就賠錢 |
SLI(量測) → SLO(目標) → SLA(合約)
越來越嚴格 →
- 定義核心服務的 SLI
- 設定 SLO(通常比 SLA 嚴格一些)
- 有 error budget(SLO 剩餘的容錯空間)
- 定期 review SLO 達成狀況
# SLO 計算範例
# SLO: 99.9% availability per month
# 一個月 30 天 = 43,200 分鐘
# 允許停機時間 = 43,200 * 0.001 = 43.2 分鐘
# Error budget = 43.2 分鐘
# 已用 error budget = 15 分鐘(本月兩次小 incident)
# 剩餘 error budget = 28.2 分鐘3. Dashboard 設計(Golden Signals)
Google SRE 定義的四個黃金信號:
| 信號 | 衡量什麼 | PromQL 範例 |
|---|---|---|
| Latency | 回應時間 | histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) |
| Traffic | 請求量 | sum(rate(http_requests_total[5m])) |
| Errors | 錯誤率 | sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) |
| Saturation | 資源飽和度 | container_memory_usage_bytes / container_spec_memory_limit_bytes |
- 每個服務有 dashboard 顯示四個黃金信號
- Dashboard 有不同時間範圍(1h、24h、7d)
- 有全局 overview dashboard
- Dashboard 有組織(不是 100 個散落的面板)
4. 告警疲勞防治
告警太多跟沒有告警一樣糟糕。
壞的告警:
- CPU > 70% → 叫人起床(但它每天都在 70% 附近)
- 任何 5xx → 告警(偶爾的 5xx 是正常的)
- Disk > 80% → 告警(但磁碟成長率是每月 1%)
好的告警:
- Error rate > 1% 持續 5 分鐘 → 告警
- P99 latency > 2s 持續 10 分鐘 → 告警
- Disk 預計 48 小時內滿 → 告警
- 每個告警都有對應的 action(收到告警知道要做什麼)
- 使用 rate 而不是 absolute value
- 有合理的閾值和持續時間(避免 flapping)
- 定期 review 告警規則(每季至少一次)
- 追蹤 alert-to-action ratio(真正需要處理的比例)
5. 告警分級與通知
| 等級 | 定義 | 通知方式 | 回應時間 |
|---|---|---|---|
| P1 Critical | 服務完全中斷 | 電話 + 簡訊 + Slack | 15 分鐘 |
| P2 High | 部分功能異常 | Slack + Email | 1 小時 |
| P3 Medium | 效能下降 | Slack | 4 小時 |
| P4 Low | 非緊急 | Email / Ticket | 次日 |
- 告警有分級
- 不同等級有不同通知方式
- P1 一定有人收到(不是只發 Slack 訊息)
6. 值班輪值(On-call Rotation)
Week 1: Alice (primary), Bob (secondary)
Week 2: Bob (primary), Carol (secondary)
Week 3: Carol (primary), Alice (secondary)
- 有明確的值班表
- 有 primary 和 secondary on-call
- 值班期間有額外補償
- 有 escalation policy(primary 沒回應就找 secondary)
| 工具 | 用途 |
|---|---|
| PagerDuty | 值班管理、告警路由 |
| OpsGenie | 值班管理(Atlassian 生態) |
| Grafana OnCall | 開源值班管理 |
| 自己用 Slack Bot | 小團隊可以 |
7. Incident Response
一個標準的 incident 處理流程:
1. 偵測(Alert fired)
2. 確認(Acknowledge)
3. 分類(P1/P2/P3)
4. 組建 War Room(P1 才需要)
5. 診斷(看 metrics, logs, traces)
6. 修復(hotfix, rollback, config change)
7. 驗證(確認恢復正常)
8. 通知(跟利害關係人更新狀態)
9. 事後檢討(Postmortem)
- 有文件化的 incident response 流程
- 有 incident channel(Slack/Teams 專用頻道)
- 有 status page 向使用者溝通
- 有 incident commander 角色
8. 事後檢討(Postmortem)
Blameless postmortem — 找原因不找戰犯。
一份好的 postmortem 應該包含:
# Incident Report: API 回應時間飆升
## 摘要
- 日期:2026-03-15 14:00 - 14:45 (UTC+8)
- 影響:API P99 latency 從 200ms 飆升到 5s,影響約 30% 使用者
- 等級:P2
## 時間線
- 14:00 部署 v1.5.2
- 14:05 告警觸發:P99 > 2s
- 14:10 on-call 確認,開始調查
- 14:20 發現新 SQL query 缺少 index
- 14:30 rollback 到 v1.5.1
- 14:35 latency 恢復正常
- 14:45 確認穩定,incident 關閉
## 根因
新功能的 SQL query 在 users 表做全表掃描(缺少 index)
## 改善措施
1. [ ] 加上缺少的 index
2. [ ] CI 加入 slow query 檢測
3. [ ] 部署後自動監控 latency 變化- 每個 P1/P2 incident 都有 postmortem
- Postmortem 在一週內完成
- Action items 有追蹤(不是寫完就忘了)
- 定期分享 postmortem(團隊學習)
工具比較
全家桶 vs 自組
| 方案 | 組合 | 優點 | 缺點 | 月費(估算) |
|---|---|---|---|---|
| 自組開源 | Prometheus + Grafana + Loki + Tempo | 免費、可控 | 維護成本 | $0 + 運維人力 |
| Datadog | 全包 | 省事、UX 好 | 貴 | $15-23/host/month |
| New Relic | 全包 | 免費額度大方 | 超量就貴 | 免費 100GB/month |
| Elastic Cloud | ELK Stack | 搜尋強大 | 資源吃很兇 | $95+/month |
適合你的方案
- 1-3 人小團隊:New Relic(免費額度)或 Grafana Cloud(免費額度)
- 5-20 人中團隊:Datadog 或自組 Prometheus + Grafana
- 20+ 人大團隊:Datadog 或自組全套(有專人維護)
實戰:Prometheus Alert Rules
# alerts.yml
groups:
- name: web-app
rules:
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m]))
/ sum(rate(http_requests_total[5m])) > 0.01
for: 5m
labels:
severity: critical
annotations:
summary: "Error rate > 1% for 5 minutes"
runbook: "https://wiki/runbooks/high-error-rate"
- alert: HighLatency
expr: |
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket[5m])) by (le)
) > 2
for: 10m
labels:
severity: warning
annotations:
summary: "P99 latency > 2s for 10 minutes"
- alert: DiskWillFull
expr: |
predict_linear(node_filesystem_avail_bytes[6h], 48*3600) < 0
labels:
severity: warning
annotations:
summary: "Disk predicted to be full in 48 hours"FAQ
Q1: 小專案需要三根支柱都做嗎?
不用。先做 Metrics(Prometheus + Grafana 或雲端監控),再做集中式 Logs。Traces 等你有微服務架構再加。但從一開始就用 OpenTelemetry 做 instrumentation,以後要加支柱會很容易。
Q2: 告警規則怎麼訂才不會太多?
一個原則:每個告警收到時,你都應該需要做些什麼。 如果一個告警收到後的標準動作是「看一眼就關掉」,那這個告警就該拿掉或調整閾值。
Q3: SLO 要設多高?
不要一開始就設 99.99%。先從 99.5% 或 99.9% 開始,觀察幾個月後再調整。設太高會讓團隊壓力很大且沒有 error budget 做實驗。
Q4: Postmortem 真的不追究責任嗎?
真的。Blameless postmortem 的精神是:人會犯錯是正常的,系統應該有機制防止人為錯誤造成大規模影響。如果一個工程師的操作就能搞掛整個系統,那是系統的問題,不是人的問題。
Q5: Datadog 好貴,有什麼替代方案?
Grafana Cloud 有不錯的免費額度(10K metrics、50GB logs、50GB traces)。自架的話,Prometheus + Grafana + Loki + Tempo 全套開源免費,但你要有人力維護。New Relic 給 100GB/month 免費額度也很大方。
系列導航
| # | 文章 | 狀態 |
|---|---|---|
| 01 | 好的前端專案該有什麼?一張體檢表 | |
| 02 | 好的後端框架需要具備哪些功能? | |
| 03 | 好的 API 該長什麼樣? | |
| 04 | 好的資料庫設計需要什麼? | |
| 05 | 好的基礎建設需要什麼? | |
| 06 | CD Pipeline 需要什麼? | |
| 07 | 好的監控系統需要什麼?告警不等於監控 | 📍 你在這裡 |
| 08 | 好的開發者體驗(DX)需要什麼? |