Skip to content

智能体活动追踪

Supported in ADKPython v1.17.0Go v1.0.0Kotlin v0.1.0

Agent Development Kit (ADK) 提供分布式追踪能力,帮助你可视化请求在智能体架构中端到端的旅程。指标告诉你过程花费了多长时间,日志告诉你发生了什么,而追踪则将这些事件连接起来,精确显示时间花费在哪里,以及 LLM 推理、工具调用和外部 API 之间的层次关系。

追踪理念

ADK 的追踪方法基于标准协议构建,确保与你现有的可观测性堆栈无缝集成。

  • OpenTelemetry 语义约定: ADK 实现了 OpenTelemetry (OTel) GenAI 语义约定。这确保了追踪 Span 和属性在标准、可预测的名称下进行记录。
  • OTLP 有线格式: ADK 使用标准 OTLP 格式发送数据,确保你的追踪可以无缝集成到任何 OTel 兼容的后端(例如 Google Cloud Trace、Jaeger、Grafana Tempo、Datadog)。
  • 层次化可视化: 追踪被组织成"Span"。智能体运行是一个根 Span,其中包含 LLM 操作的子 Span,而这些子 Span 可能又包含工具执行的子 Span。这创建了智能体推理循环的清晰的"瀑布"视图。
  • 上下文传播: ADK 自动跨进程边界传递追踪上下文,确保如果你的智能体通过工具调用外部微服务,该服务的 Span 会链接到智能体的根追踪。

追踪模式

启用追踪后,ADK 会根据 OpenTelemetry GenAI 智能体语义约定自动检测关键操作。一个典型的追踪瀑布包含以下 Span:

Span 名称 类型 描述 关键属性
invoke_agent Client / Internal Span 描述通过远程服务或本地调用 GenAI 智能体的过程。表示智能体交互的生命周期。 gen_ai.agent.namegen_ai.system
invoke_workflow Child Span 描述多步智能体工作流的调用。 gen_ai.workflow.namegen_ai.system
execute_tool Child Span 表示 GenAI 系统请求的特定工具或函数调用的执行。 gen_ai.tool.namegen_ai.system
generate_content {model.name} Internal Span 表示对底层语言模型的调用(通过 GenAI SDK)以生成内容。它跟踪请求参数、响应详情和使用指标。 gen_ai.operation.namegen_ai.systemgen_ai.request.modelgen_ai.agent.namegen_ai.conversation.iduser.idgen_ai.request.top_pgen_ai.request.max_tokensgen_ai.response.finish_reasonsgen_ai.usage.input_tokensgen_ai.usage.output_tokens

追踪导出设置

在 ADK Web 中导出追踪

如果你使用 adk webadk api_server CLI 命令运行智能体,可以配置追踪导出。

OTLP 导出

要将追踪导出到 OTLP 兼容的后端,设置标准的 OTel 环境变量:

export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="http://your-collector:4318/v1/traces"
adk web path/to/your/agents_dir

注意: 如果你希望将指标和日志也发送到同一端点,也可以设置通用的 OTEL_EXPORTER_OTLP_ENDPOINT 环境变量。

GCP 导出

要启用追踪导出到 Google Cloud Trace,请使用 --otel_to_cloud 标志:

adk web --otel_to_cloud path/to/your/agents_dir

程序化追踪导出

你也可以在应用程序代码中以编程方式配置追踪导出。

OTLP 导出设置

要启用追踪并以编程方式将 Span 导出到 OpenTelemetry Collector:

from google.adk.telemetry.setup import maybe_set_otel_providers
import os

os.environ["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"] = "http://your-collector:4318/v1/traces"
os.environ["OTEL_SERVICE_NAME"] = "your-adk-agent"
os.environ["OTEL_RESOURCE_ATTRIBUTES"] = "key1=value1,key2=value2"
maybe_set_otel_providers()

GCP 导出设置

要以编程方式将追踪导出到 Google Cloud Trace,使用 OpenTelemetry Google Cloud 导出器。以下是 Python 示例:

from google.adk.telemetry.google_cloud import get_gcp_exporters
from google.adk.telemetry.setup import maybe_set_otel_providers
import os

gcp_exporters = get_gcp_exporters(
  enable_cloud_tracing = True,
)
os.environ["OTEL_SERVICE_NAME"] = "your-adk-agent"
os.environ["OTEL_RESOURCE_ATTRIBUTES"] = "key1=value1,key2=value2"
maybe_set_otel_providers([gcp_exporters])

Kotlin 编程设置

在 Kotlin 中,ADK 自动使用 GlobalOpenTelemetry 实例导出追踪。你应在启动智能体之前配置 OpenTelemetry SDK。

OTLP 导出设置

要启用追踪并将 Span 导出到 OpenTelemetry Collector,请配置 OpenTelemetry SDK 并在全局注册:

// 1. Configure OpenTelemetry (Traces)
// ADK Kotlin uses GlobalOpenTelemetry to resolve its tracer on the JVM.
val spanExporter = OtlpGrpcSpanExporter.builder().setEndpoint("http://localhost:4317").build()

val resource =
    Resource.getDefault()
        .merge(
            Resource.create(
                Attributes.of(AttributeKey.stringKey("service.name"), "my-kotlin-agent"),
            ),
        )

val tracerProvider =
    SdkTracerProvider.builder()
        .addSpanProcessor(BatchSpanProcessor.builder(spanExporter).build())
        .setResource(resource)
        .build()

OpenTelemetrySdk.builder().setTracerProvider(tracerProvider).buildAndRegisterGlobal()

// 2. Optional: Configure ADK Telemetry behavior
// Enable capturing full message content in traces (use with caution in production)
TelemetryConfig.captureMessageContent = true

// 3. Initialize Agent and Runner with LoggingPlugin for console output
val agent = LlmAgent(name = "my_agent", model = Gemini(name = "gemini-flash-latest"))

val runner =
    InMemoryRunner(agent = agent, pluginManager = PluginManager(listOf(LoggingPlugin())))

// The runner will now automatically emit traces via GlobalOpenTelemetry
// and log activity to the console via the LoggingPlugin.
runner.run(
    userId = "user123",
    sessionId = "session456",
    newMessage = Content.fromText(Role.USER, "Hello!"),
)