Prometheus Exporter入门开发指南
Prometheus Exporter 入门开发指南
一、文档概述
Prometheus Exporter 是暴露监控指标的小程序,核心作用是将自定义的业务 / 系统指标转换为 Prometheus 能识别的格式,并通过 HTTP 接口(默认 /metrics)提供给 Prometheus 抓取,是 Prometheus 监控体系的核心组成部分。
二、环境准备
Prometheus 官方提供了 Python 客户端库 prometheus_client,这是开发 Python 版 Exporter 的标配,执行以下命令安装:
pip install prometheus-client
三、Prometheus 核心指标类型
在开发 Exporter 前,必须先理解 Prometheus 的 4 种核心指标类型,这是 Exporter 开发的基础:
| 指标类型 | 核心特点 | 典型用途 |
|---|---|---|
| Counter | 只增不减的计数器(重启后重置) | 统计请求总数、错误总数、任务完成数 |
| Gauge | 可增可减的瞬时值(支持动态更新) | 内存使用率、CPU 负载、随机值等瞬时状态 |
| Histogram | 统计数值分布(按预设桶划分) | 请求延迟分布、响应大小分布 |
| Summary | 统计滑动窗口内的分位数 | 延迟的 90/99 分位数、接口耗时 Top N |
补充:所有指标都支持添加标签(Label),用于维度拆分(如按接口路径、服务实例统计指标)。
四、完整代码解析
4.1 导入核心模块
from prometheus_client import start_http_server, Counter, Gauge, Histogram, Summary
import random
import time
-
prometheus_client:核心库,提供指标定义、HTTP 服务启动等能力:
start_http_server:启动 HTTP 服务,暴露/metrics接口;Counter/Gauge/Histogram/Summary:4 种核心指标的构造函数。
-
random:用于模拟随机的指标值(如请求耗时、随机路径); -
time:用于模拟耗时操作、控制循环间隔。
4.2 定义核心指标
(1)Counter:请求总数计数器
requests_total = Counter(
'my_requests_total', # 指标名(Prometheus 命名规范:小写+下划线)
'Total number of requests processed' # 指标描述(说明指标含义)
)
- 作用:统计所有请求的总数量,只会递增(调用
inc()方法),重启后重置为 0。 - 关键方法:
inc()(默认 + 1,也可传参数如inc(2)表示 + 2)。
(2)Gauge:动态随机值
random_value = Gauge(
'my_random_value',
'A random value that changes on each scrape'
)
random_value.set_function(lambda: random.random())
- 作用:暴露一个 0~1 之间的随机瞬时值,每次 Prometheus 抓取(scrape)时自动更新。
- 关键特性:
set_function()可以绑定一个函数,每次抓取时自动执行并更新指标值;也可手动调用set(值)/inc()/dec()修改值。
(3)Histogram:请求耗时分布
request_duration_histogram = Histogram(
'my_request_duration_seconds',
'Request duration in seconds',
buckets=[0.1, 0.5, 1, 2, 5] # 自定义桶(单位:秒)
)
- 作用:统计请求耗时的分布情况,比如 “耗时 0.1 秒内的请求数”“0.1~0.5 秒的请求数” 等。
buckets:自定义桶的边界,默认桶为[0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],适合大部分场景。- 关键方法:
observe(值)(记录一个数值到直方图)。
(4)Summary:请求耗时分位数
request_duration_summary = Summary(
'my_request_duration_summary_seconds',
'Request duration summary in seconds'
)
- 作用:统计请求耗时的分位数(默认 0.5/0.9/0.99),比如 “90% 的请求耗时不超过 X 秒”。
- 关键方法:
observe(值)(与 Histogram 用法一致)。
(5)带标签的 Counter:按路径统计请求数
requests_by_path = Counter(
'my_requests_by_path_total',
'Requests by path',
['path'] # 定义标签名(可多个,如 ['path', 'method'])
)
- 作用:按 “请求路径” 维度拆分请求数,比如
/home路径的请求数、/api路径的请求数。 - 关键用法:
labels(标签名=值).inc()(先绑定标签值,再递增)。
4.3 模拟请求处理函数
def process_request():
"""模拟一次请求处理,更新各类指标"""
# 1. 递增总请求计数器
requests_total.inc()
# 2. 随机选择请求路径,更新带标签的计数器
path = random.choice(['/home', '/api', '/health'])
requests_by_path.labels(path=path).inc() # 绑定path标签值并递增
# 3. 模拟请求耗时(0.1~2.0秒)
duration = random.uniform(0.1, 2.0)
time.sleep(duration) # 模拟实际业务的耗时操作
# 4. 记录耗时到Histogram和Summary
request_duration_histogram.observe(duration)
request_duration_summary.observe(duration)
- 核心逻辑:模拟一次完整的请求处理流程,同时更新所有定义的指标,是 Exporter 中 “指标采集逻辑” 的核心载体。
4.4 主程序入口
if __name__ == '__main__':
# 1. 启动HTTP服务,监听8000端口(暴露/metrics接口)
start_http_server(8000)
print("Exporter is running on http://localhost:8000/metrics")
# 2. 无限循环,持续模拟请求(实际场景可替换为真实业务逻辑)
while True:
process_request()
time.sleep(1) # 额外等待1秒,避免请求过于密集
start_http_server(8000):启动 HTTP 服务,Prometheus 会从http://localhost:8000/metrics抓取指标;- 无限循环:持续生成模拟请求,保证指标有数据更新(实际开发中,循环逻辑可替换为 “定时采集业务指标”“监听事件更新指标” 等)。
五、运行与测试
5.1 运行脚本
将示例代码保存为 my_exporter.py,执行以下命令运行:
python my_exporter.py
运行成功后会输出:Exporter is running on http://localhost:8000/metrics。
5.2 验证指标暴露
打开浏览器访问 http://localhost:8000/metrics,看到类似以下的指标数据(Prometheus 标准格式):
# HELP my_requests_total Total number of requests processed
# TYPE my_requests_total counter
my_requests_total 5.0
# HELP my_random_value A random value that changes on each scrape
# TYPE my_random_value gauge
my_random_value 0.789456
# HELP my_requests_by_path_total Requests by path
# TYPE my_requests_by_path_total counter
my_requests_by_path_total{path="/home"} 2.0
my_requests_by_path_total{path="/api"} 2.0
my_requests_by_path_total{path="/health"} 1.0
- 能看到这些指标,说明 Exporter 运行正常。
5.3 关键验证点
- 指标名和描述与代码中定义的一致;
my_random_value每次刷新页面会变化(Gauge 动态更新);my_requests_total会持续递增(Counter 特性);- 带标签的指标会按
/home//api//health拆分数值。
六、扩展建议
6.1 替换模拟逻辑为真实业务
将 process_request() 中的 “随机模拟” 替换为真实业务逻辑,比如:
- 采集服务器 CPU / 内存使用率(可结合
psutil库); - 统计接口实际请求数(对接 Web 框架如 Flask/Django);
- 监控数据库连接数(查询数据库状态)。
6.2 添加错误处理
建议给指标采集逻辑加异常捕获:
def process_request():
try:
# 原有逻辑
requests_total.inc()
# ... 其他逻辑
except Exception as e:
# 可选:定义一个错误计数器,统计异常数
error_total = Counter('my_error_total', 'Total number of errors')
error_total.inc()
print(f"Error processing request: {e}")
6.3 自定义指标采集频率
将固定 time.sleep(1) 替换为定时任务(如 schedule 库),更灵活控制采集频率:
pip install schedule
import schedule
def collect_metrics():
process_request()
if __name__ == '__main__':
start_http_server(8000)
# 每5秒采集一次指标
schedule.every(5).seconds.do(collect_metrics)
while True:
schedule.run_pending()
time.sleep(1)
七、Exporter 开发最佳实践
-
指标命名规范
- 小写字母 + 下划线(如
my_requests_total,避免大写 / 特殊字符);
- 小写字母 + 下划线(如
- 后缀体现指标类型(如计数器加
_total,耗时加_seconds)。
-
标签设计原则
- 标签数不宜过多(建议≤5 个),否则会导致指标爆炸;
- 标签值不宜动态生成(如用户 ID、随机字符串)。
-
性能考虑
- 避免在
/metrics请求时执行耗时操作(可提前采集并缓存);
- 避免在
- 无限循环中控制采集频率,避免占用过多 CPU / 内存。
八、总结
关键点回顾
- 开发 Python 版 Prometheus Exporter 的核心是使用
prometheus_client库,先定义指标,再更新指标值,最后通过 HTTP 服务暴露; - Prometheus 核心指标有 4 种:Counter(只增)、Gauge(瞬时值)、Histogram(分布)、Summary(分位数),带标签的指标可实现维度拆分;
- 开发时,先通过模拟逻辑验证 Exporter 运行,再逐步替换为真实业务逻辑,同时注意错误处理和命名规范。
附:my_exporter.py
from prometheus_client import start_http_server, Counter, Gauge, Histogram, Summary
import random
import time
# 1. Counter:只增计数器(例如请求总数)
requests_total = Counter(
'my_requests_total',
'Total number of requests processed'
)
# 2. Gauge:可增可减的瞬时值(例如当前随机值)
# 使用 set_function 让 Gauge 每次被抓取时自动获取最新值
random_value = Gauge(
'my_random_value',
'A random value that changes on each scrape'
)
random_value.set_function(lambda: random.random())
# 3. Histogram:直方图,用于观测值的分布(如请求延迟)
# buckets 可以自定义,默认 buckets 适合大部分场景
request_duration_histogram = Histogram(
'my_request_duration_seconds',
'Request duration in seconds',
buckets=[0.1, 0.5, 1, 2, 5] # 可选,自定义桶范围
)
# 4. Summary:摘要,用于计算滑动时间窗口内的分位数(如延迟的 90 分位数)
# 默认包含 0.5, 0.9, 0.99 分位数
request_duration_summary = Summary(
'my_request_duration_summary_seconds',
'Request duration summary in seconds'
)
# 带标签的指标示例:按路径统计请求数
requests_by_path = Counter(
'my_requests_by_path_total',
'Requests by path',
['path'] # 定义标签名
)
def process_request():
"""模拟一次请求处理,更新各类指标"""
# 更新总请求计数器
requests_total.inc()
# 模拟随机路径的请求
path = random.choice(['/home', '/api', '/health'])
requests_by_path.labels(path=path).inc() # 带标签的计数器
# 模拟请求处理耗时(随机 0.1 ~ 2.0 秒)
duration = random.uniform(0.1, 2.0)
time.sleep(duration) # 模拟耗时操作
# 将耗时记录到 Histogram 和 Summary
request_duration_histogram.observe(duration)
request_duration_summary.observe(duration)
if __name__ == '__main__':
# 启动 HTTP 服务,监听 8000 端口,暴露 /metrics 端点
start_http_server(8000)
print("Exporter is running on http://localhost:8000/metrics")
# 主循环,每 3 秒模拟一次请求
while True:
process_request()
# 注意:process_request 内部已经 sleep 了随机时长,
# 但为了让循环更稳定,我们可以再加一个固定间隔
time.sleep(1) # 额外等待 1 秒,避免请求过于密集
附:Dockerfile
FROM python:3.9-slim
WORKDIR /app
# 设置 Python 环境变量,避免生成 .pyc 文件和缓冲输出
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
RUN echo "prometheus-client>=0.20.0" > requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
COPY my_exporter.py .
EXPOSE 8000
CMD ["python", "my_exporter.py"]
附:requirements.txt
prometheus_client==0.24.1
作者:wanghongwei
版权声明:本作品遵循<CC BY-NC-ND 4.0>版权协议,商业转载请联系作者获得授权,非商业转载请附上原文出处链接及本声明。

浙公网安备 33010602011771号