Files
HomeAgent/cmd/homed/logflags_test.go
JianFeeeee 0cb20fb7f5 fix(log): 生产日志默认不再带源文件位置
## 现象

生产日志每行都带 `file.go:NNN`:

    2026/10/31 18:47:03 bootstrap.go:320: [homed] shutting down...
    2026/10/31 18:47:03 builtin_skill.go:163: [plugin] seq: removed skill ...
    2026/10/31 18:47:03 sidecar.go:419: [clawhubadapter] sidecar manager stopped

来源是 `cmd/homed/bootstrap.go` 里无条件 `log.SetFlags(... | log.Lshortfile)`。

## 判断:生产确实不需要

- 多数日志**本身带模块前缀**(`[homed]` / `[plugin]` / `[kbtree]` / `[skillmgr]`),
  去掉行号后定位能力并不缺
- `Lshortfile` 在**每一次** log 调用里做一次 `runtime.Caller`,不为零
- 它还不能真的消歧:它只打基名,26 个插件里有多个 `plugin.go`,
  `plugin.go:104` 反而指不出是哪一个 —— 真正的消歧靠的是消息里的 `[插件名]` 前缀

## 改法

`logFlags()` 抽出来,默认 `Ldate|Ltime`;`HOMED_LOG_SOURCE=1`(或 true/yes/on)
时追加 `Lshortfile`。

保留开关而不是删掉:排查插件/装配问题时行号仍有用,部署方临时开一下即可。
用法写进 `docs/zh/deploy-runbook.md` §3.0。

## 判据

- `TestLogFlagsNoSourceByDefault`:默认不得有 Lshortfile,且日期时间必须保留
- `TestLogFlagsSourceOptIn`:开关的六种正向写法生效、四种关闭写法不误开

## 验证

    go build ./...             ✓
    go vet ./cmd/homed/        ✓
    go test ./cmd/homed/       ✓(含新增两条)
2026-10-31 18:49:36 +08:00

51 lines
1.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"log"
"testing"
)
// TestLogFlagsNoSourceByDefault 钉住「默认日志不带源文件位置」。
//
// 起因(2026-10-31,用户看生产日志时提出):
//
// 2026/10/31 18:47:03 bootstrap.go:320: [homed] shutting down...
// 2026/10/31 18:47:03 builtin_skill.go:163: [plugin] seq: removed skill ...
//
// 生产日志不需要 `file.go:NNN`:多数日志本身带模块前缀(`[homed]` / `[plugin]` /
// `[kbtree]`),定位能力并不缺;而 Lshortfile 每行都多一次 runtime.Caller。
//
// 判据形状:直接测 logFlags(),因为它在 setupLogging 里被原样交给 log.SetFlags。
// 不去跑 setupLogging 本身——那会建目录、开文件,判据会变重且依赖文件系统。
func TestLogFlagsNoSourceByDefault(t *testing.T) {
t.Setenv(logSourceEnv, "")
flags := logFlags()
if flags&log.Lshortfile != 0 {
t.Error("默认不得带 Lshortfile(生产日志不该出现 file.go:NNN)")
}
if flags&log.Ldate == 0 || flags&log.Ltime == 0 {
t.Error("日期与时间必须保留:日志没有时间戳就没法关联事件")
}
}
// TestLogFlagsSourceOptIn 钉住开关本身仍然可用。
//
// 为什么保留它:排查插件/装配问题时,同名文件很多(每个插件都有自己的
// plugin.go),行号是唯一能区分的东西。删掉开关等于把那条排查路径也删了。
func TestLogFlagsSourceOptIn(t *testing.T) {
for _, v := range []string{"1", "true", "TRUE", "yes", "on", " 1 "} {
t.Setenv(logSourceEnv, v)
if logFlags()&log.Lshortfile == 0 {
t.Errorf("%s=%q 应打开 Lshortfile", logSourceEnv, v)
}
}
// 明确关掉的写法不能被当成开
for _, v := range []string{"0", "false", "off", "no", ""} {
t.Setenv(logSourceEnv, v)
if logFlags()&log.Lshortfile != 0 {
t.Errorf("%s=%q 不应打开 Lshortfile", logSourceEnv, v)
}
}
}