Go开发Prometheus客户端实战步骤

1、项目背景

在当前的IT运维环境中,我们的业务系统日益复杂,特别是针对特定的业务逻辑和定制化需求,传统的通用监控工具往往难以覆盖所有的监控场景。例如,考虑到一个复杂的电商平台,除了基础的服务器性能、网络状况等基础设施监控外,我们还迫切需要对特定业务指标进行监控,比如DNS解析成功率、API响应延迟、特定业务流程的错误率等,这些都是直接影响用户体验和业务连续性的关键因素。

面对这样的需求,虽然Prometheus官方提供了一系列标准的Exporter,如node_exporter和snmp_exporter,它们在基础监控层面表现优秀,但对于上述提到的业务逻辑相关的监控需求却鞭长莫及。为了弥补这一空白,我们需要自定义一个专为业务定制的Prometheus Exporter,以实现对这些特定业务指标的精准监控。

为此,我们选择使用Go语言(Golang)来编写这个Exporter,原因在于Go语言天生对并发友好,适合编写高性能的网络服务,且官方提供了成熟的Prometheus客户端库,便于快速集成和开发

下面的代码地址:https://github.com/nangongchengfeng/Prometheus-Go-Template

2、开发环境搭建

  1. 安装Go语言:确保机器上安装了Go语言(1.20版本以上)并配置了GOPATH。

    curl -L https://go.dev/dl/go1.21.3.linux-amd64.tar.gz -o ./go-linux-amd64.tar.gz
    解压
    sudo tar -zxvf go-linux-amd64.tar.gz -C /usr/local/lib/
    
    下面语句是给所有用户创建环境变量
    
    # 下面内容需要多行复制
    sudo tee -a ~/.bashrc << EOF
    export GOROOT=/usr/local/lib/go/
    export GOPATH=/home/${USER}/sdk/go
    export PATH=\$PATH:\$GOROOT/bin:\$GOPATH/bin
    EOF
    # 单行
    source ~/.bashrc
    
  2. 下载Prometheus包:通过go get命令下载client_golang包。

    go get github.com/prometheus/client_golang/prometheus
    go get github.com/prometheus/client_golang/prometheus/promhttp
    
  3. 开启Go模块代理

    go env -w GO111MODULE=on
    go env -w GOPROXY=https://goproxy.cn,direct
    
    如果不行,请修改 如下设置:
    set GOPRIVATE=gitlab.xx.com
    set GOPROXY=https://goproxy.cn
    set GONOPROXY=gitlab.xx.com
    set GONOSUMDB=gitlab.xx.com
    

3、编写Exporter基础代码

  1. 创建HTTP服务:使用Go的http模块创建一个服务,指定/metrics路径,并使用promhttp.Handler()作为处理器。
  2. 启动服务:通过http.ListenAndServe启动HTTP服务监听8080端口。
package main

import (
    "log"
    "net/http"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
    http.Handle("/metrics", promhttp.Handler())
    log.Fatal(http.ListenAndServe(":8080", nil))
}

访问:ip+端口:/metrics 会出现如下页面,Go模块自带的监控项,仅仅展示了一个默认的采集器,并且通过接口调用隐藏了太多实施细节
在这里插入图片描述

4、理解Prometheus指标

  1. 指标类型:Prometheus支持四种主要的指标类型:

    • Counter(累加指标)
    • Gauge(测量指标)
    • Summary(概略图)
    • Histogram(直方图)

1. Counter(累加指标)

什么是Counter?

  • Counter是一种只能增加的指标。它用来记录一些只会累加的数值,例如处理的请求数量、完成的任务数量等。

通俗解释:

  • 想象一个只能加法不能减法的计数器。每当你完成一个任务,就按一次加号,这个数字会一直增加,不会减少。

例子:

  • 记录一个网站的访问次数,每次有新的访问时,计数器增加1。

2. Gauge(测量指标)

什么是Gauge?

  • Gauge是一种可以任意增减的指标。它用来记录一些瞬时的数值,例如当前的温度、CPU使用率等。

通俗解释:

  • 想象一个温度计,温度可以升高也可以降低。它反映的是当前的状态,而不是累积的数值。

