Go开发Prometheus客户端实战步骤

news2024/11/19 9:23:49

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/

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript-内存分配

内存空间 内存分为栈和堆 栈&#xff1a;由操作系统自动释放存放的变量值和函数值等。简单数据类型存放在栈中 栈会由低到高先入后出 堆&#xff1a;存储引用类型 &#xff08;对象&#xff09; 对象会先将数据存放在堆里面&#xff0c;堆的地址放在栈里面

HTB-SherlocksDFIR

Sherlocks 中关于 DFIR 的一些内容&#xff0c;按照时间线整理&#xff0c;尚未完成&#xff0c;持续更新​ Brutus 和上一次做的 Recollection 机器一样&#xff0c;主要学习一下相关的知识&#xff0c;练习一下。按照机器描述&#xff0c;在学习完成后将熟悉 auth.log 和 wtm…

自建视频托管平台:MediaCMS

目录 1 MediaCMS简介1.1 介绍1.2 特性1.3 应用场景 2 安装配置2.1 安装1、安装2、汉化 2.2 一些常见配置 3 简单使用3.1 上传3.2 下载3.3 添加标题或者字幕3.4 通过Tag/Category实现视频/文件分类添加 Tag给任一资源分类 1 MediaCMS简介 1.1 介绍 MediaCMS是一个现代的&#…

2.10 mysql设置远程访问权限

2.10 mysql设置远程访问权限 目录1. 管理员运行mysql命令窗口2. 使用 root 用户重新登录 MySQL3. 修改用户权限4. 修改mysql安装目录下的my.ini 目录 说明&#xff1a; Mysql8.0 设置远程访问权限 一、Mysql8.0 设置远程访问权限 1. 管理员运行mysql命令窗口 2. 使用 root 用…

Java break细节(标签)

Java break细节(标签)continue也可以使用标签 break是用来跳出循环的。 当有多重循环时&#xff0c;可以配合标签来使用&#xff0c;决定跳出那一重循环。 尽量不要使用标签 1、不代标签时&#xff0c;默认跳出 break 所在的那重循环&#xff1a; 可见在 i 3 时&#xff0…

前端调用exe程序配置

前置条件 访问端安装好需要调用的exe程序 1、新建reg文件 先新建一个txt文件&#xff0c;重命名为xx.reg 点击是&#xff0c;确认更改 2、编写注册表内容 右键点击文件&#xff0c;用记事本打开&#xff0c;输入以下内容 将下面的${exeName}修改为自定义的程序名&#x…

react使用react-quill富文本编辑器自定义上传图片,添加handlers后编辑器不显示问题

Quill介绍 Quill 是一款 API 驱动、功能强大的现代富文本编辑器。它具有易于拓展、各平台表现一致性等优点。Quill 官方 1.0 版本于 2016 年 9 月发布&#xff0c;目前在 Github 上有41.8k Star。 官网地址&#xff1a;Quill - Your powerful rich text editor github仓库地…

剪画小程序:视频伪原创怎么制作?视频伪原创的几种制作方法分享!

什么是视频伪原创&#xff1f; 视频伪原创是指对已有的视频内容进行一定程度的修改和处理&#xff0c;使其在形式或部分细节上与原始视频有所不同&#xff0c;但保留了核心内容或主题。 视频伪原创包括以下一些常见操作&#xff1a; 剪辑重组&#xff1a;对原始视频进行剪辑…

整合SSM框架笔记

整合SSM框架笔记 Spring5 Spring MVC MyBatis Druid MySQL Thymeleaf 感谢尚硅谷课程&#xff1a;B站课程 前言 单Spring框架时&#xff0c;是Java工程。 Spring与Spring MVC可以共用一个配置文件&#xff0c;也可以不共用一个&#xff0c;推荐不共用一个。 Spring与Sp…

map优化多个if

原代码如下&#xff0c;多个按钮的点击操作&#xff0c;其中val是操作的按钮的标志 const operationConst {INSTALLAPP: installApp,STOPAPP: stopApp,HOME: home,CLEAR: clear...... } function moreOperation(val, list) {selectedList list && list.length 0 ?…

