遙測(Telemetry)

OpenTelemetry span / metric / event —— 且不導出任何 prompt 內容

一句話

OCR 內建一流 OpenTelemetry 支援。啟用後,每次評審產出結構化 span、metric、event——足以回答「agent 把時間花在哪?」「各模型成本如何?」「這次為何失敗?」。

預設關閉。遙測預設不啟用——要主動打開。

兩種 exporter

Exporter何時使用
console個人使用 / 除錯。span 格式化印到 stdout。
otlp系統整合。送任何 OTLP 相容 collector(Jaeger、Tempo、OTel Collector、Datadog…)。

啟用

# config 方式
ocr config set telemetry.enabled        true
ocr config set telemetry.exporter       otlp
ocr config set telemetry.otlp_endpoint  localhost:4317

# 環境變數方式
export OCR_ENABLE_TELEMETRY=1
export OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317   # 同時強制 exporter=otlp
export OTEL_SERVICE_NAME=open-code-review

Span

review.run
├── diff.parse
├── event.review.started
├── subtask.execute.<file1>
│   ├── event.plan.skipped
│   ├── event.token.threshold.exceeded
│   └── event.subtask.error
├── subtask.execute.<file2>
└── …

LLM 往返與工具執行不作為獨立 span——只出現在 metric。決策點事件是短生命週期的 event.<name> span。

Metric(節選)

Metric型別標籤
ocr.review.duration_secondshistogram
ocr.files_reviewed_totalcounter
ocr.comments_generated_totalcounter
ocr.llm.requests_totalcountermodelstatus
ocr.llm.tokens_usedcountermodeltype
ocr.tool.calls_totalcountertool.namestatus

內容日誌(重點:隱私)

遙測導出 LLM 流量的形狀(計數、時長、狀態),但絕不導出實際 prompt 或回應。OCR 不嘗試把 LLM 訊息內容附加到 span 或 event。

content_logging config key 與 OCR_CONTENT_LOGGING=1 已接入配置層,但目前不控制任何發送 prompt 內容的程式路徑——視為保留位。

要看內容?Session Viewer 讀本地 JSONL——它們完全存在 ~/.opencodereview/ 下,絕不發往 collector。

解析優先級

  1. 預設(enabled=false、exporter=console、無 endpoint)。
  2. ~/.opencodereview/config.jsontelemetry.*
  3. 環境變數(最高優先級,覆蓋檔案)。

配方:CI 送 Tempo

- name: Code review
  env:
    OCR_LLM_URL: ${{ secrets.OCR_LLM_URL }}
    OCR_LLM_TOKEN: ${{ secrets.OCR_LLM_TOKEN }}
    OCR_LLM_MODEL: claude-opus-4-6
    OCR_ENABLE_TELEMETRY: "1"
    OTEL_EXPORTER_OTLP_ENDPOINT: ${{ vars.OTEL_COLLECTOR_URL }}
    OTEL_SERVICE_NAME: open-code-review-ci
  run: ocr review --from origin/main --to HEAD --audience agent

故障排查

症狀可能原因
什麼都沒匯出預設關閉——沒設 OCR_ENABLE_TELEMETRY / telemetry.enabled
OTLP 本地可用、生產失敗OCR 目前僅實作 OTLP/gRPC;http/protobuf 被接受但未接入
span 缺 promptOCR 絕不把 prompt 內容附加到遙測——用 viewer 檢查轉錄
📖 教學解說:遙測深入

為什麼遙測預設關閉

三個原因:① 隱私(不是每個人都想把執行遙測送到外部)② 效能(OTLP exporter 有網路開銷)③ 依賴(需要 collector)。所以預設關閉,要主動打開。

span 樹的實務解讀

每個評審的 span 樹長這樣:

review.run
├── diff.parse              ← diff 解析耗時
├── event.review.started    ← 開始事件
├── subtask.execute.file1   ← 每個檔案一個
│   ├── event.plan.skipped  ← plan 跳過(小 diff)
│   └── ...
└── subtask.execute.file2

LLM 往返不作為獨立 span——只出現在 ocr.llm.requests_total metric。所以看 LLM 延遲要看 metric,不是 span。

「不導出 prompt」的隱私保證

遙測導出的是形狀(計數、時長、狀態),不是內容(prompt、response、diff)。content_logging config key 已存在但目前不控制任何發送 prompt 內容的程式路徑——視為保留位。要看 prompt 內容?用 Session Viewer 讀本地 JSONL。

練習 / 驗收清單

  • 能說出兩種 exporter 的使用場景
  • 能描述三層解析優先級
  • 能解釋 span 樹的形狀
  • 能說明遙測為何絕不導出 prompt 內容
看完這頁你應該能說出:兩種 exporter、三層解析優先級、span 樹的形狀、哪些 metric 存在、以及最重要的——遙測為何絕不導出 prompt 內容。

延伸閱讀:設定 · 架構 · Session Viewer