例子:

  • 记录服务器当前的内存使用量,这个数值会随着时间的推移而增加或减少。

3. Summary(概略图)

什么是Summary?

  • Summary是一种用来记录一系列数值的分布情况的指标。它会统计这些数值的分位数(例如中位数、90%分位数等)。

通俗解释:

  • 想象你有一堆考试成绩,你想知道这些成绩的中位数是多少,90%的成绩在哪个分数以上。这种指标会帮助你了解一组数据的分布情况。

例子:

  • 记录API响应时间,通过Summary可以知道大多数请求的响应时间情况,比如中位数响应时间、90%请求的响应时间等。

4. Histogram(直方图)

什么是Histogram?

  • Histogram也是一种记录数值分布的指标,但它会把数值划分到不同的区间(桶)中,统计每个区间的数量。

通俗解释:

  • 想象你有一堆不同高度的孩子,你把他们分成不同的身高区间,比如1米到1米1,1米1到1米2等,然后统计每个区间有多少孩子。Histogram会帮助你知道数据在不同区间的分布情况。

例子:

  • 记录API响应时间,通过Histogram可以知道不同响应时间范围内的请求数量,比如0到100ms有多少请求,100到200ms有多少请求等。

可以理解为柱状图,典型的应用如:请求持续时间,响应大小。可以对观察结果采样,分组及统计。例如设置一个name为web_request_duration_seconds的Histogram 的metrics,并设置区间值为[0.1,0.5,1]会对区间点生成一条统计数据.

# 响应时间小于0.1s的请求有5次
web_request_duration_seconds_bucket{endpoint="/query",method="GET",le="0.1"} 3
 
# 响应时间小于0.5s的请求有次
web_request_duration_seconds_bucket{endpoint="/query",method="GET",le="0.5"} 5
 
# 响应时间小于1s的请求有7次
web_request_duration_seconds_bucket{endpoint="/query",method="GET",le="1"} 7
 
# 总共7次请求
web_request_duration_seconds_bucket{endpoint="/query",method="GET",le="+Inf"} 7
 
# 7次请求duration的总和
web_request_duration_seconds_sum{endpoint="/query",method="GET"} 2.7190880529999997

5. Summary 和 Histogram 的区别

在使用 Prometheus 进行监控时,Summary 和 Histogram 都是用于测量和分析数据分布的强大工具,但它们在细节和应用场景上有所不同。下面将从两者的定义、使用场景和特点来详细阐述它们的区别。

Summary

Summary 用于提供一组数据的概述信息,它能够计算数据的分位数(例如中位数、90%分位数等)。这种指标特别适合需要了解整体数据分布情况但不需要精细区间划分的场景。

特点:

  • 分位数计算:可以直接计算出指定分位数,例如中位数、90%分位数等。
  • 适合样本量大时:当你需要了解大量请求的整体响应时间分布时,Summary 是非常有用的工具。
  • 无需预定义桶:Summary 通过算法动态计算分位数,而无需提前划分数据区间(桶)。

使用场景:

  • API 响应时间分析:需要知道绝大多数请求的响应时间情况,例如中位数响应时间和90%的请求响应时间。
  • 整体性能评估:适合评估系统的整体性能,而不需要详细的区间数据。

Histogram

Histogram 则是将数据划分到不同的区间(桶)中,统计每个区间的数据量。它适合需要详细了解数据在不同范围内分布情况的场景。

特点:

  • 区间划分:将数据划分到不同的区间(桶)中,每个区间统计数据量。
  • 精细数据分析:适合需要详细了解数据分布情况的场景,可以明确知道数据在不同区间的分布。
  • 需要预定义桶:在使用前需要定义数据的区间(桶),适合事先已知数据范围的情况。

使用场景:

  • 详细响应时间分析:需要知道在不同响应时间范围内的请求数量,比如0-100ms、100-200ms等。
  • 资源使用情况监控:可以用来监控系统资源使用情况的分布,例如内存使用量在不同范围内的分布。

5、定义和注册指标

