Logging 日志记录
智能体开发工具包 (ADK) 提供了灵活且强大的日志记录功能,用于有效监控智能体行为并调试问题。了解如何配置和解析这些日志对于监控智能体行为和排查问题至关重要。
日志理念¶
ADK 的日志理念是:在默认情况下提供详细的诊断信息,但不过度冗余。日志设计为由应用开发者自行配置,你可以根据开发或生产环境的具体需求,定制日志输出。
- 标准库集成:ADK 使用宿主语言的标准日志设施(例如 Python 的
logging模块、Go 的log包)。 - 结构化生成式 AI 日志:ADK 使用 OpenTelemetry 记录生成式 AI 请求和响应的结构化事件,从而实现在云环境中的高级监控和调试。
- 用户级配置:虽然 ADK 提供了默认设置并与其 CLI 工具集成,但最终仍由应用开发者负责根据其具体环境配置日志记录。
在 Python 中配置日志记录¶
在 Python 中,ADK 使用标准的 logging 模块。
配置示例¶
要启用详细日志(包括 DEBUG 级别信息),在脚本顶部添加如下内容:
import logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(name)s - %(message)s'
)
使用 ADK CLI 配置日志记录 (Python)¶
当使用 ADK 内置的 Web 或 API 服务器运行 Python 智能体时,你可以直接从命令行轻松控制日志的详细程度。adk web、adk api_server 和 adk deploy cloud_run 命令都接受 --log_level 选项。
要以 DEBUG 级别日志启动 Web 服务器,请运行:
可用于 --log_level 选项的日志级别有:
DEBUGINFO(默认)WARNINGERRORCRITICAL
日志级别 (Python)¶
| 级别 | 描述 | 记录的信息类型 |
|---|---|---|
DEBUG |
对调试至关重要。 最详细的级别,用于细粒度的诊断信息。 |
|
INFO |
关于智能体生命周期的通用信息。 |
|
WARNING |
表示潜在问题或使用了已弃用的功能。智能体继续运行,但可能需要注意。 |
|
ERROR |
阻止操作完成的严重错误。 |
|
注意:建议在生产环境中使用 INFO 或 WARNING 级别。仅在主动排查问题时启用 DEBUG 级别,因为 DEBUG 日志可能非常冗长且可能包含敏感信息。
在 Go 中配置日志记录¶
在 Go 中,ADK 对通用事件使用标准 log 包,对生成式 AI 活动日志使用 OpenTelemetry。
OpenTelemetry 日志记录¶
ADK Go 使用 OpenTelemetry (OTel) 记录生成式 AI 的请求和响应。默认情况下,为了安全起见,提示词内容在日志中会被省略。你可以使用环境变量或程序化配置来启用提示词日志记录。
启用提示词日志记录¶
将以下环境变量设置为 true 即可在 OTel 日志中包含完整的提示词:
程序化配置¶
你可以使用 google.golang.org/adk/telemetry 包配置遥测提供者。
import (
"context"
"google.golang.org/adk/telemetry"
)
func main() {
ctx := context.Background()
// 初始化遥测,并启用提示词内容日志记录
tp, err := telemetry.New(ctx,
telemetry.WithGenAICaptureMessageContent(true),
// 添加其他选项,如 WithOtelToCloud(true) 用于 GCP 导出
)
if err != nil {
// 处理错误
}
defer tp.Shutdown(ctx)
// 注册为全局 OTel 提供者
tp.SetGlobalOtelProviders()
// 你的 ADK 智能体代码...
}
通用日志记录¶
通用事件(如服务器启动或 HTTP 请求)使用标准 Go log 包进行记录。默认情况下,这些日志会写入 stderr。
使用 ADK Go Launcher 配置日志记录¶
当使用 ADK Go full.Launcher 或 prod.Launcher 时,遥测会自动初始化。你可以使用 -otel_to_cloud 标志启用 GCP 导出:
如何阅读和理解日志¶
日志的结构取决于你的配置。通过 OpenTelemetry 发出的结构化生成式 AI 日志遵循 生成式 AI 语义约定 (Semantic Conventions for GenAI)。
Python 日志条目示例¶
| 日志段 | 格式说明符 | 含义 |
|---|---|---|
2025-07-08 11:22:33,456 |
%(asctime)s |
时间戳 |
DEBUG |
%(levelname)s |
严重程度级别 |
google_adk.models.google_llm |
%(name)s |
日志记录器名称(生成日志的模块) |
LLM Request: contents { ... } |
%(message)s |
实际日志消息 |
通过阅读日志记录器名称,你可以立即定位日志的来源并了解其在智能体架构中的上下文。
使用日志进行调试:实际示例 (Python)¶
场景:你的智能体没有产生预期的输出,你怀疑发送给 LLM 的提示词是不正确的。
步骤:
- 启用 DEBUG 日志记录:在你的
main.py中,按照配置示例所示将日志级别设置为DEBUG。 - 运行你的智能体:像往常一样执行智能体的任务。
- 检查日志:在控制台输出中查找来自
google_adk.models.google_llm日志记录器且以LLM Request:开头的消息。... 2025-07-10 15:26:13,778 - DEBUG - google_adk.google.adk.models.google_llm - Sending out request, model: gemini-2.0-flash, backend: GoogleLLMVariant.GEMINI_API, stream: False 2025-07-10 15:26:13,778 - DEBUG - google_adk.google.adk.models.google_llm - LLM Request: ----------------------------------------------------------- System Instruction: You roll dice and answer questions about the outcome of the dice rolls. You can roll dice of different sizes. You can use multiple tools in parallel by calling functions in parallel(in one request and in one round). It is ok to discuss previous dice roles, and comment on the dice rolls. When you are asked to roll a die, you must call the roll_die tool with the number of sides. Be sure to pass in an integer. Do not pass in a string. You should never roll a die on your own. When checking prime numbers, call the check_prime tool with a list of integers. Be sure to pass in a list of integers. You should never pass in a string. You should not check prime numbers before calling the tool. When you are asked to roll a die and check prime numbers, you should always make the following two function calls: 1. You should first call the roll_die tool to get a roll. Wait for the function response before calling the check_prime tool. 2. After you get the function response from roll_die tool, you should call the check_prime tool with the roll_die result. 2.1 If user asks you to check primes based on previous rolls, make sure you include the previous rolls in the list. 3. When you respond, you must include the roll_die result from step 1. You should always perform the previous 3 steps when asking for a roll and checking prime numbers. You should not rely on the previous history on prime results. You are an agent. Your internal name is "hello_world_agent". The description about you is "hello world agent that can roll a dice of 8 sides and check prime numbers." ----------------------------------------------------------- Contents: {"parts":[{"text":"掷一个 6 面骰子"}],"role":"user"} {"parts":[{"function_call":{"args":{"sides":6},"name":"roll_die"}}],"role":"model"} {"parts":[{"function_response":{"name":"roll_die","response":{"result":2}}}],"role":"user"} ----------------------------------------------------------- Functions: roll_die: {'sides': {'type': <Type.INTEGER: 'INTEGER'>}} check_prime: {'nums': {'items': {'type': <Type.INTEGER: 'INTEGER'>}, 'type': <Type.ARRAY: 'ARRAY'>}} ----------------------------------------------------------- 2025-07-10 15:26:13,779 - INFO - google_genai.models - AFC is enabled with max remote calls: 10. 2025-07-10 15:26:14,309 - INFO - google_adk.google.adk.models.google_llm - LLM Response: ----------------------------------------------------------- Text: 我掷了一个 6 面骰子,结果是 2。 ... - 分析提示词:通过检查记录的请求中的
System Instruction、contents、functions部分,你可以验证:- 系统指令是否正确?
- 对话历史(
user和model轮次)是否准确? - 是否包含了最近的用户查询?
- 是否向模型提供了正确的工具?
- 模型是否正确调用了工具?
- 模型响应需要多长时间?
这些详细输出让你可以直接通过日志文件诊断从提示词工程到工具定义等各种问题。