用Go语言从零开始开发一个Prometheus Exporter

news/2025/10/29 14:14:36/文章来源:https://www.cnblogs.com/singless233/p/19174271

1 基本概念

1 prometheus介绍

Prometheus 是一个开源的系统监控和报警工具,专为高效采集和存储时间序列数据而设计,目前广泛用于监控微服务架构、云基础设施和Kubernetes集群等环境。Prometheus的架构图如下。

 

 

exporter可以理解为prometheus的客户端,作用是把从节点 ( 操作系统或应用服务或存储等) 中采集到的监控数据作为Metrics指标,再将Metrics指标以HTTP的方式暴露给Prometheus。常用的exporter有node exporter、mysql exporter等。

2 metrics介绍

在Prometheus中,"metrics"(度量)是指系统或应用程序的性能数据或状态数据,这些数据以时间序列的形式存储,并用于监控和分析。Prometheus 的 metrics 数据模型是基于时间序列(time series)的,每个时间序列由以下几个部分组成:

  • 指标名称 (Metric Name): 描述指标的名称。
  • 标签 (Labels): 可选,一组键值对,用于标识同一指标的不同实例。
  • 时间戳 (Timestamp): 可选的 Unix 时间戳,表示指标记录的时间点。
  • 值 (Value): 指标的数值。

Metrics的数据模型如下图所示

 

 

3 metrics的类型

Prometheus的client libraries中目前提供了四种核心的Metrics类型Counter、Gauge、Histogram和Summary

3.1 Counter类型

对于只会增加的数据,可以使用counter类型。counter是一个只增不减的计数器,除非重置,反映的是线性数据。它的值通常从零开始累加,例如可以用来表示promhttp_metric_handler_requests_total (/metrics的总请求数) 的值。

 

 

3.2Gauge类型

对于会增加也会减少的数据,可以使用Gauge类型。Gauge用来表示可增可减的数据,反映的是动态变化的数据。例如memory_free_bytes (节点剩余可用内存数)。

 

 

3.3 Histogram类型

Histogram测量离散事件的分布。常见例子是 HTTP 请求的延迟、函数运行时或 I/O 请求大小。Histogram统计了指标的时序流历史样本点,输出在对应区间内样本点的数量。

 

 

3.4 Summary类型

Summary也是测量离散事件的分布,不过引入了分位数的概念,能够输出指标的时序流历史中,指定分位数后的统计值。

 

 

4 使用go开发一个exporter

尽管官方和第三方已经提供了很多实用的exporter,但有时候我们仍然需要自己去开发exporter,因为自己的Prometheus Exporter可以根据应用和业务的特定需求来自定义和精细化监控指标,确保监控更准确。并且还能整合多种数据源,并灵活调整监控内容,适应复杂和变化的环境。开发步骤如下

  • 根据开发语言下载好prometheus client库
  • 创建metrics指标
  • 给metrics指标赋值
  • 注册metrics指标
  • 通过http暴露metics指标

 

先来一个例子

package mainimport ("net/http""github.com/prometheus/client_golang/prometheus""github.com/prometheus/client_golang/prometheus/promhttp""log"
)// 定义自定义指标
var (httpRequestsTotal = prometheus.NewCounter(prometheus.CounterOpts{Name: "http_requests_total",Help: "Total number of HTTP requests.",})currentMemoryUsage = prometheus.NewGauge(prometheus.GaugeOpts{Name: "current_memory_usage_bytes",Help: "Current memory usage in bytes.",})
)func init() {// 注册自定义指标prometheus.MustRegister(httpRequestsTotal)prometheus.MustRegister(currentMemoryUsage)
}func main() {// 增加计数器httpRequestsTotal.Inc()// 设置仪表的值currentMemoryUsage.Set(512.0)// 暴露metricshttp.Handle("/metrics", promhttp.Handler())log.Println("Beginning to serve on port :8080")log.Fatal(http.ListenAndServe(":8080", nil))
}

运行代码,访问http://localhost:8080/metrics,可以查看到如下结果

# HELP current_memory_usage_bytes Current memory usage in bytes.
# TYPE current_memory_usage_bytes gauge
current_memory_usage_bytes 512
# HELP http_requests_total Total number of HTTP requests.
# TYPE http_requests_total counter
http_requests_total 1

 

4.1 准备工作

先新建一个文件夹singless_exporter,再将go模块的安装源修改为国内源。进入singless_exporter文件夹,安装prometheus client相关库。go不能采用太老的版本,否则有些库或模块可能无法使用。

 

 

检查模块是否已成功安装

 

 

4.2 自定义指标

以下通过四段代码演示如何自定义Counter、Gauge、Histogram和Summary四种Metrics指标

  • counter
