跨组件 Trace
ADX 使用 OpenTelemetry SDK 和 W3C traceparent / tracestate。采样与导出默认关闭;开启后通过 OTLP/HTTP 向部署环境的 Collector 发送。日志采集与现有 Prometheus 指标继续独立工作。
请求与任务边界
- Ingress 接收 HTTP 上下文、创建
HTTP 方法 + 路由模板Span,并将子上下文传给 Environment API、Execd HTTP 或 Relay CONNECT。 - Rust API Server 创建以 HTTP 方法和接口模板命名的服务端 Span,gRPC 客户端拦截器携带上下文;节点地址缓存命中后的直达操作也经过同一拦截器。
- Coordinator 在创建、查询、提交和快照 RPC 入口接收上下文;独立创建/提交任务显式携带子 Span。周期节点注册/心跳及内部调度轮次不创建 Span。中心排队耗时仍包含在该请求的
coordinator.createSpan 中,不额外导出服务多个请求的调度轮次。 - adxlet 在每个 Environment 命令封装中保存
environment.queueSpan,串行执行时创建environment.execute。创建链路在执行 Span 内继续划分environment.runtime.start、environment.runtime.ready、environment.route.activate和environment.state.commit,分别覆盖执行后端启动、Execd 就绪、本机路由绑定和持久化提交。调用方断开后,已接受操作继续保持原上下文;状态提交继续向 Coordinator 透传。 - Relay 为 CONNECT 生命周期记录 Span。它转发的是字节流,Execd 的 HTTP Span 延续 Ingress 注入的上下文;两者可能是同一请求的并列子 Span。
- Execd 在解析 HTTP 头后创建以 HTTP 方法和接口模板命名的 Span,Environment ID 作为属性;
/invoke另外记录有界的rpc.method操作名。此 Span 覆盖 HTTP 操作处理;异步提交命令之后的用户进程运行时间尚不属于该 HTTP Span。
HTTP Span 包含 http.request.method、http.route,Ingress/API Server 返回后记录 http.response.status_code。HTTP Span 当前覆盖生成响应的处理阶段;创建等流式响应可能先返回,而后台任务继续运行。Span 时长不等于 SDK 等待完整操作的总耗时,完整链路与后台执行阶段需打开 Trace 查看。实例/快照/密钥 ID 使用 {id} 占位,不记录查询参数、用户端口路径或文件路径。未知接口统一使用 /unmatched。
创建、执行、删除是独立请求,各有自己的 Trace,通过 Environment ID 关联。SDK 目前没有新增自动事务级根 Span。
sandboxd 是独立运行时服务。本版本在 adxlet→sandboxd 的 gRPC 边界停止 Trace 传播;sandboxd 原有的资源指标和日志采集不依赖该传播,也不将 sandboxd span 计入本版本的端到端 Trace 验收。
配置与部署
通过统一部署配置中对应服务的 env 设置:
{
"ADX_TRACE_ENABLED": "true",
"ADX_TRACE_SAMPLE_RATIO": "0.1",
"OTEL_EXPORTER_OTLP_TRACES_ENDPOINT": "http://127.0.0.1:4318/v1/traces",
"OTEL_BSP_MAX_QUEUE_SIZE": "2048",
"OTEL_BSP_MAX_EXPORT_BATCH_SIZE": "512",
"OTEL_BSP_SCHEDULE_DELAY": "1000"
}
ADX_TRACE_SAMPLE_RATIO 在 0–1 之间。开启时使用父采样决定,根请求按比例采样;要完全关闭导出,应设置 ADX_TRACE_ENABLED=false。不合法的布尔值或比例使启动失败。
build/observability/collector.json 增加 OTLP HTTP 接收及 Trace 导出流水线,默认监听 127.0.0.1:4318。节点服务可访问本机 Collector;Execd 使用 adxlet 配置的 execd_env 设置上述变量,地址须为实例网络可达的节点/Collector 地址,不能把实例自己的 localhost 当作宿主 Collector。按部署的私网边界调整监听地址和访问规则。
本地及基础 K8s 验收使用 Collector sidecar/独立进程的 14317 接口,发送到测试接收端;这些测试地址不是产品默认值。
在 Grafana Explore 查询接口
adx-schedule 顶部的 Explore 接口查询 打开原生 Tempo Explore,带入 adx_env,
使用最近 6 小时、50 条 Trace、每条最多 3 个匹配 Span 的查询。入口固定
Table Format = Spans,选择 name、resource.service.name、
span.http.response.status_code、span.rpc.method;排除 /unmatched、健康和指标请求。
Name 显示 HTTP 方法和接口模板,rpc.method 区分 Execd 的 /invoke 操作;点击 Span ID
查看整条链路。Span 表不生成 Traces 表的 nested JSON 列。
这是查询入口的预设,不修改 Grafana 全局默认表格式;手工进入 Explore 时需在 Search Options 选择 Spans。原生 Explore 仍保留 Trace Service / Trace Name 根 Span 列, 没有看板的列隐藏配置。若客户端注入 traceparent 却没有导出父 Span,根信息会缺失; Name 和 service.name 仍来自实际匹配 Span。不要为改善展示伪造根 Span 或丢弃远端父上下文。
故障、开销与字段
业务线程只向标准 SDK 的有界批处理队列提交 Span。单次 Rust 导出超时为2秒;退出等待上限3秒。队列满时 SDK 可丢弃 Trace,不承诺 Trace 持久化或无限重试。Collector 独立配置磁盘发送队列,只有 Collector 已接收的内容才进入该队列。
Coordinator 和 adxlet 的 /metrics 增加 adx_trace_exported_spans_total、adx_trace_export_failed_spans_total,统计 SDK 导出成功/最终失败的 Span 数;不把它们解释为队列满丢弃数。Rust SDK 会记录开始丢弃及退出时的总丢弃诊断;当前没有统一暴露各语言的实时队列满丢弃计数。Collector 的接收/拒绝/排队/导出指标另外采集。
API 请求日志包含 Trace ID 和 Span ID;adxlet 操作完成日志包含 traceparent。业务字段只记录操作、方法、路由模板、状态、Environment ID等;Trace不添加API Key、请求正文、命令内容、文件内容或用户代码。传播器仅处理W3C Trace字段,不传播 baggage。
验收
真实 Redis 合约测试验证连续心跳和资源不足的调度轮次不导出 Span,而创建请求保留调用方 Trace ID、排队期限与超时清理;用例纳入 control-rpc / api-control 组件套件。组件测试覆盖跨任务/队列的并发隔离、调用方取消后已接受操作继续关联、采样关闭、导出端不可用时提交不阻塞、失败计数与退出时间。真实部署验收检查完整创建链路的Trace ID,以及每个 environment.execute 的父Span确为同Trace内的 environment.queue,同时核对EXECD收到远端上下文。
本地与Rust API Server重写后的 Buildkite #24 正式验收 已通过;统一实时队列满丢弃指标后置,详见 事项清单。节点恢复后产生新的后台Trace,以Environment/代次/状态关联,不承诺跨进程重启续接已结束的Span。
后台 Trace 裁剪验证(2026-10-08)
background_traces 使用隔离的真实 Redis 和内存 Span exporter,验证首次注册、
连续心跳及资源不足的中心调度轮次不产生心跳/轮次 Span;创建请求的 Trace ID、
父 Span、中心排队期限和超时后的队列清理保持有效。用例已加入 control-rpc
和 api-control 的 CI 驱动。另行通过原有 mTLS 节点心跳过期、对账及旧会话隔离
RPC 用例;CI harness、全工作区 Clippy、格式和文档检查通过。
日志位于执行工作区 out/otel-readability/background-*.log。本次验证为源码组件
回归;cn-north-4 的日志正文/HTTP Trace 验收镜像尚未包含此次后台埋点裁剪,
需要后续发布镜像后才停止产生这两类旧 Span。历史 Trace 保留原记录。