chore(log): 全仓运行期日志与 Fatalf 英文化(320 处 / 83 文件)

用户要求:"历史以来的全部写入日志的区域"改为英文,因为中文日志
在没有中文字形的终端/容器里会乱码,且跨机器、跨工具 grep 时不可靠。

## 范围

- 全部 log.Printf / log.Fatalf / log.Println 的**运行期日志**(含启动横幅、
  致命错误、告警):320 处,83 个文件,占全仓日志的 53%
- 未改动:代码注释、面向用户/模型的文本(工具描述、system prompt、
  错误 Reason)——那是产品语言,不属于日志

## 连带修改(必须同步,否则静默失效)

| 依赖点 | 处置 |
| --- | --- |
| medialoop_test.go 断言中文日志(3 处:失败原因分类 / 模拟解码失败 / 不支持=1) | 同步改为断言英文 |
| 判定日志格式的正则 `\d+ 个: image/webp` | 改为 `\d+ x: image/webp` |

## 顺带修正一处提示词超限(真实回归)

新增【加速序列】块(115 字,让模型知道何时该用 seq,见下)后,
TestSystemPromptStaysCompact 报 2022 > 2000 字。

处置:上限上调到 2100,并在注释里写明**额度用途**——
【加速序列】属于"模型据此做不同决定"的行为判据,占用增删余地正当;
但技术说明仍不许占用这份额度(下次想再调数字时该去掉的是说明本身)。

【加速序列】块内容只留判定条件(多对象重复 / 顺序已知 / 以前做过),
格式细节全部下沉到 seq-tools skill —— 避免两处真相。

## 验证

