iT邦幫忙

2026 iThome 鐵人賽

DAY 16
0

上一篇把 AI SRE 的架構定下來,這篇接著把它實作出來。
接下來會說明調查流程與 query 設定放在哪裡,以及 metrics、logs、traces 經過整理後,LLM 實際會收到哪些資料。


AI SRE 的流程設計

目前 AI SRE 已經分成幾個主要部分:

流程

Runner 負責接收 Grafana webhook,把告警放進 queue,再交給後面的 Agent 處理。調查程式會按照 SOP 查詢觀測資料,整理成固定格式後交給 LLM。如果固定流程取得的資料不足,Runner 才會開放 Grafana MCP,讓 LLM 補查缺少的 metrics 或 logs。

LLM 會將證據串成因果關係,並依照固定格式產生診斷報告。整個流程只會透過 Grafana datasource proxy 讀取 Prometheus、Loki 與 Tempo,沒有 Kubernetes 的操作權限。


Metrics query 與特徵化

AI SRE 要查的 PromQL 都放在 sre/core/queries.yaml。集中管理查詢語法、參數與輸出格式。

目前定義了四種 metrics query:

Query 用途
service_metrics 查詢成功率、RPS、P50 與 P99,並比較穩定狀態
infra_metrics 查詢 HikariCP 資料庫連線池、JVM heap 與 Tomcat thread 使用量
platform_health 查詢 Pod 重啟、OOMKilled、CPU throttle(CPU 被限制使用)與 node pressure
service_health 一次比較多個服務的錯誤率與 P99,用來判斷影響範圍

以 P99 為例,設定裡會記錄參數、單位、數值增加是否代表惡化與 PromQL:

service_metrics:
  params:
    service:    {required: true, enum: service}
    http_route: {required: false}
    range:      {default: 30m, max: 3h}
  baseline: true
  metrics:
    p99:
      unit: ms
      higher_is_better: false
      expr: |
        histogram_quantile(0.99,
          sum(rate(litebank_duration_milliseconds_bucket{
            service_name="{{ service }}",
            span_kind="SPAN_KIND_SERVER"{{ route }}}[{{ range }}])) by (le))

調查程式會從告警取得服務、API 與時間區間,再套入範本。LLM 無需自己拼 PromQL,查詢區間也有上限,避免過度查詢。

Prometheus 的原始 metrics 會依照服務、API、Pod 等 label 組合拆成多條 time series,每條 time series 又包含一段時間內的資料點。直接將這些資料交給 LLM,資料量很快就會膨脹。

因此調查程式會先透過 PromQL 聚合,再整理成目前值、穩定狀態、變化百分比、趨勢與單位:

{
  "p99": {
    "current": 2002.0,
    "baseline": 1423.0,
    "delta_pct": 40.7,
    "trend": "degrading",
    "unit": "ms",
    "baseline_source": "1d"
  }
}

LLM 可以直接看出目前調查區間的 P99 為 2002ms,穩定狀態參考值為 1423ms,目前高出約 40.7%。這些特徵值足以先判斷該指標是否偏離穩定狀態。需要深入確認時,值班人員可以根據調查結果中的 query 與事故時間,回到 Grafana 查看 Prometheus 的 time series。


服務依賴關係

只查告警服務很容易看到一半。異常可能從下游一路傳回來,也可能已經影響上游入口。

所以服務之間的依賴關係放在 sre/core/topology.yaml,使用「服務→下游服務」的方式記錄:

edges:
  api-gateway:
    - user-service
    - account-service
    - teller-service
    - exchange-service

  teller-service:
    - transaction-service
    - account-service

例如 teller-service 告警時,調查程式會從 topology 找出它的上游呼叫方、服務本身與下游依賴,再透過前面提到的 service_health,一次查詢這些服務的錯誤率與 P99。

Topology 只負責提供「要查哪些服務」,實際是否受影響仍然要看本次查到的 metrics。這樣報告中的連鎖範圍才有當下的觀測資料支撐,LLM 也不需要憑印象猜測上下游關係。

目前 topology 先由人工維護,後續還要定期對照 spanmetrics,避免服務關係已經改變。


Logs 與 traces 查詢

Metrics 可以說明「哪裡變慢」與「惡化多少」,logs 和 traces 則用來補上「當時發生什麼事」與「時間花在哪一段」。

目前這兩種查詢實作在 sre/core/tools/,會透過 Grafana datasource proxy 分別讀取 Loki 與 Tempo。

Logs 先使用服務名縮小範圍:

{namespace="lite-bank", container="<service>"}

接著使用 Loki pattern API 將類似的 log 合併,最多保留前五種模式與出現次數:

{
  "top_patterns": [
    {
      "pattern": "Connection is not available, request timed out after <_>ms",
      "count": 312
    }
  ],
  "pattern_total": 1
}

固定流程會先保留這些 log pattern。若調查資料的 insufficienttrue,LLM 才能透過 Grafana MCP,依照 pattern 裡的關鍵字補查原始 log。

Critical 告警還會向 Tempo 查詢超過一秒的慢 trace 樣本:

{ resource.service.name = "<service>" && duration > 1s }
| select(name, span.http.route)

程式會依照 operation 合併查詢結果,保留出現次數、平均與最高延遲、HTTP route,以及幾個 trace ID:

{
  "slow_operations": [
    {
      "operation": "AuthService.login",
      "count": 12,
      "max_ms": 909.7,
      "avg_ms": 640.2,
      "http_route": "/api/v1/auth/login"
    }
  ],
  "sampled_traces": [
    {
      "trace_id": "24ae7bba6212847a1ab39488b0307eaa",
      "duration_ms": 922
    }
  ]
}

