Prometheus开发中间件Exporter过程详解


Posted in Python onNovember 30, 2020

Prometheus 为开发这提供了客户端工具,用于为自己的中间件开发Exporter,对接Prometheus 。

目前支持的客户端

  • Go
  • Java
  • Python
  • Ruby

以go为例开发自己的Exporter

依赖包的引入

工程结构

[root@node1 data]# tree exporter/
exporter/
├── collector
│ └── node.go
├── go.mod
└── main.go

引入依赖包

require (
  github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
  github.com/modern-go/reflect2 v1.0.1 // indirect
  github.com/prometheus/client_golang v1.1.0
    //借助gopsutil 采集主机指标
  github.com/shirou/gopsutil v0.0.0-20190731134726-d80c43f9c984
)

main.go

package main

import (
  "cloud.io/exporter/collector"
  "fmt"
  "github.com/prometheus/client_golang/prometheus"
  "github.com/prometheus/client_golang/prometheus/promhttp"
  "net/http"
)

func init() {
   //注册自身采集器
  prometheus.MustRegister(collector.NewNodeCollector())
}
func main() {
  http.Handle("/metrics", promhttp.Handler())
  if err := http.ListenAndServe(":8080", nil); err != nil {
    fmt.Printf("Error occur when start server %v", err)
  }
}

为了能看清结果我将默认采集器注释,位置registry.go

func init() {
  //MustRegister(NewProcessCollector(ProcessCollectorOpts{}))
  //MustRegister(NewGoCollector())
}

/collector/node.go

代码中涵盖了Counter、Gauge、Histogram、Summary四种情况,一起混合使用的情况,具体的说明见一下代码中。

package collector

import (
  "github.com/prometheus/client_golang/prometheus"
  "github.com/shirou/gopsutil/host"
  "github.com/shirou/gopsutil/mem"
  "runtime"
  "sync"
)

var reqCount int32
var hostname string
type NodeCollector struct {
  requestDesc  *prometheus.Desc  //Counter
  nodeMetrics   nodeStatsMetrics //混合方式 
  goroutinesDesc *prometheus.Desc  //Gauge
  threadsDesc  *prometheus.Desc //Gauge
  summaryDesc  *prometheus.Desc //summary
  histogramDesc *prometheus.Desc  //histogram
  mutex     sync.Mutex
}
//混合方式数据结构
type nodeStatsMetrics []struct {
  desc  *prometheus.Desc
  eval  func(*mem.VirtualMemoryStat) float64
  valType prometheus.ValueType
}

//初始化采集器
func NewNodeCollector() prometheus.Collector {
  host,_:= host.Info()
  hostname = host.Hostname
  return &NodeCollector{
    requestDesc: prometheus.NewDesc(
      "total_request_count",
      "请求数",
      []string{"DYNAMIC_HOST_NAME"}, //动态标签名称
      prometheus.Labels{"STATIC_LABEL1":"静态值可以放在这里","HOST_NAME":hostname}),
    nodeMetrics: nodeStatsMetrics{
      {
        desc: prometheus.NewDesc(
          "total_mem",
          "内存总量",
          nil, nil),
        valType: prometheus.GaugeValue,
        eval: func(ms *mem.VirtualMemoryStat) float64 { return float64(ms.Total) / 1e9 },
      },
      {
        desc: prometheus.NewDesc(
          "free_mem",
          "内存空闲",
          nil, nil),
        valType: prometheus.GaugeValue,
        eval: func(ms *mem.VirtualMemoryStat) float64 { return float64(ms.Free) / 1e9 },
      },

    },
    goroutinesDesc:prometheus.NewDesc(
      "goroutines_num",
      "协程数.",
      nil, nil),
    threadsDesc: prometheus.NewDesc(
      "threads_num",
      "线程数",
      nil, nil),
    summaryDesc: prometheus.NewDesc(
      "summary_http_request_duration_seconds",
      "summary类型",
      []string{"code", "method"},
      prometheus.Labels{"owner": "example"},
    ),
    histogramDesc: prometheus.NewDesc(
      "histogram_http_request_duration_seconds",
      "histogram类型",
      []string{"code", "method"},
      prometheus.Labels{"owner": "example"},
    ),
  }
}

