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 修改文件指定行的方法
May 15 Python
Python中字典创建、遍历、添加等实用操作技巧合集
Jun 02 Python
python创建临时文件夹的方法
Jul 06 Python
Python中跳台阶、变态跳台阶与矩形覆盖问题的解决方法
May 19 Python
Python+pandas计算数据相关系数的实例
Jul 03 Python
WxPython实现无边框界面
Nov 18 Python
Python:type、object、class与内置类型实例
Dec 25 Python
快速解决Django关闭Debug模式无法加载media图片与static静态文件
Apr 07 Python
Python Selenium截图功能实现代码
Apr 26 Python
python程序如何进行保存
Jul 03 Python
Python Tkinter实例——模拟掷骰子
Oct 24 Python
Python入门之使用pandas分析excel数据
May 12 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
星际争霸教主Flash的ID由来:你永远不会知道他之前的ID是www!
2019/01/18 星际争霸
解析link_mysql的php版
2013/06/30 PHP
Zend Guard使用指南及问题处理
2015/01/07 PHP
部署PHP时的4个配置修改说明
2015/10/19 PHP
thinkPHP中钩子的使用方法实例分析
2017/11/16 PHP
PHP代码加密的方法总结
2020/03/13 PHP
javascript 四则运算精度修正函数代码
2010/05/31 Javascript
一个很简单的jquery+xml+ajax的无刷新树结构(无css,后台是c#)
2010/06/02 Javascript
js禁止小键盘输入数字功能代码
2011/08/01 Javascript
jQuery旋转插件—rotate支持(ie/Firefox/SafariOpera/Chrome)
2013/01/16 Javascript
JS如何判断浏览器类型和详细区分IE各版本浏览器
2017/03/04 Javascript
Angular弹出模态框的两种方式
2017/10/19 Javascript
React数据传递之组件内部通信的方法
2017/12/31 Javascript
JS处理一些简单计算题
2018/02/24 Javascript
jsonp格式前端发送和后台接受写法的代码详解
2019/11/07 Javascript
vue实现随机验证码功能(完整代码)
2019/12/10 Javascript
jQuery实现可编辑的表格
2019/12/11 jQuery
JS运算符简单用法示例
2020/01/19 Javascript
实现vuex原理的示例
2020/10/21 Javascript
TypeScript魔法堂之枚举的超实用手册
2020/10/29 Javascript
Vue实现todo应用的示例
2021/02/20 Vue.js
Python实现直方图均衡基本原理解析
2019/08/08 Python
浅析pip安装第三方库及pycharm中导入第三方库的问题
2020/03/10 Python
python中shell执行知识点
2020/05/06 Python
python批量生成身份证号到Excel的两种方法实例
2021/01/14 Python
详解使用CSS3的@media来编写响应式的页面
2017/11/01 HTML / CSS
CSS3实战第一波 让我们尽情的圆角吧
2010/08/27 HTML / CSS
英国和爱尔兰最大的地毯零售商:Kukoon
2018/12/17 全球购物
实习老师个人总结的自我评价
2013/09/28 职场文书
大专计算机个人求职的自我评价
2013/10/21 职场文书
公积金单位接收函
2014/01/11 职场文书
煤矿安全承诺书
2014/05/22 职场文书
创先争优标语
2014/06/27 职场文书
民事申诉状范本
2015/05/20 职场文书
pytorch 使用半精度模型部署的操作
2021/05/24 Python
JavaWeb Servlet实现网页登录功能
2021/07/04 Java/Android