From 0aa28bd0fd921d6c1a7c15747367dfc0a1a1b225 Mon Sep 17 00:00:00 2001 From: hazel-shen Date: Sat, 4 Jul 2026 16:50:13 +0800 Subject: [PATCH 1/2] feat(dashboard): restructure governance dashboard for live demo (Prompt 3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rebuild agent-governance.json with 5-section governance narrative: 總覽 / 行為治理(Demo1) / 資料治理(Demo2) / 規則治理(Demo3,collapsed) / 事後驗證 - Remove broken panel (audit event >= 3 always-zero stat) - Add illustrative data banner text panel at top - Add 最後push距今 (data freshness) and OPA決策延遲p99 stats to overview - Add Blocked by Reason bargauge (depends on reason label from Prompt 2) - Convert OPA test timeseries to state-timeline with PASS✓/FAIL✗ mappings - Add v Tool×Role tables to use sum by (tool,role) and add limit(20) - Wrap deny rate and patch/opa metrics with sum() for per-run grouping - Remove DS_PROMETHEUS template variable; set time=now-15m, refresh=5s - Reorganize: dashboards/governance/, dashboards/faq/, dashboards-archive/ - Set faq-bot-overview_v2 uid to prevent Grafana duplicate on folder scan - Update provisioning foldersFromFilesStructure=false for flat layout - Rewrite observability/README.md with provisioning auto-load instructions --- observability/README.md | 100 +- .../dashboards-archive/agent-governance.json | 1900 ++++++++++++++ .../faq-bot-overview_v1.json | 0 .../faq-bot-overview_v2.json | 624 +++++ .../dashboards/agent-governance.json | 2292 +++++++++-------- .../dashboards/faq-bot-overview_v2.json | 3 +- .../dashboards/faq/faq-bot-overview_v2.json | 625 +++++ .../governance/agent-governance.json | 2076 +++++++++++++++ 8 files changed, 6515 insertions(+), 1105 deletions(-) create mode 100644 observability/dashboards-archive/agent-governance.json rename observability/{dashboards => dashboards-archive}/faq-bot-overview_v1.json (100%) create mode 100644 observability/dashboards-archive/faq-bot-overview_v2.json create mode 100644 observability/dashboards/faq/faq-bot-overview_v2.json create mode 100644 observability/dashboards/governance/agent-governance.json diff --git a/observability/README.md b/observability/README.md index 45b4b48..8665b27 100644 --- a/observability/README.md +++ b/observability/README.md @@ -1,17 +1,17 @@ # Observability(本機 Prometheus + Grafana) -這個資料夾提供一套 **本機監控環境**,用於觀察 FAQ Bot 的執行情況: +這個資料夾提供一套 **本機監控環境**,用於觀察 FAQ Bot 與 Agent Governance Policy Gate 的執行情況: -- **Prometheus**:抓取後端 `/metrics`(FastAPI 服務) -- **Grafana**:內建一個「FAQ Bot Overview」儀表板(JSON 可匯入) -- **可選**:將資料 **remote_write 到 Grafana Cloud**(在 `prometheus.yml` 內已有註解) +- **Prometheus**:抓取三個來源的指標 +- **Grafana**:由 provisioning 自動載入 datasource 與 dashboard,無需手動匯入 +- **可選**:將資料 remote_write 到 Grafana Cloud(在 `prometheus.yml` 內已有註解) --- ## 前置需求 - 已安裝 **Docker** 與 **Docker Compose** -- 後端 FastAPI 服務需已在 [http://localhost:8000/metrics](http://localhost:8000/metrics) 暴露 Prometheus 指標 +- 後端 FastAPI 服務(faq-api)需已在 `http://localhost:8000/metrics` 暴露 Prometheus 指標 --- @@ -31,55 +31,82 @@ docker-compose up -d - 預設帳密:`admin / admin` - 首次登入會要求修改密碼 -### 設定 Prometheus Data Source +### Datasource 自動載入 -首次登入 Grafana 後: +Datasource(Prometheus,uid: `prometheus`)由 `provisioning/datasources/` 自動配置,無需手動設定。 -1. 進入 **Connections** → **Data Sources** -2. 新增 **Prometheus** -3. URL 填入:`http://prometheus:9090` - (因為 Grafana 與 Prometheus 在同一個 docker compose 網路中) +### Dashboard 自動載入 -> 若登入後已自動帶入 Prometheus Data Source,可略過這一步。 +Dashboard 由 `provisioning/dashboards/default.yml` 自動掃描 `dashboards/` 子目錄,啟動後 Grafana 側會出現兩個資料夾: -### 匯入儀表板 +| Grafana 資料夾 | 來源目錄 | Dashboard | +|---|---|---| +| `governance` | `dashboards/governance/` | Agent Governance — Policy Gate | +| `faq` | `dashboards/faq/` | FAQ Bot Overview v2 | -1. **Grafana** → **Dashboards** → **Import** -2. 上傳 `dashboards/faq-bot-overview.json` -3. 匯入完成後會看到 **FAQ Bot Overview** 儀表板 +> `dashboards-archive/` 不在掛載路徑內,Grafana 不再載入其中的舊版 dashboard(faq-bot-overview_v1)。 --- -## 主要指標(Prometheus metrics) +## Prometheus Scrape 來源 + +三個 scrape 目標: + +| 服務 | 位址 | 說明 | +|---|---|---| +| faq-api | `http://host.docker.internal:8000/metrics` | FAQ Bot FastAPI 後端 | +| Pushgateway | `http://pushgateway:9091` | agent-governance-demo 的 Policy Gate 指標(`honor_labels: true`) | +| OPA | `http://opa:8181/metrics` | OPA binary 自身指標(決策延遲等) | + +--- + +## 排練前清場 + +governance dashboard 為**示意數據**(demo 環境,非生產統計)。排練前可用 agent-governance-demo 的清場腳本清掉舊 schema 殘留: + +```bash +cd ../agent-governance-demo +bash scripts/metrics_reset.sh +``` + +清場後再跑 `bash scripts/run_demo.sh 2 stub` 產資料,確認「累加不倒退」後再上台。 + +--- -FAQ Bot 服務會輸出以下常用指標: +## 主要指標(Prometheus metrics) -### 請求數與延遲 +### FAQ Bot(faq-api) +#### 請求數與延遲 - `llm_requests_total` - `llm_request_latency_seconds` -### Token 與成本 - +#### Token 與成本 - `llm_tokens_total` - `llm_cost_total_usd_total` -### 快取相關 - +#### 快取相關 - `rag_cache_requests_total` - `rag_cache_results_total` -### 子流程延遲 - +#### 子流程延遲 - `rag_embedding_latency_seconds` - `rag_retrieval_latency_seconds` - `rag_rerank_latency_seconds` - `rag_llm_latency_seconds` -### 輸入檢查 / 限流 - +#### 輸入檢查 / 限流 - `input_*` +### Agent Governance(Pushgateway,job="agent-governance-demo") + +- `tool_gate_allow_total` / `tool_gate_blocked_total` / `tool_gate_approval_total` +- `tool_gate_audit_event` +- `policy_anomaly_triggered_total` +- `policy_patch_proposed_total` / `policy_patch_accepted_total` / `policy_patch_rejected_total` +- `opa_test_result` / `opa_test_run_total` / `opa_test_duration_seconds` +- `push_time_seconds`(資料新鮮度) + --- ## (可選)送資料到 Grafana Cloud @@ -94,10 +121,6 @@ remote_write: basic_auth: username: "" password: "" - write_relabel_configs: - - source_labels: [job] - target_label: job - replacement: "faq-bot-dev" ``` 3. 重新啟動: @@ -107,10 +130,6 @@ docker compose down docker compose up -d ``` -**建議**:用不同 job/label 區分 dev 與 prod,避免資料混在一起。 - -**注意**:Grafana Cloud Free Plan 保留時間為 14 天,remote_write 會增加流量與存放量。 - --- ## 關閉 / 清除資料 @@ -126,14 +145,3 @@ docker volume rm observability_prom_data observability_grafana_data ``` ⚠️ **如果要保留 Grafana 的儀表板配置,不要刪除 `grafana_data` volume。** - -## 📊 指標 (Prometheus) - -| 分類 | 指標 | 說明 | -| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | -| Runtime | `python_gc_*`, `python_info` | Python GC 與版本資訊 | -| 請求 | `llm_requests_total`, `llm_request_latency_seconds` | 請求數、延遲統計 | -| Token/成本 | `llm_tokens_total`, `llm_cost_total_usd_total` | Token 使用量與成本 | -| Cache | `rag_cache_requests_total`, `rag_cache_results_total` | Cache 查詢與命中率 | -| RAG Pipeline | `rag_embedding_latency_seconds`, `rag_retrieval_latency_seconds`, `rag_rerank_latency_seconds`, `rag_llm_latency_seconds`, `rag_errors_total` | 各階段延遲與錯誤 | -| Input Policy | `input_accepted_total`, `input_rejected_total`, `input_rate_limited_total`, `input_chars_histogram`, `input_tokens_histogram`, `input_violation_last_seen_timestamp` | 輸入檢查與限流統計 | diff --git a/observability/dashboards-archive/agent-governance.json b/observability/dashboards-archive/agent-governance.json new file mode 100644 index 0000000..12271c3 --- /dev/null +++ b/observability/dashboards-archive/agent-governance.json @@ -0,0 +1,1900 @@ +{ + "title": "Agent Governance — Policy Gate", + "uid": "agent-governance-v1", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "links": [], + "liveNow": false, + "schemaVersion": 39, + "tags": [ + "governance", + "policy-gate", + "opa" + ], + "templating": { + "list": [ + { + "name": "DS_PROMETHEUS", + "type": "datasource", + "pluginId": "prometheus", + "current": {}, + "hide": 0, + "label": "Prometheus" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "refresh": "10s", + "panels": [ + { + "id": 100, + "type": "row", + "title": "【Demo 1 / 2 / 3】Policy Gate 總覽", + "collapsed": false, + "gridPos": { + "x": 0, + "y": 0, + "w": 24, + "h": 1 + } + }, + { + "id": 1, + "type": "stat", + "title": "【D1/2/3】Total ALLOW", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 1, + "w": 4, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "green" + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(tool_gate_allow_total{job=\"agent-governance-demo\"})", + "legendFormat": "allow", + "refId": "A" + } + ] + }, + { + "id": 2, + "type": "stat", + "title": "【D1/2/3】Total BLOCKED", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 4, + "y": 1, + "w": 4, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "red" + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(tool_gate_blocked_total{job=\"agent-governance-demo\"})", + "legendFormat": "blocked", + "refId": "A" + } + ] + }, + { + "id": 3, + "type": "stat", + "title": "【D1/2/3】Total REQUIRE_APPROVAL", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 8, + "y": 1, + "w": 4, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "orange" + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "orange", + "value": null + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(tool_gate_approval_total{job=\"agent-governance-demo\"})", + "legendFormat": "approval", + "refId": "A" + } + ] + }, + { + "id": 4, + "type": "stat", + "title": "【D1/2/3】Block Rate", + "description": "BLOCKED / (ALLOW + BLOCKED + APPROVAL)", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 12, + "y": 1, + "w": 4, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "percentunit", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 0.3 + }, + { + "color": "red", + "value": 0.6 + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(tool_gate_blocked_total{job=\"agent-governance-demo\"}) / (sum(tool_gate_allow_total{job=\"agent-governance-demo\"}) + sum(tool_gate_blocked_total{job=\"agent-governance-demo\"}) + sum(tool_gate_approval_total{job=\"agent-governance-demo\"}))", + "legendFormat": "block rate", + "refId": "A" + } + ] + }, + { + "id": 5, + "type": "timeseries", + "title": "【D1/2/3】Gate 決策趨勢(累計)", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 5, + "w": 24, + "h": 7 + }, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "custom": { + "lineWidth": 2, + "fillOpacity": 10 + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "allow" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "green" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "blocked" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "red" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "approval" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "orange" + } + } + ] + } + ] + }, + "targets": [ + { + "expr": "sum(tool_gate_allow_total{job=\"agent-governance-demo\"})", + "legendFormat": "allow", + "refId": "A" + }, + { + "expr": "sum(tool_gate_blocked_total{job=\"agent-governance-demo\"})", + "legendFormat": "blocked", + "refId": "B" + }, + { + "expr": "sum(tool_gate_approval_total{job=\"agent-governance-demo\"})", + "legendFormat": "approval", + "refId": "C" + } + ] + }, + { + "id": 200, + "type": "row", + "title": "【Demo 1 / 2 / 3】決策明細 — by Tool & Role", + "collapsed": false, + "gridPos": { + "x": 0, + "y": 12, + "w": 24, + "h": 1 + } + }, + { + "id": 6, + "type": "bargauge", + "title": "【D1/2/3】Allow by Tool", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 13, + "w": 8, + "h": 7 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "green" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (tool) (tool_gate_allow_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{tool}}", + "refId": "A" + } + ] + }, + { + "id": 7, + "type": "bargauge", + "title": "【D1/2/3】Blocked by Tool", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 8, + "y": 13, + "w": 8, + "h": 7 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "red" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (tool) (tool_gate_blocked_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{tool}}", + "refId": "A" + } + ] + }, + { + "id": 8, + "type": "bargauge", + "title": "【D1/2/3】Approval by Tool", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 16, + "y": 13, + "w": 8, + "h": 7 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "orange" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (tool) (tool_gate_approval_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{tool}}", + "refId": "A" + } + ] + }, + { + "id": 9, + "type": "bargauge", + "title": "【D1/2/3】Allow by Role", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 20, + "w": 8, + "h": 7 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "green" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (role) (tool_gate_allow_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{role}}", + "refId": "A" + } + ] + }, + { + "id": 10, + "type": "bargauge", + "title": "【D1/2/3】Blocked by Role", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 8, + "y": 20, + "w": 8, + "h": 7 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "red" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (role) (tool_gate_blocked_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{role}}", + "refId": "A" + } + ] + }, + { + "id": 11, + "type": "bargauge", + "title": "【D1/2/3】Approval by Role", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 16, + "y": 20, + "w": 8, + "h": 7 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "orange" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (role) (tool_gate_approval_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{role}}", + "refId": "A" + } + ] + }, + { + "id": 300, + "type": "row", + "title": "【Demo 1 / 2 / 3】攔截明細 — Tool × Role", + "collapsed": false, + "gridPos": { + "x": 0, + "y": 27, + "w": 24, + "h": 1 + } + }, + { + "id": 12, + "type": "table", + "title": "【D1/2/3】BLOCKED — Tool × Role", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 28, + "w": 12, + "h": 7 + }, + "options": { + "footer": { + "show": false + }, + "sortBy": [ + { + "displayName": "Value", + "desc": true + } + ] + }, + "fieldConfig": { + "defaults": { + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + } + ] + } + } + ] + } + ] + }, + "targets": [ + { + "expr": "tool_gate_blocked_total{job=\"agent-governance-demo\"}", + "legendFormat": "{{tool}} / {{role}}", + "refId": "A", + "instant": true, + "format": "table" + } + ], + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "tool", + "role", + "Value" + ] + } + } + } + ] + }, + { + "id": 13, + "type": "table", + "title": "【D1/2/3】REQUIRE_APPROVAL — Tool × Role", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 12, + "y": 28, + "w": 12, + "h": 7 + }, + "options": { + "footer": { + "show": false + }, + "sortBy": [ + { + "displayName": "Value", + "desc": true + } + ] + }, + "fieldConfig": { + "defaults": { + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "orange", + "value": null + } + ] + } + } + ] + } + ] + }, + "targets": [ + { + "expr": "tool_gate_approval_total{job=\"agent-governance-demo\"}", + "legendFormat": "{{tool}} / {{role}}", + "refId": "A", + "instant": true, + "format": "table" + } + ], + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "tool", + "role", + "Value" + ] + } + } + } + ] + }, + { + "id": 500, + "type": "row", + "title": "【Demo 1 / 2 / 3】Audit Log — 每筆決策記錄", + "collapsed": false, + "gridPos": { + "x": 0, + "y": 35, + "w": 24, + "h": 1 + } + }, + { + "id": 20, + "type": "table", + "title": "【D1/2/3】Audit 明細 — 每筆決策完整脈絡", + "description": "tool_gate_audit_event:每筆各有唯一 request_id。可看出是 OPA 還是 fallback 跟哪一版 policy 決定、哪一個 caller 發出。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 36, + "w": 24, + "h": 8 + }, + "options": { + "footer": { + "show": false + }, + "sortBy": [ + { + "displayName": "ts", + "desc": true + } + ] + }, + "fieldConfig": { + "defaults": { + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "decision" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "mappings", + "value": [ + { + "type": "value", + "options": { + "allow": { + "color": "green", + "index": 0 + }, + "deny": { + "color": "red", + "index": 1 + }, + "require_approval": { + "color": "orange", + "index": 2 + } + } + } + ] + } + ] + } + ] + }, + "targets": [ + { + "expr": "tool_gate_audit_event{job=\"agent-governance-demo\"}", + "legendFormat": "", + "refId": "A", + "instant": true, + "format": "table" + } + ], + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "ts", + "tool", + "role", + "decision", + "caller", + "policy_version" + ] + } + } + }, + { + "id": "sortBy", + "options": { + "fields": [ + { + "displayName": "ts", + "desc": true + } + ] + } + } + ] + }, + { + "id": 21, + "type": "stat", + "title": "【D3】Anomaly Trigger 次數", + "description": "deny 累積超過門栖,自動觸發 propose_policy_patch 的次數。門栖預設 3,可用環境變數 ANOMALY_THRESHOLD 調整。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 44, + "w": 6, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 1 + }, + { + "color": "red", + "value": 3 + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "count(tool_gate_audit_event{job=\"agent-governance-demo\", decision=\"deny\"} >= 3) or vector(0)", + "legendFormat": "anomaly triggers", + "refId": "A" + } + ] + }, + { + "id": 22, + "type": "piechart", + "title": "【D1/2/3】Audit 決策分布", + "description": "所有 audit 筆數按 decision 分布圓餅圖。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 6, + "y": 44, + "w": 9, + "h": 8 + }, + "options": { + "legend": { + "displayMode": "table", + "placement": "right", + "values": [ + "percent", + "value" + ] + }, + "pieType": "donut", + "tooltip": { + "mode": "single" + } + }, + "fieldConfig": { + "defaults": { + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "allow" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "green" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "deny" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "red" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "require_approval" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "orange" + } + } + ] + } + ] + }, + "targets": [ + { + "expr": "count by (decision) (tool_gate_audit_event{job=\"agent-governance-demo\"})", + "legendFormat": "{{decision}}", + "refId": "A", + "instant": true + } + ] + }, + { + "id": 23, + "type": "bargauge", + "title": "【D1/2/3】Audit 決策 by policy_version", + "description": "OPA 決定 vs fallback 各占幾筆,可看出是否有呼叫走到 OPA binary。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 15, + "y": 44, + "w": 9, + "h": 8 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "palette-classic" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "count by (policy_version) (tool_gate_audit_event{job=\"agent-governance-demo\"})", + "legendFormat": "{{policy_version}}", + "refId": "A", + "instant": true + } + ] + }, + { + "id": 400, + "type": "row", + "title": "【Demo 3】OPA Test 狀態(規則治理)", + "collapsed": false, + "gridPos": { + "x": 0, + "y": 52, + "w": 24, + "h": 1 + } + }, + { + "id": 14, + "type": "stat", + "title": "【D3 ①】Baseline — OPA Test 全綠基準線", + "description": "Demo 開始前 OPA test 全綠基準線", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 53, + "w": 8, + "h": 5 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "value_and_name", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "mappings": [ + { + "type": "value", + "options": { + "0": { + "text": "FAIL", + "color": "red" + }, + "1": { + "text": "PASS", + "color": "green" + } + } + } + ] + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "opa_test_result{job=\"agent-governance-demo\", stage=\"baseline\"}", + "legendFormat": "baseline", + "refId": "A" + } + ] + }, + { + "id": 15, + "type": "stat", + "title": "【D3 ③】After Patch — 預期紅燈", + "description": "套用測試 patch 後,預期紅燈", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 8, + "y": 53, + "w": 8, + "h": 5 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "value_and_name", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "mappings": [ + { + "type": "value", + "options": { + "0": { + "text": "FAIL", + "color": "red" + }, + "1": { + "text": "PASS", + "color": "green" + } + } + } + ] + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "opa_test_result{job=\"agent-governance-demo\", stage=\"after_patch\"}", + "legendFormat": "after_patch", + "refId": "A" + } + ] + }, + { + "id": 16, + "type": "stat", + "title": "【D3 ④】After Fix — 預期綠燈(CI 核准)", + "description": "修正 rego 後,預期綠燈 — CI 可 merge", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 16, + "y": 53, + "w": 8, + "h": 5 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "value_and_name", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "mappings": [ + { + "type": "value", + "options": { + "0": { + "text": "FAIL", + "color": "red" + }, + "1": { + "text": "PASS", + "color": "green" + } + } + } + ] + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "opa_test_result{job=\"agent-governance-demo\", stage=\"after_fix\"}", + "legendFormat": "after_fix", + "refId": "A" + } + ] + }, + { + "id": 600, + "type": "row", + "title": "【Demo 3】Anomaly Detection 訊號", + "collapsed": false, + "gridPos": { + "x": 0, + "y": 65, + "w": 24, + "h": 1 + } + }, + { + "id": 30, + "type": "stat", + "title": "【D3 ②】Anomaly 觸發次數", + "description": "deny 累積超過門栖,自動觸發 _on_anomaly callback 的次數。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 66, + "w": 6, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 1 + }, + { + "color": "red", + "value": 3 + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(policy_anomaly_triggered_total{job=\"agent-governance-demo\"}) or vector(0)", + "legendFormat": "anomaly triggers", + "refId": "A" + } + ] + }, + { + "id": 31, + "type": "bargauge", + "title": "【D3 ②】Anomaly 觸發 by Tool × Role", + "description": "哪個 tool + role 組合累積觸發最多次。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 6, + "y": 66, + "w": 10, + "h": 4 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "orange" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (tool, role) (policy_anomaly_triggered_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{tool}} / {{role}}", + "refId": "A" + } + ] + }, + { + "id": 32, + "type": "timeseries", + "title": "【D3 ②】Deny 累積速率(訊號來源)", + "description": "rate(tool_gate_blocked_total[1m]) by tool+role。迷い峰即是 anomaly 觸發點。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 70, + "w": 24, + "h": 6 + }, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "fieldConfig": { + "defaults": { + "unit": "reqps", + "custom": { + "lineWidth": 2, + "fillOpacity": 15 + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "rate(tool_gate_blocked_total{job=\"agent-governance-demo\"}[1m])", + "legendFormat": "{{tool}} / {{role}}", + "refId": "A" + } + ] + }, + { + "id": 700, + "type": "row", + "title": "【Demo 3】Policy Patch 生命週期", + "collapsed": false, + "gridPos": { + "x": 0, + "y": 76, + "w": 24, + "h": 1 + } + }, + { + "id": 40, + "type": "stat", + "title": "【D3 ②】Patch 提案次數", + "description": "LLM 呼叫 propose_policy_patch 的累積次數。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 77, + "w": 6, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "blue" + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(policy_patch_proposed_total{job=\"agent-governance-demo\"}) or vector(0)", + "legendFormat": "proposed", + "refId": "A" + } + ] + }, + { + "id": 41, + "type": "stat", + "title": "【D3 ③】Patch 採納(Human 核准)", + "description": "人類審核後按 y 採納的次數。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 6, + "y": 77, + "w": 6, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "green" + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "policy_patch_accepted_total{job=\"agent-governance-demo\"} or vector(0)", + "legendFormat": "accepted", + "refId": "A" + } + ] + }, + { + "id": 42, + "type": "stat", + "title": "【D3 ③】Patch 拒絕(Human 駁回)", + "description": "人類審核後按 N 拒絕的次數。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 12, + "y": 77, + "w": 6, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "red" + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "policy_patch_rejected_total{job=\"agent-governance-demo\"} or vector(0)", + "legendFormat": "rejected", + "refId": "A" + } + ] + }, + { + "id": 43, + "type": "stat", + "title": "【D3 ③】Patch 採納率", + "description": "accepted / (accepted + rejected)。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 18, + "y": 77, + "w": 6, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "percentunit", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 0.5 + }, + { + "color": "green", + "value": 0.8 + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "policy_patch_accepted_total{job=\"agent-governance-demo\"} / clamp_min((policy_patch_accepted_total{job=\"agent-governance-demo\"} + policy_patch_rejected_total{job=\"agent-governance-demo\"}), 1)", + "legendFormat": "acceptance rate", + "refId": "A" + } + ] + }, + { + "id": 800, + "type": "row", + "title": "【Demo 3】OPA Test 執行結果與耗時", + "collapsed": false, + "gridPos": { + "x": 0, + "y": 81, + "w": 24, + "h": 1 + } + }, + { + "id": 50, + "type": "bargauge", + "title": "【D3 ③④】OPA Test 執行次數 by Stage", + "description": "每個 stage 被跟成功執行了幾次 opa test。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 82, + "w": 8, + "h": 6 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "palette-classic" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "opa_test_run_total{job=\"agent-governance-demo\"}", + "legendFormat": "{{stage}}", + "refId": "A" + } + ] + }, + { + "id": 51, + "type": "bargauge", + "title": "【D3 ③④】OPA Test 耗時(最後一次)by Stage", + "description": "opa test 最後一次执行的秒數,讓觀眾感受「CI 真的在跟」。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 8, + "y": 82, + "w": 8, + "h": 6 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "s", + "color": { + "mode": "palette-classic" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "opa_test_duration_seconds{job=\"agent-governance-demo\"}", + "legendFormat": "{{stage}} ({{result}})", + "refId": "A" + } + ] + }, + { + "id": 52, + "type": "timeseries", + "title": "【D3 ③→④】OPA Test 耗時歷史(紅燈→綠燈轉折)", + "description": "opa_test_duration_seconds 時間軸變化,可看出 after_patch(紅)到 after_fix(綠)的転折點。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 16, + "y": 82, + "w": 8, + "h": 6 + }, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "fieldConfig": { + "defaults": { + "unit": "s", + "custom": { + "lineWidth": 2, + "fillOpacity": 15 + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "opa_test_duration_seconds{job=\"agent-governance-demo\"}", + "legendFormat": "{{stage}}", + "refId": "A" + } + ] + }, + { + "id": 17, + "type": "timeseries", + "title": "【D3】OPA Test 狀態歷史(1=PASS, 0=FAIL)", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 58, + "w": 24, + "h": 7 + }, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "min": 0, + "max": 1, + "custom": { + "lineWidth": 2, + "fillOpacity": 20, + "drawStyle": "line", + "stacking": { + "mode": "none" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "opa_test_result{job=\"agent-governance-demo\"}", + "legendFormat": "{{stage}}", + "refId": "A" + } + ] + } + ], + "annotations": { + "list": [] + } +} \ No newline at end of file diff --git a/observability/dashboards/faq-bot-overview_v1.json b/observability/dashboards-archive/faq-bot-overview_v1.json similarity index 100% rename from observability/dashboards/faq-bot-overview_v1.json rename to observability/dashboards-archive/faq-bot-overview_v1.json diff --git a/observability/dashboards-archive/faq-bot-overview_v2.json b/observability/dashboards-archive/faq-bot-overview_v2.json new file mode 100644 index 0000000..18ccec1 --- /dev/null +++ b/observability/dashboards-archive/faq-bot-overview_v2.json @@ -0,0 +1,624 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "id": 100, + "type": "row", + "title": "Request Overview", + "gridPos": { + "x": 0, + "y": 0, + "w": 24, + "h": 1 + }, + "collapsed": false, + "panels": [] + }, + { + "id": 1, + "type": "stat", + "title": "RPS (requests/sec)", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 0, + "y": 1, + "w": 6, + "h": 6 + }, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto" + }, + "fieldConfig": { + "defaults": { + "unit": "reqps" + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(rate(llm_requests_total[1m]))", + "legendFormat": "rps", + "refId": "A" + } + ] + }, + { + "id": 2, + "type": "timeseries", + "title": "Latency p50 / p95 (s) — $route", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 6, + "y": 1, + "w": 18, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "s" + }, + "overrides": [] + }, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + } + }, + "targets": [ + { + "expr": "histogram_quantile(0.5, sum by (le) (rate(llm_request_latency_seconds_bucket{route=\"$route\"}[5m])))", + "legendFormat": "p50", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.95, sum by (le) (rate(llm_request_latency_seconds_bucket{route=\"$route\"}[5m])))", + "legendFormat": "p95", + "refId": "B" + } + ] + }, + { + "id": 200, + "type": "row", + "title": "Cache & Cost", + "gridPos": { + "x": 0, + "y": 7, + "w": 24, + "h": 1 + }, + "collapsed": false, + "panels": [] + }, + { + "id": 3, + "type": "timeseries", + "title": "Cache Hit / Miss (per min) — $route", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 0, + "y": 8, + "w": 12, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "reqpm" + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (result) (rate(rag_cache_results_total{route=\"$route\"}[1m])) * 60", + "legendFormat": "{{result}}", + "refId": "A" + } + ], + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + } + } + }, + { + "id": 14, + "type": "stat", + "title": "Cache Hit Ratio (%) — $route", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 12, + "y": 8, + "w": 12, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "percent" + }, + "overrides": [] + }, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto" + }, + "targets": [ + { + "expr": "100 * sum(rate(rag_cache_results_total{route=\"$route\",result=\"hit\"}[5m])) / clamp_min(sum(rate(rag_cache_requests_total{route=\"$route\"}[5m])), 1)", + "legendFormat": "hit %", + "refId": "A" + } + ] + }, + { + "id": 4, + "type": "timeseries", + "title": "Cost Rate (USD/min) by model", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 0, + "y": 14, + "w": 12, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "currencyUSD" + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (model) (rate(llm_cost_total_usd_total[1m])) * 60", + "legendFormat": "{{model}}", + "refId": "A" + } + ], + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + } + } + }, + { + "id": 15, + "type": "stat", + "title": "Avg Cost / Request (USD)", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 12, + "y": 14, + "w": 12, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "currencyUSD" + }, + "overrides": [] + }, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto" + }, + "targets": [ + { + "expr": "sum(rate(llm_cost_total_usd_total[5m])) / clamp_min(sum(rate(llm_requests_total[5m])), 1)", + "legendFormat": "avg cost/req", + "refId": "A" + } + ] + }, + { + "id": 300, + "type": "row", + "title": "Tokens & Errors", + "gridPos": { + "x": 0, + "y": 20, + "w": 24, + "h": 1 + }, + "collapsed": false, + "panels": [] + }, + { + "id": 5, + "type": "timeseries", + "title": "Tokens/sec by kind & model", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 0, + "y": 21, + "w": 12, + "h": 6 + }, + "targets": [ + { + "expr": "sum by (kind, model) (rate(llm_tokens_total[1m]))", + "legendFormat": "{{kind}} {{model}}", + "refId": "A" + } + ], + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + } + } + }, + { + "id": 6, + "type": "timeseries", + "title": "Errors (5m increase) by stage", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 12, + "y": 21, + "w": 12, + "h": 6 + }, + "targets": [ + { + "expr": "sum by (stage) (increase(rag_errors_total[5m])) or vector(0)", + "legendFormat": "{{stage}}", + "refId": "A" + } + ], + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + } + } + }, + { + "id": 400, + "type": "row", + "title": "RAG Pipeline Latency", + "gridPos": { + "x": 0, + "y": 27, + "w": 24, + "h": 1 + }, + "collapsed": false, + "panels": [] + }, + { + "id": 7, + "type": "timeseries", + "title": "Embedding Latency p95 (s) by stage", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 0, + "y": 28, + "w": 8, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "s" + }, + "overrides": [] + }, + "targets": [ + { + "expr": "histogram_quantile(0.95, sum by (le, stage) (rate(rag_embedding_latency_seconds_bucket[5m])))", + "legendFormat": "{{stage}}", + "refId": "A" + } + ] + }, + { + "id": 8, + "type": "timeseries", + "title": "Retrieval Latency p95 (s)", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 8, + "y": 28, + "w": 8, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "s" + }, + "overrides": [] + }, + "targets": [ + { + "expr": "histogram_quantile(0.95, sum by (le) (rate(rag_retrieval_latency_seconds_bucket[5m])))", + "legendFormat": "retrieval", + "refId": "A" + } + ] + }, + { + "id": 9, + "type": "timeseries", + "title": "Rerank Latency p95 (s)", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 16, + "y": 28, + "w": 8, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "s" + }, + "overrides": [] + }, + "targets": [ + { + "expr": "histogram_quantile(0.95, sum by (le) (rate(rag_rerank_latency_seconds_bucket[5m])))", + "legendFormat": "rerank", + "refId": "A" + } + ] + }, + { + "id": 10, + "type": "timeseries", + "title": "LLM Latency p95 (s) by model — $model", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 0, + "y": 34, + "w": 24, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "s" + }, + "overrides": [] + }, + "targets": [ + { + "expr": "histogram_quantile(0.95, sum by (le, model) (rate(rag_llm_latency_seconds_bucket{model=~\"$model\"}[5m])))", + "legendFormat": "{{model}}", + "refId": "A" + } + ], + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + } + } + }, + { + "id": 500, + "type": "row", + "title": "Input Health", + "gridPos": { + "x": 0, + "y": 40, + "w": 24, + "h": 1 + }, + "collapsed": false, + "panels": [] + }, + { + "id": 11, + "type": "bargauge", + "title": "Rejected Inputs (total) by type", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 0, + "y": 41, + "w": 8, + "h": 6 + }, + "targets": [ + { + "expr": "sum by (type) (input_rejected_total)", + "legendFormat": "{{type}}", + "refId": "A" + } + ] + }, + { + "id": 12, + "type": "bargauge", + "title": "Rate Limited (total) by scope", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 8, + "y": 41, + "w": 8, + "h": 6 + }, + "targets": [ + { + "expr": "sum by (scope) (input_rate_limited_total) or vector(0)", + "legendFormat": "{{scope}}", + "refId": "A" + } + ] + }, + { + "id": 13, + "type": "stat", + "title": "Accepted Inputs (total)", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 16, + "y": 41, + "w": 8, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "reqpm" + }, + "overrides": [] + }, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto" + }, + "targets": [ + { + "expr": "sum(input_accepted_total)", + "legendFormat": "total accepted", + "refId": "A" + } + ] + } + ], + "refresh": "10s", + "schemaVersion": 39, + "style": "dark", + "tags": [ + "faq-bot", + "rag", + "observability" + ], + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": "Prometheus", + "value": "prometheus" + }, + "hide": 0, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "type": "datasource" + }, + { + "name": "route", + "type": "query", + "hide": 0, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(llm_request_latency_seconds_bucket, route)", + "query": { + "query": "label_values(llm_request_latency_seconds_bucket, route)", + "refId": "A" + }, + "refresh": 2, + "includeAll": false, + "multi": false, + "sort": 1, + "current": { + "selected": true, + "text": "/ask", + "value": "/ask" + } + }, + { + "name": "model", + "type": "query", + "hide": 0, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(rag_llm_latency_seconds_bucket, model)", + "query": { + "query": "label_values(rag_llm_latency_seconds_bucket, model)", + "refId": "B" + }, + "refresh": 2, + "includeAll": true, + "allValue": ".*", + "multi": true, + "sort": 1, + "current": { + "selected": true, + "text": "All", + "value": ".*" + } + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "FAQ Bot — Overview (RAG + LLM)", + "version": 3, + "weekStart": "" +} \ No newline at end of file diff --git a/observability/dashboards/agent-governance.json b/observability/dashboards/agent-governance.json index 12271c3..0a3cfea 100644 --- a/observability/dashboards/agent-governance.json +++ b/observability/dashboards/agent-governance.json @@ -1,5 +1,6 @@ { "title": "Agent Governance — Policy Gate", + "description": "Agent Governance Policy Gate — demo 環境示意數據,非生產統計", "uid": "agent-governance-v1", "editable": true, "fiscalYearStartMonth": 0, @@ -13,33 +14,40 @@ "opa" ], "templating": { - "list": [ - { - "name": "DS_PROMETHEUS", - "type": "datasource", - "pluginId": "prometheus", - "current": {}, - "hide": 0, - "label": "Prometheus" - } - ] + "list": [] }, "time": { - "from": "now-1h", + "from": "now-15m", "to": "now" }, "timepicker": {}, "timezone": "browser", - "refresh": "10s", + "refresh": "5s", "panels": [ + { + "id": 999, + "type": "text", + "title": "", + "gridPos": { + "x": 0, + "y": 0, + "w": 24, + "h": 2 + }, + "options": { + "mode": "markdown", + "content": "⚠️ **示意數據(illustrative)** — 本 dashboard 來自 demo 環境,數據用於說明治理機制,非生產統計。" + }, + "transparent": false + }, { "id": 100, "type": "row", - "title": "【Demo 1 / 2 / 3】Policy Gate 總覽", + "title": "總覽 — Policy Gate", "collapsed": false, "gridPos": { "x": 0, - "y": 0, + "y": 2, "w": 24, "h": 1 } @@ -47,14 +55,14 @@ { "id": 1, "type": "stat", - "title": "【D1/2/3】Total ALLOW", + "title": "Total ALLOW", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "x": 0, - "y": 1, + "y": 3, "w": 4, "h": 4 }, @@ -99,14 +107,14 @@ { "id": 2, "type": "stat", - "title": "【D1/2/3】Total BLOCKED", + "title": "Total BLOCKED", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "x": 4, - "y": 1, + "y": 3, "w": 4, "h": 4 }, @@ -151,14 +159,14 @@ { "id": 3, "type": "stat", - "title": "【D1/2/3】Total REQUIRE_APPROVAL", + "title": "Total REQUIRE_APPROVAL", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "x": 8, - "y": 1, + "y": 3, "w": 4, "h": 4 }, @@ -203,7 +211,7 @@ { "id": 4, "type": "stat", - "title": "【D1/2/3】Block Rate", + "title": "Block Rate", "description": "BLOCKED / (ALLOW + BLOCKED + APPROVAL)", "datasource": { "type": "prometheus", @@ -211,7 +219,7 @@ }, "gridPos": { "x": 12, - "y": 1, + "y": 3, "w": 4, "h": 4 }, @@ -257,17 +265,131 @@ } ] }, + { + "id": 60, + "type": "stat", + "title": "最後 push 距今", + "description": "資料新鮮度:demo 跑了但資料沒進來時這顆先變紅。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 16, + "y": 3, + "w": 4, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "s", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 30 + }, + { + "color": "red", + "value": 60 + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "time() - max(push_time_seconds{job=\"agent-governance-demo\"})", + "legendFormat": "seconds ago", + "refId": "A" + } + ] + }, + { + "id": 61, + "type": "stat", + "title": "OPA 決策延遲 p99", + "description": "Gate 多增加的決策延遲,sub-millisecond 量級為正常。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 20, + "y": 3, + "w": 4, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "s", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 0.01 + }, + { + "color": "red", + "value": 0.1 + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket{job=\"opa\", handler=\"v1/data\"}[5m])))", + "legendFormat": "p99 latency", + "refId": "A" + } + ] + }, { "id": 5, "type": "timeseries", - "title": "【D1/2/3】Gate 決策趨勢(累計)", + "title": "Gate 決策趨勢(累計)", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "x": 0, - "y": 5, + "y": 7, "w": 24, "h": 7 }, @@ -357,11 +479,11 @@ { "id": 200, "type": "row", - "title": "【Demo 1 / 2 / 3】決策明細 — by Tool & Role", + "title": "行為治理(Demo 1)— Agent 能做什麼", "collapsed": false, "gridPos": { "x": 0, - "y": 12, + "y": 14, "w": 24, "h": 1 } @@ -369,14 +491,14 @@ { "id": 6, "type": "bargauge", - "title": "【D1/2/3】Allow by Tool", + "title": "Allow by Tool", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "x": 0, - "y": 13, + "y": 15, "w": 8, "h": 7 }, @@ -411,14 +533,14 @@ { "id": 7, "type": "bargauge", - "title": "【D1/2/3】Blocked by Tool", + "title": "Blocked by Tool", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "x": 8, - "y": 13, + "y": 15, "w": 8, "h": 7 }, @@ -451,16 +573,17 @@ ] }, { - "id": 8, + "id": 62, "type": "bargauge", - "title": "【D1/2/3】Approval by Tool", + "title": "Blocked by Reason", + "description": "哪類原因最常被擋,是治理收束段的核心重點。", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "x": 16, - "y": 13, + "y": 15, "w": 8, "h": 7 }, @@ -471,7 +594,7 @@ "lastNotNull" ] }, - "displayMode": "gradient", + "displayMode": "basic", "valueMode": "color" }, "fieldConfig": { @@ -479,15 +602,15 @@ "unit": "short", "color": { "mode": "fixed", - "fixedColor": "orange" + "fixedColor": "red" } }, "overrides": [] }, "targets": [ { - "expr": "sum by (tool) (tool_gate_approval_total{job=\"agent-governance-demo\"})", - "legendFormat": "{{tool}}", + "expr": "sum by (reason) (tool_gate_blocked_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{reason}}", "refId": "A" } ] @@ -495,14 +618,14 @@ { "id": 9, "type": "bargauge", - "title": "【D1/2/3】Allow by Role", + "title": "Allow by Role", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "x": 0, - "y": 20, + "y": 22, "w": 8, "h": 7 }, @@ -537,14 +660,14 @@ { "id": 10, "type": "bargauge", - "title": "【D1/2/3】Blocked by Role", + "title": "Blocked by Role", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "x": 8, - "y": 20, + "y": 22, "w": 8, "h": 7 }, @@ -576,72 +699,18 @@ } ] }, - { - "id": 11, - "type": "bargauge", - "title": "【D1/2/3】Approval by Role", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 16, - "y": 20, - "w": 8, - "h": 7 - }, - "options": { - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "displayMode": "gradient", - "valueMode": "color" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "orange" - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum by (role) (tool_gate_approval_total{job=\"agent-governance-demo\"})", - "legendFormat": "{{role}}", - "refId": "A" - } - ] - }, - { - "id": 300, - "type": "row", - "title": "【Demo 1 / 2 / 3】攔截明細 — Tool × Role", - "collapsed": false, - "gridPos": { - "x": 0, - "y": 27, - "w": 24, - "h": 1 - } - }, { "id": 12, "type": "table", - "title": "【D1/2/3】BLOCKED — Tool × Role", + "title": "BLOCKED — Tool × Role", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { - "x": 0, - "y": 28, - "w": 12, + "x": 16, + "y": 22, + "w": 8, "h": 7 }, "options": { @@ -688,7 +757,7 @@ }, "targets": [ { - "expr": "tool_gate_blocked_total{job=\"agent-governance-demo\"}", + "expr": "sum by (tool, role) (tool_gate_blocked_total{job=\"agent-governance-demo\"})", "legendFormat": "{{tool}} / {{role}}", "refId": "A", "instant": true, @@ -707,291 +776,146 @@ ] } } - } - ] - }, - { - "id": 13, - "type": "table", - "title": "【D1/2/3】REQUIRE_APPROVAL — Tool × Role", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 12, - "y": 28, - "w": 12, - "h": 7 - }, - "options": { - "footer": { - "show": false - }, - "sortBy": [ - { - "displayName": "Value", - "desc": true - } - ] - }, - "fieldConfig": { - "defaults": { - "unit": "short" }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background" - }, + { + "id": "sortBy", + "options": { + "fields": [ { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "orange", - "value": null - } - ] - } + "displayName": "Value", + "desc": true } ] } - ] - }, - "targets": [ - { - "expr": "tool_gate_approval_total{job=\"agent-governance-demo\"}", - "legendFormat": "{{tool}} / {{role}}", - "refId": "A", - "instant": true, - "format": "table" - } - ], - "transformations": [ + }, { - "id": "filterFieldsByName", + "id": "limit", "options": { - "include": { - "names": [ - "tool", - "role", - "Value" - ] - } + "limitCount": 20 } } ] }, { - "id": 500, + "id": 300, "type": "row", - "title": "【Demo 1 / 2 / 3】Audit Log — 每筆決策記錄", + "title": "資料治理(Demo 2)— Agent 能查什麼", "collapsed": false, "gridPos": { "x": 0, - "y": 35, + "y": 29, "w": 24, "h": 1 } }, { - "id": 20, - "type": "table", - "title": "【D1/2/3】Audit 明細 — 每筆決策完整脈絡", - "description": "tool_gate_audit_event:每筆各有唯一 request_id。可看出是 OPA 還是 fallback 跟哪一版 policy 決定、哪一個 caller 發出。", + "id": 8, + "type": "bargauge", + "title": "Approval by Tool", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "x": 0, - "y": 36, - "w": 24, - "h": 8 + "y": 30, + "w": 8, + "h": 7 }, "options": { - "footer": { - "show": false + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] }, - "sortBy": [ - { - "displayName": "ts", - "desc": true - } - ] + "displayMode": "gradient", + "valueMode": "color" }, "fieldConfig": { "defaults": { - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "decision" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background" - }, - { - "id": "mappings", - "value": [ - { - "type": "value", - "options": { - "allow": { - "color": "green", - "index": 0 - }, - "deny": { - "color": "red", - "index": 1 - }, - "require_approval": { - "color": "orange", - "index": 2 - } - } - } - ] - } - ] + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "orange" } - ] + }, + "overrides": [] }, "targets": [ { - "expr": "tool_gate_audit_event{job=\"agent-governance-demo\"}", - "legendFormat": "", - "refId": "A", - "instant": true, - "format": "table" - } - ], - "transformations": [ - { - "id": "filterFieldsByName", - "options": { - "include": { - "names": [ - "ts", - "tool", - "role", - "decision", - "caller", - "policy_version" - ] - } - } - }, - { - "id": "sortBy", - "options": { - "fields": [ - { - "displayName": "ts", - "desc": true - } - ] - } + "expr": "sum by (tool) (tool_gate_approval_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{tool}}", + "refId": "A" } ] }, { - "id": 21, - "type": "stat", - "title": "【D3】Anomaly Trigger 次數", - "description": "deny 累積超過門栖,自動觸發 propose_policy_patch 的次數。門栖預設 3,可用環境變數 ANOMALY_THRESHOLD 調整。", + "id": 11, + "type": "bargauge", + "title": "Approval by Role", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { - "x": 0, - "y": 44, - "w": 6, - "h": 4 + "x": 8, + "y": 30, + "w": 8, + "h": 7 }, "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", + "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ] - } + }, + "displayMode": "gradient", + "valueMode": "color" }, "fieldConfig": { "defaults": { "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "orange", - "value": 1 - }, - { - "color": "red", - "value": 3 - } - ] + "color": { + "mode": "fixed", + "fixedColor": "orange" } }, "overrides": [] }, "targets": [ { - "expr": "count(tool_gate_audit_event{job=\"agent-governance-demo\", decision=\"deny\"} >= 3) or vector(0)", - "legendFormat": "anomaly triggers", + "expr": "sum by (role) (tool_gate_approval_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{role}}", "refId": "A" } ] }, { - "id": 22, - "type": "piechart", - "title": "【D1/2/3】Audit 決策分布", - "description": "所有 audit 筆數按 decision 分布圓餅圖。", + "id": 13, + "type": "table", + "title": "REQUIRE_APPROVAL — Tool × Role", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { - "x": 6, - "y": 44, - "w": 9, - "h": 8 + "x": 16, + "y": 30, + "w": 8, + "h": 7 }, "options": { - "legend": { - "displayMode": "table", - "placement": "right", - "values": [ - "percent", - "value" - ] + "footer": { + "show": false }, - "pieType": "donut", - "tooltip": { - "mode": "single" - } + "sortBy": [ + { + "displayName": "Value", + "desc": true + } + ] }, "fieldConfig": { "defaults": { @@ -1001,44 +925,23 @@ { "matcher": { "id": "byName", - "options": "allow" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "green" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "deny" + "options": "Value" }, "properties": [ { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "red" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "require_approval" - }, - "properties": [ + "id": "custom.displayMode", + "value": "color-background" + }, { - "id": "color", + "id": "thresholds", "value": { - "mode": "fixed", - "fixedColor": "orange" + "mode": "absolute", + "steps": [ + { + "color": "orange", + "value": null + } + ] } } ] @@ -1047,849 +950,1122 @@ }, "targets": [ { - "expr": "count by (decision) (tool_gate_audit_event{job=\"agent-governance-demo\"})", - "legendFormat": "{{decision}}", + "expr": "sum by (tool, role) (tool_gate_approval_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{tool}} / {{role}}", "refId": "A", - "instant": true + "instant": true, + "format": "table" + } + ], + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "tool", + "role", + "Value" + ] + } + } + }, + { + "id": "sortBy", + "options": { + "fields": [ + { + "displayName": "Value", + "desc": true + } + ] + } + }, + { + "id": "limit", + "options": { + "limitCount": 20 + } } ] }, { - "id": 23, - "type": "bargauge", - "title": "【D1/2/3】Audit 決策 by policy_version", - "description": "OPA 決定 vs fallback 各占幾筆,可看出是否有呼叫走到 OPA binary。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, + "id": 400, + "type": "row", + "title": "規則治理(Demo 3)— 誰能改規則", + "collapsed": true, "gridPos": { - "x": 15, - "y": 44, - "w": 9, - "h": 8 + "x": 0, + "y": 37, + "w": 24, + "h": 1 }, - "options": { - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "displayMode": "gradient", - "valueMode": "color" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "palette-classic" - } - }, - "overrides": [] - }, - "targets": [ + "panels": [ { - "expr": "count by (policy_version) (tool_gate_audit_event{job=\"agent-governance-demo\"})", - "legendFormat": "{{policy_version}}", - "refId": "A", - "instant": true - } - ] - }, - { - "id": 400, - "type": "row", - "title": "【Demo 3】OPA Test 狀態(規則治理)", - "collapsed": false, - "gridPos": { - "x": 0, - "y": 52, - "w": 24, - "h": 1 - } - }, - { - "id": 14, - "type": "stat", - "title": "【D3 ①】Baseline — OPA Test 全綠基準線", - "description": "Demo 開始前 OPA test 全綠基準線", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 53, - "w": 8, - "h": 5 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "value_and_name", - "reduceOptions": { - "calcs": [ - "lastNotNull" + "id": 30, + "type": "stat", + "title": "Anomaly 觸發次數", + "description": "deny 累積超過門栖,自動觸發 _on_anomaly callback 的次數。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 38, + "w": 6, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 1 + }, + { + "color": "red", + "value": 3 + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(policy_anomaly_triggered_total{job=\"agent-governance-demo\"}) or vector(0)", + "legendFormat": "anomaly triggers", + "refId": "A" + } ] }, - "mappings": [ - { - "type": "value", - "options": { - "0": { - "text": "FAIL", - "color": "red" - }, - "1": { - "text": "PASS", - "color": "green" + { + "id": 31, + "type": "bargauge", + "title": "Anomaly 觸發 by Tool × Role", + "description": "哪個 tool + role 組合累積觸發最多次。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 6, + "y": 38, + "w": 10, + "h": 4 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "orange" } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (tool, role) (policy_anomaly_triggered_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{tool}} / {{role}}", + "refId": "A" } - } - ] - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "red", - "value": null - }, - { - "color": "green", - "value": 1 - } - ] - } + ] }, - "overrides": [] - }, - "targets": [ { - "expr": "opa_test_result{job=\"agent-governance-demo\", stage=\"baseline\"}", - "legendFormat": "baseline", - "refId": "A" - } - ] - }, - { - "id": 15, - "type": "stat", - "title": "【D3 ③】After Patch — 預期紅燈", - "description": "套用測試 patch 後,預期紅燈", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 8, - "y": 53, - "w": 8, - "h": 5 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "value_and_name", - "reduceOptions": { - "calcs": [ - "lastNotNull" + "id": 32, + "type": "timeseries", + "title": "Deny 累積速率(訊號來源)", + "description": "rate(tool_gate_blocked_total[1m]) by tool+role。迷い峰即是 anomaly 觸發點。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 42, + "w": 24, + "h": 6 + }, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "fieldConfig": { + "defaults": { + "unit": "reqps", + "custom": { + "lineWidth": 2, + "fillOpacity": 15 + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (tool, role) (rate(tool_gate_blocked_total{job=\"agent-governance-demo\"}[1m]))", + "legendFormat": "{{tool}} / {{role}}", + "refId": "A" + } ] }, - "mappings": [ - { - "type": "value", - "options": { - "0": { - "text": "FAIL", - "color": "red" - }, - "1": { - "text": "PASS", - "color": "green" - } + { + "id": 40, + "type": "stat", + "title": "Patch 提案次數", + "description": "LLM 呼叫 propose_policy_patch 的累積次數。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 48, + "w": 6, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] } - } - ] - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "red", - "value": null + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "blue" }, - { - "color": "green", - "value": 1 + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] } - ] - } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(policy_patch_proposed_total{job=\"agent-governance-demo\"}) or vector(0)", + "legendFormat": "proposed", + "refId": "A" + } + ] }, - "overrides": [] - }, - "targets": [ { - "expr": "opa_test_result{job=\"agent-governance-demo\", stage=\"after_patch\"}", - "legendFormat": "after_patch", - "refId": "A" - } - ] - }, - { - "id": 16, - "type": "stat", - "title": "【D3 ④】After Fix — 預期綠燈(CI 核准)", - "description": "修正 rego 後,預期綠燈 — CI 可 merge", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 16, - "y": 53, - "w": 8, - "h": 5 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "value_and_name", - "reduceOptions": { - "calcs": [ - "lastNotNull" + "id": 41, + "type": "stat", + "title": "Patch 採納(Human 核准)", + "description": "人類審核後按 y 採納的次數。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 6, + "y": 48, + "w": 6, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "green" + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(policy_patch_accepted_total{job=\"agent-governance-demo\"}) or vector(0)", + "legendFormat": "accepted", + "refId": "A" + } ] }, - "mappings": [ - { - "type": "value", - "options": { - "0": { - "text": "FAIL", - "color": "red" + { + "id": 42, + "type": "stat", + "title": "Patch 拒絕(Human 駁回)", + "description": "人類審核後按 N 拒絕的次數。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 12, + "y": 48, + "w": 6, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "red" }, - "1": { - "text": "PASS", - "color": "green" + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + } + ] } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(policy_patch_rejected_total{job=\"agent-governance-demo\"}) or vector(0)", + "legendFormat": "rejected", + "refId": "A" } - } - ] - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "red", - "value": null - }, - { - "color": "green", - "value": 1 + ] + }, + { + "id": 43, + "type": "stat", + "title": "Patch 採納率", + "description": "accepted / (accepted + rejected)。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 18, + "y": 48, + "w": 6, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "percentunit", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 0.5 + }, + { + "color": "green", + "value": 0.8 + } + ] } - ] - } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(policy_patch_accepted_total{job=\"agent-governance-demo\"}) / clamp_min((sum(policy_patch_accepted_total{job=\"agent-governance-demo\"}) + sum(policy_patch_rejected_total{job=\"agent-governance-demo\"})), 1)", + "legendFormat": "acceptance rate", + "refId": "A" + } + ] }, - "overrides": [] - }, - "targets": [ { - "expr": "opa_test_result{job=\"agent-governance-demo\", stage=\"after_fix\"}", - "legendFormat": "after_fix", - "refId": "A" - } - ] - }, - { - "id": 600, - "type": "row", - "title": "【Demo 3】Anomaly Detection 訊號", - "collapsed": false, - "gridPos": { - "x": 0, - "y": 65, - "w": 24, - "h": 1 - } - }, - { - "id": 30, - "type": "stat", - "title": "【D3 ②】Anomaly 觸發次數", - "description": "deny 累積超過門栖,自動觸發 _on_anomaly callback 的次數。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 66, - "w": 6, - "h": 4 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "orange", - "value": 1 + "id": 14, + "type": "stat", + "title": "Baseline — OPA Test 全綠基準線", + "description": "Demo 開始前 OPA test 全綠基準線", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 52, + "w": 8, + "h": 5 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "value_and_name", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] }, - { - "color": "red", - "value": 3 - } - ] - } + "mappings": [ + { + "type": "value", + "options": { + "1": { + "text": "PASS ✓", + "color": "green", + "index": 0 + }, + "0": { + "text": "FAIL ✗", + "color": "red", + "index": 1 + } + } + }, + { + "type": "special", + "options": { + "match": "null", + "result": { + "text": "未執行", + "color": "gray", + "index": 2 + } + } + } + ] + }, + "overrides": [] + }, + "targets": [ + { + "expr": "opa_test_result{job=\"agent-governance-demo\", stage=\"baseline\"}", + "legendFormat": "baseline", + "refId": "A" + } + ] }, - "overrides": [] - }, - "targets": [ { - "expr": "sum(policy_anomaly_triggered_total{job=\"agent-governance-demo\"}) or vector(0)", - "legendFormat": "anomaly triggers", - "refId": "A" - } - ] - }, - { - "id": 31, - "type": "bargauge", - "title": "【D3 ②】Anomaly 觸發 by Tool × Role", - "description": "哪個 tool + role 組合累積觸發最多次。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 6, - "y": 66, - "w": 10, - "h": 4 - }, - "options": { - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" + "id": 15, + "type": "stat", + "title": "After Patch — 預期紅燈", + "description": "套用測試 patch 後,預期紅燈", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 8, + "y": 52, + "w": 8, + "h": 5 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "value_and_name", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + }, + "mappings": [ + { + "type": "value", + "options": { + "1": { + "text": "PASS ✓", + "color": "green", + "index": 0 + }, + "0": { + "text": "FAIL ✗", + "color": "red", + "index": 1 + } + } + }, + { + "type": "special", + "options": { + "match": "null", + "result": { + "text": "未執行", + "color": "gray", + "index": 2 + } + } + } + ] + }, + "overrides": [] + }, + "targets": [ + { + "expr": "opa_test_result{job=\"agent-governance-demo\", stage=\"after_patch\"}", + "legendFormat": "after_patch", + "refId": "A" + } ] }, - "displayMode": "gradient", - "valueMode": "color" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "orange" - } - }, - "overrides": [] - }, - "targets": [ { - "expr": "sum by (tool, role) (policy_anomaly_triggered_total{job=\"agent-governance-demo\"})", - "legendFormat": "{{tool}} / {{role}}", - "refId": "A" - } - ] - }, - { - "id": 32, - "type": "timeseries", - "title": "【D3 ②】Deny 累積速率(訊號來源)", - "description": "rate(tool_gate_blocked_total[1m]) by tool+role。迷い峰即是 anomaly 觸發點。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 70, - "w": 24, - "h": 6 - }, - "options": { - "legend": { - "displayMode": "list", - "placement": "bottom" - }, - "tooltip": { - "mode": "multi" - } - }, - "fieldConfig": { - "defaults": { - "unit": "reqps", - "custom": { - "lineWidth": 2, - "fillOpacity": 15 - } + "id": 16, + "type": "stat", + "title": "After Fix — 預期綠燈(CI 核准)", + "description": "修正 rego 後,預期綠燈 — CI 可 merge", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 16, + "y": 52, + "w": 8, + "h": 5 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "value_and_name", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + }, + "mappings": [ + { + "type": "value", + "options": { + "1": { + "text": "PASS ✓", + "color": "green", + "index": 0 + }, + "0": { + "text": "FAIL ✗", + "color": "red", + "index": 1 + } + } + }, + { + "type": "special", + "options": { + "match": "null", + "result": { + "text": "未執行", + "color": "gray", + "index": 2 + } + } + } + ] + }, + "overrides": [] + }, + "targets": [ + { + "expr": "opa_test_result{job=\"agent-governance-demo\", stage=\"after_fix\"}", + "legendFormat": "after_fix", + "refId": "A" + } + ] }, - "overrides": [] - }, - "targets": [ { - "expr": "rate(tool_gate_blocked_total{job=\"agent-governance-demo\"}[1m])", - "legendFormat": "{{tool}} / {{role}}", - "refId": "A" - } - ] - }, - { - "id": 700, - "type": "row", - "title": "【Demo 3】Policy Patch 生命週期", - "collapsed": false, - "gridPos": { - "x": 0, - "y": 76, - "w": 24, - "h": 1 - } - }, - { - "id": 40, - "type": "stat", - "title": "【D3 ②】Patch 提案次數", - "description": "LLM 呼叫 propose_policy_patch 的累積次數。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 77, - "w": 6, - "h": 4 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "blue" + "id": 17, + "type": "state-timeline", + "title": "OPA Test 狀態歷史(PASS/FAIL 色帶)", + "datasource": { + "type": "prometheus", + "uid": "prometheus" }, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "blue", - "value": null + "gridPos": { + "x": 0, + "y": 57, + "w": 24, + "h": 7 + }, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + }, + "mergeValues": true, + "rowHeight": 0.9 + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + }, + "mappings": [ + { + "type": "value", + "options": { + "1": { + "text": "PASS ✓", + "color": "green", + "index": 0 + }, + "0": { + "text": "FAIL ✗", + "color": "red", + "index": 1 + } + } + }, + { + "type": "special", + "options": { + "match": "null", + "result": { + "text": "未執行", + "color": "gray", + "index": 2 + } + } + } + ], + "custom": { + "fillOpacity": 70 } - ] - } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "opa_test_result{job=\"agent-governance-demo\"}", + "legendFormat": "{{stage}}", + "refId": "A" + } + ] }, - "overrides": [] - }, - "targets": [ { - "expr": "sum(policy_patch_proposed_total{job=\"agent-governance-demo\"}) or vector(0)", - "legendFormat": "proposed", - "refId": "A" - } - ] - }, - { - "id": 41, - "type": "stat", - "title": "【D3 ③】Patch 採納(Human 核准)", - "description": "人類審核後按 y 採納的次數。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 6, - "y": 77, - "w": 6, - "h": 4 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "green" + "id": 50, + "type": "bargauge", + "title": "OPA Test 執行次數 by Stage", + "description": "每個 stage 被跟成功執行了幾次 opa test。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" }, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null + "gridPos": { + "x": 0, + "y": 64, + "w": 8, + "h": 6 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "palette-classic" } - ] - } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (stage) (opa_test_run_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{stage}}", + "refId": "A" + } + ] }, - "overrides": [] - }, - "targets": [ { - "expr": "policy_patch_accepted_total{job=\"agent-governance-demo\"} or vector(0)", - "legendFormat": "accepted", - "refId": "A" - } - ] - }, - { - "id": 42, - "type": "stat", - "title": "【D3 ③】Patch 拒絕(Human 駁回)", - "description": "人類審核後按 N 拒絕的次數。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 12, - "y": 77, - "w": 6, - "h": 4 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "red" + "id": 51, + "type": "bargauge", + "title": "OPA Test 耗時(最後一次)by Stage", + "description": "opa test 最後一次执行的秒數,讓觀眾感受「CI 真的在跟」。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" }, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "red", - "value": null + "gridPos": { + "x": 8, + "y": 64, + "w": 8, + "h": 6 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "s", + "color": { + "mode": "palette-classic" } - ] - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "policy_patch_rejected_total{job=\"agent-governance-demo\"} or vector(0)", - "legendFormat": "rejected", - "refId": "A" - } - ] - }, - { - "id": 43, - "type": "stat", - "title": "【D3 ③】Patch 採納率", - "description": "accepted / (accepted + rejected)。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 18, - "y": 77, - "w": 6, - "h": 4 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (stage, result) (opa_test_duration_seconds{job=\"agent-governance-demo\"})", + "legendFormat": "{{stage}} ({{result}})", + "refId": "A" + } ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "percentunit", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "red", - "value": null - }, - { - "color": "orange", - "value": 0.5 - }, - { - "color": "green", - "value": 0.8 - } - ] - } }, - "overrides": [] - }, - "targets": [ { - "expr": "policy_patch_accepted_total{job=\"agent-governance-demo\"} / clamp_min((policy_patch_accepted_total{job=\"agent-governance-demo\"} + policy_patch_rejected_total{job=\"agent-governance-demo\"}), 1)", - "legendFormat": "acceptance rate", - "refId": "A" + "id": 52, + "type": "timeseries", + "title": "OPA Test 耗時歷史(紅燈→綠燈轉折)", + "description": "opa_test_duration_seconds 時間軸變化,可看出 after_patch(紅)到 after_fix(綠)的転折點。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 16, + "y": 64, + "w": 8, + "h": 6 + }, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "fieldConfig": { + "defaults": { + "unit": "s", + "custom": { + "lineWidth": 2, + "fillOpacity": 15 + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (stage) (opa_test_duration_seconds{job=\"agent-governance-demo\"})", + "legendFormat": "{{stage}}", + "refId": "A" + } + ] } ] }, { - "id": 800, + "id": 500, "type": "row", - "title": "【Demo 3】OPA Test 執行結果與耗時", + "title": "事後驗證 — Audit", "collapsed": false, "gridPos": { "x": 0, - "y": 81, + "y": 38, "w": 24, "h": 1 } }, { - "id": 50, - "type": "bargauge", - "title": "【D3 ③④】OPA Test 執行次數 by Stage", - "description": "每個 stage 被跟成功執行了幾次 opa test。", + "id": 20, + "type": "table", + "title": "Audit 明細 — 每筆決策完整脈絡", + "description": "tool_gate_audit_event:每筆各有唯一 request_id。可看出是 OPA 還是 fallback 跟哪一版 policy 決定、哪一個 caller 發出。", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "x": 0, - "y": 82, - "w": 8, - "h": 6 + "y": 39, + "w": 24, + "h": 8 }, "options": { - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] + "footer": { + "show": false }, - "displayMode": "gradient", - "valueMode": "color" + "sortBy": [ + { + "displayName": "ts", + "desc": true + } + ] }, "fieldConfig": { "defaults": { - "unit": "short", - "color": { - "mode": "palette-classic" - } + "unit": "short" }, - "overrides": [] + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "decision" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "mappings", + "value": [ + { + "type": "value", + "options": { + "allow": { + "color": "green", + "index": 0 + }, + "deny": { + "color": "red", + "index": 1 + }, + "require_approval": { + "color": "orange", + "index": 2 + } + } + } + ] + } + ] + } + ] }, "targets": [ { - "expr": "opa_test_run_total{job=\"agent-governance-demo\"}", - "legendFormat": "{{stage}}", - "refId": "A" + "expr": "tool_gate_audit_event{job=\"agent-governance-demo\"}", + "legendFormat": "", + "refId": "A", + "instant": true, + "format": "table" } - ] - }, - { - "id": 51, - "type": "bargauge", - "title": "【D3 ③④】OPA Test 耗時(最後一次)by Stage", - "description": "opa test 最後一次执行的秒數,讓觀眾感受「CI 真的在跟」。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 8, - "y": 82, - "w": 8, - "h": 6 - }, - "options": { - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] + ], + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "ts", + "tool", + "role", + "decision", + "caller", + "policy_version" + ] + } + } }, - "displayMode": "gradient", - "valueMode": "color" - }, - "fieldConfig": { - "defaults": { - "unit": "s", - "color": { - "mode": "palette-classic" + { + "id": "sortBy", + "options": { + "fields": [ + { + "displayName": "ts", + "desc": true + } + ] } }, - "overrides": [] - }, - "targets": [ { - "expr": "opa_test_duration_seconds{job=\"agent-governance-demo\"}", - "legendFormat": "{{stage}} ({{result}})", - "refId": "A" + "id": "limit", + "options": { + "limitCount": 20 + } } ] }, { - "id": 52, - "type": "timeseries", - "title": "【D3 ③→④】OPA Test 耗時歷史(紅燈→綠燈轉折)", - "description": "opa_test_duration_seconds 時間軸變化,可看出 after_patch(紅)到 after_fix(綠)的転折點。", + "id": 22, + "type": "piechart", + "title": "Audit 決策分布", + "description": "所有 audit 筆數按 decision 分布圓餅圖。", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { - "x": 16, - "y": 82, - "w": 8, - "h": 6 + "x": 0, + "y": 47, + "w": 12, + "h": 8 }, "options": { "legend": { - "displayMode": "list", - "placement": "bottom" + "displayMode": "table", + "placement": "right", + "values": [ + "percent", + "value" + ] }, + "pieType": "donut", "tooltip": { - "mode": "multi" + "mode": "single" } }, "fieldConfig": { "defaults": { - "unit": "s", - "custom": { - "lineWidth": 2, - "fillOpacity": 15 - } + "unit": "short" }, - "overrides": [] + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "allow" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "green" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "deny" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "red" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "require_approval" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "orange" + } + } + ] + } + ] }, "targets": [ { - "expr": "opa_test_duration_seconds{job=\"agent-governance-demo\"}", - "legendFormat": "{{stage}}", - "refId": "A" + "expr": "count by (decision) (tool_gate_audit_event{job=\"agent-governance-demo\"})", + "legendFormat": "{{decision}}", + "refId": "A", + "instant": true } ] }, { - "id": 17, - "type": "timeseries", - "title": "【D3】OPA Test 狀態歷史(1=PASS, 0=FAIL)", + "id": 23, + "type": "bargauge", + "title": "Audit 決策 by policy_version", + "description": "OPA 決定 vs fallback 各占幾筆,可看出是否有呼叫走到 OPA binary。", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { - "x": 0, - "y": 58, - "w": 24, - "h": 7 + "x": 12, + "y": 47, + "w": 12, + "h": 8 }, "options": { - "legend": { - "displayMode": "list", - "placement": "bottom" + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] }, - "tooltip": { - "mode": "multi" - } + "displayMode": "gradient", + "valueMode": "color" }, "fieldConfig": { "defaults": { "unit": "short", - "min": 0, - "max": 1, - "custom": { - "lineWidth": 2, - "fillOpacity": 20, - "drawStyle": "line", - "stacking": { - "mode": "none" - } - }, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "red", - "value": null - }, - { - "color": "green", - "value": 1 - } - ] + "color": { + "mode": "palette-classic" } }, "overrides": [] }, "targets": [ { - "expr": "opa_test_result{job=\"agent-governance-demo\"}", - "legendFormat": "{{stage}}", - "refId": "A" + "expr": "count by (policy_version) (tool_gate_audit_event{job=\"agent-governance-demo\"})", + "legendFormat": "{{policy_version}}", + "refId": "A", + "instant": true } ] } diff --git a/observability/dashboards/faq-bot-overview_v2.json b/observability/dashboards/faq-bot-overview_v2.json index 18ccec1..12724d2 100644 --- a/observability/dashboards/faq-bot-overview_v2.json +++ b/observability/dashboards/faq-bot-overview_v2.json @@ -620,5 +620,6 @@ "timezone": "", "title": "FAQ Bot — Overview (RAG + LLM)", "version": 3, - "weekStart": "" + "weekStart": "", + "uid": "faq-bot-overview-v2" } \ No newline at end of file diff --git a/observability/dashboards/faq/faq-bot-overview_v2.json b/observability/dashboards/faq/faq-bot-overview_v2.json new file mode 100644 index 0000000..12724d2 --- /dev/null +++ b/observability/dashboards/faq/faq-bot-overview_v2.json @@ -0,0 +1,625 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "id": 100, + "type": "row", + "title": "Request Overview", + "gridPos": { + "x": 0, + "y": 0, + "w": 24, + "h": 1 + }, + "collapsed": false, + "panels": [] + }, + { + "id": 1, + "type": "stat", + "title": "RPS (requests/sec)", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 0, + "y": 1, + "w": 6, + "h": 6 + }, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto" + }, + "fieldConfig": { + "defaults": { + "unit": "reqps" + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(rate(llm_requests_total[1m]))", + "legendFormat": "rps", + "refId": "A" + } + ] + }, + { + "id": 2, + "type": "timeseries", + "title": "Latency p50 / p95 (s) — $route", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 6, + "y": 1, + "w": 18, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "s" + }, + "overrides": [] + }, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + } + }, + "targets": [ + { + "expr": "histogram_quantile(0.5, sum by (le) (rate(llm_request_latency_seconds_bucket{route=\"$route\"}[5m])))", + "legendFormat": "p50", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.95, sum by (le) (rate(llm_request_latency_seconds_bucket{route=\"$route\"}[5m])))", + "legendFormat": "p95", + "refId": "B" + } + ] + }, + { + "id": 200, + "type": "row", + "title": "Cache & Cost", + "gridPos": { + "x": 0, + "y": 7, + "w": 24, + "h": 1 + }, + "collapsed": false, + "panels": [] + }, + { + "id": 3, + "type": "timeseries", + "title": "Cache Hit / Miss (per min) — $route", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 0, + "y": 8, + "w": 12, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "reqpm" + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (result) (rate(rag_cache_results_total{route=\"$route\"}[1m])) * 60", + "legendFormat": "{{result}}", + "refId": "A" + } + ], + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + } + } + }, + { + "id": 14, + "type": "stat", + "title": "Cache Hit Ratio (%) — $route", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 12, + "y": 8, + "w": 12, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "percent" + }, + "overrides": [] + }, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto" + }, + "targets": [ + { + "expr": "100 * sum(rate(rag_cache_results_total{route=\"$route\",result=\"hit\"}[5m])) / clamp_min(sum(rate(rag_cache_requests_total{route=\"$route\"}[5m])), 1)", + "legendFormat": "hit %", + "refId": "A" + } + ] + }, + { + "id": 4, + "type": "timeseries", + "title": "Cost Rate (USD/min) by model", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 0, + "y": 14, + "w": 12, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "currencyUSD" + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (model) (rate(llm_cost_total_usd_total[1m])) * 60", + "legendFormat": "{{model}}", + "refId": "A" + } + ], + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + } + } + }, + { + "id": 15, + "type": "stat", + "title": "Avg Cost / Request (USD)", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 12, + "y": 14, + "w": 12, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "currencyUSD" + }, + "overrides": [] + }, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto" + }, + "targets": [ + { + "expr": "sum(rate(llm_cost_total_usd_total[5m])) / clamp_min(sum(rate(llm_requests_total[5m])), 1)", + "legendFormat": "avg cost/req", + "refId": "A" + } + ] + }, + { + "id": 300, + "type": "row", + "title": "Tokens & Errors", + "gridPos": { + "x": 0, + "y": 20, + "w": 24, + "h": 1 + }, + "collapsed": false, + "panels": [] + }, + { + "id": 5, + "type": "timeseries", + "title": "Tokens/sec by kind & model", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 0, + "y": 21, + "w": 12, + "h": 6 + }, + "targets": [ + { + "expr": "sum by (kind, model) (rate(llm_tokens_total[1m]))", + "legendFormat": "{{kind}} {{model}}", + "refId": "A" + } + ], + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + } + } + }, + { + "id": 6, + "type": "timeseries", + "title": "Errors (5m increase) by stage", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 12, + "y": 21, + "w": 12, + "h": 6 + }, + "targets": [ + { + "expr": "sum by (stage) (increase(rag_errors_total[5m])) or vector(0)", + "legendFormat": "{{stage}}", + "refId": "A" + } + ], + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + } + } + }, + { + "id": 400, + "type": "row", + "title": "RAG Pipeline Latency", + "gridPos": { + "x": 0, + "y": 27, + "w": 24, + "h": 1 + }, + "collapsed": false, + "panels": [] + }, + { + "id": 7, + "type": "timeseries", + "title": "Embedding Latency p95 (s) by stage", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 0, + "y": 28, + "w": 8, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "s" + }, + "overrides": [] + }, + "targets": [ + { + "expr": "histogram_quantile(0.95, sum by (le, stage) (rate(rag_embedding_latency_seconds_bucket[5m])))", + "legendFormat": "{{stage}}", + "refId": "A" + } + ] + }, + { + "id": 8, + "type": "timeseries", + "title": "Retrieval Latency p95 (s)", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 8, + "y": 28, + "w": 8, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "s" + }, + "overrides": [] + }, + "targets": [ + { + "expr": "histogram_quantile(0.95, sum by (le) (rate(rag_retrieval_latency_seconds_bucket[5m])))", + "legendFormat": "retrieval", + "refId": "A" + } + ] + }, + { + "id": 9, + "type": "timeseries", + "title": "Rerank Latency p95 (s)", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 16, + "y": 28, + "w": 8, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "s" + }, + "overrides": [] + }, + "targets": [ + { + "expr": "histogram_quantile(0.95, sum by (le) (rate(rag_rerank_latency_seconds_bucket[5m])))", + "legendFormat": "rerank", + "refId": "A" + } + ] + }, + { + "id": 10, + "type": "timeseries", + "title": "LLM Latency p95 (s) by model — $model", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 0, + "y": 34, + "w": 24, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "s" + }, + "overrides": [] + }, + "targets": [ + { + "expr": "histogram_quantile(0.95, sum by (le, model) (rate(rag_llm_latency_seconds_bucket{model=~\"$model\"}[5m])))", + "legendFormat": "{{model}}", + "refId": "A" + } + ], + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + } + } + }, + { + "id": 500, + "type": "row", + "title": "Input Health", + "gridPos": { + "x": 0, + "y": 40, + "w": 24, + "h": 1 + }, + "collapsed": false, + "panels": [] + }, + { + "id": 11, + "type": "bargauge", + "title": "Rejected Inputs (total) by type", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 0, + "y": 41, + "w": 8, + "h": 6 + }, + "targets": [ + { + "expr": "sum by (type) (input_rejected_total)", + "legendFormat": "{{type}}", + "refId": "A" + } + ] + }, + { + "id": 12, + "type": "bargauge", + "title": "Rate Limited (total) by scope", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 8, + "y": 41, + "w": 8, + "h": 6 + }, + "targets": [ + { + "expr": "sum by (scope) (input_rate_limited_total) or vector(0)", + "legendFormat": "{{scope}}", + "refId": "A" + } + ] + }, + { + "id": 13, + "type": "stat", + "title": "Accepted Inputs (total)", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "x": 16, + "y": 41, + "w": 8, + "h": 6 + }, + "fieldConfig": { + "defaults": { + "unit": "reqpm" + }, + "overrides": [] + }, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto" + }, + "targets": [ + { + "expr": "sum(input_accepted_total)", + "legendFormat": "total accepted", + "refId": "A" + } + ] + } + ], + "refresh": "10s", + "schemaVersion": 39, + "style": "dark", + "tags": [ + "faq-bot", + "rag", + "observability" + ], + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": "Prometheus", + "value": "prometheus" + }, + "hide": 0, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "type": "datasource" + }, + { + "name": "route", + "type": "query", + "hide": 0, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(llm_request_latency_seconds_bucket, route)", + "query": { + "query": "label_values(llm_request_latency_seconds_bucket, route)", + "refId": "A" + }, + "refresh": 2, + "includeAll": false, + "multi": false, + "sort": 1, + "current": { + "selected": true, + "text": "/ask", + "value": "/ask" + } + }, + { + "name": "model", + "type": "query", + "hide": 0, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(rag_llm_latency_seconds_bucket, model)", + "query": { + "query": "label_values(rag_llm_latency_seconds_bucket, model)", + "refId": "B" + }, + "refresh": 2, + "includeAll": true, + "allValue": ".*", + "multi": true, + "sort": 1, + "current": { + "selected": true, + "text": "All", + "value": ".*" + } + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "FAQ Bot — Overview (RAG + LLM)", + "version": 3, + "weekStart": "", + "uid": "faq-bot-overview-v2" +} \ No newline at end of file diff --git a/observability/dashboards/governance/agent-governance.json b/observability/dashboards/governance/agent-governance.json new file mode 100644 index 0000000..0a3cfea --- /dev/null +++ b/observability/dashboards/governance/agent-governance.json @@ -0,0 +1,2076 @@ +{ + "title": "Agent Governance — Policy Gate", + "description": "Agent Governance Policy Gate — demo 環境示意數據,非生產統計", + "uid": "agent-governance-v1", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "links": [], + "liveNow": false, + "schemaVersion": 39, + "tags": [ + "governance", + "policy-gate", + "opa" + ], + "templating": { + "list": [] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "refresh": "5s", + "panels": [ + { + "id": 999, + "type": "text", + "title": "", + "gridPos": { + "x": 0, + "y": 0, + "w": 24, + "h": 2 + }, + "options": { + "mode": "markdown", + "content": "⚠️ **示意數據(illustrative)** — 本 dashboard 來自 demo 環境,數據用於說明治理機制,非生產統計。" + }, + "transparent": false + }, + { + "id": 100, + "type": "row", + "title": "總覽 — Policy Gate", + "collapsed": false, + "gridPos": { + "x": 0, + "y": 2, + "w": 24, + "h": 1 + } + }, + { + "id": 1, + "type": "stat", + "title": "Total ALLOW", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 3, + "w": 4, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "green" + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(tool_gate_allow_total{job=\"agent-governance-demo\"})", + "legendFormat": "allow", + "refId": "A" + } + ] + }, + { + "id": 2, + "type": "stat", + "title": "Total BLOCKED", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 4, + "y": 3, + "w": 4, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "red" + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(tool_gate_blocked_total{job=\"agent-governance-demo\"})", + "legendFormat": "blocked", + "refId": "A" + } + ] + }, + { + "id": 3, + "type": "stat", + "title": "Total REQUIRE_APPROVAL", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 8, + "y": 3, + "w": 4, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "orange" + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "orange", + "value": null + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(tool_gate_approval_total{job=\"agent-governance-demo\"})", + "legendFormat": "approval", + "refId": "A" + } + ] + }, + { + "id": 4, + "type": "stat", + "title": "Block Rate", + "description": "BLOCKED / (ALLOW + BLOCKED + APPROVAL)", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 12, + "y": 3, + "w": 4, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "percentunit", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 0.3 + }, + { + "color": "red", + "value": 0.6 + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(tool_gate_blocked_total{job=\"agent-governance-demo\"}) / (sum(tool_gate_allow_total{job=\"agent-governance-demo\"}) + sum(tool_gate_blocked_total{job=\"agent-governance-demo\"}) + sum(tool_gate_approval_total{job=\"agent-governance-demo\"}))", + "legendFormat": "block rate", + "refId": "A" + } + ] + }, + { + "id": 60, + "type": "stat", + "title": "最後 push 距今", + "description": "資料新鮮度:demo 跑了但資料沒進來時這顆先變紅。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 16, + "y": 3, + "w": 4, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "s", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 30 + }, + { + "color": "red", + "value": 60 + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "time() - max(push_time_seconds{job=\"agent-governance-demo\"})", + "legendFormat": "seconds ago", + "refId": "A" + } + ] + }, + { + "id": 61, + "type": "stat", + "title": "OPA 決策延遲 p99", + "description": "Gate 多增加的決策延遲,sub-millisecond 量級為正常。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 20, + "y": 3, + "w": 4, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "s", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 0.01 + }, + { + "color": "red", + "value": 0.1 + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket{job=\"opa\", handler=\"v1/data\"}[5m])))", + "legendFormat": "p99 latency", + "refId": "A" + } + ] + }, + { + "id": 5, + "type": "timeseries", + "title": "Gate 決策趨勢(累計)", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 7, + "w": 24, + "h": 7 + }, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "custom": { + "lineWidth": 2, + "fillOpacity": 10 + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "allow" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "green" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "blocked" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "red" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "approval" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "orange" + } + } + ] + } + ] + }, + "targets": [ + { + "expr": "sum(tool_gate_allow_total{job=\"agent-governance-demo\"})", + "legendFormat": "allow", + "refId": "A" + }, + { + "expr": "sum(tool_gate_blocked_total{job=\"agent-governance-demo\"})", + "legendFormat": "blocked", + "refId": "B" + }, + { + "expr": "sum(tool_gate_approval_total{job=\"agent-governance-demo\"})", + "legendFormat": "approval", + "refId": "C" + } + ] + }, + { + "id": 200, + "type": "row", + "title": "行為治理(Demo 1)— Agent 能做什麼", + "collapsed": false, + "gridPos": { + "x": 0, + "y": 14, + "w": 24, + "h": 1 + } + }, + { + "id": 6, + "type": "bargauge", + "title": "Allow by Tool", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 15, + "w": 8, + "h": 7 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "green" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (tool) (tool_gate_allow_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{tool}}", + "refId": "A" + } + ] + }, + { + "id": 7, + "type": "bargauge", + "title": "Blocked by Tool", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 8, + "y": 15, + "w": 8, + "h": 7 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "red" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (tool) (tool_gate_blocked_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{tool}}", + "refId": "A" + } + ] + }, + { + "id": 62, + "type": "bargauge", + "title": "Blocked by Reason", + "description": "哪類原因最常被擋,是治理收束段的核心重點。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 16, + "y": 15, + "w": 8, + "h": 7 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "basic", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "red" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (reason) (tool_gate_blocked_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{reason}}", + "refId": "A" + } + ] + }, + { + "id": 9, + "type": "bargauge", + "title": "Allow by Role", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 22, + "w": 8, + "h": 7 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "green" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (role) (tool_gate_allow_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{role}}", + "refId": "A" + } + ] + }, + { + "id": 10, + "type": "bargauge", + "title": "Blocked by Role", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 8, + "y": 22, + "w": 8, + "h": 7 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "red" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (role) (tool_gate_blocked_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{role}}", + "refId": "A" + } + ] + }, + { + "id": 12, + "type": "table", + "title": "BLOCKED — Tool × Role", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 16, + "y": 22, + "w": 8, + "h": 7 + }, + "options": { + "footer": { + "show": false + }, + "sortBy": [ + { + "displayName": "Value", + "desc": true + } + ] + }, + "fieldConfig": { + "defaults": { + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + } + ] + } + } + ] + } + ] + }, + "targets": [ + { + "expr": "sum by (tool, role) (tool_gate_blocked_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{tool}} / {{role}}", + "refId": "A", + "instant": true, + "format": "table" + } + ], + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "tool", + "role", + "Value" + ] + } + } + }, + { + "id": "sortBy", + "options": { + "fields": [ + { + "displayName": "Value", + "desc": true + } + ] + } + }, + { + "id": "limit", + "options": { + "limitCount": 20 + } + } + ] + }, + { + "id": 300, + "type": "row", + "title": "資料治理(Demo 2)— Agent 能查什麼", + "collapsed": false, + "gridPos": { + "x": 0, + "y": 29, + "w": 24, + "h": 1 + } + }, + { + "id": 8, + "type": "bargauge", + "title": "Approval by Tool", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 30, + "w": 8, + "h": 7 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "orange" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (tool) (tool_gate_approval_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{tool}}", + "refId": "A" + } + ] + }, + { + "id": 11, + "type": "bargauge", + "title": "Approval by Role", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 8, + "y": 30, + "w": 8, + "h": 7 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "orange" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (role) (tool_gate_approval_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{role}}", + "refId": "A" + } + ] + }, + { + "id": 13, + "type": "table", + "title": "REQUIRE_APPROVAL — Tool × Role", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 16, + "y": 30, + "w": 8, + "h": 7 + }, + "options": { + "footer": { + "show": false + }, + "sortBy": [ + { + "displayName": "Value", + "desc": true + } + ] + }, + "fieldConfig": { + "defaults": { + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "orange", + "value": null + } + ] + } + } + ] + } + ] + }, + "targets": [ + { + "expr": "sum by (tool, role) (tool_gate_approval_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{tool}} / {{role}}", + "refId": "A", + "instant": true, + "format": "table" + } + ], + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "tool", + "role", + "Value" + ] + } + } + }, + { + "id": "sortBy", + "options": { + "fields": [ + { + "displayName": "Value", + "desc": true + } + ] + } + }, + { + "id": "limit", + "options": { + "limitCount": 20 + } + } + ] + }, + { + "id": 400, + "type": "row", + "title": "規則治理(Demo 3)— 誰能改規則", + "collapsed": true, + "gridPos": { + "x": 0, + "y": 37, + "w": 24, + "h": 1 + }, + "panels": [ + { + "id": 30, + "type": "stat", + "title": "Anomaly 觸發次數", + "description": "deny 累積超過門栖,自動觸發 _on_anomaly callback 的次數。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 38, + "w": 6, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 1 + }, + { + "color": "red", + "value": 3 + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(policy_anomaly_triggered_total{job=\"agent-governance-demo\"}) or vector(0)", + "legendFormat": "anomaly triggers", + "refId": "A" + } + ] + }, + { + "id": 31, + "type": "bargauge", + "title": "Anomaly 觸發 by Tool × Role", + "description": "哪個 tool + role 組合累積觸發最多次。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 6, + "y": 38, + "w": 10, + "h": 4 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "orange" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (tool, role) (policy_anomaly_triggered_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{tool}} / {{role}}", + "refId": "A" + } + ] + }, + { + "id": 32, + "type": "timeseries", + "title": "Deny 累積速率(訊號來源)", + "description": "rate(tool_gate_blocked_total[1m]) by tool+role。迷い峰即是 anomaly 觸發點。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 42, + "w": 24, + "h": 6 + }, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "fieldConfig": { + "defaults": { + "unit": "reqps", + "custom": { + "lineWidth": 2, + "fillOpacity": 15 + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (tool, role) (rate(tool_gate_blocked_total{job=\"agent-governance-demo\"}[1m]))", + "legendFormat": "{{tool}} / {{role}}", + "refId": "A" + } + ] + }, + { + "id": 40, + "type": "stat", + "title": "Patch 提案次數", + "description": "LLM 呼叫 propose_policy_patch 的累積次數。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 48, + "w": 6, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "blue" + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(policy_patch_proposed_total{job=\"agent-governance-demo\"}) or vector(0)", + "legendFormat": "proposed", + "refId": "A" + } + ] + }, + { + "id": 41, + "type": "stat", + "title": "Patch 採納(Human 核准)", + "description": "人類審核後按 y 採納的次數。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 6, + "y": 48, + "w": 6, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "green" + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(policy_patch_accepted_total{job=\"agent-governance-demo\"}) or vector(0)", + "legendFormat": "accepted", + "refId": "A" + } + ] + }, + { + "id": 42, + "type": "stat", + "title": "Patch 拒絕(Human 駁回)", + "description": "人類審核後按 N 拒絕的次數。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 12, + "y": 48, + "w": 6, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "fixed", + "fixedColor": "red" + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(policy_patch_rejected_total{job=\"agent-governance-demo\"}) or vector(0)", + "legendFormat": "rejected", + "refId": "A" + } + ] + }, + { + "id": 43, + "type": "stat", + "title": "Patch 採納率", + "description": "accepted / (accepted + rejected)。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 18, + "y": 48, + "w": 6, + "h": 4 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "percentunit", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 0.5 + }, + { + "color": "green", + "value": 0.8 + } + ] + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum(policy_patch_accepted_total{job=\"agent-governance-demo\"}) / clamp_min((sum(policy_patch_accepted_total{job=\"agent-governance-demo\"}) + sum(policy_patch_rejected_total{job=\"agent-governance-demo\"})), 1)", + "legendFormat": "acceptance rate", + "refId": "A" + } + ] + }, + { + "id": 14, + "type": "stat", + "title": "Baseline — OPA Test 全綠基準線", + "description": "Demo 開始前 OPA test 全綠基準線", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 52, + "w": 8, + "h": 5 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "value_and_name", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + }, + "mappings": [ + { + "type": "value", + "options": { + "1": { + "text": "PASS ✓", + "color": "green", + "index": 0 + }, + "0": { + "text": "FAIL ✗", + "color": "red", + "index": 1 + } + } + }, + { + "type": "special", + "options": { + "match": "null", + "result": { + "text": "未執行", + "color": "gray", + "index": 2 + } + } + } + ] + }, + "overrides": [] + }, + "targets": [ + { + "expr": "opa_test_result{job=\"agent-governance-demo\", stage=\"baseline\"}", + "legendFormat": "baseline", + "refId": "A" + } + ] + }, + { + "id": 15, + "type": "stat", + "title": "After Patch — 預期紅燈", + "description": "套用測試 patch 後,預期紅燈", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 8, + "y": 52, + "w": 8, + "h": 5 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "value_and_name", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + }, + "mappings": [ + { + "type": "value", + "options": { + "1": { + "text": "PASS ✓", + "color": "green", + "index": 0 + }, + "0": { + "text": "FAIL ✗", + "color": "red", + "index": 1 + } + } + }, + { + "type": "special", + "options": { + "match": "null", + "result": { + "text": "未執行", + "color": "gray", + "index": 2 + } + } + } + ] + }, + "overrides": [] + }, + "targets": [ + { + "expr": "opa_test_result{job=\"agent-governance-demo\", stage=\"after_patch\"}", + "legendFormat": "after_patch", + "refId": "A" + } + ] + }, + { + "id": 16, + "type": "stat", + "title": "After Fix — 預期綠燈(CI 核准)", + "description": "修正 rego 後,預期綠燈 — CI 可 merge", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 16, + "y": 52, + "w": 8, + "h": 5 + }, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "textMode": "value_and_name", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + }, + "mappings": [ + { + "type": "value", + "options": { + "1": { + "text": "PASS ✓", + "color": "green", + "index": 0 + }, + "0": { + "text": "FAIL ✗", + "color": "red", + "index": 1 + } + } + }, + { + "type": "special", + "options": { + "match": "null", + "result": { + "text": "未執行", + "color": "gray", + "index": 2 + } + } + } + ] + }, + "overrides": [] + }, + "targets": [ + { + "expr": "opa_test_result{job=\"agent-governance-demo\", stage=\"after_fix\"}", + "legendFormat": "after_fix", + "refId": "A" + } + ] + }, + { + "id": 17, + "type": "state-timeline", + "title": "OPA Test 狀態歷史(PASS/FAIL 色帶)", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 57, + "w": 24, + "h": 7 + }, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + }, + "mergeValues": true, + "rowHeight": 0.9 + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 1 + } + ] + }, + "mappings": [ + { + "type": "value", + "options": { + "1": { + "text": "PASS ✓", + "color": "green", + "index": 0 + }, + "0": { + "text": "FAIL ✗", + "color": "red", + "index": 1 + } + } + }, + { + "type": "special", + "options": { + "match": "null", + "result": { + "text": "未執行", + "color": "gray", + "index": 2 + } + } + } + ], + "custom": { + "fillOpacity": 70 + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "opa_test_result{job=\"agent-governance-demo\"}", + "legendFormat": "{{stage}}", + "refId": "A" + } + ] + }, + { + "id": 50, + "type": "bargauge", + "title": "OPA Test 執行次數 by Stage", + "description": "每個 stage 被跟成功執行了幾次 opa test。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 64, + "w": 8, + "h": 6 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "palette-classic" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (stage) (opa_test_run_total{job=\"agent-governance-demo\"})", + "legendFormat": "{{stage}}", + "refId": "A" + } + ] + }, + { + "id": 51, + "type": "bargauge", + "title": "OPA Test 耗時(最後一次)by Stage", + "description": "opa test 最後一次执行的秒數,讓觀眾感受「CI 真的在跟」。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 8, + "y": 64, + "w": 8, + "h": 6 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "s", + "color": { + "mode": "palette-classic" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (stage, result) (opa_test_duration_seconds{job=\"agent-governance-demo\"})", + "legendFormat": "{{stage}} ({{result}})", + "refId": "A" + } + ] + }, + { + "id": 52, + "type": "timeseries", + "title": "OPA Test 耗時歷史(紅燈→綠燈轉折)", + "description": "opa_test_duration_seconds 時間軸變化,可看出 after_patch(紅)到 after_fix(綠)的転折點。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 16, + "y": 64, + "w": 8, + "h": 6 + }, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "fieldConfig": { + "defaults": { + "unit": "s", + "custom": { + "lineWidth": 2, + "fillOpacity": 15 + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "sum by (stage) (opa_test_duration_seconds{job=\"agent-governance-demo\"})", + "legendFormat": "{{stage}}", + "refId": "A" + } + ] + } + ] + }, + { + "id": 500, + "type": "row", + "title": "事後驗證 — Audit", + "collapsed": false, + "gridPos": { + "x": 0, + "y": 38, + "w": 24, + "h": 1 + } + }, + { + "id": 20, + "type": "table", + "title": "Audit 明細 — 每筆決策完整脈絡", + "description": "tool_gate_audit_event:每筆各有唯一 request_id。可看出是 OPA 還是 fallback 跟哪一版 policy 決定、哪一個 caller 發出。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 39, + "w": 24, + "h": 8 + }, + "options": { + "footer": { + "show": false + }, + "sortBy": [ + { + "displayName": "ts", + "desc": true + } + ] + }, + "fieldConfig": { + "defaults": { + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "decision" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "mappings", + "value": [ + { + "type": "value", + "options": { + "allow": { + "color": "green", + "index": 0 + }, + "deny": { + "color": "red", + "index": 1 + }, + "require_approval": { + "color": "orange", + "index": 2 + } + } + } + ] + } + ] + } + ] + }, + "targets": [ + { + "expr": "tool_gate_audit_event{job=\"agent-governance-demo\"}", + "legendFormat": "", + "refId": "A", + "instant": true, + "format": "table" + } + ], + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "ts", + "tool", + "role", + "decision", + "caller", + "policy_version" + ] + } + } + }, + { + "id": "sortBy", + "options": { + "fields": [ + { + "displayName": "ts", + "desc": true + } + ] + } + }, + { + "id": "limit", + "options": { + "limitCount": 20 + } + } + ] + }, + { + "id": 22, + "type": "piechart", + "title": "Audit 決策分布", + "description": "所有 audit 筆數按 decision 分布圓餅圖。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 0, + "y": 47, + "w": 12, + "h": 8 + }, + "options": { + "legend": { + "displayMode": "table", + "placement": "right", + "values": [ + "percent", + "value" + ] + }, + "pieType": "donut", + "tooltip": { + "mode": "single" + } + }, + "fieldConfig": { + "defaults": { + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "allow" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "green" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "deny" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "red" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "require_approval" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "orange" + } + } + ] + } + ] + }, + "targets": [ + { + "expr": "count by (decision) (tool_gate_audit_event{job=\"agent-governance-demo\"})", + "legendFormat": "{{decision}}", + "refId": "A", + "instant": true + } + ] + }, + { + "id": 23, + "type": "bargauge", + "title": "Audit 決策 by policy_version", + "description": "OPA 決定 vs fallback 各占幾筆,可看出是否有呼叫走到 OPA binary。", + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "x": 12, + "y": 47, + "w": 12, + "h": 8 + }, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "displayMode": "gradient", + "valueMode": "color" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "color": { + "mode": "palette-classic" + } + }, + "overrides": [] + }, + "targets": [ + { + "expr": "count by (policy_version) (tool_gate_audit_event{job=\"agent-governance-demo\"})", + "legendFormat": "{{policy_version}}", + "refId": "A", + "instant": true + } + ] + } + ], + "annotations": { + "list": [] + } +} \ No newline at end of file From b22ae277ae0fd95d12a878e179c6e5ec6e398883 Mon Sep 17 00:00:00 2001 From: hazel-shen Date: Sat, 4 Jul 2026 17:19:49 +0800 Subject: [PATCH 2/2] fix(dashboards): remove duplicate dashboard copies from subdirectories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit flat provider 會遞迴掃描,root 與 governance//faq/ 子目錄各存一份 同 uid 的 JSON 導致重複載入——先前 Grafana 出現 duplicate 的根因之一 (另一半是舊 volume 殘留,由 faq_metrics_reset.sh --grafana 處理)。 - 刪除 dashboards/governance/、dashboards/faq/(內容與 root 版本一致,已 diff 確認) - foldersFromFilesStructure 維持 false:flat 為有意識取捨, 上台導航少一層資料夾;dashboard uid 已釘死防撞 - dashboards-archive/(含 faq-bot-overview_v1)在掛載路徑外,不被載入 --- .../dashboards/faq/faq-bot-overview_v2.json | 625 ----- .../governance/agent-governance.json | 2076 ----------------- 2 files changed, 2701 deletions(-) delete mode 100644 observability/dashboards/faq/faq-bot-overview_v2.json delete mode 100644 observability/dashboards/governance/agent-governance.json diff --git a/observability/dashboards/faq/faq-bot-overview_v2.json b/observability/dashboards/faq/faq-bot-overview_v2.json deleted file mode 100644 index 12724d2..0000000 --- a/observability/dashboards/faq/faq-bot-overview_v2.json +++ /dev/null @@ -1,625 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "links": [], - "liveNow": false, - "panels": [ - { - "id": 100, - "type": "row", - "title": "Request Overview", - "gridPos": { - "x": 0, - "y": 0, - "w": 24, - "h": 1 - }, - "collapsed": false, - "panels": [] - }, - { - "id": 1, - "type": "stat", - "title": "RPS (requests/sec)", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "gridPos": { - "x": 0, - "y": 1, - "w": 6, - "h": 6 - }, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto" - }, - "fieldConfig": { - "defaults": { - "unit": "reqps" - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum(rate(llm_requests_total[1m]))", - "legendFormat": "rps", - "refId": "A" - } - ] - }, - { - "id": 2, - "type": "timeseries", - "title": "Latency p50 / p95 (s) — $route", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "gridPos": { - "x": 6, - "y": 1, - "w": 18, - "h": 6 - }, - "fieldConfig": { - "defaults": { - "unit": "s" - }, - "overrides": [] - }, - "options": { - "legend": { - "displayMode": "list", - "placement": "bottom" - } - }, - "targets": [ - { - "expr": "histogram_quantile(0.5, sum by (le) (rate(llm_request_latency_seconds_bucket{route=\"$route\"}[5m])))", - "legendFormat": "p50", - "refId": "A" - }, - { - "expr": "histogram_quantile(0.95, sum by (le) (rate(llm_request_latency_seconds_bucket{route=\"$route\"}[5m])))", - "legendFormat": "p95", - "refId": "B" - } - ] - }, - { - "id": 200, - "type": "row", - "title": "Cache & Cost", - "gridPos": { - "x": 0, - "y": 7, - "w": 24, - "h": 1 - }, - "collapsed": false, - "panels": [] - }, - { - "id": 3, - "type": "timeseries", - "title": "Cache Hit / Miss (per min) — $route", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "gridPos": { - "x": 0, - "y": 8, - "w": 12, - "h": 6 - }, - "fieldConfig": { - "defaults": { - "unit": "reqpm" - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum by (result) (rate(rag_cache_results_total{route=\"$route\"}[1m])) * 60", - "legendFormat": "{{result}}", - "refId": "A" - } - ], - "options": { - "legend": { - "displayMode": "list", - "placement": "bottom" - } - } - }, - { - "id": 14, - "type": "stat", - "title": "Cache Hit Ratio (%) — $route", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "gridPos": { - "x": 12, - "y": 8, - "w": 12, - "h": 6 - }, - "fieldConfig": { - "defaults": { - "unit": "percent" - }, - "overrides": [] - }, - "options": { - "colorMode": "value", - "graphMode": "none", - "justifyMode": "auto" - }, - "targets": [ - { - "expr": "100 * sum(rate(rag_cache_results_total{route=\"$route\",result=\"hit\"}[5m])) / clamp_min(sum(rate(rag_cache_requests_total{route=\"$route\"}[5m])), 1)", - "legendFormat": "hit %", - "refId": "A" - } - ] - }, - { - "id": 4, - "type": "timeseries", - "title": "Cost Rate (USD/min) by model", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "gridPos": { - "x": 0, - "y": 14, - "w": 12, - "h": 6 - }, - "fieldConfig": { - "defaults": { - "unit": "currencyUSD" - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum by (model) (rate(llm_cost_total_usd_total[1m])) * 60", - "legendFormat": "{{model}}", - "refId": "A" - } - ], - "options": { - "legend": { - "displayMode": "list", - "placement": "bottom" - } - } - }, - { - "id": 15, - "type": "stat", - "title": "Avg Cost / Request (USD)", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "gridPos": { - "x": 12, - "y": 14, - "w": 12, - "h": 6 - }, - "fieldConfig": { - "defaults": { - "unit": "currencyUSD" - }, - "overrides": [] - }, - "options": { - "colorMode": "value", - "graphMode": "none", - "justifyMode": "auto" - }, - "targets": [ - { - "expr": "sum(rate(llm_cost_total_usd_total[5m])) / clamp_min(sum(rate(llm_requests_total[5m])), 1)", - "legendFormat": "avg cost/req", - "refId": "A" - } - ] - }, - { - "id": 300, - "type": "row", - "title": "Tokens & Errors", - "gridPos": { - "x": 0, - "y": 20, - "w": 24, - "h": 1 - }, - "collapsed": false, - "panels": [] - }, - { - "id": 5, - "type": "timeseries", - "title": "Tokens/sec by kind & model", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "gridPos": { - "x": 0, - "y": 21, - "w": 12, - "h": 6 - }, - "targets": [ - { - "expr": "sum by (kind, model) (rate(llm_tokens_total[1m]))", - "legendFormat": "{{kind}} {{model}}", - "refId": "A" - } - ], - "options": { - "legend": { - "displayMode": "list", - "placement": "bottom" - } - } - }, - { - "id": 6, - "type": "timeseries", - "title": "Errors (5m increase) by stage", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "gridPos": { - "x": 12, - "y": 21, - "w": 12, - "h": 6 - }, - "targets": [ - { - "expr": "sum by (stage) (increase(rag_errors_total[5m])) or vector(0)", - "legendFormat": "{{stage}}", - "refId": "A" - } - ], - "options": { - "legend": { - "displayMode": "list", - "placement": "bottom" - } - } - }, - { - "id": 400, - "type": "row", - "title": "RAG Pipeline Latency", - "gridPos": { - "x": 0, - "y": 27, - "w": 24, - "h": 1 - }, - "collapsed": false, - "panels": [] - }, - { - "id": 7, - "type": "timeseries", - "title": "Embedding Latency p95 (s) by stage", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "gridPos": { - "x": 0, - "y": 28, - "w": 8, - "h": 6 - }, - "fieldConfig": { - "defaults": { - "unit": "s" - }, - "overrides": [] - }, - "targets": [ - { - "expr": "histogram_quantile(0.95, sum by (le, stage) (rate(rag_embedding_latency_seconds_bucket[5m])))", - "legendFormat": "{{stage}}", - "refId": "A" - } - ] - }, - { - "id": 8, - "type": "timeseries", - "title": "Retrieval Latency p95 (s)", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "gridPos": { - "x": 8, - "y": 28, - "w": 8, - "h": 6 - }, - "fieldConfig": { - "defaults": { - "unit": "s" - }, - "overrides": [] - }, - "targets": [ - { - "expr": "histogram_quantile(0.95, sum by (le) (rate(rag_retrieval_latency_seconds_bucket[5m])))", - "legendFormat": "retrieval", - "refId": "A" - } - ] - }, - { - "id": 9, - "type": "timeseries", - "title": "Rerank Latency p95 (s)", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "gridPos": { - "x": 16, - "y": 28, - "w": 8, - "h": 6 - }, - "fieldConfig": { - "defaults": { - "unit": "s" - }, - "overrides": [] - }, - "targets": [ - { - "expr": "histogram_quantile(0.95, sum by (le) (rate(rag_rerank_latency_seconds_bucket[5m])))", - "legendFormat": "rerank", - "refId": "A" - } - ] - }, - { - "id": 10, - "type": "timeseries", - "title": "LLM Latency p95 (s) by model — $model", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "gridPos": { - "x": 0, - "y": 34, - "w": 24, - "h": 6 - }, - "fieldConfig": { - "defaults": { - "unit": "s" - }, - "overrides": [] - }, - "targets": [ - { - "expr": "histogram_quantile(0.95, sum by (le, model) (rate(rag_llm_latency_seconds_bucket{model=~\"$model\"}[5m])))", - "legendFormat": "{{model}}", - "refId": "A" - } - ], - "options": { - "legend": { - "displayMode": "list", - "placement": "bottom" - } - } - }, - { - "id": 500, - "type": "row", - "title": "Input Health", - "gridPos": { - "x": 0, - "y": 40, - "w": 24, - "h": 1 - }, - "collapsed": false, - "panels": [] - }, - { - "id": 11, - "type": "bargauge", - "title": "Rejected Inputs (total) by type", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "gridPos": { - "x": 0, - "y": 41, - "w": 8, - "h": 6 - }, - "targets": [ - { - "expr": "sum by (type) (input_rejected_total)", - "legendFormat": "{{type}}", - "refId": "A" - } - ] - }, - { - "id": 12, - "type": "bargauge", - "title": "Rate Limited (total) by scope", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "gridPos": { - "x": 8, - "y": 41, - "w": 8, - "h": 6 - }, - "targets": [ - { - "expr": "sum by (scope) (input_rate_limited_total) or vector(0)", - "legendFormat": "{{scope}}", - "refId": "A" - } - ] - }, - { - "id": 13, - "type": "stat", - "title": "Accepted Inputs (total)", - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "gridPos": { - "x": 16, - "y": 41, - "w": 8, - "h": 6 - }, - "fieldConfig": { - "defaults": { - "unit": "reqpm" - }, - "overrides": [] - }, - "options": { - "colorMode": "value", - "graphMode": "none", - "justifyMode": "auto" - }, - "targets": [ - { - "expr": "sum(input_accepted_total)", - "legendFormat": "total accepted", - "refId": "A" - } - ] - } - ], - "refresh": "10s", - "schemaVersion": 39, - "style": "dark", - "tags": [ - "faq-bot", - "rag", - "observability" - ], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": "Prometheus", - "value": "prometheus" - }, - "hide": 0, - "name": "DS_PROMETHEUS", - "options": [], - "query": "prometheus", - "type": "datasource" - }, - { - "name": "route", - "type": "query", - "hide": 0, - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "definition": "label_values(llm_request_latency_seconds_bucket, route)", - "query": { - "query": "label_values(llm_request_latency_seconds_bucket, route)", - "refId": "A" - }, - "refresh": 2, - "includeAll": false, - "multi": false, - "sort": 1, - "current": { - "selected": true, - "text": "/ask", - "value": "/ask" - } - }, - { - "name": "model", - "type": "query", - "hide": 0, - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "definition": "label_values(rag_llm_latency_seconds_bucket, model)", - "query": { - "query": "label_values(rag_llm_latency_seconds_bucket, model)", - "refId": "B" - }, - "refresh": 2, - "includeAll": true, - "allValue": ".*", - "multi": true, - "sort": 1, - "current": { - "selected": true, - "text": "All", - "value": ".*" - } - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "FAQ Bot — Overview (RAG + LLM)", - "version": 3, - "weekStart": "", - "uid": "faq-bot-overview-v2" -} \ No newline at end of file diff --git a/observability/dashboards/governance/agent-governance.json b/observability/dashboards/governance/agent-governance.json deleted file mode 100644 index 0a3cfea..0000000 --- a/observability/dashboards/governance/agent-governance.json +++ /dev/null @@ -1,2076 +0,0 @@ -{ - "title": "Agent Governance — Policy Gate", - "description": "Agent Governance Policy Gate — demo 環境示意數據,非生產統計", - "uid": "agent-governance-v1", - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "links": [], - "liveNow": false, - "schemaVersion": 39, - "tags": [ - "governance", - "policy-gate", - "opa" - ], - "templating": { - "list": [] - }, - "time": { - "from": "now-15m", - "to": "now" - }, - "timepicker": {}, - "timezone": "browser", - "refresh": "5s", - "panels": [ - { - "id": 999, - "type": "text", - "title": "", - "gridPos": { - "x": 0, - "y": 0, - "w": 24, - "h": 2 - }, - "options": { - "mode": "markdown", - "content": "⚠️ **示意數據(illustrative)** — 本 dashboard 來自 demo 環境,數據用於說明治理機制,非生產統計。" - }, - "transparent": false - }, - { - "id": 100, - "type": "row", - "title": "總覽 — Policy Gate", - "collapsed": false, - "gridPos": { - "x": 0, - "y": 2, - "w": 24, - "h": 1 - } - }, - { - "id": 1, - "type": "stat", - "title": "Total ALLOW", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 3, - "w": 4, - "h": 4 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "green" - }, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum(tool_gate_allow_total{job=\"agent-governance-demo\"})", - "legendFormat": "allow", - "refId": "A" - } - ] - }, - { - "id": 2, - "type": "stat", - "title": "Total BLOCKED", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 4, - "y": 3, - "w": 4, - "h": 4 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "red" - }, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "red", - "value": null - } - ] - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum(tool_gate_blocked_total{job=\"agent-governance-demo\"})", - "legendFormat": "blocked", - "refId": "A" - } - ] - }, - { - "id": 3, - "type": "stat", - "title": "Total REQUIRE_APPROVAL", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 8, - "y": 3, - "w": 4, - "h": 4 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "orange" - }, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "orange", - "value": null - } - ] - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum(tool_gate_approval_total{job=\"agent-governance-demo\"})", - "legendFormat": "approval", - "refId": "A" - } - ] - }, - { - "id": 4, - "type": "stat", - "title": "Block Rate", - "description": "BLOCKED / (ALLOW + BLOCKED + APPROVAL)", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 12, - "y": 3, - "w": 4, - "h": 4 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "percentunit", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "orange", - "value": 0.3 - }, - { - "color": "red", - "value": 0.6 - } - ] - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum(tool_gate_blocked_total{job=\"agent-governance-demo\"}) / (sum(tool_gate_allow_total{job=\"agent-governance-demo\"}) + sum(tool_gate_blocked_total{job=\"agent-governance-demo\"}) + sum(tool_gate_approval_total{job=\"agent-governance-demo\"}))", - "legendFormat": "block rate", - "refId": "A" - } - ] - }, - { - "id": 60, - "type": "stat", - "title": "最後 push 距今", - "description": "資料新鮮度:demo 跑了但資料沒進來時這顆先變紅。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 16, - "y": 3, - "w": 4, - "h": 4 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "s", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "orange", - "value": 30 - }, - { - "color": "red", - "value": 60 - } - ] - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "time() - max(push_time_seconds{job=\"agent-governance-demo\"})", - "legendFormat": "seconds ago", - "refId": "A" - } - ] - }, - { - "id": 61, - "type": "stat", - "title": "OPA 決策延遲 p99", - "description": "Gate 多增加的決策延遲,sub-millisecond 量級為正常。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 20, - "y": 3, - "w": 4, - "h": 4 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "s", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "orange", - "value": 0.01 - }, - { - "color": "red", - "value": 0.1 - } - ] - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket{job=\"opa\", handler=\"v1/data\"}[5m])))", - "legendFormat": "p99 latency", - "refId": "A" - } - ] - }, - { - "id": 5, - "type": "timeseries", - "title": "Gate 決策趨勢(累計)", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 7, - "w": 24, - "h": 7 - }, - "options": { - "legend": { - "displayMode": "list", - "placement": "bottom" - }, - "tooltip": { - "mode": "multi" - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "custom": { - "lineWidth": 2, - "fillOpacity": 10 - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "allow" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "green" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "blocked" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "red" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "approval" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "orange" - } - } - ] - } - ] - }, - "targets": [ - { - "expr": "sum(tool_gate_allow_total{job=\"agent-governance-demo\"})", - "legendFormat": "allow", - "refId": "A" - }, - { - "expr": "sum(tool_gate_blocked_total{job=\"agent-governance-demo\"})", - "legendFormat": "blocked", - "refId": "B" - }, - { - "expr": "sum(tool_gate_approval_total{job=\"agent-governance-demo\"})", - "legendFormat": "approval", - "refId": "C" - } - ] - }, - { - "id": 200, - "type": "row", - "title": "行為治理(Demo 1)— Agent 能做什麼", - "collapsed": false, - "gridPos": { - "x": 0, - "y": 14, - "w": 24, - "h": 1 - } - }, - { - "id": 6, - "type": "bargauge", - "title": "Allow by Tool", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 15, - "w": 8, - "h": 7 - }, - "options": { - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "displayMode": "gradient", - "valueMode": "color" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "green" - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum by (tool) (tool_gate_allow_total{job=\"agent-governance-demo\"})", - "legendFormat": "{{tool}}", - "refId": "A" - } - ] - }, - { - "id": 7, - "type": "bargauge", - "title": "Blocked by Tool", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 8, - "y": 15, - "w": 8, - "h": 7 - }, - "options": { - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "displayMode": "gradient", - "valueMode": "color" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "red" - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum by (tool) (tool_gate_blocked_total{job=\"agent-governance-demo\"})", - "legendFormat": "{{tool}}", - "refId": "A" - } - ] - }, - { - "id": 62, - "type": "bargauge", - "title": "Blocked by Reason", - "description": "哪類原因最常被擋,是治理收束段的核心重點。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 16, - "y": 15, - "w": 8, - "h": 7 - }, - "options": { - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "displayMode": "basic", - "valueMode": "color" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "red" - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum by (reason) (tool_gate_blocked_total{job=\"agent-governance-demo\"})", - "legendFormat": "{{reason}}", - "refId": "A" - } - ] - }, - { - "id": 9, - "type": "bargauge", - "title": "Allow by Role", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 22, - "w": 8, - "h": 7 - }, - "options": { - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "displayMode": "gradient", - "valueMode": "color" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "green" - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum by (role) (tool_gate_allow_total{job=\"agent-governance-demo\"})", - "legendFormat": "{{role}}", - "refId": "A" - } - ] - }, - { - "id": 10, - "type": "bargauge", - "title": "Blocked by Role", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 8, - "y": 22, - "w": 8, - "h": 7 - }, - "options": { - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "displayMode": "gradient", - "valueMode": "color" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "red" - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum by (role) (tool_gate_blocked_total{job=\"agent-governance-demo\"})", - "legendFormat": "{{role}}", - "refId": "A" - } - ] - }, - { - "id": 12, - "type": "table", - "title": "BLOCKED — Tool × Role", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 16, - "y": 22, - "w": 8, - "h": 7 - }, - "options": { - "footer": { - "show": false - }, - "sortBy": [ - { - "displayName": "Value", - "desc": true - } - ] - }, - "fieldConfig": { - "defaults": { - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "red", - "value": null - } - ] - } - } - ] - } - ] - }, - "targets": [ - { - "expr": "sum by (tool, role) (tool_gate_blocked_total{job=\"agent-governance-demo\"})", - "legendFormat": "{{tool}} / {{role}}", - "refId": "A", - "instant": true, - "format": "table" - } - ], - "transformations": [ - { - "id": "filterFieldsByName", - "options": { - "include": { - "names": [ - "tool", - "role", - "Value" - ] - } - } - }, - { - "id": "sortBy", - "options": { - "fields": [ - { - "displayName": "Value", - "desc": true - } - ] - } - }, - { - "id": "limit", - "options": { - "limitCount": 20 - } - } - ] - }, - { - "id": 300, - "type": "row", - "title": "資料治理(Demo 2)— Agent 能查什麼", - "collapsed": false, - "gridPos": { - "x": 0, - "y": 29, - "w": 24, - "h": 1 - } - }, - { - "id": 8, - "type": "bargauge", - "title": "Approval by Tool", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 30, - "w": 8, - "h": 7 - }, - "options": { - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "displayMode": "gradient", - "valueMode": "color" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "orange" - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum by (tool) (tool_gate_approval_total{job=\"agent-governance-demo\"})", - "legendFormat": "{{tool}}", - "refId": "A" - } - ] - }, - { - "id": 11, - "type": "bargauge", - "title": "Approval by Role", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 8, - "y": 30, - "w": 8, - "h": 7 - }, - "options": { - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "displayMode": "gradient", - "valueMode": "color" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "orange" - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum by (role) (tool_gate_approval_total{job=\"agent-governance-demo\"})", - "legendFormat": "{{role}}", - "refId": "A" - } - ] - }, - { - "id": 13, - "type": "table", - "title": "REQUIRE_APPROVAL — Tool × Role", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 16, - "y": 30, - "w": 8, - "h": 7 - }, - "options": { - "footer": { - "show": false - }, - "sortBy": [ - { - "displayName": "Value", - "desc": true - } - ] - }, - "fieldConfig": { - "defaults": { - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background" - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "orange", - "value": null - } - ] - } - } - ] - } - ] - }, - "targets": [ - { - "expr": "sum by (tool, role) (tool_gate_approval_total{job=\"agent-governance-demo\"})", - "legendFormat": "{{tool}} / {{role}}", - "refId": "A", - "instant": true, - "format": "table" - } - ], - "transformations": [ - { - "id": "filterFieldsByName", - "options": { - "include": { - "names": [ - "tool", - "role", - "Value" - ] - } - } - }, - { - "id": "sortBy", - "options": { - "fields": [ - { - "displayName": "Value", - "desc": true - } - ] - } - }, - { - "id": "limit", - "options": { - "limitCount": 20 - } - } - ] - }, - { - "id": 400, - "type": "row", - "title": "規則治理(Demo 3)— 誰能改規則", - "collapsed": true, - "gridPos": { - "x": 0, - "y": 37, - "w": 24, - "h": 1 - }, - "panels": [ - { - "id": 30, - "type": "stat", - "title": "Anomaly 觸發次數", - "description": "deny 累積超過門栖,自動觸發 _on_anomaly callback 的次數。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 38, - "w": 6, - "h": 4 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "orange", - "value": 1 - }, - { - "color": "red", - "value": 3 - } - ] - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum(policy_anomaly_triggered_total{job=\"agent-governance-demo\"}) or vector(0)", - "legendFormat": "anomaly triggers", - "refId": "A" - } - ] - }, - { - "id": 31, - "type": "bargauge", - "title": "Anomaly 觸發 by Tool × Role", - "description": "哪個 tool + role 組合累積觸發最多次。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 6, - "y": 38, - "w": 10, - "h": 4 - }, - "options": { - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "displayMode": "gradient", - "valueMode": "color" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "orange" - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum by (tool, role) (policy_anomaly_triggered_total{job=\"agent-governance-demo\"})", - "legendFormat": "{{tool}} / {{role}}", - "refId": "A" - } - ] - }, - { - "id": 32, - "type": "timeseries", - "title": "Deny 累積速率(訊號來源)", - "description": "rate(tool_gate_blocked_total[1m]) by tool+role。迷い峰即是 anomaly 觸發點。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 42, - "w": 24, - "h": 6 - }, - "options": { - "legend": { - "displayMode": "list", - "placement": "bottom" - }, - "tooltip": { - "mode": "multi" - } - }, - "fieldConfig": { - "defaults": { - "unit": "reqps", - "custom": { - "lineWidth": 2, - "fillOpacity": 15 - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum by (tool, role) (rate(tool_gate_blocked_total{job=\"agent-governance-demo\"}[1m]))", - "legendFormat": "{{tool}} / {{role}}", - "refId": "A" - } - ] - }, - { - "id": 40, - "type": "stat", - "title": "Patch 提案次數", - "description": "LLM 呼叫 propose_policy_patch 的累積次數。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 48, - "w": 6, - "h": 4 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "blue" - }, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "blue", - "value": null - } - ] - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum(policy_patch_proposed_total{job=\"agent-governance-demo\"}) or vector(0)", - "legendFormat": "proposed", - "refId": "A" - } - ] - }, - { - "id": 41, - "type": "stat", - "title": "Patch 採納(Human 核准)", - "description": "人類審核後按 y 採納的次數。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 6, - "y": 48, - "w": 6, - "h": 4 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "green" - }, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum(policy_patch_accepted_total{job=\"agent-governance-demo\"}) or vector(0)", - "legendFormat": "accepted", - "refId": "A" - } - ] - }, - { - "id": 42, - "type": "stat", - "title": "Patch 拒絕(Human 駁回)", - "description": "人類審核後按 N 拒絕的次數。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 12, - "y": 48, - "w": 6, - "h": 4 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "fixed", - "fixedColor": "red" - }, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "red", - "value": null - } - ] - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum(policy_patch_rejected_total{job=\"agent-governance-demo\"}) or vector(0)", - "legendFormat": "rejected", - "refId": "A" - } - ] - }, - { - "id": 43, - "type": "stat", - "title": "Patch 採納率", - "description": "accepted / (accepted + rejected)。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 18, - "y": 48, - "w": 6, - "h": 4 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "percentunit", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "red", - "value": null - }, - { - "color": "orange", - "value": 0.5 - }, - { - "color": "green", - "value": 0.8 - } - ] - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum(policy_patch_accepted_total{job=\"agent-governance-demo\"}) / clamp_min((sum(policy_patch_accepted_total{job=\"agent-governance-demo\"}) + sum(policy_patch_rejected_total{job=\"agent-governance-demo\"})), 1)", - "legendFormat": "acceptance rate", - "refId": "A" - } - ] - }, - { - "id": 14, - "type": "stat", - "title": "Baseline — OPA Test 全綠基準線", - "description": "Demo 開始前 OPA test 全綠基準線", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 52, - "w": 8, - "h": 5 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "value_and_name", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "red", - "value": null - }, - { - "color": "green", - "value": 1 - } - ] - }, - "mappings": [ - { - "type": "value", - "options": { - "1": { - "text": "PASS ✓", - "color": "green", - "index": 0 - }, - "0": { - "text": "FAIL ✗", - "color": "red", - "index": 1 - } - } - }, - { - "type": "special", - "options": { - "match": "null", - "result": { - "text": "未執行", - "color": "gray", - "index": 2 - } - } - } - ] - }, - "overrides": [] - }, - "targets": [ - { - "expr": "opa_test_result{job=\"agent-governance-demo\", stage=\"baseline\"}", - "legendFormat": "baseline", - "refId": "A" - } - ] - }, - { - "id": 15, - "type": "stat", - "title": "After Patch — 預期紅燈", - "description": "套用測試 patch 後,預期紅燈", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 8, - "y": 52, - "w": 8, - "h": 5 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "value_and_name", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "red", - "value": null - }, - { - "color": "green", - "value": 1 - } - ] - }, - "mappings": [ - { - "type": "value", - "options": { - "1": { - "text": "PASS ✓", - "color": "green", - "index": 0 - }, - "0": { - "text": "FAIL ✗", - "color": "red", - "index": 1 - } - } - }, - { - "type": "special", - "options": { - "match": "null", - "result": { - "text": "未執行", - "color": "gray", - "index": 2 - } - } - } - ] - }, - "overrides": [] - }, - "targets": [ - { - "expr": "opa_test_result{job=\"agent-governance-demo\", stage=\"after_patch\"}", - "legendFormat": "after_patch", - "refId": "A" - } - ] - }, - { - "id": 16, - "type": "stat", - "title": "After Fix — 預期綠燈(CI 核准)", - "description": "修正 rego 後,預期綠燈 — CI 可 merge", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 16, - "y": 52, - "w": 8, - "h": 5 - }, - "options": { - "colorMode": "background", - "graphMode": "none", - "justifyMode": "center", - "textMode": "value_and_name", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "red", - "value": null - }, - { - "color": "green", - "value": 1 - } - ] - }, - "mappings": [ - { - "type": "value", - "options": { - "1": { - "text": "PASS ✓", - "color": "green", - "index": 0 - }, - "0": { - "text": "FAIL ✗", - "color": "red", - "index": 1 - } - } - }, - { - "type": "special", - "options": { - "match": "null", - "result": { - "text": "未執行", - "color": "gray", - "index": 2 - } - } - } - ] - }, - "overrides": [] - }, - "targets": [ - { - "expr": "opa_test_result{job=\"agent-governance-demo\", stage=\"after_fix\"}", - "legendFormat": "after_fix", - "refId": "A" - } - ] - }, - { - "id": 17, - "type": "state-timeline", - "title": "OPA Test 狀態歷史(PASS/FAIL 色帶)", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 57, - "w": 24, - "h": 7 - }, - "options": { - "legend": { - "displayMode": "list", - "placement": "bottom" - }, - "tooltip": { - "mode": "multi" - }, - "mergeValues": true, - "rowHeight": 0.9 - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "red", - "value": null - }, - { - "color": "green", - "value": 1 - } - ] - }, - "mappings": [ - { - "type": "value", - "options": { - "1": { - "text": "PASS ✓", - "color": "green", - "index": 0 - }, - "0": { - "text": "FAIL ✗", - "color": "red", - "index": 1 - } - } - }, - { - "type": "special", - "options": { - "match": "null", - "result": { - "text": "未執行", - "color": "gray", - "index": 2 - } - } - } - ], - "custom": { - "fillOpacity": 70 - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "opa_test_result{job=\"agent-governance-demo\"}", - "legendFormat": "{{stage}}", - "refId": "A" - } - ] - }, - { - "id": 50, - "type": "bargauge", - "title": "OPA Test 執行次數 by Stage", - "description": "每個 stage 被跟成功執行了幾次 opa test。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 64, - "w": 8, - "h": 6 - }, - "options": { - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "displayMode": "gradient", - "valueMode": "color" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "palette-classic" - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum by (stage) (opa_test_run_total{job=\"agent-governance-demo\"})", - "legendFormat": "{{stage}}", - "refId": "A" - } - ] - }, - { - "id": 51, - "type": "bargauge", - "title": "OPA Test 耗時(最後一次)by Stage", - "description": "opa test 最後一次执行的秒數,讓觀眾感受「CI 真的在跟」。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 8, - "y": 64, - "w": 8, - "h": 6 - }, - "options": { - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "displayMode": "gradient", - "valueMode": "color" - }, - "fieldConfig": { - "defaults": { - "unit": "s", - "color": { - "mode": "palette-classic" - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum by (stage, result) (opa_test_duration_seconds{job=\"agent-governance-demo\"})", - "legendFormat": "{{stage}} ({{result}})", - "refId": "A" - } - ] - }, - { - "id": 52, - "type": "timeseries", - "title": "OPA Test 耗時歷史(紅燈→綠燈轉折)", - "description": "opa_test_duration_seconds 時間軸變化,可看出 after_patch(紅)到 after_fix(綠)的転折點。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 16, - "y": 64, - "w": 8, - "h": 6 - }, - "options": { - "legend": { - "displayMode": "list", - "placement": "bottom" - }, - "tooltip": { - "mode": "multi" - } - }, - "fieldConfig": { - "defaults": { - "unit": "s", - "custom": { - "lineWidth": 2, - "fillOpacity": 15 - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "sum by (stage) (opa_test_duration_seconds{job=\"agent-governance-demo\"})", - "legendFormat": "{{stage}}", - "refId": "A" - } - ] - } - ] - }, - { - "id": 500, - "type": "row", - "title": "事後驗證 — Audit", - "collapsed": false, - "gridPos": { - "x": 0, - "y": 38, - "w": 24, - "h": 1 - } - }, - { - "id": 20, - "type": "table", - "title": "Audit 明細 — 每筆決策完整脈絡", - "description": "tool_gate_audit_event:每筆各有唯一 request_id。可看出是 OPA 還是 fallback 跟哪一版 policy 決定、哪一個 caller 發出。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 39, - "w": 24, - "h": 8 - }, - "options": { - "footer": { - "show": false - }, - "sortBy": [ - { - "displayName": "ts", - "desc": true - } - ] - }, - "fieldConfig": { - "defaults": { - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "decision" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background" - }, - { - "id": "mappings", - "value": [ - { - "type": "value", - "options": { - "allow": { - "color": "green", - "index": 0 - }, - "deny": { - "color": "red", - "index": 1 - }, - "require_approval": { - "color": "orange", - "index": 2 - } - } - } - ] - } - ] - } - ] - }, - "targets": [ - { - "expr": "tool_gate_audit_event{job=\"agent-governance-demo\"}", - "legendFormat": "", - "refId": "A", - "instant": true, - "format": "table" - } - ], - "transformations": [ - { - "id": "filterFieldsByName", - "options": { - "include": { - "names": [ - "ts", - "tool", - "role", - "decision", - "caller", - "policy_version" - ] - } - } - }, - { - "id": "sortBy", - "options": { - "fields": [ - { - "displayName": "ts", - "desc": true - } - ] - } - }, - { - "id": "limit", - "options": { - "limitCount": 20 - } - } - ] - }, - { - "id": 22, - "type": "piechart", - "title": "Audit 決策分布", - "description": "所有 audit 筆數按 decision 分布圓餅圖。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 0, - "y": 47, - "w": 12, - "h": 8 - }, - "options": { - "legend": { - "displayMode": "table", - "placement": "right", - "values": [ - "percent", - "value" - ] - }, - "pieType": "donut", - "tooltip": { - "mode": "single" - } - }, - "fieldConfig": { - "defaults": { - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "allow" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "green" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "deny" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "red" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "require_approval" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "orange" - } - } - ] - } - ] - }, - "targets": [ - { - "expr": "count by (decision) (tool_gate_audit_event{job=\"agent-governance-demo\"})", - "legendFormat": "{{decision}}", - "refId": "A", - "instant": true - } - ] - }, - { - "id": 23, - "type": "bargauge", - "title": "Audit 決策 by policy_version", - "description": "OPA 決定 vs fallback 各占幾筆,可看出是否有呼叫走到 OPA binary。", - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "gridPos": { - "x": 12, - "y": 47, - "w": 12, - "h": 8 - }, - "options": { - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "displayMode": "gradient", - "valueMode": "color" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "color": { - "mode": "palette-classic" - } - }, - "overrides": [] - }, - "targets": [ - { - "expr": "count by (policy_version) (tool_gate_audit_event{job=\"agent-governance-demo\"})", - "legendFormat": "{{policy_version}}", - "refId": "A", - "instant": true - } - ] - } - ], - "annotations": { - "list": [] - } -} \ No newline at end of file