Traces

  • マイクロサービスのように複数のサーバーにまたがるトレースを追跡・監視する仕組み
    • TraceSpan からなる
    • Span は処理毎の実行時間等を持つデータで TraceSpan をノードとした木構造

![[Pasted image 20250525145039.png]]

(https://opentelemetry.io/img/waterfall-trace.svg より引用)

  • SpanSpan 同士を関連付けて Trace を作るために以下を持つ
    • Trace ID
    • Span ID
    • 親のSpan ID(Root Spanは空)
  • Trace IDを各Spanで共通させることでサービスを跨いでSpanの関連付けが出来る
  • どうやって? => Context Propagation

![[OpenTelemetry#OpenTelemetryとは?]]

(余談) OpenTelemetryに対応しているLLM監視ツール

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 による分散トレーシングを導入を提案されていたので紹介

目次

  1. OpenTelemetryでの分散トレーシングの概要
    • TraceはSpanの集まり、Trace IDをサービス間で共有して分散トレーシングを実現
  2. MCPの概要
    • LLMであるclientがツールであるserverを使う
  3. MCPにOpenTelemetryによる分散トレーシングを導入する提案の紹介
    • Trace IDの共有方法とSpanの送信方法が議論ポイント

MCPにおけるオブザーバビリティの必要性

MCPサーバをOpenTelemetryで計装する

  • 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

  1. 既存の構造化ロギング用の notifications/message を拡張することも出来るが以下の理由で新設したい (1) トレースとログは分離したほうがわかりやすいため(OTel signalもTraceとLogは分けているし) (2) クライアントもpayload見てトレースだけを送信するような処理を書かなくて良くなるため (3) 将来的に他のOTel signal(Metrics, Log)にも対応することになったときに /notification/otel/{metrics,logs} のように明確になるため

  2. otel.traces capabilityが有効のとき、serverはトレースを生成してもよい

議論ポイント① clientがSpanを送信することの是非

  • OTelの通常の設計(各サービスがSpanを送信する)と異なる

  • clientが送信することのpros/cons

    • 理由
      • clientにとってserverはtool callに過ぎないので実行chainの一部
    • pros(提案者談)
      • server側でclient側と同様のOTel exporterの設定や, collectorの認証設定をしなくて良い
        • serverの実装が複雑にならない
        • client側で一任してトレースデータの転送先等を決めることが出来る
      • 既存のMCP接続を活用するため、ネットワークの追加設定が不要
    • 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

  1. OTelのデフォルトのContext Propagationの方法。他にも方法があるらしい。

  2. W3C Trace Contextについて #opentelemetry - Qiita

議論ポイント② Trace IDの伝搬方法

issue: Include OpenTelemetry Trace identifiers as part of the MCP client -> server protocol #246

traceTokenを提案

stdio transportでのコンテキスト(Trace ID等)の含め方が検討

  1. JSON RPCスキーマでエンコードする
    • (httpであればヘッダが使えるが)他にもtransportの方法はあるのでJSON RPC内に含める
  2. コンテキストは params._meta に任意で含める
    • MCP server/clientは、未知のメタデータで失敗してはならない(互換性のため; OTel対応済みクライアントが未対応サーバを壊さないように)
    • TS/Python SDKは未知のメタデータを許可している
      • request.params._meta を使ってコンテキストの伝搬をしようとしているのでキー名もそれらに合わせた

これを実装したのが、Arize-ai/openinference の実装方法 openinferenceはLLMアプリにOpenTelemetryを計装するPythonパッケージ

PR: feat(mcp): mcp python context propagation by anuraaga · Pull Request #1524 · Arize-ai/openinference · GitHub