OTel Custom Log Processor — 跨 Span 注入 Context
OTel Custom Log Processor — 跨 Span 注入 Context
問題描述
OTel Log Record 預設不帶 Span 的自訂屬性。例如:
- Trace Span 上帶有
session_id(由 ADK 在StartInvokeAgentSpan時寫入) - Log Record 雖然與同一個 Span 關聯,但不會自動繼承 Span 的 attribute
結果:JSONL log 中的 session 欄位為空,無法按 session 分組查詢。
解決方案:實作自訂 Log Processor
透過包裝標準 BatchProcessor,在每筆 Log Record 被送出前,從當前 Span Context 讀取 attribute,注入到 Log Record:
1 | type SessionEnrichProcessor struct { |
ADK 的 session ID 存在 Span 的 gen_ai.conversation.id attribute,需要透過型別斷言存取:
1 | func extractSessionID(ctx context.Context) string { |
整合至 OTel Pipeline
1 | jsonlExp, _ := NewJSONLExporter("logs", version) |
通用模式
這個技巧可應用於任何「需要把 Span 上的資訊注入到 Log」的場景:
| 需求 | Span Attribute | 注入到 Log |
|---|---|---|
| 關聯 session | gen_ai.conversation.id |
session.id |
| 關聯使用者 | user.id |
user.id |
| 關聯請求 | http.request.id |
request.id |
| 關聯租戶 | tenant.id |
tenant.id |
核心步驟:
- 實作
sdklog.Processor介面(OnEmit、Shutdown、ForceFlush) - 在
OnEmit中從ctx取得 Span,讀取目標 attribute - 用
record.AddAttributes()注入 - 呼叫
p.inner.OnEmit(ctx, record)繼續傳遞
本部落格所有文章除特別聲明外,均採用CC BY-NC-SA 4.0 授權協議。轉載請註明來源 Kenny's Blog!