当前位置:网站首页>如何在 go 程序中暴露 Prometheus 指标
如何在 go 程序中暴露 Prometheus 指标
2022-07-31 01:43:00 【TechForGeek】
SLI 与 SLO
SLI(服务质量指标) 指的是一个服务的某项服务质量的一个具体量化指标(如请求延迟、错误率、QPS)。
SLO(服务质量目标) 则是服务的某个 SLI 的目标值,例如,我们可以定义一个SLO,要求 95% 的请求的延迟小于 100ms。
SLI与SLO是传统运维转型SRE绕不过的主题,它们是SRE实践的核心。传统运维通常追求 100% 的可用性,但这个目标是不可能实现的,通过实施SLO,可以带来如下好处:
监控应用程序的行为,以便更好地改进应用程序
确定工作优先级,即开发新特性还是保障服务稳定性
作为控制手段使用,通过比较SLI与SLO,决定某项操作是否执行
建立用户预期
定义 SLI
要实施 SLO,首先要定义出来 SLI,而 Prometheus 监控则是定义 SLI 的一种很好的工具,下面将介绍在 Go 程序中暴露 Prometheus Metric 来定义 SLI。
在 Golang 程序中暴露 Prometheus 指标
按照 Prometheus 官方文档[1]中的说明,在 Golang 中暴露 Prometheus 指标,可以使用 Golang 的 Prometheus Client Library —— github.com/prometheus/client_golang。
接下来的例子中,我们使用 net/http 标准模块创建一个 /login 接口,然后使用 Golang 的 Prometheus Client Library 统计接口的访问次数。
foo.go:
package main
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var http_requests_total = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Total Request",
},
[]string{"path"})
func login(w http.ResponseWriter, r *http.Request) {
http_requests_total.With(prometheus.Labels{"path": "login"}).Inc()
// 使用 WithLabelValues() 函数可以不指定 Key 值
// http_requests_total.WithLabelValues("login").Inc()
w.Write([]byte("login success\n"))
}
func logout(w http.ResponseWriter, r *http.Request) {
http_requests_total.With(prometheus.Labels{"path": "logout"}).Inc()
// 使用 WithLabelValues() 函数可以不指定 Key 值
// http_requests_total.WithLabelValues("login").Inc()
w.Write([]byte("logout success\n"))
}
func init() {
prometheus.MustRegister(http_requests_total)
}
func main() {
http.Handle("/metrics", promhttp.Handler())
http.HandleFunc("/login", login)
http.HandleFunc("/logout", logout)
http.ListenAndServe(":6060", nil)
}
执行如下命令运行上面的程序:
# 下载依赖模块
go get
# 运行程序
go run foo.go
使用 curl 命令访问 '/login' 接口:
curl http://SERVER-IP:6060/login
然后访问 '/metrics' 接口获取 Prometheus Metric 信息:
curl -s http://ops-api.stonewise.cn:6060/metrics | grep login_requests_total
输出内容如下:
# HELP login_requests_total Total Request
# TYPE login_requests_total counter
login_requests_total 1
可以看到,我们已经成功地统计了 '/login' 接口的访问次数了。
使用 Label 区分不同的 API
当我们程序中有多个 API 接口时,为每个 API 接口单独定义一个 metric,既麻烦又不便于管理,此时,我们可以定义一个 metric,然后在这个 metric 上添加 Label,使用 Label 来区分不同的 API 接口。
下面的例子中,我们在程序中定义了 '/login' 和 '/logout' 两个接口,然后定义了一个 prometheus metric —— http_requests_total,在这个 metric 上,我们添加了一个 Label —— path,通过这个 Label 来区分不同的 API。
foo.go:
package main
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var http_requests_total = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Total Request",
},
[]string{"path"})
func login(w http.ResponseWriter, r *http.Request) {
http_requests_total.With(prometheus.Labels{"path": "login"}).Inc()
// 使用 WithLabelValues() 函数可以不指定 Key 值
// http_requests_total.WithLabelValues("login").Inc()
w.Write([]byte("login success\n"))
}
func logout(w http.ResponseWriter, r *http.Request) {
http_requests_total.With(prometheus.Labels{"path": "logout"}).Inc()
// 使用 WithLabelValues() 函数可以不指定 Key 值
// http_requests_total.WithLabelValues("login").Inc()
w.Write([]byte("logout success\n"))
}
func init() {
prometheus.MustRegister(http_requests_total)
}
func main() {
http.Handle("/metrics", promhttp.Handler())
http.HandleFunc("/login", login)
http.HandleFunc("/logout", logout)
http.ListenAndServe(":6060", nil)
}
执行如下命令运行上面的程序:
# 下载依赖模块
go get
# 运行程序
go run foo.go
使用 curl 命令访问 '/login' 接口:
curl http://SERVER-IP:6060/login
使用 curl 命令访问 '/logout' 接口:
curl http://SERVER-IP:6060/logout
然后访问 '/metrics' 接口获取 Prometheus Metric 信息:
curl -s http://ops-api.stonewise.cn:6060/metrics | grep http_requests_total
输出内容如下:
# HELP http_requests_total Total Request
# TYPE http_requests_total counter
http_requests_total{path="login"} 1
http_requests_total{path="logout"} 1
可以看到,http_requests_total 已经通过 path Label 来区分不同接口的统计信息了。
到这里,我们已经成功地在 Golang 程序中暴露 Prometheus 指标了。
有了 Counter 类型的指标 http_request_total,我们可以借助 Prometheus 的 rate() 函数来计算访问不同接口的 QPS,这样我们就定义好了一个 SLI。
总结
在这篇文章中,我们介绍了使用 Golang 的 github.com/prometheus/client_golang 模块,创建 Counter 类型的指标来统计不同接口的访问次数。 github.com/prometheus/client_golang 模块除了支持 Counter 类型的指标外,还支持gauge,summary,histogram 类型的 metric,使用方法都类似,详细的使用说明可以参考 prometheus_client 模块的文档说明[2]。
参考:
[1]: https://prometheus.io/docs/instrumenting/clientlibs/
[2]: https://github.com/prometheus/client_golang
一如既往,如果你对文章中的内容有任何疑问,或者是发现文章中有任何错误,都可以通过留言告诉我;如果你喜欢我的文章,欢迎关注我的微信公众号 Tech For Geek.
边栏推荐
- PDF split/merge
- 基于Keras_bert模型的Bert使用与字词预测
- 认识DTU什么是4GDTU设备
- android的webview缓存相关知识收集
- tensorflow与GPU版本对应安装问题
- 《实战》基于电商领域的词性提取及其决策树模型建模
- [WeChat applet] This article takes you to understand data binding, event binding, event parameter transfer, and data synchronization
- Centos 7.9安装PostgreSQL14.4步骤
- Chi-square distribution of digital image steganography
- leetcode-1161:最大层内元素和
猜你喜欢
Dispatch Center xxl-Job
Parameter introduction and selection points of wireless module
leetcode-1161:最大层内元素和
MySQL (6)
小黑leetcode之旅:117. 填充每个节点的下一个右侧节点指针 II
coldfusion文件读取漏洞(CVE-2010-2861)
Teach you how to configure Jenkins automated email notifications
内网渗透——提权
Bert usage and word prediction based on Keras_bert model
Are you still working hard on the limit of MySQL paging?
随机推荐
Meta元宇宙部门第二季度亏损28亿 仍要继续押注?元宇宙发展尚未看到出路
解析云原生消息流系统 Apache Pulsar 能力及场景
初识C语言 -- 数组
分布式.分布式锁
计算S=a+aa+…+aa…a
进程间通信学习笔记
Multiplication, DFS order
Word 表格跨页,仍然显示标题
GCC Rust is approved to be included in the mainline code base, or will meet you in GCC 13
蓝牙mesh系统开发三 Ble Mesh 配网器 Provisioner
Basic Parameters of RF Devices 2
【Mysql】——索引的深度理解
Are you still working hard on the limit of MySQL paging?
Teach you how to configure Jenkins automated email notifications
类似 MS Project 的项目管理工具有哪些
关于Redis相关内容的基础学习
C语言_结构体指针数组函数选票系统
认识DTU什么是4GDTU设备
仿牛客网项目总结
软件测试基础接口测试-入门Jmeter,你要注意这些事