- .agents/skills 25 件全量 frontmatter 规范化与评审修入(含 prompt-governance 大修);.claude/skills 7 件薄壳按双层方案①落位 - 新增 skill:agentic-seat-context-design(agentic 席位与 context 工程设计基线,2026-07-05 探索蒸馏) - 设计波三件落档:复杂游戏北极星件(W-NSTAR 终审稿待拍)/黄金模板规格件(W-TPL 定稿待批)/生成侧过程蒸馏回路(W-GENLOG 骨架) - protocol/在飞板/作战清单/数据飞轮 SoT/契约 prompts 索引同步;breakout 九门证据刷新 - .gitignore 补 /localagents.md 真实忽略行(该文件自声明绝不提交,此前声明未被机器执行) - 刻意不入库:nacos-data/ 与 _tier2-gen、c2v-*、amgen-* 生成产物(可重生成,忽略行格式待拍) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
31 KiB
date, topic, status, 上级
| date | topic | status | 上级 |
|---|---|---|---|
| 2026-07-05 | 观测体系-阶段四后续波实施 | 待实施 · 第一波(观测栈五件)已起 mini-infra;后续波 ②③④⑤ 按依赖串,碰 game-cloud 单体处(② 生产上线、⑤ 业务埋点)逐波开部署窗口 | docs/agent-specs/2026-07-05-全链路可观测性-OTel三信号全栈-设计.md |
阶段四观测 · 后续波实施计划
1. 承接点
第一波已经把观测栈的后端五件起在 mini-infra:Collector 收 OTLP(100.64.0.8:4317 gRPC / 4318 HTTP),Prometheus 存指标,Tempo 与 Loki 把块存进 MinIO 的 obs-tempo / obs-loki 桶,Grafana 预配好三数据源与三联下钻。进库前的脱敏 processor(手机号 / token / 密钥 / JWT 打码)已经挂在 Collector 的三条 pipeline 上,只是还没有真实信号流过它。这一波不碰生产,纯增量旁路。
剩下四波要做的,是把信号源一个个点亮再端到端串起来:给 game-cloud 单体挂 agent 让它出 span 和指标,给两条 Python 生成路接上 OTLP 让它们真发 span,把「用户点一下到模型返回」这条最会断的三跳 trace 打通,最后落业务埋点、看板、告警和运维入口。
这份文档是施工排布,不是新设计。阶段四设计已过双评审、创始人 2026-07-05 已拍六项(见上级设计档 §10),所以这里只做分波、工单、部署窗口与验收,不重开设计、不触发双评审门。所有埋点方式、取舍、验收判据都以上级设计为准,本文只给落地路径。
2. 分波总览
四波按依赖串,越往后越依赖前一波已经在生产就位。碰 game-cloud 单体的只有两处:波② 给单体挂 agent 加 actuator(要重构建、重启单体),波⑤ 在 aigc 里手埋两个业务指标(同样改单体代码)。Python 生成线的改动碰的是 mini-desktop 上的生成进程,走生成线重启窗口,不占 game-cloud 单体的部署窗口——这两类窗口全文分开写。
| 波 | 做什么 | 碰 game-cloud 单体 | 碰生成线(mini-desktop) | 依赖 |
|---|---|---|---|---|
| ② | 单体挂 OTel Java agent + actuator + micrometer;SAA observation 从 NOOP 活过来、/actuator/prometheus 成立 |
是(staging 验证 + 生产上线两点) | 否 | 第一波 Collector 就绪 |
| ③ | 便宜档主路新接 OTLP span sink、tier2 studio_sink 改发 Collector;补 Python 侧 OTLP metrics 导出口 | 否 | 是(cheap Service/worker、tier2 Service 重启) | 第一波 |
| ④ | 打通三跳 traceparent,让 ③ 已能读 context 的生成 span 挂到 Java trace 下 | 否(Java 侧靠 ② 的 agent 自动收发,零代码) | 是(worker_service / driver / Service 改动) | ②(agent 在生产)+ ③(span 已产、可读 context) |
| ⑤ | 业务埋点(§6 清单)+ Grafana 看板 + 告警 + admin 一键进盘 + new-api 通道巡检告警 | 是(aigc 手埋 task_total / queue_depth) | 是(Python 埋点填值) | ②③④ |
一条贯穿全程的铁律:观测栈挂掉绝不能咬主链(设计 §8)。OTel agent 异步批量上报、Collector 不可达即本地丢弃而非阻塞,Python 侧 best-effort 是既有铁律,埋点开关默认关、经 profile 显式开。每一波的回滚都因此很干净。
3. 波② · game-cloud 接入
目标
给线上单体 huijing-server 点亮三件事:OTel Java agent 一个参数拿到 Spring MVC / JDBC / Redis / 出网 HTTP 的全链 span,并在出网(调 Python worker、调 new-api)时自动注入 traceparent;引 actuator 加 micrometer registry,让 /actuator/prometheus 端点成立、让已经挂好的 SAA 节点 observation 从 NOOP 活过来;把半死的 SkyWalking starter 共存收编,不删依赖、不启用、只把响应头 trace-id 的来源换成 OTel。
现状锚点(亲验)
- monitor starter(
huijing-spring-boot-starter-monitor)经 system-server 和 infra-server 两个模块传递进了单体,在席但残缺。HuijingTracerAutoConfiguration第 28–40 行 SkyWalking 的BizTraceAspect与TracerBean 整段被注释(原作者留了 TODO「后续换 opentelemetry」),只剩TraceFilter往响应头写 trace-id,而这个 trace-id 取自 SkyWalking 上下文、agent 不在时是空串。 micrometer-registry-prometheus与spring-boot-admin-starter-client在 starter 的 pom 里都是<optional>true</optional>,没随传递装进来;HuijingMetricsAutoConfiguration的@ConditionalOnClass(MeterRegistryCustomizer.class)要 actuator 在席才激活。AigcExecutorConfiguration用ObjectProvider<ObservationRegistry>.getIfAvailable(() -> ObservationRegistry.NOOP)软取 registry;SaaStudioGraph里判registry != NOOP才挂GraphLifecycleListener,拿到 NOOP 就跳过 = SAA 节点不埋点。装了 actuator/micrometer 这个 registry 才非 NOOP。- huijing-server 的 Dockerfile:
ENV JAVA_OPTS="-Xms512m -Xmx512m …",CMD java ${JAVA_OPTS} -jar app.jar $ARGS,JAVA_OPTS 可经-e覆盖。推论:agent jar 可以挂载进容器 + 改 JAVA_OPTS 追加-javaagent,不必重构建镜像;但 actuator/micrometer 是编译期依赖,必须重构建 jar。所以波② 的生产上线是一次带重构建的完整重启。
步骤
- 取 OpenTelemetry Java agent(pin 版本的
opentelemetry-javaagent.jar),放到部署机可挂载路径。 - 给单体聚合引入 actuator + micrometer registry,让指标端点成立、registry 非 NOOP;actuator 端点最小暴露 health 与 prometheus,management 端口与访问按内网口径收敛(不裸暴露到公网面)。
- 配 agent 环境:
OTEL_EXPORTER_OTLP_ENDPOINT=http://100.64.0.8:4318(跨机经 Tailscale)、OTEL_SERVICE_NAME=huijing-server、采样交给 Collector 尾采样(agent 侧parentbased_always_on)、补 resource 属性。agent 挂载与 actuator 一并经 profile 显式开、默认关(设计 §8 旁路铁律)。 - 把
TraceFilter响应头 trace-id 的来源从 SkyWalking 上下文换成 OTel 当前 span 的 traceId,让前端拿到的 trace-id 真能在 Grafana 里查到;SkyWalking toolkit 依赖留着不删、profile 不启用(不动 yudao 框架层)。 - 取消
prometheus.yml里 game-cloud 的 scrape 占位注释,metrics_path=/actuator/prometheus,target 指向生产单体的 Tailscale 地址:端口。 - 先在 staging(mini-desktop
/root/game-staging/repo)挂 agent 压一轮,量启动耗时差、P95/P99 请求耗时差、生成任务耗时差,并确认 agent 的 queue/drop 指标可见(验收第 6 条),开销在阈内再上生产 profile。
工单
T2-1 挂 agent 与配置
目标:单体启动带 -javaagent、把 span 发到 mini-infra Collector、出网自动注入 traceparent。输入:agent jar、Collector 端点、Dockerfile/JAVA_OPTS 注入位。产出:agent 挂载配置 + OTEL_* 环境 + profile 开关。验收:staging 启动后 Tempo 出现 huijing-server 的 Spring MVC/JDBC span。依赖:第一波 Collector。风险:agent 注入拖慢启动或加请求延迟——由 T2-4 量化兜。
T2-2 引 actuator + micrometer,激活 registry
目标:/actuator/prometheus 出内容、ObservationRegistry 非 NOOP。输入:单体聚合 pom、actuator/micrometer 依赖。产出:actuator 最小端点 + micrometer registry(选型见 §7 待拍第 5 点)。验收:curl /actuator/prometheus 有 JVM/HTTP 指标;dispatcher=saa 路跑一次能见 SAA 节点 span。依赖:无(编译期)。风险:actuator 端点暴露面——按内网口径收敛、management 端口不外放。
T2-3 SkyWalking 共存收编 + TraceFilter 换源
目标:半死 starter 不删不启用,响应头 trace-id 换成 OTel 当前 span。输入:HuijingTracerAutoConfiguration、TraceFilter。产出:TraceFilter 取 OTel traceId 的改动 + profile 不启用 SkyWalking。验收:响应头 trace-id 非空、且能在 Grafana 按它拉到 trace。依赖:T2-1(agent 在席才有当前 span)。风险:改动碰框架层——限定只改 trace-id 取值来源,不动 toolkit 依赖树。
T2-4 staging 压测对比(验收第 6 条) 目标:量化 agent 开销到可接受判定。输入:staging 挂 agent 版本、基线版本。产出:启动/P95/P99/生成耗时差报告 + queue/drop 截图。验收:各差值在阈内、指标可见。依赖:T2-1/T2-2。风险:staging 与生产规格不一致致误判——报告注明规格差。
T2-5 Prometheus scrape 接线
目标:Prometheus 抓到 game-cloud 指标。输入:prometheus.yml 占位、生产单体地址:端口。产出:启用 game-cloud job。验收:Prometheus target 状态 UP、huijing_* 与 JVM 指标可查。依赖:T2-2 端点成立、跨机连通。风险:跨机 scrape 走 Tailscale 抓不通——按跨机连通核对,不混成「都指 .8」。
碰生产 game-cloud 的部署窗口点
- 窗口 A(staging,不碰生产):mini-desktop staging 挂 agent 压一轮(T2-4)。
- 窗口 B(生产上线,碰生产):生产单体重构建 jar(带 actuator/micrometer)+ 挂 agent + profile 显式开 → 重启单体。这是本波唯一碰生产的动作,建议低峰做;若生产是单实例,冷重启会有短暂不可用,提前公告。前置须确认:生产 huijing-server 的部署位置与启动方式(compose / systemd / docker run),它决定 agent 挂载与 JAVA_OPTS 注入手法(见 §7 待拍第 1 点)。
验收(引设计 §8)
- 第 6 条:staging 挂 agent 压一轮,启动与 P95/P99、生成任务耗时差在阈内,agent queue/drop 可见——冒烟绿不足以发现 agent 注入的启动变慢和批量上报内存积压,这条必须真量。
- 第 4 条:actuator health + agent 出的 HTTP server 指标出得来,error budget 燃尽图与 health 探测对得上。
- 第 5 条:停掉 Collector 后单体行为不变、冒烟门全绿(旁路铁律)。
- 附:
/actuator/prometheus有内容并被 Prometheus 抓到;dispatcher=saa 路能见 SAA 节点 span(仅 saa 路;默认 http 路不跑 SAA 图,其 trace 来自 Python 线、归波④)。
回滚
摘掉 -javaagent 参数(JAVA_OPTS 改回)、关 actuator profile、还原 TraceFilter 取值来源、把 prometheus.yml 的 game-cloud job 注释回去。actuator/micrometer 是新增依赖,不启用即无副作用,主链业务代码一行不动。
4. 波③ · Python 两线接 OTLP
目标
两条生成路各接一处,让它们真产 OTLP span 发 Collector,并让生成 span 具备「读入站 W3C context 起子 span」的形态,为波④ 的贯穿铺好落点。这一波做完,两条线各自能在 Tempo 看到自产的 span(还没挂到 Java trace 下,是自成 trace);顺带把面五要的业务指标导出口在 Python 侧备齐。
现状锚点(亲验)
- 便宜档主路的 Service 入口(
cheap_service_app.py第 268–276 行)和 CLI 入口(cheap_studio.py第 206–213 行)都用make_jsonl_sink把每步 trace 写进产物目录的trace.jsonl,不产 OTLP span。真正的生成发生在 AgentScope Service 进程(127.0.0.1:8300),span 的插入点就在这两处的Tier2TraceMiddleware(sink=...)。 - otel 全套(api / sdk / exporter-otlp-proto-http,1.43.0)随 agentscope 2.0.2 装进了 cheap-worker 的 venv,依赖是齐的——但装依赖不等于在发 OTLP。
- tier2 的
studio_sink.py是全仓唯一的 OTLP exporter,可它自带私有 TracerProvider、每步自造 root span、靠 gen-ai conversation id 归组,结构上不读入站 context;端点取TIER2_STUDIO_URL/infra_config[studio].http_url,取不到即 no-op、默认关。tier2 本地无独立 venv、studio_sink 惰性 import otel,运行 venv 的 otel 到位与否要在运行环境实测(设计 §3 明示)。 - 代理坑:OTLP exporter 打
100.64.0.8:4318走 Tailscale,必须绕过本机 fake-ip 代理(198.18.x),否则被拦。cheap_service_driver已有install_proxy_bypass范式(把 host 并入 NO_PROXY),复用它。
步骤
- 便宜档新增一个 OTLP span sink(与
make_jsonl_sink同签名、吃 TraceStep 发 span),endpoint 指 Collector4318、service.name=cheap-gen-worker,best-effort(取不到 endpoint 或发送失败即降级 no-op、绝不抛,对齐 studio_sink 的 observe-only 铁律)。在cheap_service_app.py:268与cheap_studio.py:206两处把它与 jsonl sink 并接(Tier2TraceMiddleware 多 sink,或包一层 fan-out sink),jsonl 落盘保留不动。 - tier2
studio_sink端点从 Studio 改成 Collector 的 OTLP/HTTP(/v1/traces),service.name保持tier2-gen-worker;把start_as_current_span从私有 root 改成读入站 context 起子 span(context 的提取归波④,本波先把「不自造 root、用传入 context」的形态改好,无 context 时退化为自身 root、不报错)。 - Python 侧建一个 OTLP MeterProvider(同 endpoint),备好
llm_cost/gen_duration_seconds/llm_cache_hit_rate/gen_gate_fail_total的直发导出口(值来源见面五;本波只备口,填值随波⑤)。 - trace 与 metrics 两个 exporter 统一走
install_proxy_bypass/ NO_PROXY 含100.64.0.8,和既有 new-api / Service 旁路同源。 - 在扩容后的运行环境实测 tier2 venv 的 otel wheel 是否到位;缺则补 wheel,或确认惰性降级不影响主链。
工单
T3-1 便宜档 OTLP span sink + 双入口并接
目标:便宜档主路真产 span 发 Collector。输入:Tier2TraceMiddleware 接口、Collector 端点。产出:OTLP sink 模块 + Service/CLI 两入口并接。验收:跑一局便宜档生成,Tempo 见 cheap-gen-worker 的 span;jsonl 仍照落。依赖:第一波。风险:多 sink 拖慢 ingest——BatchSpanProcessor 异步发、best-effort 降级兜。
T3-2 tier2 studio_sink 改端点 + 去私有 root
目标:tier2 span 发 Collector、可读入站 context。输入:studio_sink.py。产出:端点改 Collector + 私有 root 改读入站 context。验收:tier2 跑一局,Tempo 见 tier2-gen-worker span。依赖:第一波。风险:私有 root 逻辑改动破坏 observe-only——保持 best-effort、失败降 no-op。
T3-3 Python OTLP metrics 导出口 目标:成本/耗时/缓存/门结果有 metric 直发口。输入:Collector 端点、cost.compute/wallSec/cached token/verdict.guards 取值位。产出:MeterProvider + 四个 instrument 空口。验收:导出口能发出占位指标、Prometheus 经 Collector 出口抓到。依赖:第一波。风险:值口径与面五不一致——本波只建口,填值随⑤对齐。
T3-4 OTLP 代理旁路统一
目标:两个 exporter 不被 fake-ip 代理拦。输入:install_proxy_bypass 范式。产出:trace/metrics exporter 前置装 NO_PROXY 含 100.64.0.8。验收:mini-desktop 上真发能到 Collector、无 502/连接关闭。依赖:无。风险:漏装某条路径——真 e2e 才暴露,须在生成线实机验(单测桩绕过真网络)。
T3-5 tier2 运行 venv otel 实测 目标:确认 tier2 运行环境 otel 到位或安全降级。输入:mini-desktop tier2 venv。产出:实测结论 + 缺则补 wheel。验收:tier2 真跑能发 span 或惰性降级不崩主链。依赖:扩容后运行环境。风险:无 wheel 时静默 no-op——留一条告警日志、不当成功。
碰生产 game-cloud 的部署窗口点
不碰 game-cloud 单体。碰生成线:cheap Service(8300)、worker_service(9501)、cheap CLI、tier2 Service(8200)都在 mini-desktop,改完要重启生成线进程 = 生成线重启窗口。择低峰、观察盲修空转率(既有头号观测)与九门过门率不回退;best-effort 铁律保证 OTLP 挂掉不咬生成。复现纪律:worktree/分支基线走 dev/2.0.0——默认分支 dev/1.0.0 无 game-cloud 与生成线新代码,派 worker 干活先 reset 到 dev/2.0.0 tip 或主树直改。
验收(引设计 §8)
- 第 1 条的半程:两条线各自能在 Tempo 看到自产的生成 span(此时尚未挂到 Java trace 下、是自成 trace,端到端挂接归波④)。
- 第 5 条:停 Collector 后两条生成路行为不变、冒烟门全绿(best-effort 降级 no-op)。
- 第 7 条预演:往一局便宜档生成的 brief/prompt 注入构造的手机号和 token,产出的 span 属性经 Collector redaction 后在 Tempo 查不到明文——脱敏 processor 第一波已在 Collector,这波第一次有真 span 流过它,正好把这条安全红线先验一遍。
回滚
关掉 OTLP endpoint 环境变量,两条 sink 降级 no-op、metrics 不发;jsonl sink 与生成主链一字不动。tier2 studio_sink 若要回 Studio,改回端点即可。
5. 波④ · 三跳 traceparent 打通
目标
把设计 §5 面四的「三跳不是两跳」接起来,让波③ 已能读 context 的生成 span 真挂到 Java 的 trace 下,端到端一条 trace 串到底(设计 §8 第 1 条,也是最会断的那条)。
flowchart LR
J["game-cloud<br/>WorkerDispatchClient<br/>(JDK HttpClient)"] -->|① agent 自动注入 traceparent| W["worker_service :9501<br/>(裸 http.server)<br/>② 手动 extract 建 server span"]
W -->|③ driver httpx 手动 inject| S["AgentScope Service :8300<br/>④ 生成 span 接住 context<br/>(便宜档主路)"]
W -->|⑤ urllib 手动 inject| CB["game-cloud 回调入口<br/>/dify/callback-internal<br/>Spring controller · agent 自动 extract"]
三跳的真实拓扑:worker_service(9501)是收 Java job 的裸 http.server 派发壳,它经 cheap_service_driver 打本机 AgentScope Service(8300)跑生成,拿到结果后自己用 urllib 回调 game-cloud。所以一次生成的 span 树是:worker_service 的 server span 覆盖整个 job,driver 打 Service 那跳与回调那跳都是它的子 span,Service 里的生成 span 挂在 driver 那跳之下。
现状锚点(亲验,三个断点)
- 第一跳 Java → worker_service:Java 侧靠波② 的 agent 自动注入 traceparent(依赖 ② 已上生产);worker_service 是裸 http.server(
worker_service.py),OTel 无自动埋点,do_POST收到的 traceparent 没人提取。 - 第二跳 worker_service → 本机 Service:driver 打 Service 现在 header 只有
X-User-Id(cheap_service_driver.py:239),trace 上下文在此断,而便宜档生成 span 恰恰产在 Service 进程。driver 已装 proxy-bypass,给 headers 加一个 traceparent 即可。 - 第三跳 回调 game-cloud:worker_service
post_callback用 urllib(_NO_PROXY_OPENER,禁代理)POST 回/admin-api/aigc/dify/callback-internal,要在这条 urllib 请求手动注入 traceparent;Java 回调入口是 Spring controller,agent 自动 extract,零 Java 代码。 - tier2 线同构:其派发 worker 也是裸 http.server,按同款 extract/inject 接,studio_sink(③ 已改读入站 context)承接。
步骤
- worker_service:
do_POST入口用 W3CTraceContextTextMapPropagator从self.headersextract context,起一个 server span 覆盖这次 job 处理,把 context 传进process_job。 cheap_service_driver:在drive_cheap_generation承重那跳(kick / SSE)的 httpx 请求里 inject traceparent 到 headers,与X-User-Id并列。cheap_service_app(Service 侧):在 HTTP/ASGI 入口 extract traceparent,让_cheap_middlewares_factory建的Tier2TraceMiddlewarespan 挂在传入 context 下(③ 已把「用当前 context 起子 span」改好,这波把 context 真喂进来)。- worker_service
post_callback:在 server span 的 context 内,给 urllib Request 注入 traceparent;Java 入口靠 agent 自动 extract 收尾。 - 业务 traceId 并存关联:业务 traceId 作为 span 的一个属性保留(承担产物归位与回调关联),W3C traceparent 负责跨语言贯穿,不强升业务 traceId 的格式(设计 §10 第 5 项)。
工单
T4-1 worker_service 入站 extract + server span
目标:Java 传来的 traceparent 被接住、起 server span。输入:worker_service.py do_POST、W3C propagator。产出:入站 extract + server span 覆盖 job。验收:Java 发一条带 traceparent 的 job,Tempo 见 worker_service server span 挂在 Java span 下。依赖:②。风险:extract 失败——降级为自身 root、不阻断。
T4-2 driver httpx 出站 inject
目标:worker→Service 那跳带上 traceparent。输入:cheap_service_driver.py:239 headers。产出:httpx 请求 inject traceparent。验收:Service 侧能收到 traceparent。依赖:T4-1。风险:漏在某个 sub-请求注入——承重跳(kick/SSE)必接,建 agent/session 跳可选。
T4-3 Service 侧 ASGI 入口 extract + 生成 span 挂接
目标:生成 span 挂在传入 context 下。输入:cheap_service_app HTTP 入口、③ 的 OTLP sink。产出:ASGI 入口 extract + middleware span 起在该 context。验收:便宜档生成 span 在 Tempo 挂到 worker_service span 下。依赖:③ T3-1、T4-2。风险:AgentScope Service 是框架层,入站 header 到 middleware 的 context 传递需一处接线(instrument ASGI 层或从请求上下文取)——本波核心难点,先小 spike 打通再铺开。
T4-4 回调 urllib inject
目标:回调那跳带 traceparent。输入:post_callback urllib Request。产出:server span context 内注入 traceparent。验收:game-cloud 回调入口(agent 自动 extract)把回调挂到同一 trace。依赖:T4-1、②。风险:urllib 禁代理路径上手动注 header——只加 header、不动禁代理逻辑。
T4-5 tier2 同款接线 + 端到端串联验证 目标:tier2 三跳同款打通、端到端一条 trace。输入:tier2 派发 worker、studio_sink。产出:tier2 extract/inject 接线 + 一次真生成的贯穿 trace 证据。验收:两条线各拉出一条贯穿 Java→worker→Service→回调 的单 trace。依赖:T4-1..4、③ T3-2。风险:两条线拓扑细节差异——各自小 spike 坐实。
碰生产 game-cloud 的部署窗口点
Java 侧零代码(agent 自动 inject/extract),不新增 game-cloud 单体窗口——但依赖波② 的 agent 已在生产,故本波必须排在 ② 生产上线之后。Python 侧改 worker_service / driver / Service = 生成线重启窗口,可与波③ 合并成一次重启,或紧随其后。
验收(引设计 §8)
- 第 1 条(端到端 trace_id 一致):从响应头拿到 trace-id,能在 Grafana 里拉出贯穿 Java → worker_service → 本机 Service 生成 → 回调 的单条 trace(便宜档主路;tier2 同验)。这是本波的硬命门。
- 第 5 条复验:贯穿接线全是 best-effort,停 Collector 后生成不变、冒烟门全绿。
回滚
propagator 接线是纯读 header + 起 span,失败即 best-effort 降级(extract 不到就自身 root、inject 失败就不带 header);关掉 OTLP endpoint 就整体回到波③ 前的自成 trace 态,主链不受影响。
6. 波⑤ · 业务埋点 + 看板 + 告警 + admin 进盘 + 通道巡检
目标
把 §6 埋点清单落全,建 Grafana 看板与告警规则、接飞书/钉钉 webhook、admin 一键进盘、new-api 通道巡检探活加健康告警。自动冻结阀本期不做,作为已登记的 follow-up 排下一期(设计 §10 第 4 项;2026-06 通道整批作废的教训不丢)。
埋点落点(对着设计 §6)
| 指标 | 埋在哪 | 碰生产 |
|---|---|---|
gen_task_total{status} counter |
game-cloud aigc 任务终态回填处(手埋) | game-cloud 单体 |
gen_queue_depth gauge |
game-cloud 控制平面背压判定处(手埋) | game-cloud 单体 |
gen_duration_seconds histogram |
Python worker(已算 wallSec,填进 ③ 备好的口) | 生成线 |
gen_gate_fail_total{gate} |
Python 侧聚合 verdict.guards / trace 字段 | 生成线 |
llm_cost |
Python worker cost.compute 导出,标降级(worker 自估值、非 new-api 权威;告警阈值留余量;logs.quota 权威对账薄片作 follow-up) |
生成线 |
llm_cache_hit_rate |
Python worker cached token 导出 | 生成线 |
| 服务可用性 | ② 的 agent HTTP server 指标 + actuator health | 已在 ② |
| SAA 图节点 span | ② 装 micrometer 即活,仅 dispatcher=saa 路 | 已在 ② |
| new-api 多通道健康 | 新建后台巡检 job:每通道探活 + 查 key 额度 → 健康指标 + 告警(冻结阀排下一期) | 落点待拍 |
| 全链路 trace | ④ 已打通 | — |
| 集中日志(脱敏后) | logback OTLP 或 Collector filelog,只收 WARN/ERROR,trace_id 注入 MDC,进库经 Collector 脱敏 | 采集方式待拍 |
| admin 一键进盘 | game-admin 前端加运维入口跳 Grafana | 前端发布 |
步骤
- game-cloud aigc 手埋
gen_task_total(终态回填处)与gen_queue_depth(背压判定处),用 micrometer(② 已引);SAA span 随 ② 自动活。 - Python 侧把
gen_duration_seconds/llm_cost/llm_cache_hit_rate/gen_gate_fail_total填进波③ 备好的导出口,值取 cost.compute / wallSec / cached token / verdict.guards;llm_cost明确标「估值非权威」。 - 集中日志:logback OTLP(或 Collector filelog)只收 WARN/ERROR,MDC 注入 trace_id(用 ② 的 OTel 当前 span traceId),进库经 Collector 脱敏。
- Grafana 看板:生成成功率 / 耗时 P50·P95 / 队列深度 / 九门过门率 / 单次成本 / 缓存命中 / 可用性,配指标→trace→日志三联下钻;沿用第一波已 provisioning 的三数据源。
- 告警规则:成功率跌破 80% 达标线与预警线、队列越限、可用性 error budget 燃尽、通道可用数掉下限;接飞书/钉钉 webhook。成功率告警阈值口径回写时与《观测体系》统一(设计 sot-impact 已声明)。
- admin 一键进盘:game-admin 前端加运维入口跳 Grafana(《观测体系》§2/§3.5 硬目标,本期做)。
- new-api 通道巡检 job:探活每通道 + 查 key 额度,出通道健康指标 + 告警;自动冻结阀留 follow-up。
工单
T5-1 game-cloud 业务埋点(task_total / queue_depth)
目标:两个业务指标从 aigc 直出。输入:终态回填处、背压判定处、micrometer registry(② 已引)。产出:两个 instrument + profile 开关。验收:Prometheus 抓到 huijing_gen_task_total / huijing_gen_queue_depth。依赖:②。风险:手埋碰单体代码——限定终态与背压两处、开关默认关。
T5-2 Python 埋点填值
目标:③ 的四个导出口填真值。输入:cost.compute / wallSec / cached token / verdict.guards。产出:四个 metric 填值 + llm_cost 降级标注。产收:看板见非零值。依赖:③ T3-3、④。风险:cost 自估偏差——阈值留余量、注明非权威。
T5-3 集中日志 OTLP + MDC + 脱敏对账 目标:WARN/ERROR 日志进 Loki、带 trace_id、脱敏。输入:logback/filelog、MDC、Collector 脱敏。产出:日志接入 + trace_id 关联。验收:Loki 见脱敏后日志、可从 trace 下钻到日志。依赖:②(traceId 源)。风险:采集方式选型(见 §7 待拍第 4 点)。
T5-4 Grafana 看板 目标:一块盘看到底。输入:三数据源、指标名。产出:概览盘 + 三联下钻。验收:七类指标在盘、可下钻。依赖:T5-1/T5-2、④。风险:指标名漂移——与埋点工单对名。
T5-5 告警规则 + webhook 目标:阈值越线真送达。输入:Grafana 告警、飞书/钉钉 webhook。产出:告警规则 + 通知渠道。验收:造一条越线,群里收到(验收第 2 条)。依赖:T5-4。风险:换了告警件(Grafana 替夜莺)——更要真验送达。
T5-6 admin 一键进盘 目标:运营从 admin 一键进 Grafana。输入:game-admin 前端、Grafana 地址。产出:运维入口。验收:admin 点入口进盘即见数据源与看板。依赖:第一波 Grafana。风险:前端发布窗口独立于单体。
T5-7 new-api 通道巡检 + 健康告警 目标:通道可用性有眼睛。输入:new-api 通道配置、key 额度查询。产出:巡检 job + 健康指标 + 告警;冻结阀留 follow-up。验收:关一个通道,健康指标掉、告警送达。依赖:T5-5。风险:job 落点(见 §7 待拍第 3 点);自动冻结阀本期不做、勿顺手加。
T5-8 context 装配可观测(投喂进 trace,2026-07-05 创始人拍增)
目标:生成会话的 trace 记录"这局装配了什么"——prompt/配方版本、注入块清单(块名 + 版本/哈希 + 字节数),支撑配方 A/B 与"传导断裂"类投喂归因(需求源 = agentic-seat-context-design.md §4 第 6 性质)。输入:cheap/tier2 装配点(genconfig 取值链、middlewares 工厂)、波③ OTLP sink(默认关)+ jsonl 主路。产出:span 属性 + trace.jsonl 同步字段,旗随波③ 同开关。验收:trace.jsonl 与(旗开时)Tempo 的生成 span 见配方版本与块清单;旗关 = 字节不变。依赖:③(已落)。风险:属性膨胀——只记块名/版本/哈希/字节数,不记内容本体。
碰生产 game-cloud 的部署窗口点
- game-cloud 手埋(T5-1)= 改单体代码 = 生产部署窗口(重构建 + 重启)。是否与波② 生产上线合并成一次窗口,交主控拍(见 §7 待拍第 2 点)。
- 集中日志(T5-3):走 logback 改动则落 game-cloud 生产窗口;走 Collector filelog 抓容器 stdout 则不改单体(见 §7 待拍第 4 点)。
- 通道巡检(T5-7):落 game-cloud 后台 job 则占生产窗口;落独立小 job(mini-infra)则不碰单体(见 §7 待拍第 3 点)。
- Python 埋点(T5-2)= 生成线重启窗口。
- context 装配可观测(T5-8)= 生成线重启窗口(可与 T5-2 并窗);默认旗关、不改生成行为。
- Grafana 看板/告警/webhook(T5-4/T5-5)与 admin 进盘(T5-6)= 观测栈配置 + 前端发布,不碰 game-cloud 单体。
验收(引设计 §8 全六条 + 第 7 条)
本波收口做全量:
- 端到端 trace_id 一致(④ 已打通,这波在看板上复看)。
- 告警真送达:造一条阈值越线(成功率跌破 80% 或队列越限),Grafana 告警在约定时间内落到飞书/钉钉群——换了告警件更要验这条。
- 成本抽样对账:
llm_cost指标与一笔 new-api 实际扣费抽样比对,偏差在余量内(认它是自估值)。 - 可用性 error budget 燃尽图与 health 探测对得上。
- 停 Collector 主链不变、冒烟门全绿。
- agent 性能量化(② 已做,收口复看指标在盘)。
- 脱敏真打码:往一次生成的 brief / prompt 注入构造的手机号和 token,跑完在 Tempo 的 span 属性和 Loki 的日志正文里都查不到明文、只见掩码——漏配即安全回退,这条必须能真跑。
回滚
埋点、日志、看板、告警都是增量:埋点开关默认关经 profile 开、看板告警删规则即止、巡检 job 停即止;game-cloud 手埋回滚 = 关 profile 或还原埋点代码,主链不受影响。
7. 需主控拍板的点
- 生产 huijing-server 的部署位置与启动方式(compose / systemd / docker run)。它决定波② 的 agent 挂载与 JAVA_OPTS 注入手法,以及窗口 B 的重启方式(单实例冷重启需公告短暂不可用)。
- 波② 生产上线与波⑤ game-cloud 业务埋点是否合并成一次生产窗口。合并少一次重启;但设计倾向先验 agent 开销(第 6 条)稳定再上埋点。建议 ② 单独先上、⑤ 随后,请拍。
- new-api 通道巡检 job 的落点:game-cloud 后台 job(复用鉴权与 channel 配置、但碰生产)vs 独立小 job(落 mini-infra、不碰单体)。
- 集中日志采集方式:logback OTLP appender(改单体、trace_id 注入 MDC 最干净)vs Collector filelog 抓容器 stdout(不改单体但 trace 关联弱)。
- actuator/micrometer registry 选型:OTLP registry(直发 Collector、与 trace 同管道)vs prometheus registry(暴露
/actuator/prometheus让 Prometheus scrape)。设计两者都提;scrape 占位已在prometheus.yml,倾向 prometheus registry 少一条出网,请拍。 - 生成线重启与 game-cloud 生产窗口的先后节拍:波④ 依赖波② 的 agent 已在生产(agent 未上生产前,Python 侧注入的 traceparent 在 Java 侧无 agent 承接就是断)。建议 ② 生产上线后再排 ③④ 生成线重启;③ 可先上(自成 trace 无害),④ 紧跟 ②。