Skip to content

Latest commit

 

History

History
327 lines (248 loc) · 13.3 KB

File metadata and controls

327 lines (248 loc) · 13.3 KB

Trace 输出

English | 简体中文

Trace 输出会将 GenAI 活动导出为 OpenTelemetry Trace。适用于在 Trace 或 APM 后端中分析会话、轮次、模型调用和工具调用。

Trace 输出和日志输出是分开的。SLS、JSONL、HTTP 接收事件记录;OTLP Trace 输出会将这些记录转换为 Trace spans。

通用 OTLP Trace 输出

{
  "collectTrace": true,
  "otlpTrace": {
    "endpoint": "https://otel-collector.example.com",
    "headers": {
      "Authorization": "Bearer token"
    },
    "serviceName": "loongsuite-pilot",
    "resourceAttributes": {
      "deployment.environment": "prod"
    },
    "captureMessageContent": false,
    "debug": false,
    "turnIdleTimeoutMs": 0
  }
}
配置项 说明
collectTrace Trace 上报总开关。
otlpTrace.endpoint OTLP HTTP base URL。如果路径未以 /v1/traces 结尾,Pilot 会自动追加。
otlpTrace.headers 发送到 OTLP endpoint 的请求头。
otlpTrace.serviceName 导出 span 使用的 service name。
otlpTrace.resourceAttributes 额外 OpenTelemetry resource attributes。
otlpTrace.captureMessageContent Trace 输出是否可以包含消息内容。
otlpTrace.debug 开启 Trace 转换 debug 本地输出。
otlpTrace.turnIdleTimeoutMs 可选的 turn 级 Trace 聚合空闲超时。

环境变量:

环境变量 说明
LOONGSUITE_PILOT_COLLECT_TRACE 设置为 false0 可关闭 Trace 上报。
LOONGSUITE_PILOT_OTLP_ENDPOINT OTLP Trace endpoint。
LOONGSUITE_PILOT_OTLP_HEADERS OTLP 请求头 JSON 字符串。

ARMS/CMS 兼容 Trace 输出

Pilot 也支持 CMS 风格的 Trace 配置:

{
  "collectTrace": true,
  "cms": {
    "licenseKey": "your-license-key",
    "endpoint": "https://your-arms-endpoint/v1/traces",
    "workspace": "your-workspace",
    "debug": false
  }
}

环境变量:

环境变量 说明
LOONGSUITE_PILOT_CMS_LICENSE_KEY CMS 或 ARMS license key。
LOONGSUITE_PILOT_CMS_ENDPOINT CMS 或 ARMS Trace endpoint。
LOONGSUITE_PILOT_CMS_WORKSPACE workspace header 值。

多 Trace 后端

Trace 导出会把同一批转换后的 span 同时发往所有已配置的后端(转换一次,导出时扇出)。后端来自以下配置的并集:

  • otlpTrace(通用 OTLP,用户配置)
  • cms(ARMS/CMS 简写,用户配置)
  • innerTrace.otlp[]innerTrace.cms[](托管后端,见下)

行为变更提示: otlpTracecms 现在是叠加(并集)关系,不再互斥。旧版本中同时配置两者只会使用 otlpTrace;升级后 span 会同时投递到两者——如不希望重复投递,请检查配置。

后端会按"规范化 URL + 完整请求 headers"去重,因此把同一个后端列两遍(例如既作为用户后端又作为托管后端)只会导出一次;URL 相同但鉴权 header / workspace / license 不同的两个后端会被视为不同后端各自保留。

共享 vs 单后端设置(span 按不同 service.name 各转换一次):

  • 所有后端共享: resourceAttributescaptureMessageContentresourceAttributeKeysspanAttributePassthroughPrefixesmaxExportBatchBytesturnIdleTimeoutMs
  • 每后端独立: endpoint URL、headers、compression,以及 service.name(见下文——用户后端与托管后端可不同)。

某个后端失败会被隔离——不会阻塞健康后端,其失败 span 会单独落盘到 ~/.loongsuite-pilot/logs/otlp-failed/<service>-<agent>__<后端名>.jsonl

托管后端(configs/inner/data_config.json)

托管/受管部署可通过 ~/.loongsuite-pilot/configs/inner/data_config.json(与托管 SLS endpoint 复用同一文件)下发额外的 trace 后端。这些后端会追加到用户在 config.json 中配置的后端之上:

