当前位置:网站首页>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.
边栏推荐
猜你喜欢
随机推荐
leetcode-128:最长连续序列
想要写出好的测试用例,先要学会测试设计
软件测试报告有哪些内容?
斩获BAT、TMD技术专家Offer,我都经历了什么?
Distributed. Distributed lock
华为od 转骰子 js
The sword refers to offer17---print the n digits from 1 to the largest
C language _ structure pointer array function voting system
《实战》基于电商领域的词性提取及其决策树模型建模
RTL8720DN开发笔记一 环境搭建与mqtt实例
What have I experienced when I won the offer of BAT and TMD technical experts?
手把手教你配置Jenkins自动化邮件通知
Multiplication, DFS order
Is there a way to earn 300 yuan a day by doing a side business?
聚簇索引和非聚簇索引到底有什么区别
PDF 拆分/合并
221. 最大正方形
1.非类型模板参数 2.模板的特化 3.继承讲解
Jetpack Compose学习(8)——State及remeber
Fiddler抓包模拟弱网络环境测试