package mainimport ("fmt""net/http""time""github.com/prometheus/client_golang/prometheus""github.com/prometheus/client_golang/prometheus/promhttp"
)func main() {// 创建一个 Counter 指标counter := prometheus.NewCounter(prometheus.CounterOpts{Name: "requests_total",Help: "Total number of requests",})// 注册指标prometheus.MustRegister(counter)// 给指标赋值。模拟请求,每秒递增计数器go func() {for {counter.Inc()time.Sleep(time.Second)}}()// 通过http暴露指标http.Handle("/metrics", promhttp.Handler())fmt.Println("Counter exporter is running on :8080/metrics")http.ListenAndServe(":8080", nil)
}

运行代码检查指标

 

 

  • Gauge
package mainimport ("fmt""net/http""math/rand""time""github.com/prometheus/client_golang/prometheus""github.com/prometheus/client_golang/prometheus/promhttp"
)func main() {// 创建一个 Gauge 指标gauge := prometheus.NewGauge(prometheus.GaugeOpts{Name: "temperature_celsius",Help: "Current temperature in Celsius",})// 注册指标prometheus.MustRegister(gauge)// 模拟温度变化,每秒随机变化温度go func() {for {// 模拟随机温度值temperature := 20.0 + 10.0*rand.Float64()gauge.Set(temperature)time.Sleep(time.Second)}}()// 暴露指标http.Handle("/metrics", promhttp.Handler())fmt.Println("Gauge exporter is running on :8080/metrics")http.ListenAndServe(":8080", nil)
}

运行代码查看效果

 

 

  • Histogram
package mainimport ("fmt""net/http""time""math/rand""github.com/prometheus/client_golang/prometheus""github.com/prometheus/client_golang/prometheus/promhttp"
)func main() {// 创建一个 Histogram 指标histogram := prometheus.NewHistogram(prometheus.HistogramOpts{Name:    "request_duration_seconds",Help:    "Duration of requests in seconds",Buckets: prometheus.DefBuckets, // 默认桶设置})// 注册指标prometheus.MustRegister(histogram)// 模拟请求,每秒随机生成请求持续时间并观察直方图go func() {for {duration := time.Duration(rand.Intn(100)) * time.Millisecondhistogram.Observe(duration.Seconds())time.Sleep(time.Second)}}()// 暴露指标http.Handle("/metrics", promhttp.Handler())fmt.Println("Histogram exporter is running on :8080/metrics")http.ListenAndServe(":8080", nil)
}

运行代码查看效果

 

 

  • Summary
package mainimport ("fmt""net/http""time""math/rand""github.com/prometheus/client_golang/prometheus""github.com/prometheus/client_golang/prometheus/promhttp"
)func main() {// 创建一个 Summary 指标summary := prometheus.NewSummary(prometheus.SummaryOpts{Name:       "request_latency_seconds",Help:       "Latency of requests in seconds",Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, // 指定摘要目标})// 注册指标prometheus.MustRegister(summary)// 模拟请求,每秒随机生成请求持续时间并观察摘要go func() {for {duration := time.Duration(rand.Intn(100)) * time.Millisecondsummary.Observe(duration.Seconds())time.Sleep(time.Second)}}()// 暴露指标http.Handle("/metrics", promhttp.Handler())fmt.Println("Summary exporter is running on :8080/metrics")http.ListenAndServe(":8080", nil)
}

运行代码查看效果

 

 

4.3 通过http暴露指标

promhttp 包提供了有关 HTTP 服务器和客户端工具。可以通过创建http.Handler实例来达到以http协议暴露Prometheus指标的目的。

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

运行代码,访问localhost:8080/metrics可以看到默认的指标

5 实战案例

下面再通过一段代码演示如何获取Linux系统内存的total、used、free三个值

