docs(cyrene): cmd/cyrene 存量英文注释中文化(22 个非测试文件,仅注释)
- 四组并行完成:main/wire*.go、wire_capacity|channels|runtime、channels|persona_*|emotion|observability、 voice|plugins|stream|skills|vision|subagent_tool|extractor|mcp|sessionread_tool|terminal_tool。 - 机械校验(git diff -U0 去 // 行与空行)仅剩 wire_frontend.go:84 一处行尾注释:代码前缀 「\ta.gw = gw 」经 cat -A 与 HEAD 逐字节比对一致(allow 清单已声明)。 - 验收:隔离 worktree(HEAD + 本批 patch)go build/vet 绿、全树 58 包 ok、 linux/amd64 + darwin/arm64 交叉编译绿;gofmt -l 干净。 - 备注:整树两次红均为负载敏感 flake(backthink / orchestration 的 timeout 类用例单独 -count=20 全过)。
This commit is contained in:
1 parent
5c2189efb0
commit
52f08dc343
22 files changed
+455
-586
No files matched your search
+28
-34
@@ -10,20 +10,18 @@ import (
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/services/gateway"
|
||||
)
|
||||
|
||||
// newAppTraceWriter builds the composition root's trace writer: the JSONL stderr
|
||||
// recorder (the local structured log of every span) plus room for the gateway's
|
||||
// observability sink, which can only be registered once the gateway exists (see
|
||||
// wireGatewayTraceSink).
|
||||
// newAppTraceWriter 构建组合根的 trace writer:JSONL stderr 记录器(每个 span 的
|
||||
// 本地结构化日志),外加为 gateway 可观测性出口预留的位置 —— 后者只能在 gateway
|
||||
// 存在之后注册(见 wireGatewayTraceSink)。
|
||||
func newAppTraceWriter() *traceFanout {
|
||||
return newTraceFanout(trace.NewJSONRecorder(os.Stderr))
|
||||
}
|
||||
|
||||
// wireGatewayTraceSink registers the gateway's observability sink on the app's
|
||||
// trace fanout. It is called from wireFrontend — the first moment the gateway
|
||||
// exists — because the gateway is built after the loop that emits the spans.
|
||||
// Without it the admin trace ring buffer is never fed and
|
||||
// GET /api/v1/admin/observability/trace answers an empty list forever
|
||||
// (design/19 §2). It is a no-op on a boot without a tracer or gateway.
|
||||
// wireGatewayTraceSink 把 gateway 的可观测性出口注册到应用的 trace 扇出上。它由
|
||||
// wireFrontend 调用 —— 那是 gateway 首次存在的时刻 —— 因为 gateway 构建在发出 span
|
||||
// 的循环之后。没有它,管理面板的 trace 环形缓冲区永远不会被喂数据,
|
||||
// GET /api/v1/admin/observability/trace 会永远返回空列表(design/19 §2)。在没有
|
||||
// tracer 或 gateway 的启动中是空操作。
|
||||
func wireGatewayTraceSink(a *app, gw *gateway.Server) {
|
||||
if a.traceWriter == nil || gw == nil {
|
||||
return
|
||||
@@ -32,20 +30,18 @@ func wireGatewayTraceSink(a *app, gw *gateway.Server) {
|
||||
a.log.Info("observability trace sink wired")
|
||||
}
|
||||
|
||||
// traceFanout is the composition root's trace.Writer. It fans every completed
|
||||
// span out to the sinks installed at boot (the JSONL stderr recorder) plus any
|
||||
// sink registered later in the boot sequence: the gateway's observability buffer
|
||||
// only exists once wireFrontend has built the gateway, while the loop that emits
|
||||
// the spans is built earlier in wireRuntime.
|
||||
// traceFanout 是组合根的 trace.Writer。它把每个已完成的 span 扇出到启动时安装的
|
||||
// 出口(JSONL stderr 记录器),以及启动流程中稍后注册的出口:gateway 的可观测性
|
||||
// 缓冲区要等 wireFrontend 构建好 gateway 才存在,而发出 span 的循环在 wireRuntime
|
||||
// 中更早就构建了。
|
||||
//
|
||||
// It is safe for concurrent use — the loop finishes spans from several
|
||||
// goroutines (per-step, per-tool-call, sub-agents).
|
||||
// 它可安全并发使用 —— 循环会从多个 goroutine 结束 span(按步、按工具调用、子代理)。
|
||||
type traceFanout struct {
|
||||
mu sync.RWMutex
|
||||
writers []trace.Writer
|
||||
}
|
||||
|
||||
// newTraceFanout builds a fanout over the given writers. Nil writers are dropped.
|
||||
// newTraceFanout 在给定 writers 之上构建扇出。nil writer 会被丢弃。
|
||||
func newTraceFanout(writers ...trace.Writer) *traceFanout {
|
||||
f := &traceFanout{}
|
||||
for _, w := range writers {
|
||||
@@ -54,7 +50,7 @@ func newTraceFanout(writers ...trace.Writer) *traceFanout {
|
||||
return f
|
||||
}
|
||||
|
||||
// Add installs one more sink. A nil writer is ignored.
|
||||
// Add 再安装一个出口。nil writer 被忽略。
|
||||
func (f *traceFanout) Add(w trace.Writer) {
|
||||
if w == nil {
|
||||
return
|
||||
@@ -64,9 +60,9 @@ func (f *traceFanout) Add(w trace.Writer) {
|
||||
f.writers = append(f.writers, w)
|
||||
}
|
||||
|
||||
// WriteSpan writes rec to every sink and returns the first error. Every sink is
|
||||
// tried even after a failure, so one broken sink cannot hide a span from the
|
||||
// others; the tracer only logs the returned error (trace.Tracer.emit).
|
||||
// WriteSpan 把 rec 写给每个出口并返回第一个错误。即使失败也仍会尝试所有出口,
|
||||
// 因此单个坏掉的出口无法把 span 从其他出口那里藏起来;tracer 只记录返回的错误
|
||||
// (trace.Tracer.emit)。
|
||||
func (f *traceFanout) WriteSpan(rec trace.SpanRecord) error {
|
||||
f.mu.RLock()
|
||||
defer f.mu.RUnlock()
|
||||
@@ -82,12 +78,11 @@ func (f *traceFanout) WriteSpan(rec trace.SpanRecord) error {
|
||||
return firstErr
|
||||
}
|
||||
|
||||
// wireGatewayLogBuffer hands the composition root's log ring buffer to the
|
||||
// gateway, so GET /api/v1/admin/observability/logs serves the recent backend log
|
||||
// tail. The logger is built before the gateway (its records must be captured
|
||||
// from the first log line), so the buffer is injected here, the first moment the
|
||||
// gateway exists — like wireGatewayTraceSink does for spans. It is a no-op on a
|
||||
// boot without a gateway.
|
||||
// wireGatewayLogBuffer 把组合根的日志环形缓冲区交给 gateway,使
|
||||
// GET /api/v1/admin/observability/logs 能提供最近的后端日志尾部。logger 构建在
|
||||
// gateway 之前(其记录必须从第一行日志起就被捕获),因此缓冲区在这里注入 ——
|
||||
// gateway 首次存在的时刻 —— 与 wireGatewayTraceSink 对 span 的做法一致。在没有
|
||||
// gateway 的启动中是空操作。
|
||||
func wireGatewayLogBuffer(a *app, buf *logger.RingBuffer) {
|
||||
if a == nil || a.gw == nil || buf == nil {
|
||||
return
|
||||
@@ -96,14 +91,13 @@ func wireGatewayLogBuffer(a *app, buf *logger.RingBuffer) {
|
||||
a.log.Info("observability log buffer wired", "capacity", buf.Len())
|
||||
}
|
||||
|
||||
// gatewaySpanSink adapts *gateway.Server to trace.Writer through its ObserveSpan
|
||||
// entry point, so an emitted span lands in the admin panel's trace ring buffer
|
||||
// AND in the LLM/subagent metric counters (ObserveSpan appends to the buffer and
|
||||
// observes the metrics; the buffer is what GET /api/v1/admin/observability/trace
|
||||
// serves).
|
||||
// gatewaySpanSink 通过 *gateway.Server 的 ObserveSpan 入口把它适配成 trace.Writer,
|
||||
// 使发出的 span 落在管理面板的 trace 环形缓冲区**并且**计入 LLM/子代理指标计数器
|
||||
// (ObserveSpan 既追加到缓冲区,也观测指标;缓冲区正是
|
||||
// GET /api/v1/admin/observability/trace 所提供的内容)。
|
||||
type gatewaySpanSink struct{ srv *gateway.Server }
|
||||
|
||||
// WriteSpan feeds rec to the gateway. A missing server is a no-op.
|
||||
// WriteSpan 把 rec 喂给 gateway。server 缺失时是空操作。
|
||||
func (g gatewaySpanSink) WriteSpan(rec trace.SpanRecord) error {
|
||||
if g.srv == nil {
|
||||
return nil
|
||||
|
||||
Reference in new issue
Block a user