可观测与链路追踪
KsADK 提供本地 spans 和标准 OTLP HTTP traces exporter。tracing 是可选诊断能力,不应成为 quickstart 的前置条件。托管 Agent 通过 CLI 或控制台创建时默认请求可观测性,由平台注入 Langfuse 主路和 CloudMonitor 次路;只有显式传入 --no-observability 或在控制台关闭才禁用。
从 0.6.2 开始,推荐把业务代码写成 OTel-first:应用只创建 OpenTelemetry spans、span events 和 attributes,后端通过 OTEL_EXPORTER_OTLP_* 环境变量路由到 Langfuse、OTel Collector 或其他兼容后端。
本地 in-memory exporter 是最安全的公开默认值。如果外部 exporter 未配置或初始化失败,本地运行仍应继续——tracing 永远不应阻塞 quickstart。
导出路径
| 路径 | 默认行为 | 用途 |
|---|---|---|
| In-memory spans | 本地 runner 路径默认启用 | 本地 debug API 和 Web UI trace 视图 |
| Langfuse OTLP HTTP(主) | 本地设置 OTEL_EXPORTER_OTLP_* 后启用;托管环境默认由平台注入 | 发送到 Langfuse 或任意 OTLP HTTP backend |
| CloudMonitor OTLP HTTP(次) | 本地设置 CLOUD_MONITOR_OTLP_* 后启用;托管环境默认由平台注入 | 平台扩展,双写到云监控 trace 平台 |
| OTLP gRPC | 通过 enable_otlp=True 显式启用 | 兼容旧代码路径 |
| OpenInference instrumentation | best effort | 为 ADK、LangChain 等框架补充框架级 spans |
远端 exporter 应通过环境变量启用,不要在业务代码里硬编码 endpoint 或 token。
通用 OTLP HTTP
只配置通用 endpoint 时,KsADK 会自动派生 /v1/traces:
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://otel-collector.example.com/otel"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20demo-token"
agentengine run .也可以显式配置 traces 专用 endpoint、protocol 和 headers。TRACES_* 优先于通用配置:
export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://otel-collector.example.com/otel/v1/traces"
export OTEL_EXPORTER_OTLP_TRACES_HEADERS="Authorization=Bearer%20trace-token"headers 使用 OTLP 约定的逗号分隔格式,value 建议 URL encode。KsADK 会把 Bearer%20trace-token 解码为 Bearer trace-token。
如果把 Langfuse 当作 OTLP backend,也可以只配置标准 OTLP 变量:
export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://langfuse.example.com/api/public/otel/v1/traces"
export OTEL_EXPORTER_OTLP_TRACES_HEADERS="Authorization=Basic%20<base64-public-secret>,x-langfuse-ingestion-version=4"公开文档只能使用占位 key 和用户自有 endpoint,不要发布真实 trace 截图、tenant id 或私有 URL。
OTLP 双写
KsADK 收敛为每个 Python Agent 进程对应一个 TracerProvider + 两个 OTLP/HTTP BatchSpanProcessor:Langfuse 主(标准 OTEL_EXPORTER_OTLP_*)+ CloudMonitor 次(平台扩展 CLOUD_MONITOR_OTLP_*)。Langfuse CallbackHandler 路径已删除,不再通过 Langfuse SDK 上报。
两个 exporter 都运行在 Agent 进程内并直连各自 OTLP endpoint,不会部署 OpenTelemetry Collector、sidecar、额外容器或额外 Pod。
# 主路(Langfuse OTLP)
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://langfuse.example.com/api/public/otel/v1/traces"
export OTEL_EXPORTER_OTLP_TRACES_HEADERS="Authorization=Basic%20<base64-public-secret>,x-langfuse-ingestion-version=4"
# 次路(CloudMonitor OTLP,平台注入)
export CLOUD_MONITOR_OTLP_TRACES_ENDPOINT="https://cloudmonitor.example.com/v1/traces"
export CLOUD_MONITOR_OTLP_HEADERS="Ksc-Appkey=<app-key>"
agentengine run .headers value 使用 RFC 3986 percent-encode(空格 %20 非 +)。KsADK 会解码为真实 header 值后传给 OTLP exporter。
云监控 OTLP
setup_tracing() 自动探测 CLOUD_MONITOR_OTLP_* 变量,构建 CloudMonitor OTLP exporter,与主路 Langfuse OTLP 并行写入。单条 span 同时进入两个后端,共享同一 trace_id / span_id。traces 专用 endpoint、protocol 和 headers 分别优先于通用值。
| 路径 | 鉴权 | 协议 | 触发条件 |
|---|---|---|---|
| CloudMonitor OTLP exporter | Ksc-Appkey header | http/protobuf | endpoint 已设置,且 traces 专用或通用 headers 提供 Ksc-Appkey |
涉及的环境变量:
| 变量 | 敏感 | 说明 |
|---|---|---|
CLOUD_MONITOR_APP_KEY | 是 | 已废弃,过渡兼容。仅当 CLOUD_MONITOR_OTLP_TRACES_HEADERS 和 CLOUD_MONITOR_OTLP_HEADERS 都整体缺失时翻译为 Ksc-Appkey header。 |
CLOUD_MONITOR_OTLP_ENDPOINT | 否 | CloudMonitor 通用 OTLP HTTP endpoint,未设 traces 专用 endpoint 时派生 /v1/traces。 |
CLOUD_MONITOR_OTLP_PROTOCOL | 否 | CloudMonitor 通用 OTLP 协议,当前支持 http/protobuf。 |
CLOUD_MONITOR_OTLP_HEADERS | 是 | CloudMonitor OTLP 附加 headers,逗号分隔且 RFC 3986 encoded。 |
CLOUD_MONITOR_OTLP_TRACES_ENDPOINT | 否 | CloudMonitor traces 专用 endpoint,优先于通用 endpoint。 |
CLOUD_MONITOR_OTLP_TRACES_HEADERS | 是 | CloudMonitor traces 专用 headers,优先于通用 headers;已提供但缺少 Ksc-Appkey 时 fail closed。 |
CLOUD_MONITOR_OTLP_TRACES_PROTOCOL | 否 | CloudMonitor traces 专用协议,优先于通用 protocol。 |
敏感变量
标注「是」的变量为平台 Secret 或可能携带鉴权信息,不要写入公开仓库的 .env 或镜像环境变量。使用占位值或平台密钥服务下发。
最小配置示例(占位值,请替换为自有 endpoint 与 AppKey):
export CLOUD_MONITOR_OTLP_ENDPOINT="https://cloudmonitor.example.com"
export CLOUD_MONITOR_OTLP_HEADERS="Ksc-Appkey=cm-appkey-placeholder"
agentengine run .Span event 与子 span
span event 是某个 span 内的时间点事件,适合记录:
checkpoint.savedagent.run.startedanalysis.milestone- 错误提示和恢复 hint
子 span 是 trace tree 中的独立步骤,适合记录:
- tool 调用
- checkpoint 持久化
- 外部 I/O
- 报告生成
- score 计算
在 Langfuse 等后端中,子 span 通常更容易在 trace tree 或 observation 列表里看到,也更适合做 duration、status、tool name 和错误聚合。span event 通常挂在父 span 明细中,不一定会成为独立树节点。
Metadata 与 score
长周期、多用户、多实例场景建议在关键 span 上带稳定、非敏感 attributes:
ksadk.agent_idksadk.session_idksadk.user_idksadk.invocation_idksadk.account_idksadk.runtime.serviceksadk.runtime.instance_id
invocation_id 与 account_id
ksadk.invocation_id 既是 runner payload 字段,也是 ToolExecutionContext.run_id 的来源,在 trace tree 中可以把同一次调用的 runner 层与 tool 层串起来。ksadk.account_id 可作为 span attribute 上报,便于在多租户场景下按 account 聚合 trace,但不要把 account_id 对应的密钥、token 或客户名称一起写入。
评估分数建议先用后端无关的 attributes 表达:
span.set_attribute("score.name", "answer_quality")
span.set_attribute("score.value", 0.88)
span.set_attribute("score.source", "auto_evaluator")
span.set_attribute("score.comment", "Report covers evidence and next steps.")如果后端是 Langfuse,平台服务或 OTel Collector 可以把 score.* attributes 转成 Langfuse native score。KsADK 业务代码不需要直接 import Langfuse SDK,这样后续替换后端时改动更小。
不要把 raw prompt、凭证、私有 URL、客户名称或上传文件正文写入 span attributes。
故障排查
| 现象 | 可能原因 | 检查 |
|---|---|---|
| 本地 trace 视图为空 | 没有运行产生 spans,或 tracing 被禁用 | 先跑一次请求,再确认本地服务启用了 tracing |
| Langfuse 没有收到 spans | endpoint、headers、TLS 或 auth 不匹配 | 检查 OTEL_EXPORTER_OTLP_TRACES_ENDPOINT 和 OTEL_EXPORTER_OTLP_TRACES_HEADERS(value 需 RFC 3986 encode) |
| 云监控看不到 spans | 选中的 traces/通用 headers 缺 Ksc-Appkey,或 endpoint 未派生 /v1/traces | 优先检查 CLOUD_MONITOR_OTLP_TRACES_HEADERS,再检查通用 headers 和 endpoint;旧 AppKey 只在两个 headers 变量都未设置时 fallback |
| 双写一边缺失 | 单后端故障 | 主路故障时次路仍可用,反之亦然;Agent 业务不阻断 |
| score 没有显示为 native score | 后端没有把 score.* attributes 做映射 | 在 Collector 或平台服务侧增加转换逻辑 |
| 框架 spans 较少 | optional instrumentation 未安装或未生效 | 安装 tracing extra,并检查框架 instrumentation |
公开文档规则
- 使用占位 key 和用户自有 endpoint。
- 不提交包含 tracing 凭证的
.env。 - 不发布私有 trace id、tenant id、客户名称或真实截图。
- 私有 Collector 地址和租户路由写在内部 runbook,不放进公开 SDK 仓库。