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调用C/C++动态链接库的方法详解
Jul 22 Python
在Python的Flask框架中验证注册用户的Email的方法
Sep 02 Python
Python编程中使用Pillow来处理图像的基础教程
Nov 20 Python
pytorch 数据集图片显示方法
Jul 26 Python
centos+nginx+uwsgi+Django实现IP+port访问服务器
Nov 15 Python
Pytorch DataLoader 变长数据处理方式
Jan 08 Python
如何使用selenium和requests组合实现登录页面
Feb 03 Python
pandas数据拼接的实现示例
Apr 16 Python
Python实现初始化不同的变量类型为空值
Jun 02 Python
OpenCV实现机器人对物体进行移动跟随的方法实例
Nov 09 Python
Python 利用Entrez库筛选下载PubMed文献摘要的示例
Nov 24 Python
python可视化分析绘制带趋势线的散点图和边缘直方图
Jun 25 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开启安全模式后禁用的函数集合
2011/06/26 PHP
PHP中include与require使用方法区别详解
2013/10/19 PHP
Symfony页面的基本创建实例详解
2015/01/26 PHP
最佳6款用于移动网站开发的jQuery 图片滑块插件小结
2012/07/20 Javascript
密码框显示提示文字jquery示例
2013/08/29 Javascript
jQuery操作Select的Option上下移动及移除添加等等
2013/11/18 Javascript
jQuery实现单击按钮遮罩弹出对话框(仿天猫的删除对话框)
2014/04/10 Javascript
使用JavaScript的ActiveXObject对象检测应用程序是否安装的方法
2014/04/15 Javascript
javascript实现字符串反转的方法
2015/02/05 Javascript
jQuery实现高亮显示的方法
2015/03/10 Javascript
纯javascript实现四方向文本无缝滚动效果
2015/06/16 Javascript
分享jQuery插件的学习笔记
2016/01/14 Javascript
Nodejs抓取html页面内容(推荐)
2016/08/11 NodeJs
简单理解vue中el、template、replace元素
2016/10/27 Javascript
解决ajax不能访问本地文件问题(利用js跨域原理)
2017/01/24 Javascript
JS中实现函数return多个返回值的实例
2017/02/21 Javascript
Vue下的国际化处理方法
2017/12/18 Javascript
纯js代码生成可搜索选择下拉列表的实例
2018/01/11 Javascript
Vue实现一个无限加载列表功能
2018/11/13 Javascript
Vue.js 图标选择组件实践详解
2018/12/03 Javascript
7个好用的JavaScript技巧分享(译)
2019/05/07 Javascript
详解vue项目中实现图片裁剪功能
2019/06/07 Javascript
详解vue中$nextTick和$forceUpdate的用法
2019/12/11 Javascript
vue实现计算器功能
2020/02/22 Javascript
Python环境变量设置方法
2016/08/28 Python
Python3单行定义多个变量或赋值方法
2018/07/12 Python
Apache,wsgi,django 程序部署配置方法详解
2019/07/01 Python
python3.6+django2.0+mysql搭建网站过程详解
2019/07/24 Python
python的pstuil模块使用方法总结
2019/07/26 Python
使用批处理脚本自动生成并上传NuGet包(操作方法)
2019/11/19 Python
基于pygame实现童年掌机打砖块游戏
2020/02/25 Python
解决django FileFIELD的编码问题
2020/03/30 Python
Pandas中DataFrame交换列顺序的方法实现
2020/12/14 Python
Html5中localStorage存储JSON数据并读取JSON数据的实现方法
2017/02/13 HTML / CSS
2014村务公开实施方案
2014/02/25 职场文书
MySQL中的 inner join 和 left join的区别解析(小结果集驱动大结果集)
2023/05/08 MySQL