{
  "sls": [ /* 托管 SLS endpoint(不变) */ ],
  "serviceNamePrefix": "managed-service",
  "otlp": [
    {
      "name": "team-collector",
      "endpoint": "https://collector.internal:4318",
      "headers": { "x-token": "..." },
      "compression": "gzip"
    }
  ],
  "cms": [
    {
      "name": "managed-arms",
      "endpoint": "https://proj-xxx.../apm/trace/opentelemetry",
      "licenseKey": "...",
      "workspace": "...",
      "project": "..."
    }
  ]
}
字段 适用 说明
serviceNamePrefix 顶层 所有托管后端的 service name 前缀——trace(otlp[]/cms[],作为 service.name)与 log(sls[],作为 __service_name__ tag)——用于与用户后端区分。可选;省略时回退到用户的 serviceNamePrefix(即不做区分)。
otlp[].name / cms[].name 两者 用于日志与失败日志文件名的标签。可选(默认 inner-otlp-<i> / inner-cms-<i>)。
otlp[].endpoint otlp OTLP HTTP 基础 URL(自动补 /v1/traces)。
otlp[].headers otlp 请求 header(如鉴权 token)。
otlp[].compression otlp gzip(默认)或 none
cms[].endpoint cms ARMS/CMS trace endpoint。
cms[].licenseKey cms 作为 x-arms-license-key 发送。
cms[].project cms 作为 x-arms-project 发送。省略时从 endpoint 域名提取。
cms[].workspace cms 作为 x-cms-workspace 发送。

每个 cms[] 条目会展开为一个带 x-arms-* / x-cms-* header 的 OTLP 后端;只要存在 CMS 后端,就会附加 acs.arms.service.feature=genai_app 资源属性(如上所述为共享)。此处设置 serviceNamePrefix 后,托管后端会以 <serviceNamePrefix>-<agent> 上报,用户后端仍用用户前缀;此时 span 会按不同 service.name 各转换一次(通常两次——用户与托管)。托管配置格式错误(例如 otlp/cms 写成非数组)会被忽略,而不会导致采集失败。

后端接入示例

Jaeger

Jaeger 原生支持 OTLP 数据接收。使用 v2 镜像快速搭建本地环境:

docker run -d --name jaeger \
  -p 16686:16686 \
  -p 4317:4317 \
  -p 4318:4318 \
  cr.jaegertracing.io/jaegertracing/jaeger:2.19.0

注意: Pilot 使用 HTTP/protobuf 协议进行 OTLP 导出(端口 4318)。端口 4317(gRPC)仅为其他可能需要的工具暴露。

配置 Pilot:

{
  "collectTrace": true,
  "otlpTrace": {
    "endpoint": "http://localhost:4318",
    "serviceName": "loongsuite-pilot"
  }
}

或通过环境变量:

export LOONGSUITE_PILOT_OTLP_ENDPOINT=http://localhost:4318
export LOONGSUITE_PILOT_COLLECT_TRACE=true

打开 http://localhost:16686,选择 service name 查看 Trace。

Langfuse

Langfuse 是一个 LLM 可观测平台,原生支持 OTLP 接入,提供成本追踪、Token 用量、Prompt/Completion 内容等 LLM 专属视图。

1. 启动 Langfuse(自部署):

mkdir -p ~/langfuse && cd ~/langfuse
curl -sLO https://raw.githubusercontent.com/langfuse/langfuse/v3.187.0/docker-compose.yml

# 生成随机密钥(生产环境请勿使用占位符)
umask 077
cat > .env << EOF
NEXTAUTH_SECRET=$(openssl rand -base64 32)
SALT=$(openssl rand -base64 32)
ENCRYPTION_KEY=$(openssl rand -hex 32)
LANGFUSE_INIT_ORG_NAME=MyOrg
LANGFUSE_INIT_PROJECT_NAME=loongsuite-pilot
LANGFUSE_INIT_PROJECT_PUBLIC_KEY=pk-lf-my-public-key
LANGFUSE_INIT_PROJECT_SECRET_KEY=sk-lf-my-secret-key
LANGFUSE_INIT_USER_EMAIL=admin@example.com
LANGFUSE_INIT_USER_NAME=admin
LANGFUSE_INIT_USER_PASSWORD=$(openssl rand -base64 16)
TELEMETRY_ENABLED=false
EOF

docker compose up -d

安全提示: 上述 .env 文件会自动生成随机密钥。umask 077 确保文件仅当前用户可读。启动服务前请检查生成的 .env 文件,并记录生成的登录密码。

2. 配置 Pilot:

Langfuse OTLP endpoint 需要 Basic 认证,格式为 Base64(public_key:secret_key)。推荐通过环境变量配置,避免将凭证写入配置文件:

LANGFUSE_AUTH=$(printf '%s' 'pk-lf-my-public-key:sk-lf-my-secret-key' | base64 | tr -d '\n')

export LOONGSUITE_PILOT_COLLECT_TRACE=true
export LOONGSUITE_PILOT_OTLP_ENDPOINT=http://localhost:3000/api/public/otel
export LOONGSUITE_PILOT_OTLP_HEADERS="{\"Authorization\": \"Basic $LANGFUSE_AUTH\"}"

Pilot 会将 Trace 发送到 http://localhost:3000/api/public/otel/v1/traces/v1/traces 后缀自动追加)。

也可以添加到 ~/.loongsuite-pilot/config.json(不推荐在共享或版本控制环境中使用):