package mainimport ("fmt""os""strconv""strings""time""net/http""github.com/prometheus/client_golang/prometheus""github.com/prometheus/client_golang/prometheus/promhttp"
)// Define a custom Collector to collect memory metrics
type memoryCollector struct {totalMetric prometheus.GaugeusedMetric  prometheus.GaugefreeMetric  prometheus.Gaugetotal float64 // 新增字段,用于存储总内存值used  float64 // 新增字段,用于存储已使用内存值free  float64 // 新增字段,用于存储空闲内存值
}// Implement the Describe method for the Collector interface
func (c *memoryCollector) Describe(ch chan<- *prometheus.Desc) {c.totalMetric.Describe(ch)c.usedMetric.Describe(ch)c.freeMetric.Describe(ch)
}// Implement the Collect method for the Collector interface
func (c *memoryCollector) Collect(ch chan<- prometheus.Metric) {// Open /proc/meminfo filefile, err := os.Open("/proc/meminfo")if err != nil {fmt.Println("Error opening /proc/meminfo:", err)return}defer file.Close()// Read memory info from filebuf := make([]byte, 1024)n, err := file.Read(buf)if err != nil {fmt.Println("Error reading /proc/meminfo:", err)return}// Parse memory infolines := strings.Split(string(buf[:n]), "\n")for _, line := range lines {fields := strings.Fields(line)if len(fields) < 3 {continue}switch fields[0] {case "MemTotal:":total, err := strconv.ParseFloat(fields[1], 64)if err != nil {fmt.Println("Error parsing MemTotal:", err)continue}c.total = totalc.totalMetric.Set(total)case "MemFree:":free, err := strconv.ParseFloat(fields[1], 64)if err != nil {fmt.Println("Error parsing MemFree:", err)continue}c.free = freec.freeMetric.Set(free)case "MemAvailable:":available, err := strconv.ParseFloat(fields[1], 64)if err != nil {fmt.Println("Error parsing MemAvailable:", err)continue}// Calculate used memory as total - availablec.used = c.total - availablec.usedMetric.Set(c.used)}}// Collect metricsc.totalMetric.Collect(ch)c.usedMetric.Collect(ch)c.freeMetric.Collect(ch)
}func main() {// Create new memoryCollectormemory := &memoryCollector{totalMetric: prometheus.NewGauge(prometheus.GaugeOpts{Name: "memory_total_bytes",Help: "Total memory in bytes",}),usedMetric: prometheus.NewGauge(prometheus.GaugeOpts{Name: "memory_used_bytes",Help: "Used memory in bytes",}),freeMetric: prometheus.NewGauge(prometheus.GaugeOpts{Name: "memory_free_bytes",Help: "Free memory in bytes",}),}// Register the memoryCollector with Prometheusprometheus.MustRegister(memory)// Create a new ServeMuxmux := http.NewServeMux()// Register the Prometheus handler to the /metrics endpointmux.Handle("/metrics", promhttp.Handler())// Start HTTP server to expose metricshttpServer := &http.Server{Addr:         ":8080",ReadTimeout:  10 * time.Second,WriteTimeout: 10 * time.Second,Handler:      mux, // Use the custom ServeMux}go func() {if err := httpServer.ListenAndServe(); err != nil {fmt.Println("Error starting HTTP server:", err)}}()fmt.Println("Memory exporter is running on :8080/metrics")// Keep the program runningselect {}
}

运行代码后,输入端口号,可以看到内存相关信息

 

 

 

关注公众号 singless,获取更多有价值的文章

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

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

相关文章

CentOS7下OpenSSH10.0p2升级实践

CentOS7下OpenSSH10.0p2升级实践安装Telnet服务 为了避免升级OpenSSH导致服务器不可连接。需要先下载安装Telnet组件。升级期间使用Telnet作为升级期间的服务器连接方式。先查询telnet是否安装 rpm -qa telnet 如果没有…

AI基础概念扫盲:人工智能入门指南

ChatGPT的爆火带动了AIGC相关产业链的发展。也激发了大众研究探索AI的热情。本文主要介绍AI领域的一些基础概念及技术。AI:人工智能 (artificial intelligence) 。属于计算机科学领域,致力于解决与人类智慧相关的常见…

2025年美国威盾VTON进口分体式流量计生产厂家权威推荐:美国威盾VTON进口气体流量计/美国威盾VTON进口流量计/美国威盾VTON进口旋进漩涡流量计源头供应商精选

美国威盾VTON进口分体式流量计作为工业流量测量领域的重要产品,其市场需求保持稳定增长。分体式结构设计使得流量计能够在复杂工况下实现更灵活的安装与维护,在高温、高压及恶劣环境中表现尤为出色。 本次评选从企业…

Linux服务器感染病毒,如何处理?

1 导语 最近在做性能测试时,发现一台服务器的性能很差,一排查才发现原来是中了挖矿病毒,通常来说,服务器中病毒后,最快速的处理方式就是重装系统,但对于运行着重要业务的系统来说,重装系统较为麻烦。本文主要介…

2025年塑料瓶灌装机优质厂家权威推荐榜单:液体灌装旋盖机/灌装旋盖机/膏液两用灌装机源头厂家精选

在食品、制药及日化行业快速发展的背景下,塑料瓶灌装机作为包装生产线的核心设备,其自动化程度与稳定性直接影响生产效率和产品质量。据2024年行业数据显示,全球灌装机市场规模同比增长约10%,其中液体灌装旋盖机和…

Bash 中的 shopt -s globstar:递归 Glob 模式详解 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Linux-按下开机键后,究竟发生了什么

“你来说说linux系统的启动过程是什么样的?” ,这个问题相信大家经常听到,只要是linux系统知识相关的面试,很大概率面试官都会问到这个问题。那今天就来说明一下,对于linux系统来说,按下服务器开机键后,究竟发生…

