Microsoft Foundry と Azure Monitor を使用して LangChain アプリと LangGraph アプリをトレースする

langchain-azure-ai 統合パッケージを使用して、LangChain および LangGraph アプリケーションから OpenTelemetry トレースを出力し、Azure アプリケーション Insights にシンクします。 この記事では、AzureAIOpenTelemetryTracer を構成し、それを実行環境に取り付けて、Azure Monitor のトレースを検査します。

トレーサーは、エージェントの実行、モデル呼び出し、ツールの実行、および取得操作のスパンを出力します。 Foundry Agent Service またはマルチエージェント LangGraph ソリューションを呼び出す、完全にローカルなハイブリッド フローを実行するアプリに使用できます。

前提 条件

  • Azure サブスクリプション。 無料で作成します
  • Foundry プロジェクト
  • デプロイされた Azure OpenAI チャット モデル (たとえば、gpt-4.1)。
  • Python 3.10 以降。
  • Azure CLI にサインインしたため、DefaultAzureCredential が認証できます。

環境を構成する

必要なパッケージをインストールします。

pip install -U "langchain-azure-ai[opentelemetry]" azure-identity

この記事で使用する環境変数を設定します。

import os

# Option 1: Project endpoint (recommended)
os.environ["AZURE_AI_PROJECT_ENDPOINT"] = (
	"https://<resource>.services.ai.azure.com/api/projects/<project>"
)

# Option 2: Direct OpenAI-compatible endpoint + API key
os.environ["OPENAI_BASE_URL"] = (
	"https://<resource>.services.ai.azure.com/openai/v1"
)
os.environ["OPENAI_API_KEY"] = "<your-api-key>"
os.environ["APPLICATION_INSIGHTS_CONNECTION_STRING"] = "InstrumentationKey=0ab1c2d3..."

メッセージとツール呼び出しの内容をトレースに記録するかどうかを制御するには、enable_content_recording コンストラクターにAzureAIOpenTelemetryTracerを渡します。 コンテンツの記録は既定で有効になっています。

ヒント

enable_content_recording=False コンストラクターでAzureAIOpenTelemetryTracerを設定して、トレースからのメッセージの内容とツール呼び出しの引数を編集します。

トレーサーを作成する

1 つのトレーサー インスタンスを作成し、ワークフロー全体で再利用します。

import os

from azure.identity import DefaultAzureCredential
from langchain_azure_ai.callbacks.tracers import AzureAIOpenTelemetryTracer

tracer = AzureAIOpenTelemetryTracer(
	project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
	credential=DefaultAzureCredential(),
	name="langchain-tracing-sample",
	agent_id="support-bot",
	trace_all_langgraph_nodes=True,
)

このスニペットが行う内容: Foundry プロジェクト エンドポイントから関連する Application Insights 接続文字列を解決し、LangGraph ノードのトレースを有効にするトレーサーを構成します。 agent_idパラメーターを使用して、エージェントを呼び出すときにgen_ai.agent.id属性を設定します。 name パラメーターは、OpenTelemetry トレーサー名を設定します。

トレーサーは、運用ワークフローの一般的なコントロールをサポートしています。

  • 特定の Application Insights リソースをターゲットに connection_string 渡すか、環境変数 APPLICATION_INSIGHTS_CONNECTION_STRINGを構成します。
  • 既定ですべてのノードをトレースするように trace_all_langgraph_nodes=True を設定します。
  • 特定のノードを含めたりスキップしたりするには、 otel_trace: Trueotel_trace: False などのノード メタデータを使用します。
  • メッセージがカスタム状態の図形 (たとえば、message_keys) の下に入れ子になっている場合は、message_pathschat_historyを使用します。

参照:

エージェントのトレース

トレースをすばやく検証できるように、最小限の LangChain エージェントから開始します。 LangGraph の場合は、コンパイルされたグラフに with_config を含むトレーサーをアタッチします。

from langchain.agents import create_agent

agent = create_agent(
    model="azure_ai:gpt-5.2", 
    system_prompt="You're an informational agent. Answer questions cheerfully.", 
).with_config(
    {"callbacks": [tracer]}
)

response = agent.invoke({"messages": "what's your name?"})
response["messages"][-1].pretty_print()
================================== Ai Message ==================================

I’m ChatGPT, your AI assistant.

このスニペットの機能: 単純な LangGraph エージェントを作成し、トレーサーをアタッチし、メッセージを使用してエージェントを呼び出します。

参照:

LangChain ランナブルをトレースする

トレースをすばやく検証できるように、最小限の LangChain フローから開始します。

import os

from azure.identity import DefaultAzureCredential
from langchain_core.prompts import ChatPromptTemplate
from langchain_azure_ai.chat_models import AzureAIChatCompletionsModel

model = AzureAIChatCompletionsModel(
	endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
	credential=DefaultAzureCredential(),
	model=os.environ["AZURE_OPENAI_DEPLOYMENT"],
)

prompt = ChatPromptTemplate.from_template(
	"You are concise. Answer in one sentence: {question}"
)
chain = prompt | model

