Skip to content

Release Monitoring

對應主管要求 ⑤ release monitoring。 目的:把每一次 release 的執行狀況從個別 issue 抽離,成為可量測的指標

概念對應

指標從哪來
變更密度plan / issue 的時間分佈
失敗率task_run.state = FAILED 比例
重試率同 task 的 attempt > 1 比例
回滾率type = Rollback 的 plan 比例
平均審批時長bb.issue.createbb.issue.approve audit log 差值
平均執行時長task_run.finished_at - task_run.started_at
凍結期違規bb.setting.update(MaintenanceWindow override)+ bb.taskrun.start 在凍結期

內建畫面

Projects → <p> → Releases → Health

  • 最近 30 release 的失敗 / 成功 / 重試比例(堆疊柱狀)
  • 平均審批時長 / 執行時長(趨勢線)
  • 高風險變更次數(drop / truncate / large DML)
  • 凍結期變更次數(理應為 0)
  • 各 environment 的「落後 release 數」

此畫面需要 bb.releases.list + bb.taskRuns.listsecondaryBusinessOps / readOnlyAuditor 預設可看(IAM)。

自訂儀表

1. 直接 metrics(Prometheus)

Argus server 暴露 /metrics,含內建 release 相關指標:

Metric型別標籤
argus_task_run_totalcounterstate (done / failed / canceled)
argus_task_run_duration_secondshistogramengine, task_type
argus_plan_check_run_totalcounterstate, severity
argus_plan_check_run_duration_secondshistogramcheck_type
argus_issue_approval_duration_secondshistogramenvironment
argus_rollout_totalcounterenvironment, state

互動 SQL 治理(A2 PR-1 之後可用):

Metric型別標籤含意
argus_sql_advisor_violation_totalcounterrule_type, severity, query_path互動 path(Query / AdminExecute / Export)一次違規一次 +1。query_path 拆 fleet 分布
argus_sql_advisor_run_error_totalcounterquery_path, reasonadvisor 跑失敗計數。非零代表該 workspace 的 soak 數據不完整
argus_sql_advisor_run_duration_secondshistogramquery_pathadvisor 跑多久,sized 5s sync wait budget 之用

審批治理(R2 PR-1 之後可用):

Metric型別標籤含意
argus_iam_allusers_binding_skipped_totalcounterrole, workspace某 role 帶 AllUsers binding 但被 approval-role resolver 跳過。非零代表 workspace 還有 legacy AllUsers binding;R2 PR-2 soak 期間用此值決策該 workspace 是否需要 migrate

Risk Rule(P0-3 之後可用):

Metric型別標籤含意
argus_risk_rule_eval_error_totalcounterrule_id, kind (compile / eval)risk rule CEL 預判表達式失敗 — 該 rule 實質沒生效。fail-open 而非 fail-close,需要 ops 主動修

Schema Drift Detection(概念):

Metric型別標籤含意
argus_schema_drift_runner_tick_totalcounterrunner 每 10 分鐘 tick 一次。flat-line = runner 死了 — 即使 0 件 drift 也應該每 10 分鐘 +1
argus_schema_drift_runner_databases_scanned_totalcounterrunner 每個 tick 處理多少 db。除以 tick 數可知平均每 tick 掃幾 db
argus_schema_drift_checks_totalcounteroutcome (bootstrap / no_drift / drift / baseline_error / event_error / audit_error)每個 db 每次 check 的結果。drift 是真正寫了 event 的;*_error 非零代表 runner 內部錯誤
argus_schema_drift_events_totalcounterseverity (info / warning / error)寫進 schema_drift_event 的事件總數。這個 counter 上升 = 真的有未授權變更被偵測到
argus_schema_drift_blessing_totalcounteroutcome (skipped / blessed / schema_missing / baseline_error)TaskRun 完成後 blessing 結果。baseline_error 非零是嚴重的接線 regression — Plan-driven 變更會在下次 tick 被誤判為 drift

Grafana panel 範例(PromQL):

promql
# Prod task 失敗率 (7d)
sum(rate(argus_task_run_total{state="failed"}[7d])) by (engine)
  /
sum(rate(argus_task_run_total[7d])) by (engine)

# Prod issue 平均審批時長 (1d)
histogram_quantile(0.5,
  sum(rate(argus_issue_approval_duration_seconds_bucket{environment="prod"}[1d])) by (le)
)

