iT邦幫忙

2026 iThome 鐵人賽

DAY 20
0
AI 自動化

讓 AI 接手工程師的 SOP:30 天 AI 自動化實戰系列 第 20

Day 20:實作 AI 分析壓測報告的資料準備流程

  • 分享至 

  • xImage
  •  

上一篇把 AI 壓測報告需要的資料與整體架構定下來,這篇說明實作的部分。

我們先用一個壓測案例來說明實作流程,這次使用薪轉日的情境。


情境說明

薪轉日通常會有大量使用者在短時間內登入,接著查詢帳戶、確認薪資是否入帳,再進行轉帳或查詢交易紀錄。這次模擬 1,000 位使用者在一分鐘內登入 Lite-Bank,登入成功後先查詢帳戶與餘額,再依照下面的比例執行後續操作:

  • 60% 的使用者執行轉帳。
  • 30% 的使用者查詢交易紀錄。
  • 10% 的使用者停留在餘額頁面。

每位使用者的 Session 維持 15 分鐘,這段時間會持續執行對應的操作。整個情境會經過 api-gatewayuser-serviceaccount-serviceteller-servicetransaction-service,所以這次要驗證的是完整業務流程在指定負載下的效能與穩定性。

接下來就用這個案例來進行說明。


記錄測試條件

起點是 manifest.yaml。它會在壓測前記錄測試類型、測試目的、業務操作、觀測服務、負載設定與驗收門檻。

以下節錄一小段設定:

test:
  type: BUSINESS_JOURNEY
  name: Lite-Bank 發薪日流程
  objective: 驗證指定負載下,登入與後續銀行操作是否達到驗收條件

target:
  operations:
    - id: login
      name: 使用者登入
      protocol: HTTP
      method: POST
      route: /api/v1/auth/login

    - id: transfer
      name: 執行 TWD 轉帳
      protocol: HTTP
      method: POST
      route: /api/v1/transfers

  services:
    - service: api-gateway
      metrics:
        type: gateway

    - service: user-service
      metrics:
        type: application

    - service: teller-service
      metrics:
        type: application

acceptance:
  - id: login-latency
    type: LATENCY_P99
    threshold_ms: 1000
    scope:
      operation: login

  - id: transfer-latency
    type: LATENCY_P99
    threshold_ms: 3000
    scope:
      operation: transfer

test 記錄測試名稱、目的與類型。這裡使用 BUSINESS_JOURNEY,代表這次要驗證登入、查詢帳戶與轉帳的完整業務流程。

K6 腳本會替每種 request 設定 operation tag,用來分開統計各項業務操作。Manifest 的 operations 使用相同的 ID,再補上操作名稱、HTTP method 與 route。以登入為例,K6 將 request 標記為 login,Manifest 也使用 id: login。後續程式讀取 K6 summary 時,就能將登入的數值對應到「使用者登入」與 /api/v1/auth/login。轉帳也是同樣的做法,兩邊都使用 transfer

最後由 acceptance 設定每個操作的驗收門檻。第一條使用 operation: login,程式會從 K6 summary 取得登入的 P99,檢查是否低於 1 秒。第二條使用 operation: transfer,會取得轉帳的 P99,門檻是 3 秒。Manifest 裡的 operation id、K6 request tag 與 acceptance 使用相同名稱,程式才能找到正確的數值。

services 負責另一件事:寫下這次要從 Prometheus 觀測哪些服務。metrics.type 決定要套用哪一組 metrics query;gateway 會多查 route 資料,application 會查一般應用程式與 Kubernetes metrics。

還有一個區段是 workload,以下是節錄:

workload:
  tool: K6
  planned_duration: PT15M
  scenarios:
    - id: payday_journey
      executor: CONSTANT_ARRIVAL_RATE
      rate: 1000
      time_unit: PT1M
      arrival_duration: PT1M
      pre_allocated_vus: 1001
      max_vus: 1001
      completed_metric: iterations

