理想上,每個服務都應該主動吐出 Metrics。但現實常常不是這樣:老舊系統難以改造、相容工具不存在、或是動程式碼的風險太高。Span Metrics 提供了一條退路——只要服務願意吐 Trace,就能反向產生與 Request 相關的 Metrics。
從 Trace 反推 Metrics#
Span Metrics Connector 是 OpenTelemetry Collector 的 Contrib 版本中提供的 Connector,會把 Trace 資料即時轉成 Metrics。注意這是 Contrib 版本獨有的元件,使用 Core 版本不會有它。
下面是一份最小可用設定,把同一份 Trace 同時送往 Tempo 與 Span Metrics Connector,最後由 Prometheus Exporter 揭露 Metrics:
receivers:
otlp:
protocols:
grpc:
http:
exporters:
otlp:
endpoint: tempo:4317
tls:
insecure: true
prometheus:
endpoint: "0.0.0.0:8889"
connectors:
spanmetrics:
processors:
batch:
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [spanmetrics, otlp]
metrics/spanmetrics:
receivers: [spanmetrics]
exporters: [prometheus]資料流程的重點在於 Connector 同時扮演兩種角色:
- 在
tracesPipeline 裡作為 Exporter,接收上游 Trace 並轉換出 Metrics。 - 在
metrics/spanmetricsPipeline 裡作為 Receiver,把轉換出來的 Metrics 餵給 Prometheus Exporter。
最終 Collector 會在 8889 Port 對外揭露這些 Metrics,由 Prometheus 主動爬取。
預設輸出與自訂 Label#
預設情境下,Span Metrics Connector 會輸出四種 Metrics:
calls_total:Span 被觀察到的總次數。duration_milliseconds_bucket:執行時間分布。duration_milliseconds_sum:執行時間總和。duration_milliseconds_count:累計次數。
預設帶的 Label 也固定:service_name、span_name、span_kind、status_code,分別來自 Span 的 service.name、name、span.kind、status.code。
如果想拉更多維度(例如想分開觀察不同 HTTP route 的延遲),可以透過 dimensions 加入額外 Span Attribute:
connectors:
spanmetrics:
dimensions:
- name: http.method
- name: http.status_code
- name: http.route這些 Attribute 會被改寫成 Prometheus 慣例的命名(例如 http_method、http_status_code、http_route)。
不過 Label 的維度組合會直接吃 Collector 記憶體,預設上限是 1000 種組合。系統流量大或 Attribute cardinality 高時,常常會撞到天花板,可以調大上限:
connectors:
spanmetrics:
dimensions_cache_size: 10000值得提醒的是,「調大快取」只是延後問題;如果某個 Attribute 本身就是高基數(例如 user id),更好的做法是不要把它放進 dimensions。
Jaeger Service Performance Monitoring#
Jaeger 從 1.43 起內建 Service Performance Monitoring(SPM),底層機制與上述完全一致:透過 OpenTelemetry Collector 的 Span Metrics Connector 把 Trace 轉成 Metrics,再由 Jaeger UI 直接呈現 RED Metrics(Request、Error、Duration)。
實務上常見搭配版本(Jaeger 1.50、OpenTelemetry Collector 0.86)需要調整 Jaeger Query 設定才能正確讀取 Prometheus:
- 環境變數:
METRICS_STORAGE_TYPE=prometheus。 - 啟動參數:
--prometheus.query.support-spanmetrics-connector=true--prometheus.server-url=http://prometheus:9090--prometheus.query.normalize-duration=true--prometheus.query.normalize-calls=true
搭配 OpenTelemetry Collector 0.80 之後的版本時,Span Metrics Connector 改了 Metrics 名稱規則,導致 Jaeger SPM 抓不到資料。Jaeger 1.47 起在 PR「Support normalized metric names #4555」加入相容性支援,必須同時開啟
--prometheus.query.normalize-duration與--prometheus.query.normalize-calls兩個旗標,UI 才會顯示資料。
Lab:Basic 與 Jaeger SPM 兩條路線#
範例專案提供兩組 Docker Compose:
- Basic:Collector 把 Trace 同時送 Tempo 與 spanmetrics,Prometheus 抓 Metrics,Grafana 透過 Provisioning 載入 OpenTelemetry APM Dashboard。
- Jaeger SPM:把後端換成 Jaeger Collector + Jaeger Query + Cassandra,由 Jaeger UI 的 Monitor 頁籤呈現 RED Metrics。
啟動方式:
# Basic
docker-compose up -d
# Jaeger SPM
docker-compose -f docker-compose.jaeger.yaml up -d兩條路線都用 k6 打流量:
k6 run --vus 1 --duration 300s k6-script.jsJaeger SPM 啟動時要稍等 Cassandra 初始化完成,否則 Jaeger Collector 與 Jaeger Query 會啟動失敗,可用 docker-compose ps 觀察狀態。
小結#
Span Metrics 的價值在於「最低改動成本換取 Request 視角的 Metrics」。對於難以塞 Prometheus Client 的系統,只要能透過 OpenTelemetry Automatic Instrumentation 拿到 Trace(甚至更進一步用 Service Mesh 的 Sidecar 直接從網路流量抽 Trace),就能取得一組可觀測的 RED Metrics。
這個概念也呼應 Tempo 的 Metrics-generator:Trace 不只是排查單一請求的工具,它本身就蘊含了大量可被衍生的資料,往後可預期會出現更多以 Trace 為原料、產出新型態 Signal 的工具。
原文出處#
- 原書/iThome:https://ithelp.ithome.com.tw/articles/10336986