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如何查看系统网络流量的信息
Sep 12 Python
基于python(urlparse)模板的使用方法总结
Oct 13 Python
Python实现简单的语音识别系统
Dec 13 Python
面向初学者的Python编辑器Mu
Oct 08 Python
python3下载抖音视频的完整代码
Jun 05 Python
在linux系统下安装python librtmp包的实现方法
Jul 22 Python
python-tornado的接口用swagger进行包装的实例
Aug 29 Python
pandas实现将日期转换成timestamp
Dec 07 Python
pytorch中tensor张量数据类型的转化方式
Dec 31 Python
为什么黑客都用python(123个黑客必备的Python工具)
Jan 31 Python
python tkiner实现 一个小小的图片翻页功能的示例代码
Jun 24 Python
用python计算文件的MD5值
Dec 23 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 数组遍历的差异(array_diff 的实现)
2008/03/23 PHP
飞鱼(shqlsl) javascript作品集
2006/12/16 Javascript
认识延迟时间为0的setTimeout
2008/05/16 Javascript
jQuery对象和DOM对象相互转化
2009/04/24 Javascript
jquery+json 通用三级联动下拉列表
2010/04/19 Javascript
js获取class的所有元素
2013/03/28 Javascript
JS获得QQ号码的昵称,头像,生日的简单实例
2013/12/04 Javascript
jquery和雅虎的yql服务实现天气预报服务示例
2014/02/08 Javascript
JS获取Table中td值的方法
2015/03/19 Javascript
javascript父子页面通讯实例详解
2015/07/17 Javascript
Bootstrap入门书籍之(零)Bootstrap简介
2016/02/17 Javascript
基于jQuery实现照片墙自动播放特效
2017/01/12 Javascript
浅谈js中startsWith 函数不能在任何浏览器兼容的问题
2017/03/01 Javascript
Vue使用json-server进行后端数据模拟功能
2018/04/17 Javascript
Postman的下载及安装教程详解
2018/10/16 Javascript
微信小程序实现slideUp、slideDown滑动效果及点击空白隐藏功能示例
2018/12/11 Javascript
vue19 组建 Vue.extend component、组件模版、动态组件 的实例代码
2019/04/04 Javascript
[01:29]2017 DOTA2国际邀请赛官方英雄手办展示
2017/03/18 DOTA
从零学python系列之数据处理编程实例(一)
2014/05/22 Python
web.py获取上传文件名的正确方法
2014/08/26 Python
python操作字典类型的常用方法(推荐)
2016/05/16 Python
Django获取应用下的所有models的例子
2019/08/30 Python
Python3 Tkinkter + SQLite实现登录和注册界面
2019/11/19 Python
解决python -m pip install --upgrade pip 升级不成功问题
2020/03/05 Python
python和php哪个更适合写爬虫
2020/06/22 Python
CSS3盒子模型详解
2013/04/24 HTML / CSS
CSS3 重置iphone浏览器按钮input,select等表单元素的默认样式
2014/10/11 HTML / CSS
HTML5 客户端数据库简易使用:IndexedDB
2019/12/19 HTML / CSS
Hoka One One法国官网:美国专业跑鞋品牌
2018/12/29 全球购物
推荐信格式要求
2014/05/09 职场文书
健康教育评估方案
2014/05/25 职场文书
机电一体化专业毕业生自荐信
2014/06/19 职场文书
民政工作个人总结
2015/02/28 职场文书
刑事案件上诉状
2015/05/23 职场文书
golang中的空接口使用详解
2021/03/30 Python
详解Redis在SpringBoot工程中的综合应用
2021/10/16 Redis