AI Navigate

OpenTelemetryがLLMトレーシングを標準化しました。コード上では実際にはこのようになっています。

Dev.to / 2026/3/22

📰 ニュースDeveloper Stack & InfrastructureIdeas & Deep AnalysisTools & Practical Usage

要点

  • OpenTelemetryは、LLM呼び出しをトレースするための新しいGenAI Semantic Conventions標準を公開しました。これにより、スパン名の付け方、属性、PIIを保護するロギングプロンプトに関するガイダンスが提供されます。
  • この標準は、異なるプラットフォーム間でLLMツールがトレースデータを公開する方法を統一することを目指しており、現在の断片化(ベンダーが異なる形式を使用している状態)を解消します。
  • この記事は、複数のプルリクエスト、ギャップ分析、初期にはトレースがエクスポートされなかった実運用上の問題を含む、実践的な実装経験を共有します。
  • この仕様を既存のダッシュボードやベンダー統合に採用する際の課題を強調し、現場の実務者が今日実践すべき具体的なポイントを提示します。

Screenshot: Span
Span命名移行: 古い形式は、すべての GenAI対応バックエンドには見えませんでした。

エージェント属性 — パスが間違っていました

エージェントを構築している場合(ReAct、ツール使用、複数ステップ)、仕様はアイデンティティとツール属性を定義しています:

// What OTel says:
span.setAttribute("gen_ai.agent.name", "weather-bot");
span.setAttribute("gen_ai.agent.id", "agent-001");
span.setAttribute("gen_ai.tool.name", "search");
span.setAttribute("gen_ai.tool.type", "function");

// What we had:
span.setAttribute("gen_ai.agent.tool.name", "search");  // wrong path
// gen_ai.agent.name — didn’t exist at all

gen_ai.agent.tool.name のパスは妥当なように見えます。読んだ感じでも自然です。しかし仕様はツール属性を gen_ai.tool.* に配置します — エージェントの下にはネストされていません。私たちの形式は、再び、標準に従うバックエンドには見えません。

コンテンツ記録 — 仕様も私たちに賛同しています(いい気分です)

これは私たちが最初の日から正しくできていた唯一の点であり、多くのチームがそれを間違えるため、指摘しておく価値があります。

仕様では: デフォルトではプロンプトと完了を記録しない。 計装は、明示的に有効化されない限り、コンテンツを捕捉すべきではありません。

公式の3つのパターン:

  1. デフォルト: 記録しない。 スパンにはプロンプトも完了もない。プライバシー優先。
  2. スパン属性によるオプトイン。 gen_ai.input.messages および gen_ai.output.messages を JSON 文字列として。
  3. 外部ストレージ。 コンテンツを別の場所に保存し、スパンに参照を置く。

v1 からデフォルトは recordContent: false でした。仕様がこのアプローチを確認したとき、それは、直感が非常に賢い人々の委員会によって裏付けられたという、まれな瞬間の1つでした。

デフォルトでスパンにプロンプトをログしている場合は、セキュリティチームが代わりにそれを行う前に、再検討したほうがよいかもしれません。

正直なギャップ分析

ここに全体像があります。歪曲なし、抜粋なし。

初日から正しかった点

私たちの属性 OTel 規格 判定
gen_ai.provider.name gen_ai.provider.name ✅ 完全一致
gen_ai.request.model gen_ai.request.model ✅ 完全一致
gen_ai.usage.input_tokens gen_ai.usage.input_tokens ✅ 完全一致
error.type error.type ✅ 完全一致

私たちが間違えた点

項目 私たちの版 OTel 規格 状態
スパン名 gen_ai.openai.gpt-4o chat gpt-4o 修正済み
ツール名属性 gen_ai.agent.tool.name gen_ai.tool.name 修正済み
カスタム属性 gen_ai.agent.step.* 予約済みの名前空間 移動先は gen_ai.toad_eye.*
エージェントの識別情報 存在しませんでした gen_ai.agent.name 追加済み

仕様を超えて構築したもの

