跳至正文

可观测性与调用链 ​

运行变慢或失败时,从运行记录打开“详情 → 查看调用链”,查看入口解析、可信上下文、业务授权、主/子智能体、知识检索、模型、工具与等待确认的实际耗时。运维人员可将进程指标接入 Prometheus,将抽样节点导出到支持 OTLP/HTTP JSON 的 Collector。

在控制台排障 ​

  1. 打开顶部“运行中心 → 运行观测”,选择最近 1 小时、24 小时或 7 天。
  2. 查看各执行环节的平均、最长及 P95 上界,定位耗时较高或错误较多的环节。
  3. 点击“查看运行与调用链”,在具体运行详情中查看节点的资源精确版本、Span、父 Span 和开始时间。
  4. 平台管理员另可查看采集队列、导出状态、丢弃与认证拒绝计数。应用管理员只能查看自己应用的摘要和节点。

统计基于窗口内保留的抽样节点,包含嵌套调用;不能作为完整业务请求总数。P95 为固定桶的上界,不是精确分位数;超过 600 秒显示 > 600 s。运行中心的“累计运行”依然来自业务运行记录。

节点异步保存,终态后通常短暂延迟才可见,可以点击刷新。rootRecorded 只表示运行终态节点已记录,不保证子节点没有丢弃。旧版运行没有回填;未抽样、过期或达到容量的运行可能只有部分或没有节点。完整审计与业务执行账本独立保存。

配置留存和采样 ​

环境变量默认范围与作用
SPARKTIDE_TRACE_RETENTION_HOURS1681–8760;到期自动清理调用链元数据,不删除审计、原件、会话或执行账本
SPARKTIDE_TRACE_CAPACITY1000001000–1000000;全库 Span 上限,超过后丢弃新的观测节点并计数
SPARKTIDE_TRACE_SAMPLE_PERCENT1000–100;按 Trace ID 决定是否采集;0 关闭节点采集,进程耗时指标继续计量
SPARKTIDE_OTLP_ENDPOINT空默认不导出;Collector 完整 URL,路径以 /v1/traces 结尾
SPARKTIDE_OTLP_ORIGINS空独立的精确 origin 白名单,逗号分隔;业务 Provider 白名单不授予观测出口权限
SPARKTIDE_OTLP_TOKEN空可选 Collector Bearer 凭据,由部署环境注入,不写入业务配置、Git 或浏览器

每个 Run 最多保存 512 个节点。元数据等待队列 1024,导出队列 256,每批最多导出 32。采集写入发生在业务提交后,由独立线程保存;观测失败、队列满或 Collector 拒绝不会重试业务工具,也不会回滚业务事务。配置变更需要重启。

修改到期时间会影响已有元数据的下一次清理。过期节点不能从运行事件自动恢复;需要长期保存时提前将外部 Collector 配置为自己的持久化存储。

接入 Prometheus ​

采集路径为 /v1/operations/metrics,需要平台管理员凭据;/actuator/health 仍只表示服务健康。将管理员凭据放入采集服务器的受限文件,不放在前端应用或 URL 中。已有 Prometheus 的配置可以加入:

yaml
scrape_configs:
  - job_name: sparktide
    scheme: https
    metrics_path: /v1/operations/metrics
    authorization:
      type: Bearer
      credentials_file: /run/secrets/sparktide_monitor_token
    static_configs:
      - targets: ["platform.example.com"]

platform.example.com 是地址占位,请换成自己的平台。多实例分别采集每个实例,避免负载均衡器随机选实例导致计数错位。

指标用途
sparktide_operation_duration_seconds固定 operation / outcome 标签的累计耗时直方图;run 包含排队及确认等待,其他节点可嵌套
sparktide_model_ttft_seconds首个非空模型文字耗时;非流式包含整轮响应等待,纯工具返回没有文字样本
sparktide_active_runs固定运行状态的当前任务数
sparktide_trace_export_queue当前外部导出队列大小
sparktide_span_dropped_total元数据队列、存储或容量导致的丢弃,以及未提交业务的采集丢弃
sparktide_exported_total / export_rejected_totalCollector 接受或明确拒绝的节点数
sparktide_export_failed_total / export_dropped_total失败批次数和丢弃节点数;没有自动重试
sparktide_http_rejected_total / quota_rejected_totalHTTP 401/403 和 429 拒绝计数;429 包含限流及配额拒绝

耗时单位是秒,标签不包含应用、用户、租户、Trace ID 或资源编号。Prometheus 指标属于当前进程,重启归零;应用窗口摘要来自数据库中当前保留的元数据。HTTP 耗时测量 Servlet 请求处理,不代表完整 SSE 连接持续时间。

示例查询模型调用 P95,按实例采集后合并固定桶:

promql
histogram_quantile(0.95,
  sum by (le) (rate(sparktide_operation_duration_seconds_bucket{operation="model"}[5m]))
)

导出到 Collector ​

在平台进程或容器环境中配置自己的 Collector:

dotenv
SPARKTIDE_OTLP_ENDPOINT=https://collector.example.com/v1/traces
SPARKTIDE_OTLP_ORIGINS=https://collector.example.com
# 可选,真实值通过受控 secret 注入:
SPARKTIDE_OTLP_TOKEN=

