协作办公
用 samber/slog-* 构建 Go…
在 Go 项目中使用或迁移到 slog,或代码库已引入 github.com/samber/slog-* 包时,搭建可组合的日志处理管道。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
用 samber/slog-* 构建 G通用
解决思路
- 按固定顺序组织管道:record → [Sampling] → [Pipe: trace/PII] → [Router] → [Sinks],采样放最外层先丢弃噪声,格式化在路由前完成以保证所有 sink 收到干净属性。
- 用 slog-multi 组合 handler:Fanout 广播到所有 handler(延迟为各 handler 之和);Router().Add(h, predicate).Handler() 路由到所有匹配 handler;Router().Add(...).FirstMatch().Handler() 只路由到首个匹配;Failover()(handlers...) 依次尝试直到成功;Pool()(handlers...) 负载均衡每条记录只发一个 handler;Pipe(middlewares...).Handler(sink) 在 sink 前挂中间件链。
- 使用内置谓词做路由:LevelIs、LevelIsNot、MessageIs、MessageIsNot、MessageContains、MessageNotContains、AttrValueIs、AttrKindIs。
- 用 slog-sampling 控制吞吐:UniformSamplingOption 按固定比例丢弃;ThresholdSamplingOption 每间隔先记录前 N 条再按速率 R 采样(生产推荐);AbsoluteSamplingOption 每间隔全局上限 N 条;CustomSamplingOption 用自定义函数按记录返回采样率。
- 用匹配器对相似记录分组去重:MatchByLevel()、MatchByMessage()、MatchByLevelAndMessage()(默认)、MatchBySource()、MatchByAttribute(groups, key)。
- 用 slog-formatter 作为 Pipe 中间件转换属性:PIIFormatter、ErrorFormatter、TimeFormatter、UnixTimestampFormatter、IPAddressFormatter、HTTPRequestFormatter、HTTPResponseFormatter;通用格式化器 FormatByType[T]、FormatByKey、FormatByKind、FormatByGroup、FormatByGroupKey;用 FlattenFormatterMiddleware 展平嵌套属性。
- HTTP 中间件统一用 router.Use(slogXXX.New(logger)) 接入:slog-gin、slog-echo、slog-fiber、slog-chi、slog-http;共享 Config 字段 DefaultLevel、ClientErrorLevel、ServerErrorLevel、WithRequestBody、WithResponseBody、WithUserAgent、WithRequestID、WithTraceID、WithSpanID、Filters,例如用 sloggin.IgnorePath("/health", "/metrics") 跳过健康检查。
- 后端 sink 统一用 Option{}.NewXxxHandler() 构造:云服务 slog-datadog/slog-sentry/slog-loki/slog-graylog,消息 slog-kafka/slog-fluentd/slog-logstash/slog-nats,通知 slog-slack/slog-telegram/slog-webhook,存储 slog-parquet,桥接 slog-zap/slog-zerolog/slog-logrus。
- 批处理 handler 必须优雅关闭以刷新缓冲:Datadog 用 handler.Stop(ctx),Loki 用 lokiClient.Stop(),Kafka 用 writer.Close(),否则缓冲日志丢失。
- 避免常见错误:采样不要放在格式化之后;不要 Fanout 到多个同步 handler(改用 Pool() 并发分发);批处理 handler 要加 shutdown flush;Router 要加无谓词的 catch-all 兜底 handler;AttrFromContext 前先装 HTTP 中间件;无中间件时不要用 Pipe。
- 关注性能:Fanout 延迟为各 handler 之和(5 个 10ms handler 每次日志 50ms),用 Pool() 降到 max(latencies);Pipe 中间件链保持 2-4 个;slog-formatter 顺序处理属性,热路径优先在类型上实现 slog.LogValuer;上线前用 go test -bench 压测管道。
- 用 slogmulti.NewHandleInlineHandler 测试管道,断言各阶段收到的记录而无需真实 sink。
- 用 AttrFromContext 把 HTTP 中间件的请求级属性传播到所有 handler。
- 当不同 handler 需要不同记录子集时优先用 Router 而非 Fanout,Router 会评估谓词并跳过不匹配的 handler。
- 需要 Go 包文档、符号、版本、导入方和已知漏洞时用 godig(golang-pkg-go-dev skill),优先于 Context7;导航自身代码用 gopls skill;Context7 作为 pkg.go.dev 未索引文档的兜底。
适用边界 · 注意事项
- 项目未使用 slog 且未引入任何 github.com/samber/slog-* 包时,无需套用此管道模型。
- 需要极简日志、无多后端路由/采样/PII 脱敏需求时,直接使用标准库 slog 即可,引入 Pipe 等会增加每记录开销。
- 对延迟极度敏感的热路径,若无法接受中间件与格式化开销,应改用 slog.LogValuer 或简化管道。