python服务需用prometheus-client启动http服务暴露/metrics端点,不可仅依赖连接prometheus;须避免高基数标签、正确使用counter/histogram、确保scrape路径通畅且rate区间合理。

Python服务怎么暴露/metrics端点给Prometheus
必须让Python进程主动提供符合Prometheus格式的指标文本,否则Prometheus抓不到任何数据。核心是用 prometheus_client 启一个HTTP服务,不是“连上Prometheus”就完事。
- 装包:
pip install prometheus-client,别用prometheus-python(已废弃) - 最简暴露方式:在应用启动后加三行代码,监听
/metrics(默认路径,可改) - 别把
start_http_server(8000)放在子线程里还忘了join()——常见导致进程退出后端点立刻消失 - 若用 FastAPI/Flask,别硬塞
start_http_server;应注册路由,用generate_latest(REGISTRY)手动返回响应体,避免端口冲突
from prometheus_client import Counter, start_http_server
from prometheus_client.core import REGISTRY
<p>req_total = Counter('http_requests_total', 'Total HTTP Requests')</p><p>if <strong>name</strong> == '<strong>main</strong>':
start_http_server(8000) # 阻塞式,放最后或另起线程并 keep alive</p><h1>... your app logic</h1>
哪些指标该暴露、怎么命名才不踩坑
乱暴露指标会导致Grafana查不出数据、Prometheus存储膨胀、甚至标签爆炸。重点不在“多”,而在“可聚合+有维度”。
- 避免用请求ID、用户名、邮箱等高基数字段做标签(
user_id="u_123456"),会触发cardinality explosion - 计数器(
Counter)只增不减,适合http_requests_total;测量耗时用Histogram或Summary,别用Gauge记 latency - 命名统一用小写+下划线,如
db_query_duration_seconds,别写DbQueryTimeMs——Grafana里大小写敏感,且社区约定俗成 - 业务指标优先暴露失败率、P95延迟、队列长度,而不是“当前连接数”这种瞬时抖动大、难告警的
Gauge
Grafana里查不到Python指标?先盯紧这几个地方
90% 的“查不到”问题出在数据链路中间某处断了,不是Grafana配置错。
- curl 一下你的服务:
curl http://your-service:8000/metrics—— 如果返回空、404、或格式报错(比如含非UTF-8字符),Grafana肯定读不到 - Prometheus targets 页面看对应 job 状态:
DOWN表示网络不通或端点返回非200;UP但scrape_samples_post_metric_relabeling为0,说明 relabel_rules 把指标全过滤掉了 - Grafana 数据源选的是 Prometheus,不是 “Prometheus (experimental)” 或其它插件;查询表达式开头别漏
job="your-job-name",尤其当多个Python服务共用一个exporter时 - 时间范围选对:Prometheus默认只存15天,如果查“7天前”的
rate(http_requests_total[5m])却没数据,可能是指标根本没上报过,或 rate 区间内无样本
Python进程重启后指标归零,告警乱触发怎么办
Counter 类型天然重启归零,直接算 rate() 没问题,但用 increase() 或做绝对值比较就会误告警。
- 所有告警规则必须用
rate(metric_name[5m]),别用increase(metric_name[1h]) > 100——Counter重置时 increase 会跳变 - 需要跨重启累计值?自己用 Redis 或数据库存 last_value,启动时调
set()初始化,但代价高,一般不必要 - 若真要监控“自启动以来总请求数”,用
Gauge+ 主动持久化,但失去 Prometheus 原生 rate/increase 优化,慎用 - 本地开发时频繁启停,可在
Counter初始化时加registry=None避免全局REGISTRY污染,否则热重载会报ValueError: Duplicated timeseries
事情说清了就结束。真正卡住的往往不是语法,而是 metrics 路径没通、标签基数失控、或者 rate 区间比 scrape interval 还短。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