// Describe returns all descriptions of the collector.
//实现采集器Describe接口
func (n *NodeCollector) Describe(ch chan<- *prometheus.Desc) {
  ch <- n.requestDesc
  for _, metric := range n.nodeMetrics {
    ch <- metric.desc
  }
  ch <- n.goroutinesDesc
  ch <- n.threadsDesc
  ch <- n.summaryDesc
  ch <- n.histogramDesc
}
// Collect returns the current state of all metrics of the collector.
//实现采集器Collect接口,真正采集动作
func (n *NodeCollector) Collect(ch chan<- prometheus.Metric) {
  n.mutex.Lock()
  ch <- prometheus.MustNewConstMetric(n.requestDesc,prometheus.CounterValue,0,hostname)
  vm, _ := mem.VirtualMemory()
  for _, metric := range n.nodeMetrics {
    ch <- prometheus.MustNewConstMetric(metric.desc, metric.valType, metric.eval(vm))
  }

  ch <- prometheus.MustNewConstMetric(n.goroutinesDesc, prometheus.GaugeValue, float64(runtime.NumGoroutine()))

  num, _ := runtime.ThreadCreateProfile(nil)
  ch <- prometheus.MustNewConstMetric(n.threadsDesc, prometheus.GaugeValue, float64(num))

  //模拟数据
  ch <- prometheus.MustNewConstSummary(
    n.summaryDesc,
    4711, 403.34,
    map[float64]float64{0.5: 42.3, 0.9: 323.3},
    "200", "get",
  )

  //模拟数据
  ch <- prometheus.MustNewConstHistogram(
      n.histogramDesc,
      4711, 403.34,
      map[float64]uint64{25: 121, 50: 2403, 100: 3221, 200: 4233},
      "200", "get",
    )
  n.mutex.Unlock()
}

执行的结果http://127.0.0.1:8080/metrics

Prometheus开发中间件Exporter过程详解

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python 列表理解及使用方法
Oct 27 Python
Python安装图文教程 Pycharm安装教程
Mar 27 Python
Python数据分析matplotlib设置多个子图的间距方法
Aug 03 Python
Python实现的KMeans聚类算法实例分析
Dec 29 Python
python 限制函数执行时间,自己实现timeout的实例
Jan 12 Python
python提取log文件内容并画出图表
Jul 08 Python
Flask框架学习笔记之路由和反向路由详解【图文与实例】
Aug 12 Python
python3 enum模块的应用实例详解
Aug 12 Python
解析python的局部变量和全局变量
Aug 15 Python
python中字典按键或键值排序的实现代码
Aug 27 Python
Python无损压缩图片的示例代码
Aug 06 Python
使用django自带的user做外键的方法
Nov 30 Python
python实现猜拳游戏项目
Nov 30 #Python
Python解析微信dat文件的方法
Nov 30 #Python
Python应用自动化部署工具Fabric原理及使用解析
Nov 30 #Python
使用python将微信image下.dat文件解密为.png的方法
Nov 30 #Python
Python 微信公众号文章爬取的示例代码
Nov 30 #Python
python爬虫工具例举说明
Nov 30 #Python
编译 pycaffe时报错:fatal error: numpy/arrayobject.h没有那个文件或目录
Nov 29 #Python
You might like
Array of country list in PHP with Zend Framework
2011/10/17 PHP
php实现字符串反转输出的方法
2015/03/14 PHP
php使用parse_str实现查询字符串解析到变量中的方法
2017/02/17 PHP
thinkphp框架page类与bootstrap分页(美化)
2017/06/25 PHP
php ajax confirm 删除实例详解
2019/03/06 PHP
JavaScript asp.net 获取当前超链接中的文本
2009/04/14 Javascript
javascript xml为数据源的下拉框控件
2009/07/07 Javascript
Javascript base64编码实现代码
2011/12/02 Javascript
JavaScript新窗口与子窗口传值详解
2014/02/11 Javascript
简单的js图片轮换代码(js图片轮播)
2014/05/06 Javascript
jQuery网页版打砖块小游戏源码分享
2015/08/20 Javascript
JavaScript的兼容性与调试技巧
2016/11/22 Javascript
Javascript for in的缺陷总结
2017/02/03 Javascript
vue中Axios的封装与API接口的管理详解
2018/08/09 Javascript
ElementUI Tree 树形控件的使用并给节点添加图标
2020/02/27 Javascript
Javascript confirm多种使用方法解析
2020/09/25 Javascript
Python操作使用MySQL数据库的实例代码
2017/05/25 Python
python学习笔记--将python源文件打包成exe文件(pyinstaller)
2018/05/26 Python
使用Python机器学习降低静态日志噪声
2018/09/29 Python
python pygame模块编写飞机大战
2018/11/20 Python
python 抓包保存为pcap文件并解析的实例
2019/07/23 Python
手把手教你Python yLab的绘制折线图的画法
2019/10/23 Python
python scatter函数用法实例详解
2020/02/11 Python
python如何修改文件时间属性
2021/02/05 Python
css3气泡 css3关键帧动画创建的动态通知气泡
2013/02/26 HTML / CSS
Expedia泰国:预订机票、酒店和旅游包(航班+酒店)
2016/09/27 全球购物
双立人加拿大官网:Zwilling加拿大
2020/08/10 全球购物
Prototype是怎么扩展DOM的
2014/10/01 面试题
《油菜花开了》教学反思
2014/02/22 职场文书
企业挂职心得体会
2014/09/10 职场文书
保研推荐信格式
2015/03/25 职场文书
2015年医德医风工作总结
2015/04/02 职场文书
2015小学教师年度工作总结
2015/05/12 职场文书
保姆聘用合同
2015/09/21 职场文书
mybatis使用oracle进行添加数据的方法
2021/04/27 Oracle
springboot利用redis、Redisson处理并发问题的操作
2021/06/18 Java/Android