用flask实现自定义Prometheus的exporter

想要简单的把监控的东西 放在一个 dict 里面 然后 用 flask 提供服务给 Prometheus 采集
官方的 prometheus_client 提供的 server 不满足需求 找了一圈也没找到合适的轮子 所以自己造一个 方法感觉略蠢 有好用的轮子 M我 谢了

Idea

官方的demo提供了生成 Gauge 的方法 Gauge()
所以我赌五毛钱应该可以 遍历 metrics 然后将生成的 Gauge 放入一个 list 中 再使用 prometheus_client.generate_latest()方法
将数据整理为 Prometheus 需要的格式

1
2
3
4
for t in gauge_buffer:
t.labels(instance='{}:{}'.format('ip', 'port')).set(data[index_buffer[gauge_buffer.index(t)]])
# generate_latest更新列表
res_list.append(prometheus_client.generate_latest(t))

跑一下代码 发现可行…
but 当第二次访问的时候 View 函数会重新调用 Gauge() 方法 初始化 第二次访问接口就会报错
google 了好久 没有合适的轮子 只好自己想了个蠢的办法 (ps:肯定有更好的方法 我一直在寻找)
在 flask 初始化服务的时候 先初始化 Gauge 同时定义一个列表 来记录 Gauge 实例的 index
然后在 view 函数被调用的时候更新数据 再根据 index 索引到 Gauge
最后 使用 prometheus_client.generate_latest() 返回 response

1
2
ele = Gauge('{}'.format(ele), '', ['instance', ])
gauge_buffer.append(ele)

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# DATE :  2018/7/23 
# AUTHOR : kongandmarx@163.com


import prometheus_client
from prometheus_client import Gauge
from flask import Response, Flask

test = {r'monitor': 1}
app = Flask(__name__)
gauges = test
# Gauge列表
gauge_buffer = []
# 位置列表
index_buffer = []
for ele in gauges:
# 记录Gauge 列表位置
index_buffer.append(ele)
# 循环生成Gauge实例,添加到列表
ele = Gauge('{}'.format(ele), '', ['instance', ])
gauge_buffer.append(ele)


@app.route('/metrics')
def metrics():
# 每次访问调用 test
data = test
res_list = []
for t in gauge_buffer:
t.labels(instance='{}:{}'.format('ip', 'port')).set(data[index_buffer[gauge_buffer.index(t)]])
# generate_latest更新列表
res_list.append(prometheus_client.generate_latest(t))
return Response(res_list, mimetype='text/plain')
pass


if __name__ == '__main__':
app.debug = True
app.run(host='localhost', port=10110)
pass