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常用库推荐
Dec 04 Python
使用Python写CUDA程序的方法
Mar 27 Python
python实现m3u8格式转换为mp4视频格式
Feb 28 Python
python中使用PIL制作并验证图片验证码
Mar 15 Python
Pandas中把dataframe转成array的方法
Apr 13 Python
利用Pycharm断点调试Python程序的方法
Nov 29 Python
在Python中表示一个对象的方法
Jun 25 Python
浅谈在JupyterNotebook下导入自己的模块的问题
Apr 16 Python
python如何从键盘获取输入实例
Jun 18 Python
如何将json数据转换为python数据
Sep 04 Python
Python读写锁实现实现代码解析
Nov 28 Python
Python编程中Python与GIL互斥锁关系作用分析
Sep 15 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
php空间不支持socket但支持curl时recaptcha的用法
2011/11/07 PHP
PHP中$_SERVER的详细参数与说明介绍
2013/10/26 PHP
easyui的tabs update正确用法分享
2014/03/21 PHP
ThinkPHP中Session用法详解
2014/11/29 PHP
PHP网络操作函数汇总
2015/05/18 PHP
php结合正则批量抓取网页中邮箱地址
2015/05/19 PHP
实现WordPress主题侧边栏切换功能的PHP脚本详解
2015/12/14 PHP
php简单构造json多维数组的方法示例
2017/06/08 PHP
jquery固定底网站底部菜单效果
2013/08/13 Javascript
JS获取地址栏参数的小例子
2013/08/23 Javascript
JavaScript实现鼠标点击后层展开效果的方法
2015/05/13 Javascript
使用Meteor配合Node.js编写实时聊天应用的范例
2015/06/23 Javascript
jQuery时间轴插件使用详解
2015/07/16 Javascript
jquery插件treegrid树状表格的使用方法详解(.Net平台)
2017/01/03 Javascript
js 数字、字符串、布尔值的转换方法(必看)
2017/04/07 Javascript
javascript实现文本框标签验证的实例代码
2018/10/14 Javascript
vue中@change兼容问题详解
2019/10/25 Javascript
原生Vue 实现右键菜单组件功能
2019/12/16 Javascript
小程序实现上传视频功能
2020/08/18 Javascript
[27:53]2014 DOTA2华西杯精英邀请赛 5 24 NewBee VS iG
2014/05/26 DOTA
python中如何使用朴素贝叶斯算法
2017/04/06 Python
Django的HttpRequest和HttpResponse对象详解
2018/01/26 Python
python处理csv中的空值方法
2018/06/22 Python
pycharm在调试python时执行其他语句的方法
2018/11/29 Python
通过pykafka接收Kafka消息队列的方法
2018/12/27 Python
pyqt弹出新对话框,以及关闭对话框获取数据的实例
2019/06/18 Python
Python selenium爬取微博数据代码实例
2020/05/22 Python
用python实现学生管理系统
2020/07/24 Python
美国一家专业的太阳镜网上零售商:Solstice太阳镜
2016/07/25 全球购物
Lucene推荐的分页方式是什么?
2015/12/07 面试题
我的画教学反思
2014/04/28 职场文书
财会专业毕业生自荐信
2014/07/09 职场文书
村级个人对照检查材料
2014/08/22 职场文书
常务副县长“四风”个人对照检查材料思想汇报
2014/10/02 职场文书
2019公司管理制度
2019/04/19 职场文书
python爬取某网站原图作为壁纸
2021/06/02 Python