在这里插入图片描述

  1. 引入依赖库:通过go get命令获取prometheus库。

    import (
    	"github.com/prometheus/client_golang/prometheus"
    	"sync/atomic"
    )
    
  2. 定义指标:创建Counter类型的指标,例如API请求次数的监控

    // APIRequestCounter 结构体,用于管理API请求次数的监控
    type APIRequestCounter struct {
    	Zone           string
    	APIRequestDesc *prometheus.Desc
    	requestCount   uint64
    }
    
  3. 注册指标:使用prometheus.MustRegister将指标注册到默认的Registry中。

        apiRequestCounter := collector.NewAPIRequestCounter(*metricsNamespace)
    
       // 创建一个新的Prometheus指标注册表
    	registry := prometheus.NewRegistry()
    	// 注册APIRequestCounter实例到Prometheus注册表
    	registry.MustRegister(apiRequestCounter)
    
    
    

6、实现自定义数据采集

  1. 实现Collector接口:创建自定义的Collector结构体来实现数据采集。

    // APIRequestCounter 结构体,用于管理API请求次数的监控
    type APIRequestCounter struct {
    	Zone           string
    	APIRequestDesc *prometheus.Desc
    	requestCount   uint64
    }
    
    
  2. 定义指标描述符:使用prometheus.NewDesc创建指标描述符。

    // NewAPIRequestCounter 创建一个新的APIRequestCounter实例
    func NewAPIRequestCounter(zone string) *APIRequestCounter {
    	return &APIRequestCounter{
    		Zone: zone,
    		APIRequestDesc: prometheus.NewDesc(
    			"api_request_count_total",
    			"API请求总次数",
    			nil,
    			prometheus.Labels{"zone": zone},
    		),
    	}
    }
    
  3. 实现Describe和Collect方法Describe方法发送指标描述符到channel,Collect方法执行数据采集并返回数据。

    // Describe 向Prometheus描述收集的指标
    func (c *APIRequestCounter) Describe(ch chan<- *prometheus.Desc) {
    	ch <- c.APIRequestDesc
    }
    
    // Collect 收集指标数据并发送到Prometheus
    func (c *APIRequestCounter) Collect(ch chan<- prometheus.Metric) {
    	count := atomic.LoadUint64(&c.requestCount)
    	ch <- prometheus.MustNewConstMetric(
    		c.APIRequestDesc,
    		prometheus.CounterValue,
    		float64(count),
    	)
    }
    

7、实现数据采集逻辑

  1. 自定义数据采集函数:实现一个函数来模拟或获取系统状态数据。

    // IncrementRequestCount  增加API请求计数
    func (c *APIRequestCounter) IncrementRequestCount() {
    	atomic.AddUint64(&c.requestCount, 1)
    }
    
    
  2. 收集数据:在Collect方法中调用数据采集函数,并使用MustNewConstMetric创建指标数据。

8、集成和测试

  1. 创建自定义Collector实例:根据需要创建多个Collector实例。
  2. 注册到Registry:使用NewPedanticRegistry创建一个新的Registry,并注册自定义Collector。
  3. 设置HTTP Handler:使用promhttp.HandlerFor创建一个HTTP Handler,用于处理/metrics路径的请求并返回指标数据。
var (
	// Set during go build
	// version   string
	// gitCommit string

	// 命令行参数
	listenAddr       = flag.String("web.listen-port", "8080", "An port to listen on for web interface and telemetry.")
	metricsPath      = flag.String("web.telemetry-path", "/metrics", "A path under which to expose metrics.")
	metricsNamespace = flag.String("metric.namespace", "app", "Prometheus metrics namespace, as the prefix of metrics name")
)


