OpenAgents SDK 在 openagents.observability 模块中内置了结构化日志系统,与 openagents.* logger 命名空间绑定。日志系统支持:
- 全局级别控制与按 logger 名称精细覆盖
- Rich 富文本渲染(需要
[rich]extra) - 运行时数据脱敏(API key、token、password 等)
- 前缀白名单/黑名单过滤
- 环境变量驱动配置,无需修改代码
如需观测运行时事件(tool 调用、LLM 调用、run 生命周期),请参阅本页末尾的 Event Bus 可观测性 一节。
LoggingConfig 是一个 Pydantic 模型,所有字段均可通过配置文件或环境变量设置。
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
auto_configure |
bool |
false |
若为 true,Runtime.__init__ 时自动调用 configure() |
level |
str |
"INFO" |
根 logger 级别(CRITICAL/ERROR/WARNING/INFO/DEBUG/NOTSET) |
per_logger_levels |
dict[str, str] |
{} |
按 logger 名称覆盖级别,仅对 openagents.* 命名空间有效 |
pretty |
bool |
false |
启用 Rich 富文本渲染(需要 [rich] extra) |
stream |
"stdout" | "stderr" |
"stderr" |
日志输出流 |
include_prefixes |
list[str] | null |
null |
Logger 白名单;null 表示允许全部 |
exclude_prefixes |
list[str] |
[] |
Logger 黑名单;匹配前缀的 logger 消息将被过滤 |
redact_keys |
list[str] |
["api_key", "authorization", "token", "secret", "password"] |
脱敏字段名列表(大小写不敏感) |
max_value_length |
int |
500 |
日志输出中字符串值的最大字符数,超出部分被截断 |
show_time |
bool |
true |
Rich 模式下显示时间列 |
show_path |
bool |
false |
Rich 模式下显示代码路径列 |
loguru_sinks |
list[LoguruSinkConfig] |
[] |
多 sink 日志后端(需要 [loguru] extra);与 pretty=true 互斥。详见 多 sink 日志(loguru) |
在 agent.json(或其他配置文件)中设置 logging 块,并将 auto_configure 设为 true,Runtime 初始化时会自动调用 configure():
{
"logging": {
"auto_configure": true,
"level": "DEBUG",
"pretty": true,
"stream": "stderr",
"show_time": true,
"show_path": false
}
}适合需要程序化控制日志配置的场景:
from openagents.observability.logging import configure
from openagents.observability.config import LoggingConfig
configure(LoggingConfig(
level="DEBUG",
pretty=True,
per_logger_levels={
"openagents.llm": "DEBUG",
"openagents.plugins": "WARNING",
},
))也可以直接从环境变量构建配置:
from openagents.observability.logging import configure_from_env
configure_from_env() # 读取所有 OPENAGENTS_LOG_* 环境变量无需修改任何代码,只需设置环境变量并在配置文件或代码中启用 auto_configure:
export OPENAGENTS_LOG_LEVEL=DEBUG
export OPENAGENTS_LOG_PRETTY=true
export OPENAGENTS_LOG_AUTOCONFIGURE=true所有环境变量均可与配置文件字段混合使用:环境变量优先级高于配置文件(通过 merge_env_overrides() 合并)。
| 环境变量 | 对应字段 | 类型 | 示例值 |
|---|---|---|---|
OPENAGENTS_LOG_AUTOCONFIGURE |
auto_configure |
布尔 | true |
OPENAGENTS_LOG_LEVEL |
level |
字符串 | DEBUG |
OPENAGENTS_LOG_LEVELS |
per_logger_levels |
逗号分隔键值对 | openagents.llm=DEBUG,openagents.plugins=WARNING |
OPENAGENTS_LOG_PRETTY |
pretty |
布尔 | true |
OPENAGENTS_LOG_STREAM |
stream |
字符串 | stdout |
OPENAGENTS_LOG_INCLUDE |
include_prefixes |
逗号分隔列表 | openagents.runtime,openagents.llm |
OPENAGENTS_LOG_EXCLUDE |
exclude_prefixes |
逗号分隔列表 | openagents.observability |
OPENAGENTS_LOG_REDACT |
redact_keys |
逗号分隔列表 | api_key,secret,token |
OPENAGENTS_LOG_MAX_VALUE_LENGTH |
max_value_length |
整数 | 200 |
OPENAGENTS_LOG_LOGURU_DISABLE |
(仅运行时开关) | 布尔 | 1 — 强制把非空 loguru_sinks 降级为纯文本 StreamHandler,CI / debug 逃生门 |
布尔类型接受 1、true、yes、on(大小写不敏感)为真值,其余值均为假。
!!! note "loguru_sinks 不支持 env var"
loguru_sinks 是结构化列表,无法通过环境变量表达;多 sink 配置只能通过 LoggingConfig 对象或 YAML/JSON 配置文件给出。OPENAGENTS_LOG_LOGURU_DISABLE 仅作为降级开关存在,不能用于添加 sink。
Rich 模式提供带颜色高亮、时间列、代码路径列的终端日志输出,适合本地开发和调试。
uv sync --extra rich
# 或者
pip install "io-openagent-sdk[rich]"{
"logging": {
"auto_configure": true,
"pretty": true,
"show_time": true,
"show_path": false
}
}或通过环境变量:
export OPENAGENTS_LOG_PRETTY=true!!! warning "缺少 rich 时会报错"
若 pretty=true 但 rich 未安装,configure() 会立即抛出 RichNotInstalledError,提示安装命令。这是有意为之——显式报错比静默回退为纯文本更容易排查问题。
| 字段 | 说明 |
|---|---|
show_time |
在每行左侧显示时间戳(默认 true) |
show_path |
在每行右侧显示代码文件名和行号(默认 false,会使输出变宽) |
loguru_sinks 提供第三种输出形态——和纯文本 StreamHandler、rich RichHandler 三选一。它的独占价值是多 sink + rotation/retention/compression + serialize=True 的 JSON 行:同一进程同时把彩色日志写到 stderr、把详细日志按大小轮转写到文件、把结构化 JSON 写到第三个 sink,一份 LoggingConfig 全部表达。
uv sync --extra loguru
# 或者
pip install "io-openagent-sdk[loguru]"logging:
level: INFO
pretty: false
loguru_sinks:
- target: stderr
level: INFO
colorize: true
- target: .logs/app.log
level: DEBUG
rotation: "10 MB"
retention: "7 days"
compression: gz
- target: .logs/events.jsonl
level: INFO
serialize: true
enqueue: true每个 sink 由一组字段配置,全部映射到 loguru.logger.add(...) 的同名参数。
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
target |
str |
(必填) | "stderr" / "stdout" / 文件路径 |
level |
str |
"INFO" |
sink 自己的级别下限 |
format |
str | null |
null |
loguru format 字符串;null 走 loguru 默认 |
serialize |
bool |
false |
true → 每条记录输出为一行 JSON |
colorize |
bool | null |
null |
null → loguru 自动检测(终端着色) |
rotation |
str | null |
null |
轮转策略,例如 "10 MB"、"00:00"、"1 week" |
retention |
str | null |
null |
保留时长,例如 "7 days" |
compression |
str | null |
null |
压缩格式,例如 "gz"、"zip" |
enqueue |
bool |
false |
异步 sink(进程内队列),适合多线程场景 |
filter_include |
list[str] | null |
null |
进一步按 logger 名前缀过滤(在 _openagents 标签过滤之后) |
- 与
pretty=true互斥:同时设置会在LoggingConfig校验阶段抛pydantic.ValidationError。需要彩色输出请用colorize: true的 stderr sink 表达。 - 不触碰用户自己注册的 loguru sink:每个我们注册的 sink 都带
record["extra"]["_openagents"] is True过滤器;用户在自己应用代码里from loguru import logger; logger.add(...)注册的 sink 不会收到 SDK 的记录,反之亦然。 reset_logging()只移除我们装的 sink:通过 sink ID 精准回收,绝不调用无参loguru.logger.remove()(否则会清空用户的 sink)。OPENAGENTS_LOG_LOGURU_DISABLE=1逃生门:在 CI / debug 场景下,不修改配置即可把loguru_sinks降级为纯文本StreamHandler;同时打一条 WARNING 到openagents.observability.logginglogger 提示降级。- 不覆盖 EventBus 通道:
loguru_sinks只接管库内logging.getLogger("openagents.*")的记录,不影响运行时事件(FileLoggingEventBus/OtelBridge等仍是 RuntimeEvent 的归档/导出工具,作用域不同)。
!!! warning "缺少 loguru 时会报错"
若 loguru_sinks 非空但 loguru 未安装,configure() 会立即抛 LoguruNotInstalledError,提示 pip install io-openagent-sdk[loguru]。这是有意为之——显式报错比静默回退到纯文本更易排查。如需 CI / debug 场景下临时降级,使用 OPENAGENTS_LOG_LOGURU_DISABLE=1 即可。
RedactFilter 在日志输出时对匹配 redact_keys 的 key 进行遮蔽,原始数据对象不受影响。
默认脱敏字段(大小写不敏感):api_key、authorization、token、secret、password
脱敏示例:
import logging
logger = logging.getLogger("openagents.mymodule")
logger.info("Calling API", extra={"api_key": "sk-abc123", "model": "claude-3"})
# 输出:api_key=*** model=claude-3值截断:超过 max_value_length(默认 500)字符的字符串值在日志中会被截断,但原始数据不变。
自定义脱敏字段:
{
"logging": {
"redact_keys": ["api_key", "authorization", "token", "secret", "password", "x_api_secret"]
}
}通过 include_prefixes 和 exclude_prefixes 可以精确控制哪些 logger 的消息会出现在输出中:
{
"logging": {
"level": "DEBUG",
"include_prefixes": ["openagents.runtime", "openagents.llm"],
"exclude_prefixes": ["openagents.observability"]
}
}include_prefixes为null(默认)时,允许所有openagents.*下的消息通过。exclude_prefixes优先级高于include_prefixes:若一个 logger 名同时匹配两者,黑名单胜出。
通过 per_logger_levels 可以让某个 logger 比根级别更详细或更安静:
{
"logging": {
"level": "INFO",
"per_logger_levels": {
"openagents.llm": "DEBUG",
"openagents.plugins.loader": "WARNING"
}
}
}!!! note "仅作用于 openagents.* 命名空间"
per_logger_levels 中填写 openagents.* 以外的 logger 名会被忽略,并打印一条警告。SDK 从不修改第三方 logger 或根 logger。
configure() 是幂等的:可安全地从 Runtime.reload() 中重复调用。每次调用前都会先执行 reset_logging(),移除所有由 SDK 安装的 handler,然后重新安装新配置的 handler。
reset_logging() 会:
- 移除所有带有
_openagents_installed=True标记的 handler - 将
openagentslogger 的propagate恢复为True - 清除根级别回到
NOTSET - 重置所有由
per_logger_levels设置过的子 logger 级别
SDK 作为库使用时:若应用不调用 configure(),openagents.* logger 下的所有消息会静默(propagate=True 且无 handler)。应用自己的 logging 配置完全不受 SDK 影响。
除结构化日志外,运行时事件(tool 调用、LLM 调用、run 生命周期等)通过 Event Bus 传播。以下内置 Event Bus 实现支持可观测性集成:
| type 键 | 说明 |
|---|---|
file_logging |
将运行时事件以 NDJSON 格式追加写入文件,适合离线分析 |
otel_bridge |
将运行时事件映射为 OpenTelemetry span,集成 Jaeger/Tempo 等后端 |
rich_console |
将运行时事件以富文本格式打印到终端(需要 [rich] extra) |
Event Bus 在配置文件的顶层 events 字段配置,参见配置参考。
{
"events": {
"type": "file_logging",
"config": {
"path": "logs/runtime_events.ndjson"
}
}
}{
"events": {
"type": "rich_console",
"config": {
"show_payload": true
}
}
}- 配置参考 —
logging块和events块的完整 JSON schema - 插件开发指南 — 自定义 Event Bus 插件
- Seams 与扩展点 —
eventsseam 的决策树