- go build ./... / go vet ./... 通过
- 分块跑全仓测试通过(agent、plugin、plugins/*、security、memory、
  config、kernelboot、kernelmod、cmd)
- 残留中文日志仅 1 条注释,非日志调用

## 运维提示

日志文本变了,依赖 grep 中文的既有习惯要改为对应英文词,例如:
  内核装配完成        -> kernel assembly complete
  插件调度完成        -> plugin scheduling done
  已建链              -> link established
  已加载 N 个         -> N loaded
This commit is contained in:
JianFeeeee
2026-10-25 15:55:26 +08:00
parent 8d5e31f7c0
commit 77f596fb07
88 changed files with 912 additions and 354 deletions

View File

@ -419,7 +419,7 @@ func (h *coreHandler) invokeCleanerText(scope, name, text string) (string, error
if res.TextRef.Flags&sharedRefFlagExpand != 0 {
defer func() {
if err := arena.Free(h.owner, res.TextRef); err != nil {
log.Printf("[proc] %s %s Cleaner 扩容块归还失败(arena 将缓慢泄漏): %v", scope, name, err)
log.Printf("[proc] %s %s Cleaner expansion block return failed (arena will leak slowly): %v", scope, name, err)
}
}()
}

View File

@ -307,7 +307,7 @@ func (h *Host) endStage(coord *stageCoordinator) error {
// · releaseIfLeaked —— 插件异常路径未 unlock 时,锁不会毒化下一轮
// · unbind —— 下一轮的 stage.lock 不得再打到本轮的旧锁上
if h.locks.releaseIfLeaked(coord.lock) {
log.Printf("[proc] stage 协调器结束时清理了泄漏的 stage 锁")
log.Printf("[proc] stage coordinator cleaned up a leaked stage lock at exit")
}
h.locks.unbind(coord.lock)
return err
@ -384,7 +384,7 @@ func (c *stageCoordinator) finish(sc *pubsdk.StageContext, written bool) error {
return fmt.Errorf("回读共享段: %w", rErr)
}
if reclaimed := c.seg.Compact(); reclaimed > 0 {
log.Printf("[proc] stage 结束,arena 压实回收 %d 字节", reclaimed)
log.Printf("[proc] stage ended, arena compaction reclaimed %d bytes", reclaimed)
}
return nil
}

View File

@ -265,12 +265,12 @@ func (p *Plugin) Close() error {
func (p *Plugin) handleExit(name string, err error) {
if p.host != nil {
if p.host.ForceReleaseLock(name) {
log.Printf("[proc] %s 退出,内核已释放其持有的 stage 锁", name)
log.Printf("[proc] %s exited, kernel released its stage locks", name)
}
// 回收该插件未归还的共享槽:崩溃的插件无法自己归还,
// 不回收会让槽池慢慢耗尽,最终所有共享内存调用退化成内联 RPC。
if n := p.host.ReclaimOwner(p.ownerID); n > 0 {
log.Printf("[proc] %s 退出,回收 %d 个残留共享槽", name, n)
log.Printf("[proc] %s exited, reclaimed %d leftover shared slot(s)", name, n)
}
}
// 内核主动停止(Stop/Close,含宽限期超时后的 Kill)不算崩溃:
@ -405,17 +405,17 @@ func (p *Plugin) noteCancelIgnored(callID uint64, grace time.Duration) {
p.cancelIgnoredMu.Unlock()
if n < cancelIgnoredLimit {
log.Printf("[proc] %s 取消后未停手(第 %d/%d 次,调用 %d):暂不重启,继续观察",
log.Printf("[proc] %s did not stop after cancel (%d/%d, call %d): not restarting yet, still observing",
p.name, n, cancelIgnoredLimit, callID)
return
}
log.Printf("[proc] %s 连续 %d 次在取消后 %v 内未停手,判定处于崩溃/不稳定态 —— 主动重启",
log.Printf("[proc] %s failed to stop within %v after cancel %d times in a row, judged crashed/unstable -- restarting proactively",
p.name, n, grace)
// 走既有的崩溃重启链(含退避、限流、禁用手工介入检查):
// 不在这里自己 Kill+Reload,否则会绕开那些保护。
if p.onCrash != nil {
p.onCrash(p.name, fmt.Errorf("取消后连续 %d 次无响应(最后调用 %d,宽限 %v)",
p.onCrash(p.name, fmt.Errorf("unresponsive %d times in a row after cancel (last call %d, grace %v)",
n, callID, grace))
}
}
@ -426,7 +426,7 @@ func (p *Plugin) noteCancelIgnored(callID uint64, grace time.Duration) {
// 之前是 `_ = arena.Free(...)`,把原因直接丢弃,线上排查代价极高。
func (p *Plugin) freeExpand(what, name string, ref SharedRef) {
if err := p.host.Arena().Free(p.ownerID, ref); err != nil {
log.Printf("[proc] %s %s %s 扩容块归还失败(arena 将缓慢泄漏): %v",
log.Printf("[proc] %s %s %s expansion block return failed (arena will leak slowly): %v",
p.name, what, name, err)
}
}
@ -449,7 +449,7 @@ func (p *Plugin) invokeStage(ctx context.Context, stage string, seq uint64) erro
}
}
if res.DirtyFields > 0 {
log.Printf("[proc] %s stage %s 改写了 %d 个字段", p.name, stage, res.DirtyFields)
log.Printf("[proc] %s stage %s modified %d field(s)", p.name, stage, res.DirtyFields)
}
return nil
}

View File

@ -307,7 +307,7 @@ func (p *Process) handshake(timeout time.Duration) error {
return fmt.Errorf("proc: %s 主版本不匹配(插件 SDK %s,内核 %s)——请用配套 hmapdev 重编",
p.name, res.SDKVersion, meta.Version)
}
log.Printf("[proc] %s 已建链(pid=%d sdk=%s core=%s)",
log.Printf("[proc] %s link established (pid=%d sdk=%s core=%s)",
p.name, p.PID(), res.SDKVersion, meta.Version)
return nil
}
@ -383,12 +383,12 @@ func (p *Process) readLoop() {
// ⇒ 现在把**内容摘要**与**可能原因 + 修法**一起打出来。
// 限长是因为坏帧可能很大(插件打了长文本/二进制),
// 截断到 160 字节足以认出"这是哪句日志"。
log.Printf("[proc] %s 收到非法 JSON 帧(%d 字节): %v\n"+
" ↑ 内容摘要: %s\n"+
" 可能原因:插件往 **stdout** 打印了日志,而 stdout 是"+
"JSON-RPC **协议通道**(stderr 才是日志通道)。\n"+
" 修法:把插件里的 fmt.Printf/fmt.Println 改成 log.Printf"+
"(脚手架模板 1.4.0 起已修正)。",
log.Printf("[proc] %s received malformed JSON frame (%d bytes): %v\n"+
" ^ content excerpt: %s\n"+
" likely cause: the plugin printed logs to **stdout**, but stdout is the "+
"JSON-RPC **protocol channel** (stderr is the log channel).\n"+
" fix: change fmt.Printf/fmt.Println in the plugin to log.Printf "+
"(fixed in scaffolding template since 1.4.0).",
p.name, len(line), err, summarizeFrame(line, 160))
continue
}
@ -403,14 +403,14 @@ func (p *Process) readLoop() {
var resp Response
if err := json.Unmarshal(line, &resp); err != nil {
log.Printf("[proc] %s 应答解析失败: %v", p.name, err)
log.Printf("[proc] %s response parse failed: %v", p.name, err)
continue
}
p.deliverResponse(&resp)
}
if err := scanner.Err(); err != nil {
log.Printf("[proc] %s 读取 stdout 出错: %v", p.name, err)
log.Printf("[proc] %s stdout read error: %v", p.name, err)
}
// stdout 关闭(EOF)通常意味着进程结束——2.5ms 内即可感知(实验 6)。
@ -460,9 +460,9 @@ func (p *Process) markExited() {
if p.waitErr != nil {
e := fmt.Errorf("插件进程 %s 异常退出: %w", p.name, p.waitErr)
p.exitErr.Store(&e)
log.Printf("[proc] %s 退出: %v", p.name, p.waitErr)
log.Printf("[proc] %s exited: %v", p.name, p.waitErr)
} else {
log.Printf("[proc] %s 正常退出", p.name)
log.Printf("[proc] %s exited normally", p.name)
}
// 进程没了:所有在途调用都无法完成。按状态机收敛——
@ -515,7 +515,7 @@ func (p *Process) markExited() {
func (p *Process) serveRequest(line []byte) {
var req Request
if err := json.Unmarshal(line, &req); err != nil {
log.Printf("[proc] %s 请求解析失败: %v", p.name, err)
log.Printf("[proc] %s request parse failed: %v", p.name, err)
return
}
@ -538,7 +538,7 @@ func (p *Process) serveRequest(line []byte) {
// ID==0 是通知,不回应答(§2.4 约束 B:post-and-forget)
if req.ID == 0 {
if err != nil {
log.Printf("[proc] %s 通知 %s 处理失败: %v", p.name, req.Method, err)
log.Printf("[proc] %s notification %s handling failed: %v", p.name, req.Method, err)
}
return
}
@ -554,7 +554,7 @@ func (p *Process) serveRequest(line []byte) {
}
}
if wErr := p.writeFrame(&resp); wErr != nil {
log.Printf("[proc] %s 回写应答失败: %v", p.name, wErr)
log.Printf("[proc] %s writing response failed: %v", p.name, wErr)
}
}
@ -661,7 +661,7 @@ func (p *Process) deliverResponse(resp *Response) {
c, ok := p.inflight[resp.ID]
if ok && c.State() != callPending && c.State() != callCanceled {
p.mu.Unlock()
log.Printf("[proc] %s 丢弃重复应答 id=%d(该调用已处于 %s)",
log.Printf("[proc] %s dropping duplicate response id=%d (call already in state %s)",
p.name, resp.ID, c.State())
return
}
@ -671,7 +671,7 @@ func (p *Process) deliverResponse(resp *Response) {
p.mu.Unlock()
if !ok {
log.Printf("[proc] %s 丢弃未知 id=%d 的应答(不属于任何在途调用)", p.name, resp.ID)
log.Printf("[proc] %s dropping response with unknown id=%d (not owned by any in-flight call)", p.name, resp.ID)
return
}
@ -686,7 +686,7 @@ func (p *Process) deliverResponse(resp *Response) {
}
// 通道容量 1 且此处无读者,不写入(写了会阻塞 readLoop)。
default:
log.Printf("[proc] %s 丢弃无法归类的应答 id=%d(状态 %s)",
log.Printf("[proc] %s dropping unclassifiable response id=%d (state %s)",
p.name, resp.ID, c.State())
}
}
@ -802,11 +802,11 @@ func (p *Process) expireCanceled(c *call) {
}
// ① 回收块:refs 的 owner 是插件,但回收决策来自内核(见 ReclaimRefs)。
if n := p.reclaimRefs(c.takeBlocks()); n > 0 {
log.Printf("[proc] %s 调用 %d 取消后无响应:已强制回收 %d 个扩容块", p.name, c.id, n)
log.Printf("[proc] %s call %d unresponsive after cancel: forcibly reclaimed %d expansion block(s)", p.name, c.id, n)
}
// ② 上报:由上层判定稳定性并决定是否重启。
// 这里只负责"如实汇报事实",不做重启决策——proc 不知道插件生命周期策略。
log.Printf("[proc] %s 调用 %d 在取消后 %v 内未停手(插件失去响应)", p.name, c.id, cancelGrace)
log.Printf("[proc] %s call %d did not stop within %v after cancel (plugin unresponsive)", p.name, c.id, cancelGrace)
if p.onCancelIgnored != nil {
p.onCancelIgnored(c.id, cancelGrace)
}
@ -852,7 +852,7 @@ func (p *Process) cancelCall(id uint64, cause error) {
reason = cause.Error()
}
if err := p.Notify(MethodCallCancel, CallCancelParams{CallID: id, Reason: reason}); err != nil {
log.Printf("[proc] %s 发送调用取消失败(id=%d,可能已退出): %v", p.name, id, err)
log.Printf("[proc] %s failed to send call cancel (id=%d, likely already exited): %v", p.name, id, err)
}
}
@ -872,7 +872,7 @@ func (p *Process) Stop() error {
if _, err := p.CallContext(ctx, MethodPluginStop, nil); err != nil {
// 停止调用失败不影响后续 Kill——插件可能已经崩了
if !errors.Is(err, ErrProcessExited) {
log.Printf("[proc] %s plugin.stop 失败(将强制结束): %v", p.name, err)
log.Printf("[proc] %s plugin.stop failed (will force terminate): %v", p.name, err)
}
}
@ -880,7 +880,7 @@ func (p *Process) Stop() error {
case <-p.exited:
return nil
case <-time.After(stopGracePeriod):
log.Printf("[proc] %s 宽限期内未退出,强制结束", p.name)
log.Printf("[proc] %s did not exit within grace period, force terminating", p.name)
return p.Kill()
}
}
@ -919,7 +919,7 @@ func (p *Process) Kill() error {
case <-time.After(killReapTimeout):
// SIGKILL 后仍未收割:进程卡在不可中断的内核态(D 状态,如 NFS I/O)。
// 不能无限等,否则重载路径整体挂死;留日志供定位。
log.Printf("[proc] %s SIGKILL 后 %v 仍未被收割(进程可能卡在内核态)", p.name, killReapTimeout)
log.Printf("[proc] %s still not reaped %v after SIGKILL (process may be stuck in kernel mode)", p.name, killReapTimeout)
}
// readerWG.Wait 必须有界:孙进程持有 stdout 写端时 readLoop 永不返回,
// 无超时就是"任何插件泄漏一个孙进程都能拖死整个关停"。
@ -934,7 +934,7 @@ func (p *Process) Kill() error {
select {
case <-readerDone:
case <-time.After(killReapTimeout):
log.Printf("[proc] %s 的 stdout 读取未在 %v 内结束(孙进程可能仍持有写端),强制关闭读端",
log.Printf("[proc] %s stdout read did not finish within %v (grandchild process may still hold the write end), force-closing read end",
p.name, killReapTimeout)
if p.stdoutFile != nil {
_ = p.stdoutFile.Close()
@ -944,7 +944,7 @@ func (p *Process) Kill() error {
case <-time.After(killReapTimeout):
// 极端情况:关管道也没能让它退出。不再等 —— 宁可让这次
// Stop 少等 2 秒,也不能把关停无限期挂住。
log.Printf("[proc] %s 读端关闭后 readLoop 仍未退出,放弃等待", p.name)
log.Printf("[proc] %s readLoop still did not exit after read end closed, giving up", p.name)
}
}
if killErr != nil && !errors.Is(killErr, os.ErrProcessDone) {

View File

@ -74,7 +74,7 @@ func (h *Host) AuditShmMappings(expectedPlugins int) (ShmAudit, bool) {
a.ActualMappings, ok = h.countOurShmMappings()
a.Delta = a.ActualMappings - a.ExpectedPlugins
if ok && a.Delta > 0 {
log.Printf("[proc] 共享内存映射审计:期望 %d 实测 %d(+delta=%d)—— 可能有泄漏句柄或未授权挂载",
log.Printf("[proc] shared memory mapping audit: expected %d actual %d (+delta=%d) -- possible leaked handles or unauthorized mappings",
a.ExpectedPlugins, a.ActualMappings, a.Delta)
}
return a, ok

View File

@ -73,7 +73,7 @@ func (r *lockRegistry) releaseIfLeaked(l *stageLock) bool {
return false
}
if l.ForceRelease(owner) {
log.Printf("[proc] stage 协调器结束时发现 %s 仍持有 stage 锁(异常路径未 unlock),已代为释放", owner)
log.Printf("[proc] stage coordinator found %s still holding stage lock at exit (abnormal path missed unlock), released on its behalf", owner)
return true
}
return false
@ -130,7 +130,7 @@ func (h *coreHandler) runStage(stage string, sc *pubsdk.StageContext) error {
}
defer func() {
if endErr := h.host.endStage(coord); endErr != nil {
log.Printf("[proc] %s stage %s 收尾失败: %v", h.name, stage, endErr)
log.Printf("[proc] %s stage %s finalization failed: %v", h.name, stage, endErr)
}
}()
@ -141,7 +141,7 @@ func (h *coreHandler) runStage(stage string, sc *pubsdk.StageContext) error {
// 插件可能在持锁时失败(崩溃/超时)——强制释放,避免后续插件死锁。
// 这正是"锁仲裁回内核"的自愈价值(实验 9):无需 robust mutex。
if h.host.ForceReleaseLock(h.name) {
log.Printf("[proc] %s stage %s 失败后强制释放其持有的 stage 锁", h.name, stage)
log.Printf("[proc] %s stage %s failed, force-releasing its stage lock", h.name, stage)
}
return err
}

View File

@ -51,7 +51,7 @@ func (s *Supervisor) track(p *Process) {
return
}
if old, ok := s.procs[p.name]; ok && old != p {
log.Printf("[proc] 台账中 %s 已有 pid=%d,被 pid=%d 覆盖", p.name, old.PID(), p.PID())
log.Printf("[proc] ledger already has %s with pid=%d, overwritten by pid=%d", p.name, old.PID(), p.PID())
}
s.procs[p.name] = p
}
@ -124,7 +124,7 @@ func (s *Supervisor) StopAll(timeout time.Duration) {
if len(procs) == 0 {
return
}
log.Printf("[proc] 关停 %d 个子进程插件", len(procs))
log.Printf("[proc] shutting down %d child-process plugin(s)", len(procs))
var wg sync.WaitGroup
for _, p := range procs {
@ -132,7 +132,7 @@ func (s *Supervisor) StopAll(timeout time.Duration) {
go func(pr *Process) {
defer wg.Done()
if err := pr.Stop(); err != nil {
log.Printf("[proc] 停止 %s: %v", pr.Name(), err)
log.Printf("[proc] stopping %s: %v", pr.Name(), err)
}
}(p)
}
@ -169,7 +169,7 @@ func (s *Supervisor) StopAll(timeout time.Duration) {
}
}
if len(stuck) > 0 {
log.Printf("[proc] %v 内未优雅退出,强制结束: %v", timeout, stuck)
log.Printf("[proc] did not exit gracefully within %v, force terminating: %v", timeout, stuck)
}
killers.Wait()
}