使用 prometheus python 库编写自定义指标的方法(完整代码)
作者:haozlee 发布时间:2021-03-03 06:03:58
虽然 prometheus 已有大量可直接使用的 exporter 可供使用,以满足收集不同的监控指标的需要。例如,node exporter 可以收集机器 cpu,内存等指标,cadvisor 可以收集容器指标。然而,如果需要收集一些定制化的指标,还是需要我们编写自定义的指标。
本文讲述如何使用 prometheus python 客户端库和 flask 编写 prometheus 自定义指标。
安装依赖库
我们的程序依赖于flask 和prometheus client 两个库,其 requirements.txt
内容如下:
flask==1.1.2
prometheus-client==0.8.0
运行 flask
我们先使用 flask web 框架将 /metrics
接口运行起来,再往里面添加指标的实现逻辑。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask
app = Flask(__name__)
@app.route('/metrics')
def hello():
return 'metrics'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
打开浏览器,输入 http://127.0.0.1:5000/metrics
,按下回车后浏览器显示 metrics 字符。
编写指标
Prometheus 提供四种指标类型,分别为 Counter,Gauge,Histogram 和 Summary。
Counter
Counter 指标只增不减,可以用来代表处理的请求数量,处理的任务数量,等。
可以使用 Counter
定义一个 counter 指标:
counter = Counter('my_counter', 'an example showed how to use counter')
其中,my_counter
是 counter 的名称,an example showed how to use counter
是对该 counter 的描述。
使用 counter 完整的代码如下:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask, Response
from prometheus_client import Counter, generate_latest
app = Flask(__name__)
counter = Counter('my_counter', 'an example showed how to use counter')
@app.route('/metrics')
def hello():
counter.inc(1)
return Response(generate_latest(counter), mimetype='text/plain')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
访问 http://127.0.0.1:5000/metrics
,浏览器输出:
# HELP my_counter_total an example showed how to use counter
# TYPE my_counter_total counter
my_counter_total 6.0
# HELP my_counter_created an example showed how to use counter
# TYPE my_counter_created gauge
my_counter_created 1.5932468510424378e+09
在定义 counter 指标时,可以定义其 label 标签:
counter = Counter('my_counter', 'an example showed how to use counter', ['machine_ip'])
在使用时指定标签的值:
counter.labels('127.0.0.1').inc(1)
这时浏览器会将标签输出:
my_counter_total{machine_ip="127.0.0.1"} 1.0
Gauge
Gauge 指标可增可减,例如,并发请求数量,cpu 占用率,等。
可以使用 Gauge
定义一个 gauge 指标:
registry = CollectorRegistry()
gauge = Gauge('my_gauge', 'an example showed how to use gauge', ['machine_ip'], registry=registry)
为使得 /metrics
接口返回多个指标,我们引入了 CollectorRegistry
,并设置 gauge 的 registry 属性。
使用 set
方法设置 gauge 指标的值:
gauge.labels('127.0.0.1').set(2)
访问 http://127.0.0.1:5000/metrics
,浏览器增加输出:
# HELP my_gauge an example showed how to use gauge
# TYPE my_gauge gauge
my_gauge{machine_ip="127.0.0.1"} 2.0
Histogram
Histogram 用于统计样本数值落在不同的桶(buckets)里面的数量。例如,统计应用程序的响应时间,可以使用 histogram 指标类型。
使用 Histogram
定义一个 historgram 指标:
buckets = (100, 200, 300, 500, 1000, 3000, 10000, float('inf'))
histogram = Histogram('my_histogram', 'an example showed how to use histogram', ['machine_ip'], registry=registry, buckets=buckets)
如果我们不使用默认的 buckets
,可以指定一个自定义的 buckets
,如上面的代码所示。
使用 observe()
方法设置 histogram 的值:
histogram.labels('127.0.0.1').observe(1001)
访问 /metrics
接口,输出:
# HELP my_histogram an example showed how to use histogram
# TYPE my_histogram histogram
my_histogram_bucket{le="100.0",machine_ip="127.0.0.1"} 0.0
my_histogram_bucket{le="200.0",machine_ip="127.0.0.1"} 0.0
my_histogram_bucket{le="300.0",machine_ip="127.0.0.1"} 0.0
my_histogram_bucket{le="500.0",machine_ip="127.0.0.1"} 0.0
my_histogram_bucket{le="1000.0",machine_ip="127.0.0.1"} 0.0
my_histogram_bucket{le="3000.0",machine_ip="127.0.0.1"} 1.0
my_histogram_bucket{le="10000.0",machine_ip="127.0.0.1"} 1.0
my_histogram_bucket{le="+Inf",machine_ip="127.0.0.1"} 1.0
my_histogram_count{machine_ip="127.0.0.1"} 1.0
my_histogram_sum{machine_ip="127.0.0.1"} 1001.0
# HELP my_histogram_created an example showed how to use histogram
# TYPE my_histogram_created gauge
my_histogram_created{machine_ip="127.0.0.1"} 1.593260699767071e+09
由于我们设置了 histogram
的样本值为 1001,可以看到,从 3000 开始,xxx_bucket 的值为 1。由于只设置一个样本值,故 my_histogram_count
为 1 ,且样本总数 my_histogram_sum
为 1001。
读者可以自行试验几次,慢慢体会 histogram 指标的使用,远比看网上的文章理解得快。
Summary
Summary 和 histogram 类型类似,可用于统计数据的分布情况。
定义 summary 指标:
summary = Summary('my_summary', 'an example showed how to use summary', ['machine_ip'], registry=registry)
设置 summary 指标的值:
summary.labels('127.0.0.1').observe(randint(1, 10))
访问 /metrics
接口,输出:
# HELP my_summary an example showed how to use summary
# TYPE my_summary summary
my_summary_count{machine_ip="127.0.0.1"} 4.0
my_summary_sum{machine_ip="127.0.0.1"} 16.0
# HELP my_summary_created an example showed how to use summary
# TYPE my_summary_created gauge
my_summary_created{machine_ip="127.0.0.1"} 1.593263241728389e+09
附:完整源代码
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from random import randint
from flask import Flask, Response
from prometheus_client import Counter, Gauge, Histogram, Summary, \
generate_latest, CollectorRegistry
app = Flask(__name__)
registry = CollectorRegistry()
counter = Counter('my_counter', 'an example showed how to use counter', ['machine_ip'], registry=registry)
gauge = Gauge('my_gauge', 'an example showed how to use gauge', ['machine_ip'], registry=registry)
buckets = (100, 200, 300, 500, 1000, 3000, 10000, float('inf'))
histogram = Histogram('my_histogram', 'an example showed how to use histogram',
['machine_ip'], registry=registry, buckets=buckets)
summary = Summary('my_summary', 'an example showed how to use summary', ['machine_ip'], registry=registry)
@app.route('/metrics')
def hello():
counter.labels('127.0.0.1').inc(1)
gauge.labels('127.0.0.1').set(2)
histogram.labels('127.0.0.1').observe(1001)
summary.labels('127.0.0.1').observe(randint(1, 10))
return Response(generate_latest(registry), mimetype='text/plain')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
参考资料
https://github.com/prometheus/client_python
https://prometheus.io/docs/concepts/metric_types/
https://prometheus.io/docs/instrumenting/writing_clientlibs/
https://prometheus.io/docs/instrumenting/exporters/
https://pypi.org/project/prometheus-client/
https://prometheus.io/docs/concepts/metric_types/
http://www.coderdocument.com/docs/prometheus/v2.14/best_practices/histogram_and_summary.html
https://prometheus.io/docs/practices/histograms/
来源:https://blog.csdn.net/lihao21/article/details/106988390
猜你喜欢
- ASP使用xmlhttp获取远程网页内容,解决乱码问题方法一:<%function getHTTPPage(url)on error
- 斐波那契记忆优化法:<script type="text/javascript">var fibonacci
- 当您使用FILESYSTEMOBJECT(fso)对象获得某个目录下的文件列表的时候,你有没有发现无法控制它们的排序方式,比如按照名字排序,
- 八月的UCDChina书友会主题是“信息分类和方法”,在会场中的内容是不足以简单的概述的,而这次交流至少对于分类、属性、关键词与Tag的定义
- 我们经常使用傅里叶变换来计算数字信号的频谱,进而分析数字信号,离散时间傅里叶变换的公式为:可是自己动手实现一遍才是最好的学习。在数字分析里面
- 许多 Microsoft 的编程语言,如 Visual Basic、VBScript 和 Jscript,都提供集合(collection)
- AlexNet是2012年ImageNet比赛的冠军,虽然过去了很长时间,但是作为深度学习中的经典模型,AlexNet不但有助于我们理解其中
- 组合集总计: group by with rollup/cube grouping sets 子查询按执行方式分:标准子查询、关联子查询 标
- 我刚进入5gsns的时候,我真不知道怎么玩,我是通过白鸦的博客过去的,之前也没有怎么去玩过这类的网站。对于sns网站还算是陌生,不过还好网站
- ASCII码键盘ASCII 码键盘ASCII 码键盘ASCII 码键盘27ESC32SPACE33!34"35#36$37%38&
- 目录什么是异常?异常处理try-except 格式一-try...except...格式二-try...except {error
- asp函数实现把数字格式化为每3个数字时以逗号间隔的数字见下:<%Function Comma(str)If No
- 这篇文章主要介绍了JavaScript监听触摸事件代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要
- jQuery 将马上发布 1.4 正式版,代码也从 googlecode 上迁移到了 github. jQuery 是我接触的第一个 JS
- 在JavaScript中,我们应该尽可能的用局部变量来代替全局变量,这句话所有人都知道,可是这句话是谁先说的?为什么要这么做?有什么根据么?
- 下面这个例子描述的是在Godaddy-Linux托管帐户上使用JSP连接到某个MySQL数据库。 <%@ page
- 我设了两个SESSION:SESSION(A1),SESSION(A2),然后我现在想结束其中一个SESSION(如:ESEEION(A1)
- 案例故事:大部分带彩色屏幕的终端设备,不管是手机,车机,电视等等,都需要涉及图片的显示,作为一名专业的多媒体测试人员,我们需要一堆的规范化标
- 首先,未来Python完全取代Java的可能性并不大,但是Python的发展确实能够挤占一部分Java的应用空间。Python语言在最近几年
- PHP convert_uuencode() 函数实例编码字符串:<?php $str = "Hello world!&qu