mcpField
G
go-observability

go-observability

github.com/eduardo-sl开发83157 次安装2 周前更新
代码仓库

关于 go-observability

go-observability 是面向 Go 生产服务开发者的可观测性技能,介绍结构化日志、OpenTelemetry 追踪与指标、告警、信号关联及遥测关闭,并提供按需参考资料。

主要功能

  1. 01使用 slog 进行结构化日志记录
  2. 02OpenTelemetry 追踪模式
  3. 03指标与基数管理指导
  4. 04告警与 SLO 实践
  5. 05关联日志、追踪与指标
  6. 06平稳关闭遥测组件

适用场景

  1. 01为 Go 服务添加可观测性
  2. 02将日志与请求追踪关联
  3. 03设计服务指标和告警

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/eduardo-sl/go-agent-skills --skill go-observability

安装后在 Claude Code 中输入/go-observability确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
alerting.md
metrics.md
slog.md
tracing.md

详细介绍

Go 可观测性

对于生产服务,可观测性不是可选项。每个服务都必须生成结构化日志、公开指标并传递跟踪上下文。使用标准库 log/slog 记录日志,并使用 OpenTelemetry 进行跟踪和指标采集。

社区默认规范。如果项目的 skill 或 agent-config 规则明确取代 go-observability,则优先遵循该规则。

按需加载的详细参考资料:

  • references/slog.md — 处理器设置、日志记录器注入、子日志记录器、LogValuer 脱敏、跟踪 ID 处理器、热点路径、运行时级别。
  • references/tracing.md — 跟踪器提供程序、跨度、上下文传播、采样、性能分析标签、关闭。
  • references/metrics.md — 指标定义、HTTP 插桩。
  • references/alerting.md — RED/USE、直方图与摘要、燃烧率告警、告警卫生、示例。

只有在下文内容不足时,才阅读参考文件。

1. 使用 slog 进行结构化日志记录

在生产环境中使用 log/slog(Go 1.21+)和 JSON 处理器。每一行都必须是键值对,绝不能是格式化句子:

// ✅ Good — structured, leveled
logger.Info("user created", slog.String("user_id", user.ID), slog.Duration("latency", elapsed))

// ❌ Bad — unparseable in production
log.Printf("user %s created in %v", user.ID, elapsed)

将日志记录器作为依赖项注入;绝不要使用包级全局变量。使用 logger.With(...) 派生子日志记录器,将组件、方法和请求 ID 附加一次,而不是在每个调用点都重复附加。参见 references/slog.md。

日志级别 — 保持一致
级别用途
Debug详细诊断信息,在生产环境中禁用
Info正常操作:收到请求、任务完成
Warn可恢复的问题:重试成功、使用了已弃用功能
Error需要关注的故障:数据库宕机、外部调用失败

绝不要将预期情况记录为 Error 级别(未找到用户 → Info 或 Warn)。

敏感数据 — 绝不要记录
  • 密码、令牌、API 密钥
  • 完整信用卡号、SSN
  • 个人标识信息:可用于识别个人的电子邮件地址、电话号码、IP 地址
  • 包含 PII 的原始请求正文
// ✅ Good — an opaque internal ID, no personal data
logger.Info("auth attempt", slog.String("user_id", userID), slog.Bool("success", ok))

// ❌ Bad — leaks a credential and a personal identifier
logger.Info("auth attempt", slog.String("password", password))
logger.Info("auth attempt", slog.String("user", email))

记录稳定的内部 ID,并在允许存储个人数据的系统中关联个人数据。日志保留期限、搜索访问权限和第三方日志接收端,通常都达不到用户表所适用的保护标准。

将脱敏设为类型本身的特性:为密钥以及存储个人数据的结构体实现 slog.LogValuer,这样 slog.Any(user) 在任何地方都只会记录安全字段。

成本与控制
  • 热点路径使用 logger.LogAttrs,并使用 logger.Enabled 防止生成昂贵的属性。
  • 在 HandlerOptions 中使用 slog.LevelVar,即可在不重新部署的情况下更改级别。
  • slog.NewMultiHandler(Go 1.26+)可将日志分发给多个处理器。

2. 使用 OpenTelemetry 进行分布式跟踪

对于所有值得在瀑布图中观察的操作都启动一个跨度——入站请求、数据库调用、出站 HTTP、重要业务步骤——并始终使用 defer span.End()。

参考示例遵循的规则:

  • 使用操作名称命名跨度(GetUser、db.query),不要使用完全限定的函数名,也不要使用 doStuff。
  • 失败时调用 span.RecordError(err) 和 span.SetStatus(codes.Error, ...),否则失败请求会显示为绿色跨度。
  • 将 ctx 沿整个调用链传递。在调用链中途使用 context.Background() 会悄然启动新的跟踪,并断开父级关联。
  • 使用 ParentBased(TraceIDRatioBased(r)) 进行采样,确保各服务对同一跟踪达成一致;通过收集器中的尾部采样保留错误和慢请求。
  • 性能分析是第四种信号:在生产环境中持续进行性能分析,并使用范围受限的 pprof.Labels(路由、租户等级)拆分热点函数。

设置和示例见 references/tracing.md。

3. 使用 OpenTelemetry / Prometheus 记录指标

类型用途示例
Counter单调递增的值请求总数、错误总数
Gauge可升可降的值活跃连接数、队列深度
Histogram值的分布请求延迟、响应大小

命名格式为 <namespace>_<subsystem>_<name>_<unit>:

http_request_duration_seconds     ✅ (unit in name)
http_requests_total               ✅ (counter with _total suffix)
db_connections_active             ✅ (gauge, no suffix needed)
user_signups                      ❌ (missing _total for counter)
requestLatency                    ❌ (camelCase, no unit)

保持基数有界。使用路由模式、方法和状态码作为标签—— 切勿使用用户 ID、请求 ID 或原始 r.URL.Path;这些值会为每个取值创建新的 时间序列,最终导致指标后端宕机。

定义和中间件见 references/metrics.md。

4. 关联日志、追踪和指标

没有追踪 ID 的日志行无法关联到生成它的请求。将处理程序包装一次,让每个 *Context 日志调用都从 ctx 添加 trace_id 和 span_id——包装器还必须重写 WithAttrs 和 WithGroup,否则子日志记录器会丢失这些字段。为延迟直方图附加示例(追踪 ID),以便从 p99 峰值跳转到问题追踪。

5. 告警和 SLO

  • 对服务按路由衡量 RED(速率、错误、时长),对资源池和队列衡量 USE (利用率、饱和度、错误)。
  • 延迟必须使用 Histogram,而非 Summary——Summary 分位数无法跨实例 聚合。围绕 SLO 阈值设置桶。
  • 同时基于长窗口和短窗口的 SLO 消耗速率触发页面告警;较慢的消耗则创建工单。
  • 针对症状而非原因设置告警;使用 rate() 而非 irate();对 必须存在的序列使用 absent();每条页面告警都附上运行手册链接。

查询和示例接线方式见 references/alerting.md。

6. 遥测的优雅关闭

批处理 span 处理器会将 spans 保存在内存中。退出时使用其独立的超时时间调用 tp.Shutdown(ctx),否则崩溃前最后几秒的 spans——那些最值得关注的——将永远无法到达收集器。

示例见 references/tracing.md。

验证清单

  1. 所有日志都使用 log/slog 和结构化键值对,而非 fmt.Printf 或 log.Printf
  2. Logger 作为依赖注入,而非用作全局变量
  3. 日志输出中不包含敏感数据(密码、令牌、PII)
  4. 通过 context.Context 在所有函数调用间传递追踪上下文
  5. 为重要操作(数据库调用、HTTP 请求、业务逻辑)创建 spans
  6. 使用 span.RecordError(err) 记录 span 错误并设置错误状态
  7. 指标遵循命名约定:_seconds、_total、_bytes
  8. 指标中不使用高基数标签(用户 ID、请求 ID)
  9. 服务退出时优雅关闭遥测提供程序
  10. 在日志条目中包含追踪 ID,以便关联
  11. 使用直方图记录延迟;页面告警应基于 SLO 消耗速率,并附带运行手册

评论

支持 Markdown