機能 名前空間 なぜOTelに含まれていないのか
リクエストあたりのコスト gen_ai.toad_eye.cost 価格設定はベンダー依存です
予算ガード gen_ai.toad_eye.budget.* ランタイムの強制は観測性とは同等ではない
影のガードレール gen_ai.toad_eye.guard.* 検証はアプリケーションレベルです
意味論的ずれ gen_ai.toad_eye.semantic_drift 品質指標であり、トレース標準ではない
ReAct のステップ追跡 gen_ai.toad_eye.agent.step.* ReAct は一つのパターンです;仕様はパターンに依存しません

重要な洞察: OTel 規格は何が起こったかをカバーします。私たちはなぜ起こったのかとどれくらいの量をカバーします。 競争しているわけではなく、補完的です。あなたのカスタム指標はあなたの名前空間の下に格納します。規格の属性はバックエンドが期待する場所に配置されます。

移行: デュアル出力、ユーザーを壊さない

私たちはクリーンな分断を行いませんでした。 v2.4 は古い属性名と新しい属性名の両方を出力します:

// New (OTel spec-compliant)
span.setAttribute(\"gen_ai.tool.name\", toolName);

// Old (deprecated, still emitted for backward compat)
span.setAttribute(\"gen_ai.agent.tool.name\", toolName);

スクリーンショット: 属性プレフィックス移行差分は @deprecated タグとデュアルエミット
デュアルエミットアプローチ: 古い属性は @deprecated、新しい属性は仕様に従います。v3 まで両方が出力されます。

deprecated 属性の出力をいつ止めるかは、環境変数で制御します:

OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental

これは4つのPR(プルリクエスト)でした(#170, #171, #172, #173). v3 では非推奨の別名を完全に削除します。

皮肉

これらを実装している最中、私たちは手動のテストを一連のテストを行いました。

結局、私たちのトレースは全くエクスポートされませんでした。決して。OTel NodeSDKspanProcessors: [] を渡すとトレースのエクスポートを静かに無効にします。私たちは252件のテストを通過しました。すべて SDK をモックしていました。

つまり、誰にも見られないトレースの属性を完全に標準化しました。

両方を修正しました。1日で6つのパッチバージョンを公開しました。記事 #2 に全文があります。

この機能を実際にサポートしているバックエンド

これが重要な理由です。今日、適切な属性を出力すると、明日6つのバックエンドがあなたのトレースを可視化します:

バックエンド GenAI スパンを認識 エージェントの可視化 コスト
Jaeger 基本(ネストされたスパン) 階層ビュー 無料
Arize Phoenix 完全な GenAI UI エージェント ワークフロー 無料プラン
SigNoz GenAI ダッシュボード ネストされたスパン 無料 / クラウド
Datadog LLM 可観測性 エージェントのトレース 有料
Langfuse 完全な GenAI UI セッション表示 無料プラン
Grafana + Tempo 属性でのクエリ カスタムダッシュボード 無料

ベンダーロックインなし。1セットの属性。6つの可視化先。

今日すべきこと

LLM 呼び出しをトレースしている場合—カスタムコードを使っていても—現時点で仕様に合わせておくと、後での苦労を減らせます。規約は実験的ですが、方向性は確定しています。

クイックチェックリスト:

  • すべての LLM スパンに gen_ai.operation.name を設定します: chatinvoke_agent、または execute_tool
  • スパン名を {operation} {model_or_agent_name} の形式にします
  • 公式属性を使用します: gen_ai.agent.namegen_ai.tool.namegen_ai.tool.type
  • あなたのカスタム属性を あなたの名前空間の下に置きます — gen_ai.* ではなく
  • デフォルトではプロンプト/完了を記録しないでください — オプトインにしてください
  • 少なくとも 2 つのバックエンドでトレースをテストしてください(Jaeger + Phoenix のような GenAI 専用のものを 1 つ)

完全仕様: OpenTelemetry GenAI セマンティック規約
エージェント・スパン: GenAI エージェント・スパン

前の記事:

toad-eye — オープンソースの LLM 観測性、OTel-native: GitHub · npm