func main() {
	// 解析命令行参数
	flag.Parse()
	apiRequestCounter := collector.NewAPIRequestCounter(*metricsNamespace)

	// 创建一个新的Prometheus指标注册表
	registry := prometheus.NewRegistry()
	// 注册APIRequestCounter实例到Prometheus注册表
	registry.MustRegister(apiRequestCounter)


	// 设置HTTP服务器以处理Prometheus指标的HTTP请求
	http.Handle(*metricsPath, promhttp.HandlerFor(registry, promhttp.HandlerOpts{}))

	// 设置根路径的处理函数,用于返回一个简单的HTML页面,包含指向指标页面的链接
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(`<html>
	            <head><title>A Prometheus Exporter</title></head>
	            <body>
	            <h1>A Prometheus Exporter</h1>
	            <p><a href='/metrics'>Metrics</a></p>
	            </body>
	            </html>`))
	})
	// 模拟API请求的处理函数
	http.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
		apiRequestCounter.IncrementRequestCount()
		// 模拟API处理时间
		w.Write([]byte("API请求处理成功"))
	})

	// 记录启动日志并启动HTTP服务器监听
	log.Printf("Starting Server at http://localhost:%s%s", *listenAddr, *metricsPath)
	log.Fatal(http.ListenAndServe(":"+*listenAddr, nil))
}

9、启动服务并测试

请下载:https://github.com/nangongchengfeng/Prometheus-Go-Template.git 启动测试

  1. 启动HTTP服务:启动服务并监听8080端口。
  2. 访问指标数据:通过浏览器访问http://localhost:8080/metrics查看指标数据。
测试接口
http://localhost:8080/api
http://localhost:8080/query

在这里插入图片描述

10、原理

1、Prometheus 监控总结

在使用 Prometheus 进行监控时,理解指标的采集方式和不同指标类型的应用场景至关重要。以下是对相关概念的总结:

  1. 指标采集:
    Exporter 定期采集指标数据,并通过 HTTP 接口暴露。这些数据可以由 Prometheus 服务进行抓取和存储,便于后续的分析和展示。

  2. 指标类型:

    • Counter:适用于持续增长的指标,例如请求计数、任务完成次数等。它只会递增,不会减少。
    • Gauge:适用于可能增减的指标,例如当前内存使用量、CPU 使用率等。它既可以递增,也可以递减。
    • Histogram:适用于需要聚合和统计数据分布的场景,例如请求响应时间分布。它将数据划分到不同的区间(桶)中,并统计每个区间的数据量。
    • Summary:同样适用于需要聚合和统计分布的场景,但它通过计算分位数来描述数据分布情况,例如中位数、90% 分位数等。
  3. 数据聚合:
    Histogram 和 Summary 这两种类型的指标专注于数据的聚合和统计分布。它们能够提供关于数据分布的详细信息,便于深入分析系统性能和行为。

  4. 自定义 Collector:
    开发者可以通过实现 Collector 接口来自定义数据采集逻辑,以满足特定的监控需求。自定义 Collector 需要实现 describecollect 两个方法,以便将自定义逻辑集成到 Prometheus 的数据采集流程中。

2、Golang 中的监控器逻辑解析

在 Golang 中使用 Prometheus 进行监控时,了解监控器的逻辑和工作原理至关重要。下面将简要总结一下监控器的基本逻辑:

  1. 监控器初始化:
    默认情况下,当引入 registry 包时,会触发对 gocollect 这个采集器的初始化,这是因为 registry 在初始化时会调用 describe 接口,而 gocollect 正是实现了这个接口。

  2. 数据采集流程:
    当有 HTTP 请求到达时,http.handle 会调用 registrygather 函数。在 gather 函数内部,会调用具体采集器的 collect 接口,这个实现就是 gocollect 中的 collect 函数。这一流程确保了数据的采集和处理。

  3. 多类型处理:
    上述流程仅是一种特殊情况,实际上,对于四种不同类型的监控器(Counter、Gauge、Histogram 和 Summary),都有对应的结构体继承了基本函数接口,并实现了相应的接口。每种监控器都有自己独特的逻辑和实现方式,但整体流程大致相同。

  4. 自定义监控器:
    如果需要实现自定义的监控器逻辑,可以新建一个结构体作为监控器,实现 describecollect 接口。这样,就可以根据自己的需求实现特定的监控逻辑。最终,这些自定义监控器的实现原理也是调用了四种不同类型监控器的相关函数,以实现数据的采集和处理。

    在这里插入图片描述
    参考项目和文档:

https://github.com/crockitwood/go-prometheus-example.git

Prometheus四种指标详细解释

