Go 标准库想增加 metrics 指标,你支持吗?

大家好,我是煎鱼。

在 Go 的标准库中,有一个神奇的标准库 runtime/metrics,这个标准库提供了一系列预定义好的 Go 自身的相关指标。

如果没有编写过基础监控库或者关注的比较少的朋友可能会没接触到这类指标。

今天这篇文章是展开现有的 metrics 指标,并结合现有的社区讨论一起看看还有没有必要增加更多的标准库指标。

快速了解 runtime/metrics

以下是一个快速 Demo。代码如下:

go 复制代码
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")
}

输出结果:

bash 复制代码
/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#hdr-Supported_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 等的延迟调用指标的配置和设置了。

文章持续更新,可以微信搜【脑子进煎鱼了】阅读,本文 GitHub github.com/eddycjy/blo... 已收录,学习 Go 语言可以看 Go 学习地图和路线,欢迎 Star 催更。

Go 图书系列

推荐阅读

相关推荐
郝同学的测开笔记1 天前
云原生探索系列(十二):Go 语言接口详解
后端·云原生·go
一点一木2 天前
WebAssembly:Go 如何优化前端性能
前端·go·webassembly
千羽的编程时光2 天前
【CloudWeGo】字节跳动 Golang 微服务框架 Hertz 集成 Gorm-Gen 实战
go
27669582924 天前
阿里1688 阿里滑块 231滑块 x5sec分析
java·python·go·验证码·1688·阿里滑块·231滑块
Moment5 天前
在 NodeJs 中如何通过子进程与 Golang 进行 IPC 通信 🙄🙄🙄
前端·后端·go
唐僧洗头爱飘柔95275 天前
(Go基础)变量与常量?字面量与变量的较量!
开发语言·后端·golang·go·go语言初上手
黑心萝卜三条杠5 天前
【Go语言】深入理解Go语言:并发、内存管理和垃圾回收
google·程序员·go
不喝水的鱼儿6 天前
【LuatOS】基于WebSocket的同步请求框架
网络·websocket·网络协议·go·luatos·lua5.4
微刻时光6 天前
程序员开发速查表
java·开发语言·python·docker·go·php·编程语言
lidenger7 天前
服务认证-来者何人
后端·go