refactor(go)!: 日志改 stdlib log/slog 仅 kv 传参 + spec 契约收敛与四语言 span_id 预留 - #4
Conversation
四语言一致性收敛,spec 作为唯一契约源先行: - time 固定毫秒精度(3 位小数):Go 由 RFC3339Nano 改为固定 3 位,与 Python(%03d) / Node(toISOString) 对齐;纳秒对日志无实际收益,毫秒换来 稳定的 LTS 正则。 - 新增 span_id:log-format / common-fields 增加预留位,二期 trace 接入前 恒空、有值才输出;明确 request_id/trace_id/span_id 均为高基数值, 禁止用作 metrics label。 - error 字段放宽:不再限定为「原因链文本」,允许带异常上下文的语言 (Python 等)写入完整 traceback(多行,JSON 转义为 \n,仍是单行 JSON); 同时补注该字段不适合聚合(取值逐次不同),按错误类型聚合请用 msg 常量 + 业务字段另作维度。 - community 取源修正:旧 infra-common / service.md 已过时,改取 opensourceways/infrastructure 仓 service.yaml 顶层 communities, 枚举刷新为 18 项,并附可复现的 awk 同步命令(含 services: 缩进 - name: 是服务名而非社区名的坑位说明)。 - 新增「msg 常量 + kv 承载数据」传参约定:msg 内嵌值会让每行都不同, 无法聚合计数、告警规则失效,明确禁止 printf 风格。 Co-Authored-By: Claude Code <noreply@anthropic.com>
对齐主流(stdlib log/slog、kratos v3):日志 API 只保留 kv 传参,
Info(msg string, args ...any) 交替键值,去掉 printf 变体。msg 内嵌值会让
每行都不同、无法聚合计数,这是契约层已禁止 printf 风格的实现侧落地。
- log/log.go 重写为 kratos v3 形态的包级 API:Level = slog.Level 别名、
SetDefault/Default、X/XContext 成对、ParseLevel(容错 FATAL/WARNING)、
LevelFatal = slog.LevelError + 4。各导出helper 直接调用同一 emitter,
保证 runtime.Callers 的固定 skip 计数成立。
- 新增 log/handler.go:自定义 slog.Handler,单行扁平 JSON 写 stdout。
Handle(ctx, record) 能拿到 ctx,故 InfoContext(ctx, ...) 可自动从
sdkctx.From(ctx) 附加请求字段,调用点无需 WithRequest 绑定 —— 这正是
slog 方案相对旧 API 的 DX 收益。
- 字段严格按契约顺序输出;community 取请求上下文覆盖,未覆盖回退部署默认。
- logger 字段(调用位置 service/webhook.go:51)用 runtime.CallersFrames
取帧:runtime.Callers 返回的是返回地址,FuncForPC(pc).FileLine 会归到
上一层帧;CallersFrames 才能正确解释(并展开内联帧)。代码注释已写明,
避免回归。路径只取末两段,不泄漏构建机绝对路径。
- error 值统一转 .Error() 文本:encoding/json 此前把多数 error 渲染成 {},
这是本次修掉的根因。
- appendJSONString 不转义 <>&(与 slog JSONHandler 一致,可读性优先),
但非法 UTF-8 回退 json.Marshal 以免产出非法 JSON。
- sdkctx 增加 SpanID 预留位,日志侧有值才输出。
- README 同步为 slog 方案与 kv 用法。
Co-Authored-By: Claude Code <noreply@anthropic.com>
三语言对齐 Go/spec 的 span_id 预留位,首期只保证可写可透传、有值才输出: - Python:_context.Request 增 span_id 字段与 span_id() 访问器,bind() 合并; log.py 非空才写入 span_id。 - Node:context.js 增 spanId() 访问器,bindRequest 合并 spanId; log.js 非空才写入 span_id。 - Java:RequestContext 增 spanId(4 参 of/push 重载,保留 3 参以兼容首期用法)、 currentSpanId()、asMdcFields 含 span_id;ObsLogging 增 MDC_SPAN_ID 写入与 清理;logback-json.xml 的 mdc provider 增 span_id 键。 - 各语言补测试:含/不含 span_id 两条路径、与 trace_id 互不干扰、 span-only bind 不误产出 trace_id;README 字段清单同步。 Co-Authored-By: Claude Code <noreply@anthropic.com>
Welcome To opensourceways CommunityHey @TangJia025 , thanks for your contribution to the community. Bot Usage ManualI'm the Bot here serving you. You can find the instructions on how to interact with me at Here . That means you can comment below every pull request or issue to trigger Bot Commands. Contact GuideIf you have any questions, please contact the SIG: infratructure , |
CLA Signature PassTangJia025, thanks for your pull request. All authors of the commits have signed the CLA. 👍 |
Linking Issue Notice@TangJia025 , the pull request must be linked to at least one issue. |
Co-Authored-By: Claude Code <noreply@anthropic.com>
此前 Java 侧只把字段写进 MDC,真正决定输出的 encoder provider 用的是默认配置, 实测(examples/logback-json.xml)与契约存在五处不符: @timestamp(纳秒 + 本地时区 +08:00)、level 大写 INFO、message、logger_name, 且未配 <stackTrace/> 时 throwable 被整条丢弃 —— 错误日志直接丢失原因。 纯 XML 配置无法修好:<logLevel/> 只能输出大写(7.4 无大小写配置项, <logLevelValue/> 输出的是数字 20000),字段名走 LogstashFieldNames 而 LoggingEventCompositeJsonEncoder 没有 setFieldNames。故固定字段这一层的所有权 收到 SDK 内。 - 新增 log.ObsJsonProvider(logstash AbstractJsonProvider 实现):按契约顺序输出 time/level/msg/service/env/instance/community/request_id/trace_id/span_id/logger/error。 time 由 DateTimeFormatter 固定毫秒 UTC + XXX 输出 Z(不受 JVM 时区影响); level 小写(TRACE 归入 debug);logger 取调用位置 file:line,对齐 Go 侧语义; error 用 ThrowableProxyUtil.asString 输出完整堆栈。JSON 转义交给 Jackson 的 JsonGenerator,不手写转义。空值省略,预留位(trace_id/span_id)无值即不出现。 覆写 prepareForDeferredProcessing 提前提取调用点,兼容 AsyncAppender。 - examples/logback-json.xml 简化为一行 <provider class="...ObsJsonProvider"/>, 并为业务字段留出「在本 provider 之后追加 <mdc>/<keyValuePairs/>」的注释位。 - pom 增 jackson-core(provided,2.15.2 与 logstash 7.4 对齐):provider 直接实现 其接口、直接用 JsonGenerator,不应依赖传递依赖。 - 新增 ObsJsonProviderTest:直接加载 examples/logback-json.xml 跑真实 encoder, 断言字段名/顺序/时间格式(单测内故意用非 UTC 时区验证)/级别小写/logger 为调用 位置/MDC 取值/异常堆栈保留。仅断言 MDC 是测不出这批问题的。 - README 的示例 JSON 与字段说明同步(原示例即错误输出)。 Co-Authored-By: Claude Code <noreply@anthropic.com>
CLA Signature PassTangJia025, thanks for your pull request. All authors of the commits have signed the CLA. 👍 |
承接 #2061。PR #1 合入后,在 spec 契约与四语言 SDK 上做的第二轮收敛,含破坏性 API 变更(Go 侧)。
spec 契约
RFC3339Nano改为固定 3 位小数,与 Python(.%03dZ) / Node(toISOString) 对齐。纳秒对日志无实际收益,毫秒换来稳定的 LTS 正则。span_id预留位:log-format.md/common-fields.md增加字段,二期 trace 接入前恒空、有值才输出;并明确request_id/trace_id/span_id均为高基数值,禁止用作 metrics label。error字段放宽:不再限定「原因链文本」,允许带异常上下文的语言(Python 等)写入完整 traceback(多行,JSON 转义为\n,仍是单行 JSON)。同时补注该字段不适合聚合(取值逐次不同),按错误类型聚合请用msg常量 + 业务字段另作维度。community取源修正:旧infra-common/service.md已过时,改取infrastructure仓service.yaml顶层communities,枚举刷新为 18 项,附可复现的 awk 同步命令。Go:日志改用 stdlib
log/slog自定义 Handler(破坏性变更)对齐主流(stdlib
log/slog、kratos v3)——日志 API 只保留 kv 传参,Info(msg string, args ...any)交替键值,去掉 printf 变体。log/log.go重写为 kratos v3 形态的包级 API:Level = slog.Level别名、SetDefault/Default、X/XContext成对、ParseLevel(容错FATAL/WARNING)、LevelFatal = slog.LevelError + 4。log/handler.go:自定义slog.Handler,单行扁平 JSON → stdout。Handle(ctx, record)能拿到 ctx,故InfoContext(ctx, ...)自动从sdkctx.From(ctx)附加请求字段,调用点无需WithRequest绑定。error值统一转.Error()文本:encoding/json此前把多数error渲染成{},这是本次修掉的根因。logger字段(调用位置service/webhook.go:51)用runtime.CallersFrames取帧 ——runtime.Callers返回的是返回地址,FuncForPC(pc).FileLine会归到上一层帧;CallersFrames才能正确解释(并展开内联帧)。代码注释已写明避免回归。路径只取末两段,不泄漏构建机绝对路径。sdkctx增加SpanID预留位,日志侧有值才输出。Python / Node / Java:
span_id预留注入首期只保证可写可透传、有值才输出:
_context.Request增span_id与访问器,bind()合并;log.py非空才写。context.js增spanId(),bindRequest合并;log.js非空才写。RequestContext增spanId(4 参of/push重载,保留 3 参兼容首期用法)、currentSpanId()、asMdcFields含span_id;ObsLogging增MDC_SPAN_ID写入与清理;logback-json.xml的mdcprovider 增键。验证
go vet ./... && go test -race -count=1 ./...ok(含并发写测试)pytest -q15 passednpm test10 pass / 0 failmvn -B testTests run: 12, Failures: 0, Errors: 0Go 本地为 1.26.7,CI 走
go-version-file(1.22);新代码未使用任何 1.23+ 语言特性或标准库,结果可外推。🤖 Generated with Claude Code
AI 使用声明
当前 PR 是否有 AI 参与: