快速了解 runtime/metrics
以下是一个快速 Demo。代码如下:
func main() { descs := metrics.All() samples := make([]metrics.Sample, len(descs)) for i := range samples { samples[i].Name = descs[i].Name } metrics.Read(samples) for _, sample := range samples { name, value := sample.Name, sample.Value switch value.Kind() { case metrics.KindUint64: fmt.Printf("%s: %d\n", name, value.Uint64()) case metrics.KindFloat64: fmt.Printf("%s: %f\n", name, value.Float64()) case metrics.KindFloat64Histogram: fmt.Printf("%s: %f\n", name, medianBucket(value.Float64Histogram())) ... } } } func medianBucket(h *metrics.Float64Histogram) float64 { total := uint64(0) for _, count := range h.Counts { total += count } thresh := total / 2 total = 0 for i, count := range h.Counts { total += count if total >= thresh { return h.Buckets[i] } } panic("should not happen") }
输出结果:
/cgo/go-to-c-calls:calls: 0
/cpu/classes/gc/mark/assist:cpu-seconds: 0.000000
/cpu/classes/gc/mark/dedicated:cpu-seconds: 0.000000
...
/gc/cycles/automatic:gc-cycles: 0
/gc/cycles/forced:gc-cycles: 0
/gc/cycles/total:gc-cycles: 0
/gc/gogc:percent: 100
/gc/gomemlimit:bytes: 9223372036854775807
/gc/heap/allocs-by-size:bytes: 8193.000000
/gc/heap/allocs:bytes: 56832
/gc/heap/allocs:objects: 6
/gc/heap/frees-by-size:bytes: 1.000000
/gc/heap/frees:bytes: 0
/gc/heap/frees:objects: 0
/gc/heap/goal:bytes: 4194304
...
里面包含了相当多的 Go 系统指标。完整的代码运行和输出可以查看 https://go.dev/play/p/CKASbysqX9x
。
我梳理了一张对照清单。其中 10 个指标如下:
序号 | 指标 | 含义 |
---|---|---|
1 | /cgo/go-to-c-calls:calls | 当前进程从 Go 调用到 C 的次数 |
2 | /cpu/classes/gc/mark/assist:cpu-seconds | 预计执行 GC 程序所花费的 CPU 总时长,以协助 GC 并防止其落后于应用程序 |
3 | /cpu/classes/gc/mark/dedicated:cpu-seconds | 在专门用于执行 GC 任务的 CPU 处理器(根据 GOMAXPROCS 的定义)上执行 GC 任务预计需要花费的 CPU 总时长 |
4 | /cpu/classes/gc/mark/idle:cpu-seconds | 在空闲 CPU 资源上执行 GC 任务所花费的 CPU 总时间 |
5 | /cpu/classes/gc/pause:cpu-seconds | GC 暂停应用程序预计所花费的 CPU 总时长 |
6 | /gc/cycles/automatic:gc-cycles | Go Runtime 程序已完成的 GC 循环次数。 |
7 | /gc/gogc:percent | 用户配置的堆大小目标百分比 |
8 | /gc/heap/allocs:objects | 应用程序触发的堆分配累计计数 |
9 | /memory/classes/heap/free:bytes | Go Runtime 对物理内存的可用空间大小的预估(完全空闲并可返回底层系统但尚未返回的内存) |
10 | /sched/gomaxprocs:threads | 当前 runtime.GOMAXPROCS 的值,或是可以同时执行用户级 Go 代码的操作系统线程数。 |
对于完整指标有兴趣的可以查看:
https://pkg.go.dev/runtime/metrics
更多的 metrics 指标
最近在 Go 社区中有同学发起了一项讨论《metrics for the standard library》,希望探讨和在其他标准库中添加更多的 metrics 指标,提供更多的可观察性。
比较多同学期望的是网络、延迟类的指标,针对性能、错误等。如下几种场景:
net/http 服务端:
- 处理延迟。
- 请求/响应体大小。
- 恐慌(panic)、恢复(recover)。
- 错误/警告(触发
net/http.Server.ErrorLog
的所有内容) - 被拒绝的无效请求。
net/http 客户端:
- 调用延迟。
- 请求/响应体大小
- 连接池相关。
database/sql 客户端:
- 查询延迟。
- 响应大小。
- 连接池相关。
net 网络包相关:
- 例如 TCP、UDP 等,对应的打开连接的数量、连接状态(空闲、激活、关闭)、连接错误等。
- 例如 TLS,在握手阶段相关的指标,握手持续时间、握手失败计数等。
总结
整体上会发现大家对于 Go 标准库的指标诉求,更多的趋向于底层包。因为无论你用的是什么开源仓库,其绝大部分都是基于上述提到的包。
在现阶段,如果自己的 Go 业务应用程序去记录这些指标,就需要再封装一层,每一个包,例如:ORM 就需要去实现一遍插件等。
而第三方库实现不会把 metrics 这类非核心功能直接加入初始化实现中。因此官方标准库对 metrics 的支持是非常有必要的。
至少这样就不用每个团队都搞一遍 net/http、database/sql 等的延迟调用指标的配置和设置了。
以上就是Go 标准库增加metrics指标探讨分析的详细内容,更多关于Go 标准库metrics指标的资料请关注好代码网其它相关文章!