百木园-与人分享,
就是让自己快乐。

Prometheus 基于Python Django实现Prometheus Exporter

基于Python Django实现Prometheus Exporter

需求描述

运行监控需求,需要采集Nginx 每个URL请求的相关信息,涉及两个指标:一分钟内平均响应时间,调用次数,并且为每个指标提供3个标签:请求方法,请求状态,请求URL,并向普罗米修斯暴露这些指标相关数据

实践环境

Python 3.6.5

Django 3.0.6

prometheus-client 0.11.0

代码设计与实现

说明:为了更好的表达主题,代码中数据采集部分暂且采用data变量替代。

基于官方SDK

Gauge Metric为例

view视图实现

CustomExporters.url_exporter_views.UrlExporterView

#!/usr/bin/env python
# -*- coding:utf-8 -*-

# Create your views here.
from django.http import HttpResponse
from django.views.generic import View
from prometheus_client import CollectorRegistry, Gauge, generate_latest

import logging
import traceback
logger = logging.getLogger(\'mylogger\')

REGISTRY = CollectorRegistry()
LABELS = [\'req_status\', \'req_method\', \'req_url\'] # 标签定义

# 指标定义
g_requests_total = Gauge(\'requests_total\', \'url request num each minute\', LABELS, registry=REGISTRY)
g_avg_response_time_seconds = Gauge(\'avg_response_time_seconds\', \'url avg response time of one minute\', LABELS, registry=REGISTRY)

class UrlExporterView(View):
def get(self, request, *args, **kwargs):
try:
data = {
\'count\': 34,
\'method\': \'get\',
\'status\': 200,
\'url\': \'url\',
\'avg_rt\':50
}
g_requests_total.labels(data.get(\'status\'),data.get(\'method\'),data.get(\'url\')).set(data.get(\'count\')) #set设定值
g_avg_response_time_seconds.labels(data.get(\'status\'),data.get(\'method\'),data.get(\'url\')).set(data.get(\'avg_rt\'))

return HttpResponse(generate_latest(REGISTRY),status=200, content_type=\"text/plain\")
except Exception:
error_msg = \'%s\' % traceback.format_exc()
logger.error(error_msg)
return HttpResponse(\'# HELP Error occured\', status=500, content_type=\"text/plain\")

注意:通过官方SDK无法向普罗米修斯暴露数据生成时间(非采集时间),以上实现方式无法满足这种需求

项目URL路由配置

CustomPrometheusExporters.CustomPrometheusExporters.urls.py

from django.contrib import admin
from django.urls import path, re_path, include

urlpatterns = [
re_path(r\'^exporters/\', include(\'CustomExporters.urls\')),
path(\'admin/\', admin.site.urls),
]

应用urls.py url路由配置

CustomExporters.urls.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-

from django.urls import path,re_path

from CustomExporters.url_exporter_views import UrlExporterView

urlpatterns = [
re_path(r\'url-exporter/metrics$\', UrlExporterView.as_view(), name=\'url-exporter\')
]

查看运行结果

浏览器中访问 http://127.0.0.1:8000/exporters/url-exporter/metrics,输出如下:

# HELP requests_total url request num each minute
# TYPE requests_total gauge
requests_total{req_method=\"get\",req_status=\"200\",req_url=\"url\"} 34.0
# HELP avg_response_time_seconds url avg response time of one minute
# TYPE avg_response_time_seconds gauge
avg_response_time_seconds{req_method=\"get\",req_status=\"200\",req_url=\"url\"} 50.0

不基于官方SDK

view视图实现

CustomExporters.url_exporter_views.UrlExporterView

#!/usr/bin/env python
# -*- coding:utf-8 -*-

# Create your views here.
from django.http import HttpResponse
from django.views.generic import View
from prometheus_client.utils import floatToGoString

import logging
import traceback
logger = logging.getLogger(\'mylogger\')

class UrlExporterView(View):

def get(self, request, *args, **kwargs):
try:
data = {
\'count\': 34,
\'method\': \'get\',
\'status\': 200,
\'url\': \'url\',
\'avg_rt\':50,
\'timestamp\': 1634099490000
}
requests_total_line_list = [\'# HELP requests_total The total requests number of url to req_service, req_method, status \\n\'] # 存放 requests_total指标输出
avg_response_time_line_list = [\'# HELP avg_response_time_milseconds average request response time for url correspond to req_service, req_method, status\\n\'] # 存放 avg_response_time_seconds指标输出
line_template = \'%(metric_name)s{req_method=\"%(req_method)s\",req_status=\"%(req_status)s\",req_url=\"%(req_url)s\"} %(label_value)s %(timestamp)s\\n\'

requests_total_line_list.append(line_template % {
\'metric_name\':\'requests_total\',
\'req_method\':data.get(\'method\'),
\'req_status\':data.get(\'status\'),
\'req_url\':data.get(\'url\'),
\'label_value\':floatToGoString(data.get(\'count\')),
\'timestamp\':data.get(\'timestamp\')
})

avg_response_time_line_list.append(line_template % {
\'metric_name\':\'avg_response_time_milseconds\',
\'req_method\':data.get(\'method\'),
\'req_status\':data.get(\'status\'),
\'req_url\':data.get(\'url\'),
\'label_value\':floatToGoString(data.get(\'avg_rt\')),
\'timestamp\':data.get(\'timestamp\')
})

output_list = []
output_list.extend(requests_total_line_list)
output_list.append(\'\\n\')
output_list.extend(avg_response_time_line_list)

return HttpResponse(\'\'.join(output_list).encode(\'utf-8\'), status=200, content_type=\"text/plain\")
except Exception:
error_msg = \'%s\' % traceback.format_exc()
logger.error(error_msg)
return HttpResponse(\'# HELP Error occured\', status=500, content_type=\"text/plain\")

查看运行结果

浏览器中访问 http://127.0.0.1:8000/exporters/url-exporter/metrics,输出如下:

# HELP requests_total The total requests number of url to req_service, req_method, status
requests_total{req_method=\"get\",req_status=\"200\",req_url=\"url\"} 34.0 1634099490000

# HELP avg_response_time_milseconds average request response time for url correspond to req_service, req_method, status
avg_response_time_milseconds{req_method=\"get\",req_status=\"200\",req_url=\"url\"} 50.0 1634099490000

样本数据格式说明

普罗米修斯基于文本的(text-based)格式是面向行的。行由换行符(\\n)分隔。最后一行必须以换行字符结尾。空行将被忽略

在一行中,tokens可以由任意数量的空格和/或制表符分隔(如果它们与前一个令牌合并,则必须至少由一个空格分隔)。忽略行收尾随空格。

以 # 作为首个非空白字符的行,被当作注释,且除非#后面第一个token为HELP、TYPE,形如 # HELP、# TYPE,否则罗米修斯会自动忽略该行。

如果token为HELP,则至少需要1个token,该token为Metric名称,剩余所有token为该属性的文档字符串说明(dockstring)。HELP行可以是任意UTF-8序列字符,如果包含反斜杠 \\、 换行符\\n字符,需要进行显示转义,形如 \\\\, \\n

如果token为TYPE,则至少需要2个token,第一个token为Metric名称,第二个为counter,gauge, histogram, summary, 或者 untyped,定义名称指定的Metric的类型。针对同一个给定的Metric名称,只能存在一种Type。TYPE行必须位于该Metric的第一行数据样本行之前。如果该Metric没有定义对应的TYPE行,则默认TYPE为untyped。

剩余的行描述样本(每行对应一个数据样本)使用以下格式

metric_name[{label_name1=\"label_value\",label_name2=\"label_value\",..,label_nameN=\"label_valueN\"}] value [timestamp]

  • metric_name 和label_name遵守普罗米修斯惯用的语言表达式限制
  • label_value 可以是任意UTF-8序列字符,如果包含反斜杠 \\、双引号\"、 换行符\\n字符,需要进行显示转义,形如 \\\\, \\\", \\n
  • value 代表浮点数,正如Go ParseFloat()所需参数。此外,除标准数值外,NaN、+Inf和-Inf分别表示非数字、正无穷大和负无穷大的有效值
  • timestamp 数据自身生成时间,为64整数(1970-01-01 00:00:00 UTC到现在的毫秒数) ,正如Go ParseInt()所需参数

来源:https://www.cnblogs.com/shouke/p/15426777.html
图文来源于网络,如有侵权请联系删除。

未经允许不得转载:百木园 » Prometheus 基于Python Django实现Prometheus Exporter

相关推荐

  • 暂无文章