什麼是 Metric#
一個 Metric 資料點,本質上就是一個帶有時間戳的數值。當我們把同一個量測值隨時間不斷記錄,就形成了一條 Time Series(時間序列)。
舉例來說,「每秒 HTTP 請求數」就是一條時間序列 ── 每隔固定間隔(例如 15 秒),系統記錄一次當前的請求計數,連接起來就能看到流量隨時間的變化趨勢。
Metric 回答的是「什麼出了問題」和「什麼時候出了問題」,但它很難回答「為什麼出了問題」。要回答「為什麼」,通常需要 Logs 或 Traces 的輔助。
Labels 與維度#
單純的數值本身用途有限。真正讓 Metrics 變得強大的是 Labels(也叫 Tags)── 附加在每條時間序列上的 key-value pair。
以 HTTP 請求數為例:
http_requests_total只告訴你「總共多少請求」http_requests_total{method="GET", status="200", service="api"}則讓你能按 HTTP Method、狀態碼、服務名稱任意切片查詢
每一組唯一的 Label 組合就構成一條獨立的時間序列。這代表 Labels 越多、值的種類越多,時間序列的數量就會爆炸性增長。這就是所謂的 Cardinality 問題── 高基數的 Label(例如 user ID、request ID)會讓儲存與查詢成本急劇攀升。
選擇 Label 時要謹慎。把 user ID 這類高基數值當作 Label 是 Metrics 系統的常見殺手。一般原則:如果某個 Label 值的種類可能超過幾百種,就不適合作為 Metric Label。這類資料更適合放在 Logs 或 Traces 中。
指標資訊的處理流程#
Metrics 從產生到被使用,會經歷四個階段。理解這個流程,有助於你判斷在每個環節該做什麼技術選型。
生成(Instrumentation)#
指標的起點是埋點。埋點有兩種主要方式:
- 應用層埋點:在你的程式碼中使用 Client Library(如 Prometheus Client)主動記錄業務指標。例如:每次收到請求就將計數器加一,每次完成處理就記錄延遲時間
- 基礎設施層匯出:透過 Exporter 從既有系統(資料庫、作業系統、中介軟體)擷取指標,不需要修改被監控系統的程式碼
好的埋點策略是「從外到內」:先監控使用者能感受到的指標(延遲、錯誤率),再逐步深入到內部元件的資源使用狀況。
收集(Collection)#
生成的指標需要被收集到中央系統。收集有兩種模式:
- Pull(拉):監控系統主動去各個目標抓取指標。Prometheus 就是典型的 Pull 模式。優點是監控系統掌握主動權,能清楚知道哪些目標健康、哪些目標失聯
- Push(推):應用程式主動把指標推送到收集端。StatsD 是典型的 Push 模式。優點是適合短暫存活的任務(如 batch job、serverless function),因為它們可能在下次被拉取前就已經結束
兩種模式沒有絕對的好壞,取決於你的架構特性。長駐服務適合 Pull,短暫任務適合 Push。
儲存(Storage)#
收集到的指標需要寫入 TSDB(Time Series Database,時間序列資料庫)。TSDB 針對時間序列資料做了專門的優化:
- 高壓縮比:時間序列資料具有高度規律性,TSDB 利用差值編碼等技術實現極高的壓縮率
- 高寫入吞吐:系統持續不斷地產生指標,TSDB 必須能承受大量的並發寫入
- 時間範圍查詢最佳化:「最近一小時的 CPU 使用率」這類查詢是最常見的操作,TSDB 對此做了索引優化
常見的 TSDB 包括 Prometheus 內建的本地儲存、InfluxDB、VictoriaMetrics、Thanos 等。
使用(Consumption)#
儲存的指標透過三種主要方式被消費:
- Dashboard:將指標視覺化,讓團隊對系統狀態一目了然。Grafana 是最普遍的選擇
- 告警(Alerting):設定規則,當指標超過閾值時自動通知。例如「錯誤率超過 5% 持續 5 分鐘」觸發 PagerDuty 通知
- 查詢與分析:使用查詢語言(如 PromQL)做即時的資料探索,用於排查問題或容量規劃
為什麼 Metrics 是最先被引入的信號#
在可觀測性的三大信號中,Metrics 幾乎總是團隊最先導入的。這不是偶然,而是由它的技術特性決定的:
- 低儲存成本:一個數值加上時間戳,壓縮後每個資料點只需要幾個 byte。相比之下,一行 Log 可能就要數百 byte
- 高壓縮比:時間序列資料天生適合壓縮,TSDB 能以極少的磁碟空間保存大量歷史資料
- 適合聚合:數字可以直接做數學運算 ── 求和、平均、百分位數、比率。這讓 Metrics 天然適合回答「整體狀況如何」的問題
- 查詢速度快:因為資料結構簡單且有索引,時間範圍查詢通常在毫秒級完成
Metrics 的侷限性#
Metrics 雖然強大,但有明確的邊界:
- 只能告訴你「什麼」,不能告訴你「為什麼」:你能看到延遲飆高,但無法從 Metrics 中得知是哪個 SQL 查詢造成的
- Cardinality 限制:高基數的維度不適合用 Metrics 表達,否則系統會因為時間序列爆炸而崩潰
- 聚合即資訊損失:當你把一千個請求的延遲聚合為 P99,你就失去了個別請求的細節
- 無法表達因果關係:Metrics 能顯示 Service A 和 Service B 同時出問題,但無法告訴你誰影響了誰
Metrics 的價值在於持續且低成本地回答「系統現在還好嗎」。當 Metrics 告訴你「不好了」,你再切換到 Logs 和 Traces 去找原因。三種信號各有分工,不該試圖讓 Metrics 回答所有問題。