workload 主要記錄 K6 施加什麼負載。這個案例使用 CONSTANT_ARRIVAL_RATE,在一分鐘內啟動 1,000 次薪轉日流程,每位使用者持續操作 15 分鐘。K6 會預先準備 1,001 個 VUs,最多也使用 1,001 個,避免啟動使用者時因為 VUs 不足而來不及執行。

completed_metric: iterations 表示後續會用 K6 完成的 iteration 數量,確認實際跑完多少次流程。這些設定會放進 Bundle 與報告,讓 AI 知道本次結果是在什麼負載條件下量到的。實際執行仍由 K6 腳本負責,兩邊的設定需要保持一致。

將這份 YAML 交給 AI 分析前,測試人員要先填好測試類型、operations、觀測的 servicesworkloadacceptance,說明這次要測什麼、如何施加負載,以及最後的驗收標準。


收集資料並保存至 Snapshot

K6 壓測完成後會產生 summary JSON。程式會先從 K6 summary 確認正式測量時間,再依照 Manifest 的 servicesmetrics.type 展開對應的 PromQL,向 Prometheus 查詢 K6、應用程式與 Kubernetes metrics。服務 metrics 會多收集壓測結束後五分鐘的恢復期,確認負載停止後 CPU、Memory 等資源是否恢復;K6 metrics 則只保留正式壓測期間的資料。部分 metrics 會透過 PromQL 以固定間隔查詢,例如 CPU 使用率在 15 分鐘的正式壓測期間每 30 秒取一個資料點,包含開始與結束時間,最後會取得 31 個資料點。

查詢結果會保存成 prometheus-snapshot.json。Snapshot 會記錄實際執行的 PromQL、查詢時間、Prometheus 回傳結果與查詢狀態,保留當下取得的原始資料。即使 Prometheus 的歷史資料之後過期,也能回頭確認當時查了什麼,以及實際拿到哪些資料。

抓取完成後,程式會將 Snapshot 資訊回寫到 Manifest:

artifacts:
  prometheus_snapshot:
    path: results/payday-run/prometheus-snapshot.json
    format: PROM_QUERY_SNAPSHOT
    sha256: <SHA-256>

path 記錄 Snapshot 的位置,format 表示檔案格式,sha256 用來確認後續讀到的檔案沒有被替換或修改。這三個欄位由程式產生,不需要測試人員手動填寫。

將 Snapshot 做特徵化

Snapshot 保存的是 Prometheus 查回來的原始資料,還需要先整理成 AI 能直接分析的特徵,將每項 metric 的時間序列分成邊界、正式測量與恢復期,檢查資料是否完整,再計算最大值、最小值與平均值等摘要。實際產物是 JSON,以下用 YAML 節錄 CPU 使用率的特徵化結果:

queries:
  - query_id: cpu_usage
    metric:
      type: RATE
      unit: cpu_cores

    series:
      - labels:
          pod: user-service-7b8c9d
          container: user-service

        observations:
          boundary:
            - at: "2026-08-20T03:41:03.533Z"
              state: FINITE
              value: "0.08"
            # 其餘邊界資料點省略

          measurement:
            - at: "2026-08-20T03:43:03.533Z"
              state: FINITE
              value: "0.42"
            - at: "2026-08-20T03:43:33.533Z"
              state: ABSENT
            # 其餘正式測量資料點省略

          recovery:
            - at: "2026-08-20T03:56:33.533Z"
              state: FINITE
              value: "0.15"
            # 其餘恢復期資料點省略

        coverage:
          expected_points: 27
          state_counts:
            FINITE: 26
            ABSENT: 1

        continuity_breaks:
          - position: MIDDLE
            starts_at: "2026-08-20T03:43:33.533Z"
            ends_at: "2026-08-20T03:43:33.533Z"
            point_count: 1

        summaries:
          observed_min:
            status: PARTIAL_COVERAGE
            value: 0.18
          observed_max:
            status: PARTIAL_COVERAGE
            value: 0.92
          observed_mean:
            status: NOT_COMPUTABLE
            reason: INCOMPLETE_MEASUREMENT