response = chain.invoke(
	{"question": "What does OpenTelemetry help me do?"},
	config={"callbacks": [tracer]},
)

print(response.content)
OpenTelemetry helps you observe requests, latency, dependencies, and failures across your AI workflow.

このスニペットの機能: 標準の LangChain パイプラインを実行し、チャット スパンを AzureAIOpenTelemetryTracer 経由で OpenTelemetry に送信します。

参照:

LangGraph グラフをトレースする

LangGraph の場合は、コンパイルされたグラフに with_config を含むトレーサーをアタッチします。 このスニペットは、前の例の modeltracer を再利用します。

from langgraph.graph import END, START, MessagesState, StateGraph
from langgraph.prebuilt import ToolNode
from langgraph.checkpoint.memory import MemorySaver
from langchain_core.tools import tool
from langchain_azure_ai.utils.agents import pretty_print

@tool
def play_song_on_spotify(song: str):
    """Play a song on Spotify"""
    # Integrate with Spotify API here.
    return f"Successfully played {song} on Spotify!"

@tool
def play_song_on_apple(song: str):
    """Play a song on Apple Music"""
    # Integrate with Apple Music API here.
    return f"Successfully played {song} on Apple Music!"

tool_node = ToolNode([play_song_on_apple, play_song_on_spotify])
model_with_tools = model.bind_tools([play_song_on_apple, play_song_on_spotify])

def should_continue(state: MessagesState):
    messages = state["messages"]
    last_message = messages[-1]
    return "continue" if getattr(last_message, "tool_calls", None) else "end"

def call_model(state: MessagesState):
    messages = state["messages"]
    response = model_with_tools.invoke(messages)
    return {"messages": [response]}

memory = MemorySaver()
workflow = (
    StateGraph(MessagesState)
    .add_node("agent", call_model)
    .add_node("action", tool_node)
    .add_edge(START, "agent")
    .add_conditional_edges(
        "agent",
        should_continue,
        {
            "continue": "action",
            "end": END,
        },
    )
    .add_edge("action", "agent")
    .compile(checkpointer=memory)
)

その後、通常どおりグラフを実行できます。

from langchain_core.messages import HumanMessage

config = {"configurable": {"thread_id": "1"}, "callbacks": [tracer]}
message = HumanMessage(content="Can you play Taylor Swift's most popular song?")

result = workflow.invoke({"messages": [message]}, config)
pretty_print(result)
================================ Human Message =================================

Can you play Taylor Swift's most popular song?
================================== Ai Message ==================================
Tool Calls:
  play_song_on_spotify (call_xxx)
 Call ID: call_xxx
  Args:
    song: Anti-Hero
================================= Tool Message =================================
Name: play_song_on_spotify

Successfully played Anti-Hero on Spotify!
================================== Ai Message ==================================

I played Taylor Swift's popular song "Anti-Hero" on Spotify.

このスニペットの機能: 単純な LangGraph アプリを作成し、トレースするノードをマークし、 invoke_agent とモデル/ツールスパンを同じトレースに出力します。

参照:

トレース構造を理解する

トレーサーは、 OpenTelemetry GenAI セマンティック規則に従うスパンを出力します。 各スパンの種類では、特定の gen_ai.operation.name 値が使用されます。

スパンの種類 gen_ai.operation.name 説明
エージェント/チェーン呼び出し invoke_agent 各 LangGraph ノードまたはチェーン ステップ。 スパン名は invoke_agent {gen_ai.agent.name}
チャット モデルの呼び出し chat LLM 推論リクエスト。 スパン名は chat {gen_ai.request.model}
テキスト補完 text_completion チャット以外のLLM呼び出し。
ツールの実行 execute_tool モデルによってトリガーされるツール呼び出し。 スパン名は execute_tool {gen_ai.tool.name}
レトリーバー execute_tool ベクター ストアまたは検索からの取得操作。

スパンには、次の重要な属性も含まれます。

  • gen_ai.agent.name — エージェントまたはノード名。
  • gen_ai.agent.idagent_id コンストラクター パラメーターから設定します。
  • gen_ai.agent.description — エージェントの説明。
  • gen_ai.provider.name — モデル プロバイダー (たとえば、 openaiazure.ai.inference)。
  • gen_ai.request.model — 推論に使用されるモデル名。
  • gen_ai.conversation.id — スレッドまたはセッション識別子 (使用可能な場合)。
  • gen_ai.usage.input_tokens / gen_ai.usage.output_tokens — モデルの応答からのトークン数。
  • gen_ai.input.messages / gen_ai.output.messages — メッセージの内容 (コンテンツの記録が有効になっている場合)。

トレーサーが解決する方法 gen_ai.agent.name

トレーサーは、空でない最初の値から次の順序でエージェント名を解決します。

  1. agent_name ノード メタデータに含まれます。
  2. langgraph_node ノードメタデータにおいて (LangGraph によって自動的に設定されます)。
  3. agent_type ノード メタデータに含まれます。
  4. LangChain コールバックからの name キーワード引数。
  5. langgraph_path (最後の要素) 上記が汎用プレースホルダーの場合。
  6. シリアル化されたチェーン ID またはクラス名。
  7. name コンストラクターからの AzureAIOpenTelemetryTracer パラメーター (フォールバックの既定値)。

