From ffd22f22c24d60fbcbb234f9ea7db19eb871a1ee Mon Sep 17 00:00:00 2001 From: zizi Date: Wed, 24 Jun 2026 11:49:03 +0000 Subject: [PATCH] =?UTF-8?q?feat(tier2):=20C1=20trace=20=E4=B8=AD=E9=97=B4?= =?UTF-8?q?=E4=BB=B6=E6=8E=A5=20with=5Fstudio(=E5=BC=80=20Studio=20?= =?UTF-8?q?=E5=8D=B3=E6=97=81=E8=B7=AF=E6=8E=A8=20OTLP=20span)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit C1 此前建了 observability.with_studio + studio_sink(OTLP→Studio),但没 wire 进真正跑的 Tier2TraceMiddleware(它在 worker/middleware.py、C1 没动)。本提交把中间件新建 adapter 的路径从 TraceAdapter(...) 换成 with_studio(...):drop-in——TIER2_STUDIO_URL/infra_config[studio] 取不到时 studio sink 自动 no-op,行为与原 TraceAdapter 完全一致(CLI/服务两线不开 Studio 即无感);取到地址则 每步在原 sink 外旁路推一份 OTLP span 给 AgentScope Studio(observe-only,best-effort,不阻塞主链)。 存 _studio_sink 句柄供收口 flush。配合 mini-desktop 起 Studio(创始人:now)即得真跑可视化。 Co-Authored-By: Claude Opus 4.8 (1M context) --- tier2/gen-worker/worker/middleware.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tier2/gen-worker/worker/middleware.py b/tier2/gen-worker/worker/middleware.py index 5a297c3e..c7461782 100644 --- a/tier2/gen-worker/worker/middleware.py +++ b/tier2/gen-worker/worker/middleware.py @@ -64,14 +64,14 @@ except Exception: # pragma: no cover —— 直跑兜底:worker 包未就位时 # make_phase_marker / PHASE_* 是 U3 给三道新钩子产「相位段」typed event 用的(走 adapter 同一条 ingest 路)。 try: from observability.trace import ( # type: ignore - TraceAdapter, make_phase_marker, PHASE_REASONING, PHASE_ACTING, PHASE_MODEL_CALL) + TraceAdapter, with_studio, make_phase_marker, PHASE_REASONING, PHASE_ACTING, PHASE_MODEL_CALL) except Exception: # pragma: no cover —— 直跑/路径未就位兜底:把 gen-worker/ 加进 sys.path 再取 import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from observability.trace import ( # type: ignore - TraceAdapter, make_phase_marker, PHASE_REASONING, PHASE_ACTING, PHASE_MODEL_CALL) + TraceAdapter, with_studio, make_phase_marker, PHASE_REASONING, PHASE_ACTING, PHASE_MODEL_CALL) # 成本折算(¥ 累进硬熔断用):compute 折单条 usage → ¥(纯函数,显式传参);活价取不到时回落次数闸。 # newapi_pricing.fetch_pricing_params 一步取齐 new-api 计费三件套(失败 best-effort 返回 None)。 @@ -521,8 +521,13 @@ class Tier2TraceMiddleware(MiddlewareBase): """ self.trace_id = trace_id # 复用传入 adapter 或新建;adapter 是 trace 的产出件(H1/H2),本 middleware 只负责把事件喂进去。 - self.adapter = adapter or TraceAdapter( + # 新建走 with_studio(C1 接线):若 TIER2_STUDIO_URL / infra_config[studio] 可解析,则每步在原 sink + # 之外旁路推一份 OTLP span 给 AgentScope Studio(observe-only);取不到地址 → studio sink 自动 no-op, + # 行为 == 原 TraceAdapter(sink=...),零影响(故 CLI/服务两条线都白拿 Studio 可观测、不开即无感)。 + self.adapter = adapter or with_studio( trace_id=trace_id, sink=sink, keep_in_memory=keep_in_memory) + # studio sink 句柄(收口 flush 残留 span 用;with_studio 把它挂在 adapter._studio_sink,无则 None)。 + self._studio_sink = getattr(self.adapter, "_studio_sink", None) # 兜底层告警计数(adapter 自身抛异常的极端情况;正常应为 0,因 adapter 内部已 best-effort)。 self._middleware_dropped = 0