observations 會保留完整時間序列,並分成 boundarymeasurementrecoveryboundary 是壓測剛開始的緩衝資料,這個案例的 CPU 使用率用 rate() 計算,前兩分鐘會帶到壓測開始前的資料,所以前四個資料點只留作計算參考。measurement 保存正式壓測期間用來分析的資料,recovery 保存壓測結束後五分鐘的資料,用來確認資源是否恢復。

每個資料點都會標記狀態。FINITE 代表有取得數值,ABSENT 代表該時間點沒有資料,程式不會把缺值補成 0coverage 用來確認資料有沒有收齊。這個例子原本應該有 27 個資料點,實際取得 26 個,另外 1 個是缺值。continuity_breaks 會接著記錄缺值發生的時間、位置與持續多久。

最後,summaries 會依照 metrics 類型計算適用的摘要。這個例子少了一個資料點,所以最大值與最小值標記為 PARTIAL_COVERAGE,平均值則標記為 NOT_COMPUTABLE。AI 看到這些欄位後,可以分清楚完整結果、部分資料與無法計算的情況,同時還能回到 observations 核對原始資料點。

判斷驗收結果

完成特徵化後,程式會拿 Manifest 的 acceptance 與 K6 summary 的實測值進行比對。這次登入的 P99 是 30,171.80 ms,超過 1,000 ms 的門檻;轉帳的 P99 是 242.95 ms,低於 3,000 ms,以下節錄登入與轉帳的判定結果:

verdict: FAIL
conditions:
  - id: login-latency
    verdict: FAIL
    threshold_ms: 1000
    actual: 30171.80
    unit: ms

  - id: transfer-latency
    verdict: PASS
    threshold_ms: 3000
    actual: 242.95
    unit: ms

每一條條件都會保留門檻、實測值與判定結果。只要有一條條件是 FAIL,整體結果就是 FAIL;需要的數值缺少時,則會標記為 UNDETERMINED。這個判定由固定程式完成,AI 不會自行決定門檻或修改結果。

組合成 Bundle

驗收結果完成後,程式會將前面產生的資料組合成 Bundle。以下用 YAML 簡化呈現它的主要內容:

run:
  id: payday-15m-business-journey
  measurement:
    start_at: "2026-09-12T14:41:59.130Z"
    end_at: "2026-09-12T14:56:59.130Z"

test:
  type: BUSINESS_JOURNEY
  name: Lite-Bank 發薪日流程

feature_artifact:
  queries:
    - query_id: cpu_usage
      # observations、coverage 與 summaries 省略

k6:
  workload:
    planned_duration: PT15M
  results:
    operations:
      login:
        status: OBSERVED
        http_req_duration_ms:
          p99: 30171.80
      transfer:
        status: OBSERVED
        http_req_duration_ms:
          p99: 242.95

acceptance:
  verdict: FAIL
  conditions:
    - id: login-latency
      verdict: FAIL
    - id: transfer-latency
      verdict: PASS

topology:
  services:
    - service: api-gateway
    - service: user-service
    - service: teller-service
  operations:
    - id: login
    - id: transfer

runtest 說明這次執行的時間和目的,feature_artifact 提供 K6、服務與 Kubernetes metrics 的完整特徵,k6 保存負載設定與使用者實際感受到的結果,acceptance 記錄驗收判定,topology 是從 manifest.yamltarget 組出來,交代這次觀測的服務與業務操作。

總結

這篇先用薪轉日壓測說明 AI 分析前的資料準備流程實作。測試人員先用 Manifest 定義測試情境、觀測服務、負載與驗收門檻,程式再收集 Prometheus 資料、建立 Snapshot、整理特徵、判斷驗收結果,最後組合成 Bundle。

壓測情境、K6 結果、服務 metrics 與驗收結果都已經整理完成。下一篇再從 Bundle 接著往下,說明 AI 如何根據這些資料產生壓測報告。

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


上一篇
Day 19:設計 AI 壓測報告分析架構
下一篇
Day 21:實作壓測報告產生流程
系列文
讓 AI 接手工程師的 SOP:30 天 AI 自動化實戰24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言