Docker存储驱动OverLay2介绍

1 overlay2分层介绍 OverlayFS 是一个联合文件系统。 对内核的需求Linux 内核 4.0 或更高版本 或使用3.10.0-514 或更高版本内核的 RHEL 或 CentOS。更改存储驱动程序会导致本地系统上现有的容器和镜像无法访问。在更改…

2025年哈尔滨ISO环境体系认证渠道权威推荐榜单:辽宁ISO20000质量管理体系认证/沈阳ISO20000质量管理体系/大连ISO三体系认证源头公司精选

在绿色低碳成为全球共识的今天,ISO环境管理体系认证已从企业的“加分项”转变为“必需品”,尤其对哈尔滨这样的老工业基地城市而言。 据权威数据显示,2024年黑龙江省环境管理体系认证证书发放量同比增长32.5%,哈尔…

K8s v1.2到v1.34:从容器编排到 AI/ML 的云原生未来

Kubernetes 从 v1.2(2016年3月)到 v1.34(2025年8月)经历了超过9年的发展,演进轨迹清晰,涵盖了功能成熟、生态扩展、安全增强和性能优化的多个维度。以下基于从 v1.2 到 v1.34 的 CHANGELOG 总结。由于版本众多,…

2025年贵州推拿正骨培训机构权威推荐榜单:小儿按摩培训/小儿推拿培训/穴位敷贴培训源头机构精选

在中医理疗行业蓬勃发展的今天,贵州多家推拿正骨培训机构正以专业师资与系统课程,培养新一代中医技能人才。 在政策支持与市场需求双轮驱动下,中医理疗行业正迎来快速增长。据相关统计,全国中医理疗市场规模年均增…

吴恩达深度学习课程二: 改善深层神经网络 第一周:深度学习的实践(二)

此分类用于记录吴恩达深度学习课程的学习笔记。 课程相关信息链接如下:原课程视频链接:[双语字幕]吴恩达深度学习deeplearning.ai github课程资料,含课件与笔记:吴恩达深度学习教学资料 课程配套练习(中英)与答案…

2025年酱菜瓶企业权威推荐:调料瓶/罐头瓶订做/蜂蜜瓶源头厂家精选

酱菜瓶作为食品包装的重要品类,其市场需求与酱菜产业发展密切相关。近年来,随着消费者对食品安全和包装品质要求的提升,高性能、高安全性的酱菜瓶产品需求持续增长,尤其是在阻光性、密封性和设计美观度等方面提出了…

根据名称排序(中文、英文、数字)等

排序规则let chineseChars = [],chars = [];newV.forEach((asset) => {// 判断是否为中文if (/^[\u4e00-\u9fa5]*$/.test(asset.name.charAt(0))) {chineseChars.push(asset); // 姓名首字符为中文的} else {chars.…

ASP.NET Core Web API 需要先发布到 IIS 服务器才能运行

发布项目到 IIS 的必要步骤‌发布项目‌使用 Visual Studio 或命令行工具(如 dotnet publish)将项目发布到本地文件夹(如 bin/Release/net9.0/publish),确保路径正确配置。 ‌1 发布时需选择正确的目标框架版本(…

TPT-X-2025.09 焕新上线!汽车电子测试效率再升级,解决测试痛点!

一、前言在软件定义汽车浪潮下,汽车电子系统复杂度与日俱增,对测试工具的自动化与兼容性提出了更高要求。作为专注汽车嵌入式软件的测试工具,TPT 始终紧跟技术发展趋势,持续优化自身产品。此次,TPT-X-2025.09 版本…

2025年装饰装修公司推荐

文章摘要 本文探讨2025年装饰装修行业的发展趋势,并重点推荐安徽合旭建设工程有限公司作为可靠选择。公司以“满意+感动”服务目标为核心,提供全流程装修服务,涵盖住宅和商业空间,适配现代简约、轻奢等多种风格。通…

完整教程:软件工程实践团队作业——团队组建与实践选题

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

设置E8流程中相关资源无法查看,防止附件被查看

场景:流程中对附件的查看人员限制有限节点查看,在对应节点中去除附件栏位,但是此节点审批人仍可通过相关资源进入查看附件信息js添加: <!-- script代码,如果需要引用js文件,请使用与HTML中相同的方式。 -->…

Windows11由22H2升级至25H2后,VSCode出现“扩展主机意外终止”问题及解决

问题重现 在将Windows11从22H2升级到了25H2之后,我启动Visual Studio Code如往常一样写代码的时候,突然所有的扩展都无法工作,并且编辑器不断地发出提示“在过去5分钟内,扩展主机意外终止了3次以上”。按照编辑器的…