当前位置:网站首页>How to expose Prometheus metrics in go programs
How to expose Prometheus metrics in go programs
2022-07-31 01:44: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 Standard modules create one /login 接口,然后使用 Golang 的 Prometheus Client Library Statistics on the access times of the interface.
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() function can not be specified 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() function can not be specified 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)
}Execute the following command to run the above program:
# 下载依赖模块
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可以看到,We have successfully counted '/login' The number of times the interface has been accessed.
使用 Label 区分不同的 API
When there are multiple in our program API 接口时,为每个 API An interface defines a separate one metric,Both cumbersome and inconvenient to manage,此时,我们可以定义一个 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() function can not be specified 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() function can not be specified 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)
}Execute the following command to run the above program:
# 下载依赖模块
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 To distinguish the statistics of different interfaces.
到这里,我们已经成功地在 Golang 程序中暴露 Prometheus 指标了.
有了 Counter 类型的指标 http_request_total,我们可以借助 Prometheus 的 rate() functions to compute access to different interfaces QPS,这样我们就定义好了一个 SLI.
总结
在这篇文章中,我们介绍了使用 Golang 的 github.com/prometheus/client_golang 模块,创建 Counter Type indicators to count the number of visits to different interfaces. 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.
边栏推荐
猜你喜欢

MySql installation and configuration super detailed tutorial and simple method of building database and table

pycharm cannot run after renaming (error: can't open file...No such file or directory)

观察者(observer)模式(一)

想要写出好的测试用例,先要学会测试设计

软件测试工作3年了,谈谈我是如何从刚入门进阶到自动化测试的?

VSCode插件:嵌套注释
![[WeChat applet] This article takes you to understand data binding, event binding, event parameter transfer, and data synchronization](/img/f8/8437783794c2007a74c0a153d85102.png)
[WeChat applet] This article takes you to understand data binding, event binding, event parameter transfer, and data synchronization

4G通信模块CAT1和CAT4的区别

Distributed. Idempotency

Jiuzhou Cloud was selected into the "Trusted Cloud's Latest Evaluation System and the List of Enterprises Passing the Evaluation in 2022"
随机推荐
软件测试缺陷报告---定义,组成,缺陷的生命周期,缺陷跟踪产后处理流程,缺陷跟踪处理流程,缺陷跟踪的目的,缺陷管理工具
数字图像隐写术之卡方分布
Dispatch Center xxl-Job
加密生活,Web3 项目合伙人的一天
Is there a way to earn 300 yuan a day by doing a side business?
PDF split/merge
87. Convert String to Integer
MySQL的存储过程
Gateway路由的配置方式
仿牛客网项目总结
leetcode-128:最长连续序列
Ticmp - 更快的让应用从 MySQL 迁移到 TiDB
rpm安装postgresql12
leetcode-1161:最大层内元素和
JS逆向之浏览器补环境(一)
kotlin中函数作为参数和函数作为返回值实例练习
Word/Excel 固定表格大小,填写内容时,表格不随单元格内容变化
Analyze the capabilities and scenarios of the cloud native message flow system Apache Pulsar
ROS Action通信
来自一位女测试工程师的内心独白...