Tempo 搜尋只會回傳部分符合條件的慢 trace,無法保證這些就是整段時間內最慢的幾筆。因此,報告會將它標記為抽樣資料,不會直接當成最慢 trace 排名。


調查 SOP

前面的 metrics query、topology、logs 和 traces 都準備好之後,接著才能定義整體調查順序。

調查 SOP 放在 sre/core/sop.yaml。這份 YAML 負責定義每個步驟要呼叫哪個工具、查詢多長時間,以及哪些條件需要分流或降級:

steps:
  - id: dependency_scan
    action: service_health
    with:
      services: "{{ neighbors_of(service) }}"
      range: 15m

  - id: business_metrics
    action: service_metrics
    with:
      service: "{{ service }}"
      http_route: "{{ http_route }}"
      range: 30m
      baseline: 1d

  - id: resource_platform
    action: [infra_metrics, platform_health]
    with: {service: "{{ service }}", range: 30m}

  - id: log_patterns
    action: loki_patterns
    with: {service: "{{ service }}", range: 15m}

  - id: trace_drilldown
    action: tempo_slow
    with: {service: "{{ service }}", range: 15m}
    run_if: "severity == 'critical' and tools.tempo.available"

這條 SOP 會先確認告警服務與上下游的影響範圍,再查詢業務 metrics、應用程式資源與平台狀態,接著整理 logs。Critical 告警才會繼續查詢慢 traces,避免每一種告警都跑完整流程。

整理查詢結果

取得各步驟的查詢結果後,流程會按照 sop.yaml 的門檻,先將數值轉成 signals,再產生問題範圍與層級的 hints

HikariCP 等待數 14、node pressure 0
→ hikaricp_saturated=true、node_memory_pressure=false
→ layer_hint=app

signals 會記錄哪些條件已經超過門檻,例如 hikaricp_saturated=true。程式再根據這些結果產生 hints,初步指出問題可能發生在哪個範圍與層級。LLM 會接著對照 metrics、logs 與 traces,判斷真正的故障原因。

流程執行完 SOP 後,會將結果整理成固定格式的調查資料,再交給 LLM 判讀。以下再用一組簡化後的示意資料,只節錄主要欄位;實際輸出還會保留每個步驟的 query、時間區間與執行狀態:

{
  "alert": {
    "service": "teller-service",
    "severity": "critical"
  },
  "steps": {
    "business_metrics": {
      "action": "service_metrics",
      "result": {
        "p99": {"current": 2002, "baseline": 1423, "trend": "degrading"}
      }
    },
    "log_patterns": {
      "action": "loki_patterns",
      "result": {
        "top_patterns": [
          {"pattern": "Connection timed out after <_>ms", "count": 312}
        ],
        "pattern_total": 1
      }
    },
    "trace_drilldown": {
      "action": "tempo_slow",
      "result": {
        "slow_operations": [
          {"operation": "POST /api/v1/withdrawals", "max_ms": 909.7}
        ],
        "sampled_traces": [
          {"trace_id": "24ae7bba6212847a1ab39488b0307eaa"}
        ],
        "trace_count": 3
      }
    }
  },
  "signals": {
    "hikaricp_saturated": true,
    "node_memory_pressure": false,
    "has_error_pattern": true
  },
  "hints": {"scope_hint": "single_service", "layer_hint": "app"},
  "degraded": [],
  "insufficient": false
}

每個 steps 都會保留使用的工具與整理後的結果。查詢失敗或略過的步驟會放進 degraded;現有證據仍無法提供方向時,insufficient 會設成 true,允許 LLM 進一步補查。


LLM 推理規則

SOP 負責調查順序與資料整理,LLM 接手後開始做因果推論與撰寫報告。

SKILL.md 將 LLM 的工作限制在三個步驟:

步驟 LLM 要做的事
讀取調查資料 使用 Runner 已完成的調查結果,不重新執行 SOP
根因推論 閱讀 metrics、logs、traces、signalshints,將證據串成因果關係
產生報告 依照 docs/sre/report-template.md 輸出固定章節的診斷報告

LLM 提出的根因必須有 metrics、logs 或 traces 支撐。證據無法指向明確結論時,報告要降低信心程度;無法從觀測資料確認的觸發原因,只能列為待人工確認。

如果調查資料中的 insufficienttrue,Skill 才會允許 LLM 呼叫 MCP,最多只能呼叫四次,查詢時間區間上限為一小時。找到足夠證據就停,避免 Agent 一路查下去。

報告會區分實際觀察、根因推論與待確認事項,並且保留 Grafana 連結與可重跑的 query。Runner 完成調查後,會將結論、影響與建議動作回覆在同一則 Slack 告警訊息下方,完整報告另存成 Markdown 檔案。


總結

實際把程式做完後,各項功能分別放在下面幾個檔案和目錄:

實作 負責內容
queries.yaml 管理 metrics query、參數、時間區間與特徵化輸出
topology.yaml 提供服務依賴關係,讓調查可以檢查連鎖影響
sre/core/tools/ 查詢 Loki 與 Tempo,將 logs 與 traces 整理成摘要
sop.yaml 定義固定調查順序、分類規則、降級與證據不足的處理
SKILL.md 指導 LLM 閱讀調查資料、進行因果推論與產生報告

實作先寫到這裡。下一篇會讓 lite-bank 真的發生異常,再看 AI SRE 能不能根據 metrics、logs 與 traces 找到問題。

今天就先寫到這,我們明天見!


上一篇
Day 15:設計 AI SRE 架構
下一篇
Day 17:讓 AI SRE 接手一場告警演練
系列文
讓 AI 接手工程師的 SOP:30 天 AI 自動化實戰18
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言