diff --git a/.agents/skills/unidesk-otel/SKILL.md b/.agents/skills/unidesk-otel/SKILL.md new file mode 100644 index 00000000..493a591c --- /dev/null +++ b/.agents/skills/unidesk-otel/SKILL.md @@ -0,0 +1,105 @@ +--- +name: unidesk-otel +description: UniDesk OpenTelemetry/Tempo 链路追踪运维技能。用户提到 OTel、OpenTelemetry、Tempo、trace backend、platform-infra observability、链路追踪、按 traceId 查 span、provider-stream-disconnected、Code Agent/AgentRun/HWLAB 跨服务追踪、或要求“用 otel 查/改进 otel”时使用。 +--- + +# UniDesk OTel + +Skill(cli-spec) + +UniDesk 的 OTel 运行面在 `platform-infra` namespace:OTel Collector 负责接收 OTLP traces,Tempo 负责查询。操作入口统一走 UniDesk YAML-first CLI,不直接 `kubectl port-forward`、手写 Tempo API 或裸 `curl`。 + +**固定入口**: `cd /root/unidesk && bun scripts/cli.ts platform-infra observability ...` + +## 基本状态 + +```bash +bun scripts/cli.ts platform-infra observability status --target D601 +bun scripts/cli.ts platform-infra observability validate --target D601 +``` + +- `status` 检查 `platform-infra` namespace、`otel-collector`、`tempo` Deployment/Service/Pod 和 readiness probe。 +- `validate` 生成一条测试 trace,经 Collector 写入 Tempo,再通过受控 service proxy 查询,证明采集和查询闭环可用。 +- `--full` 只在需要展开远端 stdout/stderr 或完整 status payload 时使用;默认输出必须保持低噪声。 + +## 查询 Trace + +```bash +bun scripts/cli.ts platform-infra observability trace \ + --target D601 \ + --trace-id +``` + +`--trace-id` 是 32 位 hex OpenTelemetry trace id,不是业务 traceId。默认输出只返回有界摘要: + +- `spanCount`、`serviceCount`、`services` +- `businessTraceIds` +- `errorSpanCount` +- `spanNameCounts` +- `errorSpans` +- 去重后的关键 spans +- 下一步 drill-down 命令 + +默认输出不得展开完整 Tempo JSON;需要原始响应时才用 `--raw`。 + +## 噪声压制 + +按错误文案、span 名、failureKind 或关键属性定位时,优先用 `--grep`: + +```bash +bun scripts/cli.ts platform-infra observability trace \ + --target D601 \ + --trace-id \ + --grep provider-stream-disconnected \ + --limit 20 +``` + +- `--grep ` 在 span 名、status message 和关键 attributes 的摘要 JSON 中过滤。 +- `--limit ` 控制返回 span 数,避免大 trace 淹没上下文。 +- `--full` 展开完整 span 摘要,但仍不输出 Tempo raw body。 +- `--raw` 仅用于排查 Tempo 响应结构、CLI 解析器或后端返回本身。 + +## 业务 Trace 映射 + +HWLAB/Code Agent 的业务 traceId 通常形如 `trc_...`。当已知 OTel trace id 时,直接用 `trace --trace-id` 查询;当只知道业务 traceId 时,优先从 HWLAB trace/result、Code Agent result 或已记录的 issue 证据中取得对应 OTel trace id。不要为了找 OTel trace id 去打印 Secret、Authorization header、完整 DSN 或运行面 raw transcript。 + +OTel trace 内常见业务关联属性: + +- `traceId`: HWLAB 业务 traceId +- `otel.trace_id`: OTel trace id +- `runId` / `commandId`: AgentRun run/command +- `sessionId` / `turnId` / `threadId`: HWLAB/AgentRun 会话与 turn 关联 +- `failureKind` / `willRetry` / `terminalStatus`: 错误与终态判断 + +## Code Agent / AgentRun 排障 + +追 `Code Agent 代理暂时无法连接上游`、`provider-stream-disconnected`、Workbench 加载/转圈、turn idle 报错、AgentRun command terminal 状态时: + +1. 先确认 OTel backend ready: + `bun scripts/cli.ts platform-infra observability status --target D601` +2. 查业务 trace 对应 OTel trace: + `bun scripts/cli.ts platform-infra observability trace --target D601 --trace-id ` +3. 用错误关键词过滤: + `bun scripts/cli.ts platform-infra observability trace --target D601 --trace-id --grep --limit 20` +4. 对照 `errorSpanCount`、`matchedSpanCount`、`terminalStatus`、`willRetry`、`runId`、`commandId` 判断是 terminal failure、retryable transient 还是旧 trace 缺 instrumentation。 + +旧 trace 不会因为后续 instrumentation 修复自动回填。若旧 trace 查不到错误 span,但新的 canary/真实 trace 能查到同类 `runner_error.*` span,应把旧 trace 结论写成“当时未采集到该事件”,不要倒推出运行面没有发生过错误。 + +## 何时先改进 OTel + +遇到以下情况,先修 OTel CLI 或 instrumentation,再继续业务排障: + +- trace 命令只能返回 raw/tail,不能给出可读 span 摘要。 +- 大 trace 输出淹没上下文,缺少 `--grep`、`--limit`、错误 span 汇总或下一步 drill-down。 +- 关键 runner/backend/projection 事件只存在业务事件流,不进入 OTel。 +- error span 缺 `failureKind`、`willRetry`、`terminalStatus`、`runId`、`commandId` 等定位字段。 +- CLI 默认输出 Secret、Authorization header、DSN 或其他敏感值。 + +改进后必须用一条 canary 或真实 trace 证明新 span/摘要可查询,再继续定位原业务问题。 + +## 交付边界 + +- OTel 平台配置真相是 `config/platform-infra/observability.yaml`。 +- OTel CLI 实现在 `scripts/src/platform-infra-observability.ts`,帮助入口由 `scripts/src/platform-infra.ts` 暴露。 +- 修改 OTel CLI 属于 UniDesk 轻量 CLI 变更:默认只做语法检查、命令形态验证和真实 trace 查询,不新增合同测试。 +- 修改 AgentRun/HWLAB instrumentation 属于对应仓库/运行面的代码变更,必须按目标 repo 的 source truth、PR/CD 和原入口验收规则执行。 diff --git a/.agents/skills/unidesk-otel/agents/openai.yaml b/.agents/skills/unidesk-otel/agents/openai.yaml new file mode 100644 index 00000000..08047cbe --- /dev/null +++ b/.agents/skills/unidesk-otel/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "UniDesk OTel" + short_description: "UniDesk OpenTelemetry/Tempo tracing operations" + default_prompt: "Use UniDesk OTel to inspect trace backend readiness and query Tempo traces with bounded summaries." diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 7f7c76c4..c6e6d45e 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -87,7 +87,7 @@ PipelineRun 失败或长时间未完成时,先按定点 `control-plane status `status` 返回 read/write URL、last sync/write/flush、本地 ref、GitHub staging ref 和 pending flush 状态,并在 `cache.summary` 给出 `localV02`、`localGitops`、`githubGitops`、`pendingFlush`、`flushNeeded`、`githubInSync` 和下一条受控 `flushCommand`。confirmed `sync` 和 `flush` 默认创建 `.state/jobs/` 异步 job 并立刻返回可查询状态,只有现场同步调试才显式加 `--wait`;mirror 不设置 CronJob。 如果 PipelineRun 的 `gitops-promote` 阶段报 git mirror 控制面漂移或 refs 不一致,先执行 `hwlab g14 git-mirror apply --confirm` 重新应用当前 `devops-infra/git-mirror.yaml` hook/ConfigMap,再执行 `hwlab g14 git-mirror sync --confirm --wait` 复核 refs;失败的同名 PipelineRun 只能通过 `hwlab g14 control-plane cleanup-runs --lane --pipeline-run --confirm` 受控清理后重试,不要用原生 `kubectl delete` 或手工改 mirror hook。修复后仍必须用 `control-plane status --pipeline-run ` 和 `git-mirror status` 分别确认 runtime closeout 与 GitHub flush。 - `platform-infra sub2api|langbot|n8n|wechat-archive ...` 是 `platform-infra` namespace 内平台公共服务和公共工作流的受控入口;`sub2api` 支持 `plan|apply|status|validate|codex-pool`,`langbot` 和 `n8n` 支持各自 YAML-controlled `plan|apply|status|logs|validate` 等公共服务操作,`wechat-archive` 支持 `plan|apply|status|validate|pull`,用 `config/platform-infra/wechat-archive.yaml` 声明 LangBot/n8n/Baidu Netdisk 归档链路,以及 D601 Windows 隔离 PC 微信 + WeChatFerry host + D601 k3s 只读 collector 的 personal WeChat upstream;collector 必须复用 D601 已有 `platform-infra` namespace,`createNamespace=false`。`--target` 选择运行目标,默认 `G14` 为 active runtime,`D601` 为同一 YAML 控制的 standby predeploy target。镜像版本和 target 边界由 `config/platform-infra/*.yaml` 控制,Codex 上游池、统一 API key Secret、FRP 公网端口和 master `~/.codex` 消费端由 `config/platform-infra/sub2api-codex-pool.yaml` 控制;完整 Sub2API 日常部署、上游增删、FRP 暴露、local Codex 配置、验收和排障步骤统一见 `$unidesk-sub2api`(`.agents/skills/unidesk-sub2api/SKILL.md`)。`docs/reference/platform-infra.md` 保留 namespace、YAML-first、路由、Secret 脱敏、PK01 Caddy+FRP 和探针开发边界。 -- `platform-infra observability plan|apply|status|validate|trace --target D601` 是 `platform-infra` 内 OTel Collector 和 Tempo trace backend 的受控入口。`trace --trace-id ` 默认输出有界 trace 摘要、service/span 计数、error spans、关键 span 和下一步 drill-down,不展开完整 Tempo JSON;按错误文案或 failureKind 定位时使用 `--grep `,按需要用 `--limit ` 调整返回 span 数,只有排查解析器或后端原始响应时才使用 `--raw`,需要完整 span 摘要时使用 `--full`。旧 trace 不会因后续 instrumentation 修复自动回填;同类错误是否已可观测应通过新的 canary/真实 trace 复查。 +- `platform-infra observability plan|apply|status|validate|trace --target D601` 是 `platform-infra` 内 OTel Collector 和 Tempo trace backend 的受控入口;具体 trace 查询、噪声压制、Code Agent/AgentRun 排障和“先改进 OTel”的操作面统一见 `$unidesk-otel`(`.agents/skills/unidesk-otel/SKILL.md`)。 - `secrets plan|sync|status --config config/secrets-distribution.yaml --scope platform-infra` 是平台服务本地 Secret sourceRef 到 Kubernetes Secret key 的受控下发入口。`plan` 只读展示 sourceRef、必需 key、目标 Secret/key、missingKeys 和 fingerprint;`sync --confirm` 只按 YAML 声明创建允许生成的本地 key 并下发到声明的目标 Secret;`status` 只验证 live Secret key presence。该入口禁止从 live pod 或 Kubernetes Secret 反推密码、API key、JWT secret、n8n encryption key 或 `DATABASE_URL`,输出也不得打印 base64、解码值或远端 raw transcript;即使显式 `--raw` 也只返回脱敏 summary 和 raw omission 标记。LangBot/n8n Secret 轮换和缺 key 修复规则见 `docs/reference/platform-infra.md#secret-distribution-boundary`。 - `hwlab g14 observability status|apply|query|targets|boundary|closeout [--lane v02] [--promql ] [--expect-count N] [--expect-value V] [--dry-run|--confirm]` 是 G14 `devops-infra` 共享监控基础设施和 HWLAB v0.2 监控 closeout 的受控入口。`apply` 固定安装 Prometheus Operator `v0.91.0`、Prometheus `v3.12.0`、Prometheus 发现 RBAC、`devops-infra` 内 Prometheus 实例和 ClusterIP query Service,并给被允许发现的 workload namespace 打低风险 label;它不把 Prometheus、Grafana 或 Alertmanager 部署到 `hwlab-v02`,也不接管 HWLAB runtime Deployment/Service。`status` 只读汇总 CRD、operator Deployment、Prometheus CR/pod/service、`hwlab-v02` ServiceMonitor/PrometheusRule 和 bounded `up` 查询;`query` 只通过 Kubernetes service proxy 查询 Prometheus,支持 `--expect-count` / `--expect-value` 输出 `assertion`、bad values 和 missing/extra series;`targets` 汇总 ServiceMonitor/PrometheusRule、metrics sidecar readiness/restart、三层指标值和 `metrics.k8s.io` 当前 CPU/内存资源快照;`boundary` 验证 workload namespace 没有 Prometheus/Alertmanager,并对 `19666/19667` 公网 `/metrics` 做负向验证;`closeout` 聚合平台 ready、scrape reachable、sidecar serving、business health probe、resource snapshot、namespace boundary 和 public metrics exposure 语义结论。长期边界见 `docs/reference/g14-observability-infra.md`。 - `hwlab g14 tools-image status|build --name ci-node-tools --tag [--dockerfile deploy/ci/hwlab-ci-node-tools.Dockerfile] [--dry-run|--confirm]` 是 G14 固定 HWLAB CI tools image 的受控 host build/push 入口;构建和 push 只发生在 G14 host 与本地 registry,不在 master server 构建,也不把 `apk add`/runtime install 塞进 Tekton PipelineRun。