Pandas格式化DataFrame的浮点数列

在呈现数据的同时&#xff0c;以所需的格式显示数据也是一个重要而关键的部分。有时&#xff0c;值太大了&#xff0c;我们只想显示其中所需的部分&#xff0c;或者我们可以说以某种所需的格式。 让我们看看在Pandas中格式化DataFrame的数值列的不同方法。 例1&#xff1a;将…

数字化业务流程升级再造,解困基本半导体的CRM应用5年之痒

在新能源汽车、工业互联、5G通信、消费电子等需求的强力拉动下&#xff0c;以碳化硅为代表的第三代半导体产业迎来爆发式增长。 深圳基本半导体有限公司&#xff08;以下简称“基本半导体”&#xff09;是中国第三代半导体创新企业&#xff0c;专业从事碳化硅功率器件的研发与…

探索标准差与方差的奥秘

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、标准差与方差的基础理解 代码案例 二、标准差与方差的计算方法 方差的计算 标准差的…

Selenium 自动化测试工具(1) (Selenium 工作原理,常用API的使用)

文章目录 什么是自动化测试什么是测试工具&#xff1a;Selenium 工作原理(重要)Selenium API定位元素CSS 选择器xpath 定位元素 通过Java代码实现自动化1. 定位元素2. 关闭浏览器3. 获取元素文本4. 鼠标点击与键盘输入5. 清空内容6.打印信息 什么是自动化测试 关于自动化&…

11.3G全国矢量地名路网SHP地图

我们在《2015年中国电子地图数据》一文中&#xff0c;分享了一份26.8G的全矢量地名路网地图。 这里再分享一份11.3G的全国矢量地名路网地图&#xff0c;这份数据虽然比2015版更小&#xff0c;但它比那一版更新。 值得一提的是这份数据的图层更丰富&#xff0c;比2015版多32个…

于ThinkPHP开发的赛事报名小程序

基于ThinkPHP开发的赛事报名微信小程序 功能包括 1、参赛公告 2、会员中心&#xff08;会员注册、登录、成绩查询、资料管理、参赛记录管理&#xff09; 3、个人报名和企业报名 &#xff08;身份证验证防止重复报名&#xff09; 4、培训报名 5、查询是否在库人员&#xff0c;根…

收藏:六款好用的企业防泄密软件推荐

企业数据如同企业的生命线&#xff0c;保护数据安全免遭泄露变得至关重要。 面对日益复杂的网络安全威胁&#xff0c;一套高效的企业防泄密软件成为企业安全架构的基石。 以下是精心挑选的六款企业防泄密软件&#xff0c;它们在数据加密、访问控制、行为监控等方面表现出色&am…

Java开发-特殊文本文件,日志技术

目录 01.特殊文件,日志技术概述 02.特殊文件:Properties属性文件 ​编辑Properties案例 特殊文件:XML文件 XML的作用和应用场景 读取XML文件中的数据 XML的生成 约束XML文件的编写[了解] 日志技术 日志技术的体系 ​编辑 ​编辑 Logback日志框架的概述 Logback快…

JS 中怎么删除数组元素?有哪几种方法?

正文开始之前推荐一位宝藏博主免费分享的学习教程,学起来! 编号学习链接1Cesium: 保姆级教程+源码示例2openlayers: 保姆级教程+源码示例3Leaflet: 保姆级教程+源码示例4MapboxGL: 保姆级教程+源码示例splice() JavaScript中的splice()方法是一个内置的数组对象函数, 用于…

VM虚拟机共享文件夹fuse: bad mount point `/mnt/hgfs‘: No such file or directory

报错显示挂载点 /mnt/hgfs 不存在&#xff0c;你需要先创建这个目录。可以按照以下步骤进行操作&#xff1a; 创建挂载点目录&#xff1a; sudo mkdir -p /mnt/hgfs 手动挂载共享文件夹&#xff1a; sudo vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other 确保每次启动时自动…