Traces
- マイクロサービスのように複数のサーバーにまたがるトレースを追跡・監視する仕組み
TraceとSpanからなるSpanは処理毎の実行時間等を持つデータでTraceはSpanをノードとした木構造
![[Pasted image 20250525145039.png]]
(https://opentelemetry.io/img/waterfall-trace.svg より引用)
SpanはSpan同士を関連付けてTraceを作るために以下を持つ- Trace ID
- Span ID
- 親のSpan ID(Root Spanは空)
- Trace IDを各Spanで共通させることでサービスを跨いでSpanの関連付けが出来る
- どうやって? => Context Propagation
![[OpenTelemetry#OpenTelemetryとは?]]
(余談) OpenTelemetryに対応しているLLM監視ツール
- OpenLIT
- OpenLLMetry
- langfuse
- TODO
MCPの概要
Specification - Model Context Protocol
- LLMと外部データ・ツールを繋げるためのプロトコル
- MCP serverとしてResources, Prompts, Tools の機能を提供できる
- Tool: MCP clientであるLLM modelが使用する機能、ツールの一覧取得や呼び出しが可能
- MCP clientとMCP serverの通信方式
- フォーマット: JSON-RPC
- 2つの通信方式が策定
- stdio(ローカル)
- HTTP + SSE(Server-sent events) → Streamable HTTP(リモート)
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"location": "New York"
}
}
}
はじめに
- Webサービスでは分散トレーシングをはじめとしたオブザーバビリティ(監視)が重要に
- 監視を実現するベンダー中立なプロトコル/実装として OpenTelemetry(OTel)がある
- LLMアプリは確率的な上に複雑化しているので監視が重要視されつつある(LLMOps)
- 確率的: モデル出力、トークン数に応じたコスト・レスポンス時間の変化
- 複雑化: 外部サービスの呼び出し、Tool Call → AI Agent → MCP
- OpenTelemetryの分散トレーシングに興味があった + MCPを触っていた
- => MCPに OpenTelemetry による分散トレーシングを導入を提案されていたので紹介
目次
- OpenTelemetryでの分散トレーシングの概要
- TraceはSpanの集まり、Trace IDをサービス間で共有して分散トレーシングを実現
- MCPの概要
- LLMであるclientがツールであるserverを使う
- MCPにOpenTelemetryによる分散トレーシングを導入する提案の紹介
- Trace IDの共有方法とSpanの送信方法が議論ポイント
MCPにおけるオブザーバビリティの必要性
-
MCP serverをローカル以外で動くようになった
- Web appがMCP clientを使う
- MCP serverを自作している
-
MCP client/serverは、マイクロサービスで構成されたアプリケーションとして見ることができ、通常の(マイクロ)サービスと同様に オブザーバビリティ が重要に
-
(分散トレーシングの可視化はデバッグ用途としても便利)
-
もんだいてん
- MCP client -> serverリクエストが挟まるとTraceが断片化されてしまう
![[MCP#Streamable HTTP transport]]
MCPをOTel Traceに対応させる提案
issue: modelcontextprotocol/modelcontextprotocol #269 [Proposal] Adding OpenTelemetry Trace Support to MCP
提案内容の概要
① serverはclientに都度 Span を送信(/notification/otel/trace 宛に 12)
②Trace IDの共有方法
- clientはリクエストを識別するためのTrace IDに相当する
traceTokenをserverに送る
![[Pasted image 20250525155612.png|500]] (issueより引用)
それに対して以下が議論ポイント ①clientがSpanを送信することの問題点 ②Trace IDの伝搬方法 ③MCPのSemantic Conventionsの標準化
Footnotes
-
既存の構造化ロギング用の
notifications/messageを拡張することも出来るが以下の理由で新設したい (1) トレースとログは分離したほうがわかりやすいため(OTel signalもTraceとLogは分けているし) (2) クライアントもpayload見てトレースだけを送信するような処理を書かなくて良くなるため (3) 将来的に他のOTel signal(Metrics, Log)にも対応することになったときに/notification/otel/{metrics,logs}のように明確になるため ↩ -
otel.tracescapabilityが有効のとき、serverはトレースを生成してもよい ↩
参考文献
- OpenTelemetry
- Model Context Protocol
- OpenTelemetry 分散トレーシングのシステムアーキテクチャ
- modelcontextprotocol/modelcontextprotocol #269 [Proposal] Adding OpenTelemetry Trace Support to MCP
- Include OpenTelemetry Trace identifiers as part of the MCP client -> server protocol #246
- modelcontextprotocol/modelcontextprotocol Document request.params._meta convention #414
- open-telemetry/semantic-conventions #2043 Semantic conventions for Model Context Protocol
- feat(mcp): mcp python context propagation by anuraaga · Pull Request #1524 · Arize-ai/openinference · GitHub
- AIエージェントのオブザーバビリティについて - Speaker Deck
- OpenTelemetry + LLM = OpenLLMetry!? - Speaker Deck
- GenAI向けのOpenTelemetry SemanticsとCloud Traceへの表示
③ MCPのSemantic Conventionsの標準化
issue: open-telemetry/semantic-conventions #2043 Semantic conventions for Model Context Protocol
TODO: semantic conventionとは
- 生成AI呼び出しも規約化されている Semantic conventions for generative AI spans | OpenTelemetry
preview: https://github.com/lmolkova/semantic-conventions/blob/mcp/docs/registry/attributes/mcp.md
議論ポイント① clientがSpanを送信することの是非
-
OTelの通常の設計(各サービスがSpanを送信する)と異なる
-
clientが送信することのpros/cons
- 理由
- clientにとってserverはtool callに過ぎないので実行chainの一部
- pros(提案者談)
- server側でclient側と同様のOTel exporterの設定や, collectorの認証設定をしなくて良い
- serverの実装が複雑にならない
- client側で一任してトレースデータの転送先等を決めることが出来る
- 既存のMCP接続を活用するため、ネットワークの追加設定が不要
- server側でclient側と同様のOTel exporterの設定や, collectorの認証設定をしなくて良い
- cons
- Spanのデータ量が多くなってしまうかも
- Spanには機密情報が含まれていることもあるのでclientに送り返すのがセキュリティ的な懸念になるのでは?
- => Spanのサニタイズはserver側で必須にします。負担はserver側に押し付けます。
- clientとserverの組織が違う場合、セキュリティリスクが大きすぎる
- client側の実装が大変(SpanをOTLPを使ってcollectorに送信するのが大変そう
- clientがserverのOTel collectorとなる案
- 理由
Open Questions/Future Work
- リクエストボディのフォーマットの決定
- OTelのsemantic conventionsの定義
- OTel Metrics and Logsのサポート
Span送信のレート制限をclientから制御できる機能
![[OpenTelemetry#シグナル]]
Context Propagation とは
サービス間でContext(Trace ID等)を共有するための仕組み。基本的に計装ライブラリが自動で行う
- Spanは各サービスから可視化バックエンド(OTel collector等)に送信される
- TODO: OTel collectorの説明?
- ContextはHTTPリクエスト時に
traceparentヘッダに含める 1 : W3C Trace Context 2
![[Pasted image 20250525151006.png]]
(OpenTelemetry 分散トレーシングのシステムアーキテクチャ より引用)
Footnotes
-
OTelのデフォルトのContext Propagationの方法。他にも方法があるらしい。 ↩
議論ポイント② Trace IDの伝搬方法
issue: Include OpenTelemetry Trace identifiers as part of the MCP client -> server protocol #246
traceTokenを提案
stdio transportでのコンテキスト(Trace ID等)の含め方が検討
- JSON RPCスキーマでエンコードする
- (httpであればヘッダが使えるが)他にもtransportの方法はあるのでJSON RPC内に含める
- コンテキストは
params._metaに任意で含める- MCP server/clientは、未知のメタデータで失敗してはならない(互換性のため; OTel対応済みクライアントが未対応サーバを壊さないように)
- TS/Python SDKは未知のメタデータを許可している
request.params._metaを使ってコンテキストの伝搬をしようとしているのでキー名もそれらに合わせた
これを実装したのが、Arize-ai/openinference の実装方法 openinferenceはLLMアプリにOpenTelemetryを計装するPythonパッケージ