JSONL LLM Log 持久化方案
JSONL LLM Log 持久化方案
OTel 將 LLM 的 prompt 與 response 送到 Aspire Dashboard 可即時查看,但資料不持久。透過自訂 JSONLExporter,可將每筆 LLM Log Record 寫入 JSONL 檔案,供長期保存與提示詞版本分析使用。
動機
OTel 將 LLM 的 prompt 與 response 送到 Aspire Dashboard 可即時查看,但資料不持久。
JSONL 持久化的目的:
- 歷史對話存檔:保留所有 LLM 的 input/output,供後續分析
- 提示詞優化分析:比對不同 prompt 版本在相同情境下的輸出差異
- 版本追蹤:每筆 log 帶有 git commit hash,可精確對應到當時的提示詞版本,評估修改效果
架構:OTel 雙路徑輸出
ADK 預設的 OTLP pipeline 和自訂 JSONL pipeline 是兩條獨立路徑:
1 | ADK Framework(產生 OTel Log Records) |
透過 telemetry.WithLogRecordProcessors() 新增額外的 Processor,不影響原有的 OTLP pipeline。
自訂 JSONLExporter
實作 OTel sdklog.Exporter 介面,將每筆 Log Record 寫成一行 JSON:
1 | type JSONLExporter struct { |
日誌格式
每行一個 JSON 物件:
1 | { |
| 欄位 | 說明 |
|---|---|
timestamp |
ISO 8601 UTC,來自 OTel Record.ObservedTimestamp |
event |
OTel EventName(gen_ai.choice、gen_ai.system.message 等) |
agent |
Agent 名稱,從 gen_ai.agent.name attribute 或 service.name resource 取得 |
session |
對話 session ID(由 SessionEnrichProcessor 注入) |
invocation |
本次調用 ID,來自 gen_ai.operation.name |
input_tokens |
輸入 token 數,來自 gen_ai.usage.input_tokens |
output_tokens |
輸出 token 數,來自 gen_ai.usage.output_tokens |
version |
git commit hash(帶 -dirty 若有未提交變更),用於對照提示詞版本 |
body |
LLM 的完整 prompt 或 response 內容 |
版本追蹤設計
version 欄位自動偵測當前 git commit hash:
1 | func DetectVersion() string { |
使用流程:
- 修改提示詞 → commit → 取得新的 hash
- 執行 agent,JSONL 每筆 log 帶有該 commit hash
- 對比不同 hash 的 log,評估提示詞修改效果
日誌輪替
- 以 UTC 日期為單位,每天建立新檔:
logs/llm-2026-03-14.jsonl - 日期切換時,前一天的檔案自動移至
logs/archive/ - 目前寫入的檔案永遠在
logs/根目錄,方便 tail / jq
jq 查詢範例
1 | # 查看特定 session 的所有 LLM 對話 |
本部落格所有文章除特別聲明外,均採用CC BY-NC-SA 4.0 授權協議。轉載請註明來源 Kenny's Blog!



