Summary
cpdaemon uploads its own log lines to CPM in SyncMetricsRequest.Logs, formatted by SyncLogHandler (cpdaemon/pkg/cpm/synclog.go). Every error attached with slogx.Error(err) arrives at CPM without its text:
msg="register loop error, will retry" loggerName=cpm.syncer pa_uuid=… platform_id=p ={e:0x26c132018330}
slogx.Error returns an attribute with an empty key whose value is a slog.LogValuer (cpgolib/slogx/log.go). SyncLogHandler.convert → formatSyncLogAttrs → slogx.ValueToString never calls Value.Resolve(), so the LogValuer is printed with %+v of its struct ({e:0x…}), not as the error=<text> / errorVerbose=<stack> group it resolves to. slog's own handlers resolve LogValuers before formatting.
slogx.Error appears 16 times in syncer.go and 2 times in worker_mgr.go, and the worker package logs through the same logger. Among the lines affected are "register loop error", "sync strategy failed", "apply strategy failed", "collect cpworker stats error" and "send metrics to cpm error". In CPM, every failure the daemon reports therefore shows no cause.
A related problem sits in the same function. formatSyncLogAttrs builds a base prefix for nested groups but never uses it for the leaf key. slog.Group("worker", slog.Int("pid", 42)) is written as pid=42, and logger.WithGroup("mgr") attributes lose mgr.. slog's text convention is worker.pid=42. This is latent today, because no product code logs a named group.
Expected
- Resolve each attribute value (
attr.Value = attr.Value.Resolve()) before formatting.
- Inline groups with an empty key, as slog does.
- Qualify named groups with
base.
The failed-registration line above would then end in error="cpm down".
Reproduction
Branch feat/verification-coverage, all registered as known failures:
TestSyncer_UploadedLogsCarryTheErrorText (cpdaemon/pkg/cpm/syncer_faults_test.go): a failed registration, then the uploaded metrics logs are checked for the error text.
TestSyncLog_ErrorAttributesAreInlined and TestSyncLog_GroupedAttributesAreQualified (cpdaemon/pkg/cpm/synclog_test.go).
中文原文
cpdaemon 通过 SyncMetricsRequest.Logs 把自身日志上报给 CPM,格式由 SyncLogHandler 生成。所有用 slogx.Error(err) 附带的错误在 CPM 端都显示为 ={e:0x…}:slogx.Error 返回 key 为空、值为 LogValuer 的属性,而 formatSyncLogAttrs/ValueToString 从不调用 Value.Resolve(),于是打印的是结构体指针而非 error=<文本>。syncer.go 16 处、worker_mgr.go 2 处使用,注册失败、同步失败、上报失败等日志在 CPM 中均看不到原因。同一函数中,嵌套 group 的 base 前缀被计算却未用于叶子 key,worker.pid=42 被写成 pid=42(目前产品代码未使用命名 group,属潜在问题)。应先 Resolve 再格式化,空 key 的 group 内联,命名 group 加前缀。复现:syncer_faults_test.go 的 TestSyncer_UploadedLogsCarryTheErrorText,synclog_test.go 的两个测试,均已登记为已知失败。
Summary
cpdaemon uploads its own log lines to CPM in
SyncMetricsRequest.Logs, formatted bySyncLogHandler(cpdaemon/pkg/cpm/synclog.go). Every error attached withslogx.Error(err)arrives at CPM without its text:slogx.Errorreturns an attribute with an empty key whose value is aslog.LogValuer(cpgolib/slogx/log.go).SyncLogHandler.convert→formatSyncLogAttrs→slogx.ValueToStringnever callsValue.Resolve(), so theLogValueris printed with%+vof its struct ({e:0x…}), not as theerror=<text>/errorVerbose=<stack>group it resolves to. slog's own handlers resolveLogValuers before formatting.slogx.Errorappears 16 times in syncer.go and 2 times in worker_mgr.go, and the worker package logs through the same logger. Among the lines affected are "register loop error", "sync strategy failed", "apply strategy failed", "collect cpworker stats error" and "send metrics to cpm error". In CPM, every failure the daemon reports therefore shows no cause.A related problem sits in the same function.
formatSyncLogAttrsbuilds abaseprefix for nested groups but never uses it for the leaf key.slog.Group("worker", slog.Int("pid", 42))is written aspid=42, andlogger.WithGroup("mgr")attributes losemgr.. slog's text convention isworker.pid=42. This is latent today, because no product code logs a named group.Expected
attr.Value = attr.Value.Resolve()) before formatting.base.The failed-registration line above would then end in
error="cpm down".Reproduction
Branch
feat/verification-coverage, all registered as known failures:TestSyncer_UploadedLogsCarryTheErrorText(cpdaemon/pkg/cpm/syncer_faults_test.go): a failed registration, then the uploaded metrics logs are checked for the error text.TestSyncLog_ErrorAttributesAreInlinedandTestSyncLog_GroupedAttributesAreQualified(cpdaemon/pkg/cpm/synclog_test.go).中文原文
cpdaemon 通过 SyncMetricsRequest.Logs 把自身日志上报给 CPM,格式由 SyncLogHandler 生成。所有用 slogx.Error(err) 附带的错误在 CPM 端都显示为 ={e:0x…}:slogx.Error 返回 key 为空、值为 LogValuer 的属性,而 formatSyncLogAttrs/ValueToString 从不调用 Value.Resolve(),于是打印的是结构体指针而非 error=<文本>。syncer.go 16 处、worker_mgr.go 2 处使用,注册失败、同步失败、上报失败等日志在 CPM 中均看不到原因。同一函数中,嵌套 group 的 base 前缀被计算却未用于叶子 key,worker.pid=42 被写成 pid=42(目前产品代码未使用命名 group,属潜在问题)。应先 Resolve 再格式化,空 key 的 group 内联,命名 group 加前缀。复现:syncer_faults_test.go 的 TestSyncer_UploadedLogsCarryTheErrorText,synclog_test.go 的两个测试,均已登记为已知失败。