トレーサーが解決する方法 gen_ai.agent.id

トレーサーは、次の場所からエージェントIDを得ます。

  1. agent_id ノード メタデータ (ノードごとのオーバーライド)。
  2. agent_id コンストラクター パラメーター (すべてのスパンの既定値)。

ノード メタデータを使用して属性をカスタマイズする

LangGraph メタデータを使用して、ノードごとに agent_nameagent_id、および agent_description を設定できます。 gen_ai.で始まるメタデータ キーもスパン属性として転送されます。

config = {
    "callbacks": [tracer],
    "metadata": {
        "agent_name": "support-bot",
        "agent_id": "support-bot-v2",
        "agent_description": "Handles customer support requests",
        "thread_id": "session-abc-123",
    },
}
result = graph.invoke({"messages": [message]}, config)

LangGraph を使用する場合は、グラフ定義のノードごとにメタデータを設定することもできます。

workflow = StateGraph(MessagesState)
workflow.add_node(
    "planner",
    planner_fn,
    metadata={
        "agent_name": "PlannerAgent",
        "agent_id": "planner-v1",
        "otel_agent_span": True,
    },
)

参照:

Azure Monitorでトレースを表示する

トレースは Azure アプリケーション Insights に送信され、Azure Monitorを使用してクエリを実行できます。

  1. Azure ポータルに移動します。

  2. 構成した Azure アプリケーション Insights に移動します。

  3. 左側のナビゲーション バーを使用して、 調査>Agents (プレビュー) を選択します。

  4. エージェント、モデル、ツールの実行を示すダッシュボードが表示されます。 エージェントの全体的なアクティビティを理解するには、このビューを使用します。

  5. [ エージェントの実行を含むトレースの表示] を選択します。 サイド パネルには、エージェントの実行によって生成されたすべてのトレースが表示されます。

    エージェント (プレビュー) セクションを表示する Azure Monitor のスクリーンショットで複数の実行を示す>

  6. トレースのいずれかを選択します。 詳細が表示されます。

    選択した実行のトレースの詳細を示すスクリーンショット。

Foundry コントロール プレーンでトレースを表示する

LangGraph または LangChain ソリューションをデプロイした場合は、そのデプロイを Foundry コントロール プレーン に登録して、可視性とガバナンスを実現できます。

Foundry コントロール プレーンにアプリケーションを登録して、Foundry ポータルでトレースを表示します。

次の手順に従います。

  1. Foundry コントロール プレーンのカスタム エージェント機能を使用するための要件を満たしていることを確認します。

    • Foundry リソースで構成された AI ゲートウェイ。 Foundry では、Azure API Managementを使用してエージェントを API として登録します。

    • 到達可能なエンドポイントを介してデプロイして公開するエージェント。 エンドポイントには、Foundry リソースをデプロイするネットワークから到達可能なパブリック エンドポイントまたはエンドポイントを指定できます。

  2. プロジェクトで可観測性が構成されていることを確認します。

  3. クラス AzureAIOpenTelemetryTracerを構成するときは、エージェントを登録するプロジェクトのエンドポイントを必ず使用してください。 agent_idを構成していることを確認します。

  4. Foundry ポータルに移動します。

  5. ツール バーの [ 操作] を選択します。

  6. [ 概要 ] ウィンドウで、[ エージェントの登録] を選択します。

  7. 登録ウィザードが表示されます。 まず、登録するエージェントの詳細を完了します。

    • エージェント URL: エージェントが実行され、要求を受信するエンドポイント (URL)。
    • プロトコル: エージェントがサポートする通信プロトコル。
    • OpenTelemetry エージェント ID: agent_id クラスで構成した指定したAzureAIOpenTelemetryTracer パラメーター。
    • Project: AzureAIOpenTelemetryTracer クラスでトレースを受信するように構成したproject。
    • エージェント名: エージェントの名前 ( agent_idと同じにすることができます)。
  8. エージェントを呼び出して、稼働していることを確認します。

  9. ツール バーの [ 操作] を選択します。

  10. 左側のウィンドウで、[アセット] を選択 します

  11. 作成したエージェントを選択します。

  12. [トレース] セクションには、エージェントのエンドポイントに対して行われた HTTP 呼び出しごとに 1 つのエントリが表示されます。

    詳細を表示するには、エントリを選択します。

    実行とストリームのルートでのエージェントのエンドポイントへの呼び出しのスクリーンショット。

トラブルシューティング

  • トレースが表示されない場合は、 connection_string が構成されているか、プロジェクト エンドポイントがテレメトリを公開していることを確認します。
  • メッセージの内容が編集されたと思われる場合は、enable_content_recording=True コンストラクターでAzureAIOpenTelemetryTracerを設定します。
  • 一部の LangGraph ノードがない場合は、 trace_all_langgraph_nodes=True 設定するか、ノード メタデータ otel_trace: Trueを追加します。