{
  "collectTrace": true,
  "otlpTrace": {
    "endpoint": "http://localhost:3000/api/public/otel",
    "headers": {
      "Authorization": "Basic <base64-encoded-credentials>"
    },
    "serviceName": "loongsuite-pilot"
  }
}

打开 http://localhost:3000,进入 Traces 页面查看 Agent 会话,包括模型名称、Token 用量和费用详情。

注意: Langfuse 使用 HTTP 接收 OTLP 数据,不支持 gRPC(端口 4317)。LLM 消息内容默认包含在 Trace 中(captureMessageContent 默认为 true)。如需关闭,请在配置中显式设置 captureMessageContentfalse

Trace 中的内容采集

如果开启消息内容采集,Trace span 可能包含敏感内容。敏感或团队统一管理的环境建议:

{
  "otlpTrace": {
    "captureMessageContent": false
  },
  "agents": {
    "claude-code": { "captureMessageContent": false },
    "codex": { "captureMessageContent": false },
    "cursor": { "captureMessageContent": false }
  }
}

如果 Trace 数据可能包含密钥,也建议开启 数据脱敏

自定义 Span 属性

有两类额外属性可以附加到 trace span 上:

1. Git/工作区属性(自动):当 agent 上报了工作目录时,span 会自动带上 git.repogit.branchgit.domainworkspace.current_root(由本地 git 仓库推断)。这几个字段同时也会出现在 event log(SLS / JSONL)中。

2. 用户自定义属性:从三个来源给 span 附加任意键值对,优先级 config < env < 文件。与上面的 git 字段不同,这些只写入 trace span(不进 event log / SLS / JSONL):

  • config.jsonglobalSpanAttributes(启动时读一次):

    { "globalSpanAttributes": { "team": "infra", "deployment.env": "prod" } }
  • 环境变量 OTEL_SPAN_ATTRIBUTES(OTel 格式,启动时读一次):

    export OTEL_SPAN_ATTRIBUTES="team=infra,deployment.env=prod"
  • 可变文件 ~/.loongsuite-pilot/span-attributes.json{"key":"value"}),改动后会被重新读取,无需重启。推荐用 CLI 管理(而非手动编辑):

    loongsuite-pilot span-attr set release 2026.07
    loongsuite-pilot span-attr set oncall alice
    loongsuite-pilot span-attr list
    loongsuite-pilot span-attr unset oncall
    loongsuite-pilot span-attr clear

说明:

  • 值均为字符串。文件改动会在下一个处理周期生效(受采集轮询间隔约束,约 30s),并非即时。
  • key 会原样作为 span 属性名。请避免以 agent. 开头及其它保留前缀(gen_ai.git.workspace.event.trace_user.cost_)——这类 key 会被跳过。
  • 属性为 fill-only,绝不覆盖 span 已有属性。

3. 按次调用的透传属性。 上述三个来源都是进程级全局的(一台机器一个共享 pilot daemon),无法按每次 agent 调用区分。若要对单次调用做归因(如哪个用户 / issue 触发了本次运行),由调用方在被拉起的 agent 子进程上设置按次环境变量,daemon 再把匹配前缀的 key 透传到该次调用的 span 上。

  • 宿主进程在 agent 子进程上设置 LOONGSUITE_PILOT_SPAN_ATTRIBUTES(同样是 key=value,key=value 格式)。agent 的 hook/plugin 在启动时解析它,并把这些键值对作为顶层字段写入它产出的每条 record,因此每次调用都带上各自的值。

    # 由启动器在每次 agent 调用时设置
    export LOONGSUITE_PILOT_SPAN_ATTRIBUTES="multica.issue.id=AGE-992,multica.user.id=staff"
  • config.jsonotlpTrace.spanAttributePassthroughPrefixes 列出 daemon 需要透传到 span 的 key 前缀:

    { "otlpTrace": { "spanAttributePassthroughPrefixes": ["multica."] } }

说明:

  • 与来源 #2(仅 span)不同,透传属性是普通的顶层 record 字段,因此会同时出现在 event log(SLS / JSONL)和 trace span 上——与 git 字段行为一致。
  • 保留前缀 key(gen_ai.git.workspace.event.trace_user.cost_agent.)以及敏感命名(token/secret/password/…)会被 hook 丢弃。请使用 multica.* 等专用命名空间。
  • 仅匹配所配置前缀的 key 会被透传,其它顶层字段不受影响。支持在进程内构建 record 的 agent(claude-code、qoder、opencode)。
  • value 不能包含逗号 ,(逗号是键值对分隔符);单个 value 长度上限 512 字符。

验证 Trace 输出

loongsuite-pilot restart
loongsuite-pilot status

如果开启了 otlpTrace.debugcms.debug,debug 输出会写入:

~/.loongsuite-pilot/logs/otlp-debug/

Trace 导出失败的数据可能会持久化到:

~/.loongsuite-pilot/logs/otlp-failed/