https://kingjcy.github.io/post/monitor/metrics/prometheus/library/client_golang/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/662846.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python+Playwright自动化测试-playwright操作iframe(三)

1.简介 iframe 是web自动化里面一个比较头疼的测试场景&#xff0c;在Selenium中处理 iframe 需要切换来切换去非常麻烦。但是在playwright中&#xff0c;让其变得非常简单&#xff0c;我们在使用中无需切换iframe&#xff0c;直接定位元素即可。 2.iframe是什么 iframe就是我…

异步编程的魔力:如何显著提升系统性能

异步编程的魔力:如何显著提升系统性能 今天我们来聊聊一个对开发者非常重要的话题——异步编程。异步编程是提升系统性能的一种强大手段,尤其在需要高吞吐量和低时延的场景中,异步设计能够显著减少线程等待时间,从而提升整体性能。 异步设计如何提升系统性能? 我们通过…

文心智能体平台丨创建你的四六级学习小助手

引言 在人工智能飞速发展的今天&#xff0c;我们迎来了文心智能体平台。该平台集成了最先进的人工智能技术&#xff0c;旨在为用户提供个性化、高效的学习辅助服务。今天&#xff0c;我们将向大家介绍如何利用文心智能体平台&#xff0c;创建一个专属于你的四六级学习小助手。…

EthernetiP转modbusTCP网关在加氢催化中的应用

在现代工业控制系统中&#xff0c;Ethernet/IP和ModbusTCP是两种常见的通信协议。它们在各种设备和系统间传输数据&#xff0c;实现设备的监控和控制&#xff0c;尤其在催化加氢装置这类关键工业过程中发挥着不可或缺的作用。本文将深入探讨开疆智能KJ-EIP-206型Ethernet/IP转M…

博物馆三维实景vr展示

VR技术应用到地产行业的优势不言而喻&#xff0c;随着购房政策的进一步放宽&#xff0c;购房刚需者借助VR商铺样板间展示系统看房&#xff0c;远比之前跑楼盘更便捷高效。那么VR商铺全景展示具体有哪些好处呢? VR技术与商铺的结合&#xff0c;为客户带来了前所未有的购房体验。…

相对位姿估计

相对位姿估计 示意图 理论推导 离线数据库&#xff1a; P的位置 P [ X , Y , Z ] T P[X,Y,Z]^{T} P[X,Y,Z]T 相机内参 k 1 k_{1} k1​ 安卓手机&#xff1a; 相机内参 k 2 k_{2} k2​ 两个像素点位置 &#xff1a; p 1 和 p 2 p_1和p_2 p1​和p2​ 公式一&#xff1a;…

中断向量码

中断请求引脚 INTR-可屏蔽中断请求信号输入引脚 NMI-不可屏蔽中断请求信号输入引脚 #INTA-可屏蔽中断请求信号应答引脚 IF-中断允许标志位 TF-陷阱标志位 中断向量表 由中断向量码确定中断源的类型 存储结构 中断向量地址 中断程序入口地址 示例 中断类型 内存中结构 5个…

C语言 宏

目录 一、宏定义 1.1 预定义符号 1.2 预处理指令 #define 1.3 带有副作用宏定义 1.4 宏和函数的一个对比 ​编辑 1.5 #undef 二、条件编译 2.1 #if、#else、#elif、#endif 2.2 #ifdef和#ifndef 2.3 C语言中如何通过条件编译来预防头文件的重复包含&#xff1f; 一、宏定义 在C语…

cobaltstrike启动teamserver报错Picked up _JAVA_OPTIONS:

1.报错如下图所示&#xff1a; 解决方法&#xff1a; 这是因为系统环境变量里多了一个变量&#xff1a; _JAVA_OPTIONS 只需要删掉它就行了&#xff01; 1、windows下在环境变量里找到、然后删除就行了 2、linux下、在/etc/profile文件中添加以下命令&#xff08;可添加至第一行…

uniapp或微信小程序一些问题解决