路径可以有前缀,但必须以 /v1/traces 结尾。默认要求 HTTPS,禁止 URL 内凭据、查询参数和跳转。本机隔离验证才显式开启已有 SPARKTIDE_ALLOW_HTTP=true。部署 Docker 时把这些变量添加到平台服务的 environment;Collector 需自行配置 OTLP HTTP JSON 接收器、存储、认证和访问控制。

出口发送固定服务名称、Trace/Span/父 Span、时间、结果及受限资源版本关联;不导出消息、工具参数、业务返回、用户/租户、凭据或供应商错误正文。HTTP 服务端节点只导出至 Collector,不计入某个 Run 的持久化节点列表。

请求上限 5 秒,不跟随跳转、不自动重试;HTTP 非 200、非法回执或超过 64 KiB 的响应会计为导出失败。OTLP partialSuccess.rejectedSpans 分别计入接受和拒收数,不重新发送已部分接受的批次。队列是内存缓冲,进程异常退出可能丢失待导出节点,不用它代替审计或交付保证。

API 和权限 ​

API权限结果
GET /v1/apps/{app}/observability?hours=24本应用 APP_ADMIN / PLATFORM_ADMIN1–168 小时的固定操作摘要,默认 24
GET /v1/apps/{app}/runs/{runId}/trace本应用管理员;USER 必须是仍授权的所有者RunTrace 元数据;他人运行不可见
GET /v1/operations/observabilityPLATFORM_ADMIN留存、容量、队列和当前进程计数;不返回出口地址或密钥
GET /v1/operations/metricsPLATFORM_ADMINPrometheus text/plain version 0.0.4;错误仍是统一 JSON

完整字段与类型见运维 API、任务 API和数据结构。

Java、Kotlin 和前端接入 ​

平台接受有效 W3C v00 traceparent,为请求和运行建立新的子 Span,并通过同一 header 传给模型、工具和业务回调。无效头被丢弃,baggage / tracestate 不透传。关联头不参与身份、授权或幂等摘要,不能替代 Bearer 凭据。外部采样标志不能提高本地配置的采样比例。

Java SDK 请求自动传播当前作用域;工具、知识、业务权限和模型回调处理器自动绑定来访上下文。已有业务 OpenTelemetry 上下文可以通过 header 提取桥接;这套 SDK 不自动导出业务服务内部方法。

java
import dev.sparktide.sdk.TraceContext;

// incomingTraceparent 来自可信 HTTP 框架读取的关联头,仍要独立校验身份。
try (var scope = TraceContext.accept(incomingTraceparent)) {
    var run = userClient.chat("查询当前设备", null, "request-unique-key");
    executor.execute(TraceContext.wrap(() -> {
        // 此处的 PlatformClient 请求继续使用捕获的上下文。
    }));
}
var trace = userClient.runTrace("monitor-app", runId).toCompletableFuture().get();
var summary = managerClient.observability("monitor-app", 24).toCompletableFuture().get();

Java Scope 必须在创建线程关闭。Kotlin 用协程上下文跨挂起和调度器切换,不能跨线程关闭普通 Java Scope:

kotlin
import dev.sparktide.sdk.TraceContext
import dev.sparktide.sdk.kotlin.asCoroutineContext
import dev.sparktide.sdk.kotlin.awaitResult
import kotlinx.coroutines.withContext

val trace = TraceContext.parse(incomingTraceparent).orElseGet(TraceContext::fresh).child()
withContext(trace.asCoroutineContext()) {
    val run = userClient.chat("查询当前设备", null, "request-unique-key").awaitResult()
    // 可切换 Dispatchers.IO,关联上下文随协程恢复。
}

Kotlin 注解工具、知识、业务 Provider 与模型适配器会将回调上下文带入自己创建的协程。Java 业务适配器自行提交线程池时使用 TraceContext.wrap,或由业务框架负责传播。

前端 SDK 的 runTrace 查询保持业务凭据,不为业务浏览器注入平台管理员令牌:

typescript
const trace = await client.runTrace(runId, { signal: abortController.signal })
for (const span of trace.items) {
  console.log(span.operation, span.durationMs, span.outcome)
}

已有浏览器遥测可在 SparkTideClient 配置可选 traceparent: () => currentHeader,提供合法 v00 header;不配置时保留默认请求行为。旧平台尚无本页接口时明确返回 404,不将其当成空的成功结果。

排查采集缺失 ​

现象处理
Run 已结束但节点暂为空刷新;检查运行是否是新版、已抽样及是否到期
只有部分节点查 span_dropped;容量上限、队列满或存储异常不会回滚业务
导出一直失败查 Collector URL、独立 origin 白名单、HTTPS、网络、凭据和 OTLP HTTP JSON 接收器
导出队列积压检查 Collector 延迟、拒收/失败计数,评估降低采样并扩大外部接收能力
Trace 在业务线程或协程中断开使用 Java wrap / Kotlin asCoroutineContext,检查业务内部异步客户端是否继续传播
指标无法采集使用平台管理员 Bearer;检查网关是否允许 /v1/operations/metrics

接口遵循 W3C Trace Context、OTLP JSON及 Prometheus 文本格式。具体 Collector、供应商网络及生产监控存储需在部署环境验收。

适用版本:0.1 发布线 · 最近核对:2026-10-03 · SparkTide 产品文档

汇聚智能,驱动涌现。