Prometheus 基于Python Django实现Prometheus Exporter

本文涉及的产品
可观测监控 Prometheus 版,每月50GB免费额度
简介: 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为HELPTYPE,形如 # 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名称,只能存在一种TypeTYPE行必须位于该Metric的第一行数据样本行之前。如果该Metric没有定义对应的TYPE行,则默认TYPEuntyped

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

metric_name[{label_name1="label_value",label_name2="label_value",..,label_nameN="label_valueN"}] value [timestamp]
  • metric_namelabel_name遵守普罗米修斯惯用的语言表达式限制
  • label_value 可以是任意UTF-8序列字符,如果包含反斜杠 \、双引号"、 换行符\n字符,需要进行显示转义,形如 \\, \", \n
  • value 代表浮点数,正如Go ParseFloat()所需参数。此外,除标准数值外,NaN+Inf-Inf分别表示非数字、正无穷大和负无穷大的有效值
  • timestamp 数据自身生成时间,为64整数(1970-01-01 00:00:00 UTC到现在的毫秒数) ,正如Go ParseInt()所需参数
相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
目录
相关文章
|
2月前
|
前端开发 JavaScript UED
探索Python Django中的WebSocket集成:为前后端分离应用添加实时通信功能
通过在Django项目中集成Channels和WebSocket,我们能够为前后端分离的应用添加实时通信功能,实现诸如在线聊天、实时数据更新等交互式场景。这不仅增强了应用的功能性,也提升了用户体验。随着实时Web应用的日益普及,掌握Django Channels和WebSocket的集成将为开发者开启新的可能性,推动Web应用的发展迈向更高层次的实时性和交互性。
96 1
|
1月前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
174 45
|
1月前
|
Prometheus 监控 Cloud Native
Prometheus中的Exporter详解
【10月更文挑战第25天】Prometheus Exporter分为直接采集(如cAdvisor, Kubernetes)和间接采集(如Node Exporter)两类。
|
1月前
|
安全 数据库 开发者
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第26天】本文详细介绍了如何在Django框架下进行全栈开发,包括环境安装与配置、创建项目和应用、定义模型类、运行数据库迁移、创建视图和URL映射、编写模板以及启动开发服务器等步骤,并通过示例代码展示了具体实现过程。
59 2
|
1月前
|
安全 数据库 C++
Python Web框架比较:Django vs Flask vs Pyramid
Python Web框架比较:Django vs Flask vs Pyramid
44 1
|
2月前
|
安全 数据库 C++
Python Web框架比较:Django vs Flask vs Pyramid
Python Web框架比较:Django vs Flask vs Pyramid
42 4
|
2月前
|
安全 数据库 C++
Python Web框架比较:Django vs Flask vs Pyramid
【10月更文挑战第10天】本文比较了Python中三个最受欢迎的Web框架:Django、Flask和Pyramid。Django以功能全面、文档完善著称,适合快速开发;Flask轻量灵活,易于上手;Pyramid介于两者之间,兼顾灵活性和安全性。选择框架时需考虑项目需求和个人偏好。
39 1
|
2月前
|
安全 数据库 C++
Python Web框架比较:Django vs Flask vs Pyramid
【10月更文挑战第6天】本文比较了Python中三个最受欢迎的Web框架:Django、Flask和Pyramid。Django功能全面,适合快速开发;Flask灵活轻量,易于上手;Pyramid介于两者之间,兼顾灵活性和可扩展性。文章分析了各框架的优缺点,帮助开发者根据项目需求和个人偏好做出合适的选择。
47 4
|
3月前
|
机器学习/深度学习 算法 TensorFlow
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
交通标志识别系统。本系统使用Python作为主要编程语言,在交通标志图像识别功能实现中,基于TensorFlow搭建卷积神经网络算法模型,通过对收集到的58种常见的交通标志图像作为数据集,进行迭代训练最后得到一个识别精度较高的模型文件,然后保存为本地的h5格式文件。再使用Django开发Web网页端操作界面,实现用户上传一张交通标志图片,识别其名称。
127 6
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
|
3月前
|
机器学习/深度学习 人工智能 算法
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
文本分类识别系统。本系统使用Python作为主要开发语言,首先收集了10种中文文本数据集("体育类", "财经类", "房产类", "家居类", "教育类", "科技类", "时尚类", "时政类", "游戏类", "娱乐类"),然后基于TensorFlow搭建CNN卷积神经网络算法模型。通过对数据集进行多轮迭代训练,最后得到一个识别精度较高的模型,并保存为本地的h5格式。然后使用Django开发Web网页端操作界面,实现用户上传一段文本识别其所属的类别。
112 1
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台