# Schema drift event 速率(24h 滑窗)
sum(rate(argus_schema_drift_events_total[24h])) by (severity)

# Drift runner 健康度(必非零,否則 runner 卡了)
rate(argus_schema_drift_runner_tick_total[10m])

# Blessing 失敗率 — 預警「下次 tick 會大規模誤報」
rate(argus_schema_drift_blessing_total{outcome="baseline_error"}[5m])

2. 直接從 metastore SQL

sql
-- 過去 30 天,按 environment 拆分的 task 失敗率
SELECT
  e.resource_id AS environment,
  sum(case when tr.state = 'FAILED' then 1 else 0 end)::float / count(*)::float AS failure_rate,
  count(*) AS total
FROM task_run tr
JOIN task t ON (t.project = tr.project AND t.id = tr.task AND t.pipeline = tr.pipeline)
JOIN environment e ON (e.id = t.environment)
WHERE tr.started_at >= now() - interval '30 days'
GROUP BY e.resource_id
ORDER BY failure_rate DESC;

-- 重試率
SELECT
  count(distinct (project, task)) FILTER (WHERE max_attempt > 1)::float
    / count(distinct (project, task))::float AS retry_rate
FROM (
  SELECT project, task, max(attempt) AS max_attempt
  FROM task_run
  WHERE started_at >= now() - interval '7 days'
  GROUP BY project, task
) t;

-- 凍結期變更(理應為 0)
SELECT al.*
FROM audit_log al
WHERE al.action = 'bb.taskrun.start'
  AND al.ts >= now() - interval '30 days'
  AND EXISTS (
    SELECT 1 FROM maintenance_window mw
    WHERE mw.kind = 'FREEZE'
      AND al.ts BETWEEN mw.start_at AND mw.end_at
  );

⚠️ 表名 / 欄位請以 LATEST.sql 為準;以上為示意。直連 metastore 屬於 二線運維 SOP 涵蓋的高權限存取。

3. 接 BI / 數倉

灌進 BigQuery / Snowflake / 自家數倉的常見管道:

來源工具
metastore(OLTP)CDC(Debezium) → Kafka → 數倉
audit log(append-only)bb.auditlog.export 排程 → S3 → 數倉 ETL
metricsPrometheus remote-write → Mimir / Thanos

不要直接讓 BI 查 metastore — 會干擾 Argus 自身運行。走 read replica 或 CDC。

健康度警報

建議的常駐警報(按嚴重度):

警報條件嚴重度
Prod task 失敗率 spike1h 失敗率 > 過去 30d 平均的 3 倍warning
凍結期變更任何 taskrun 在 FREEZE 窗口內啟動critical
Audit log 寫入停止5 分鐘無新 entrycritical
平均審批時長 > 4 小時過去 24h 中位數info(流程問題訊號)
Plan check error override 比例 > 5%過去 7dwarning(標準下降訊號)
Argus server /healthz 異常任何 5xxcritical
Metastore lag(HA replica) > 30s任何時刻warning

週 / 月報

建議的固定報表:

週報(dev / 平台團隊)

  • 本週 release 數量 / 失敗 / 重試 / 回滾
  • Top 3 失敗最多的 project / DB
  • 平均審批時長 / 執行時長變化趨勢
  • 新發現的 high-risk pattern(plan check warning 統計)

月報(管理層 / 稽核)

  • 各 environment 變更分佈
  • 凍結期違規(理應 0;任何 > 0 都要說明)
  • Audit log 完整性驗證(hash chain)
  • IAM 變更摘要(誰被新增 / 撤銷 / 升級)
  • 高風險變更清單 + 結果

月報建議由 readOnlyAuditor 角色匯出 audit log,避免 reporter 與 actor 角色衝突。

反模式

反模式為什麼
只看「失敗 / 成功」二元指標看不見「執行時間爆長」「重試很多次最後成功」這種隱性問題
把 monitoring dashboard 鎖在 admin role二線運維 / 業務 owner 應該能自助查;用 secondaryBusinessOps 開放
警報訊息只說「failed」沒有 actor / resource / link 的警報沒人想處理
直接讀 metastore 跑 BI report干擾 Argus;走 read replica 或 CDC

相關

Argus — 公司內部資料庫變更審計平台