1.按钮边框如何去除&#xff1f; 参考博主&#xff1a;微信小程序按钮去不掉边框_微信小程序button去掉边框-CSDN博客文章浏览阅读1k次。最近在学uni-app&#xff0c;顺便自己写个小程序。左上角放了个button&#xff0c;可边框怎么也去不掉…原来微信小程序的按钮要去掉边框要…

重构2:重构的原则

最近在看重构2&#xff1a;改善既有代码的设计这本书&#xff0c;对于代码重构指导非常有帮助&#xff0c;然后也是做个笔记记录下&#xff0c;以下是我阅读本书的前两章的时候整理的思维导图&#xff1a;

用户流失分析:如何使用Python训练一个用户流失预测模型?

引言 在当今商业环境中&#xff0c;客户流失分析是至关重要的一环。随着市场竞争的加剧&#xff0c;企业需要更加注重保持现有客户&#xff0c;并深入了解他们的离开原因。本文探讨了用户流失分析的核心概念以及如何构建客户流失预测模型的案例。通过分析用户行为数据和交易模式…

动手学操作系统(四、MBR读取硬盘加载Loader)

动手学操作系统&#xff08;四、MBR读取硬盘加载Loader&#xff09; 在上一节中&#xff0c;我们学习了使用MBR来直接控制显卡进行显示&#xff0c;在这一节中我们学习如何让MBR来操作硬盘&#xff0c;加载Loader来完成操作系统的后续启动过程。 文章目录 动手学操作系统&…

005、API_数据结构

键的数据结构类型&#xff0c;它们分别是&#xff1a; string&#xff08;字符串&#xff09;、hash&#xff08;哈希&#xff09;、list&#xff08;列表&#xff09;、set&#xff08;集合&#xff09;、zset&#xff08;有序集 合&#xff09;&#xff0c;这些只是Redis对外…

pg_lakehouse 与 datafusion

原理分析 pg_lakehouse 是 ParadeDB 推出的一个开源插件&#xff0c;支持对多种数据湖里的数据做分析计算。它的出现&#xff0c;使得 Postgres 能够像访问本地数据一样轻松访问 S3 等对象存储&#xff0c;轻松访问 Delta Lake 上的表格&#xff0c;具备数据湖分析能力。 pg_…

ES报错1

ES在kibana的JSON如图: 提交后错误信息如下 所以是什么错误呢: 原来是:json的格式有误改成 这里的错误其实是我在文件传输时,为了节约空间,没有以json格式传递,而是一串字符就传过来了,需要使用josn的格式化工具格式化才行,结果格式化的不正确,才遇到此坑

Guns框架:基于主流技术Spring Boot2 + Vue3 + Antd Vue的现代Java应用开发新纪元

Guns框架&#xff1a;基于主流技术Spring Boot2 Vue3 Antd Vue的现代Java应用开发新纪元 摘要&#xff1a;随着信息技术的飞速发展&#xff0c;软件开发框架在提升开发效率、降低成本方面扮演着至关重要的角色。Guns框架&#xff0c;作为一个现代化的Java应用开发框架&#x…

【Linux多线程】认识多线程创建线程

文章目录 什么是多线程为什么称linux下的线程是轻量级进程呢&#xff1f; 线程的优点线程的缺点线程异常线程和进程创建线程1.pthread_create2.pthread_self 什么是多线程 进程是正在运行的程序的实例&#xff0c;而线程&#xff08;thread&#xff09;是进程中的一个执行路线…

如何顺利通过软考中级系统集成项目管理工程师?

中级资格的软考专业包括"信息系统"&#xff0c;属于软考的中级级别。熟悉软考的人都知道&#xff0c;软考分为初级、中级和高级三个级别&#xff0c;涵盖计算机软件、计算机网络、计算机应用技术、信息系统和信息服务五个专业&#xff0c;共设立了27个资格。本文将详…

GPT-4o:重塑人机交互的未来

一个愿意伫立在巨人肩膀上的农民...... 一、推出 在人工智能&#xff08;AI&#xff09;领域&#xff0c;自然语言处理&#xff08;NLP&#xff09;技术一直被视为连接人类与机器的桥梁。近年来&#xff0c;随着深度学习技术的快速发展&#xff0c;NLP领域迎来了前所未有的变革…