用 Prometheus 监控 Python 应用:新手实战
Python 应用接入 Prometheus:prometheus-client 库安装、/metrics 端点暴露、Counter/Gauge/Histogram 埋点、Flask/FastAPI 中间件集成与生产注意事项。
Python 应用接入 Prometheus 用官方客户端库 prometheus-client,十分钟就能让应用暴露标准指标端点。本文走完从安装到生产部署的完整流程。
安装与最小示例
pip install prometheus-client
from prometheus_client import start_http_server, Counter
import random, time
# 定义指标
REQUEST_COUNT = Counter('app_requests_total', 'Total requests', ['method', 'endpoint'])
def handle_request():
REQUEST_COUNT.labels(method='GET', endpoint='/api').inc()
if __name__ == '__main__':
start_http_server(8000) # 在 8000 端口暴露 /metrics
while True:
handle_request()
time.sleep(random.random())
访问 http://localhost:8000/metrics 可见指标输出,包括默认的 Python 运行时指标(GC 对象数等)。
三种核心指标类型
from prometheus_client import Counter, Gauge, Histogram
# Counter:只增计数(请求数、错误数)
errors = Counter('app_errors_total', 'Total errors', ['type'])
# Gauge:瞬时值(队列深度、在线连接)
queue_depth = Gauge('job_queue_depth', 'Current queue depth')
queue_depth.set(42) # 或 .inc()/.dec()
# Histogram:延迟分布
latency = Histogram('request_duration_seconds', 'Request latency',
buckets=[0.01, 0.05, 0.1, 0.5, 1, 5])
with latency.time(): # 用上下文管理器自动计时
do_something()
Web 框架集成
Flask:
from flask import Flask, request
from prometheus_client import Counter, Histogram, generate_latest, CONTENT_TYPE_LATEST
import time
app = Flask(__name__)
REQS = Counter('http_requests_total', 'Requests', ['method', 'endpoint', 'status'])
LAT = Histogram('http_request_duration_seconds', 'Latency', ['endpoint'])
@app.before_request
def before(): request._start_time = time.perf_counter()
@app.after_request
def after(resp):
if request.endpoint != 'metrics':
endpoint = request.url_rule.rule if request.url_rule else 'unmatched'
REQS.labels(request.method, endpoint, str(resp.status_code)).inc()
LAT.labels(endpoint).observe(time.perf_counter() - request._start_time)
return resp
@app.route('/metrics')
def metrics():
return generate_latest(), 200, {'Content-Type': CONTENT_TYPE_LATEST}
FastAPI 更省事——直接用 prometheus-fastapi-instrumentator 中间件,一行挂载。
生产环境注意事项
- 多进程问题(Gunicorn/uWSGI):每个 worker 的内存指标相互独立,抓到一个 worker 不代表整个应用的总量。以上 Flask 示例适用于单进程;多进程部署需在启动前设置
PROMETHEUS_MULTIPROC_DIR,并用独立的CollectorRegistry和MultiProcessCollector汇总,不能只设置环境变量。具体步骤见官方多进程指南; - 标签基数:endpoint 标签用路由模板(
/users/{id})而非原始路径; - /metrics 端点别暴露公网:只对内网/Prometheus 服务器开放。
若要把本文的自定义指标接入观测云,在 DataKit 的 prom 配置里填入该 Python 服务的 /metrics 地址。分别触发一次成功与失败请求,核对 Counter 增量和 Histogram 桶,再检查多 worker 场景是否重复采集;APM 请求统计不能替代这些业务埋点。
常见问题(FAQ)
Q:Celery 任务怎么监控?
A:任务里埋点(处理数 Counter、耗时 Histogram),暴露方式用 start_http_server 或 textfile;监控队列积压用 Redis/RabbitMQ 的 exporter。
Q:能看到 P99 延迟吗?
A:Histogram 类型暴露 bucket 后,可在 PromQL 中对 bucket 的 rate(...) 用 histogram_quantile(0.99, ...) 估算。Python 官方客户端的 Summary 只提供观测次数与总和,不计算分位数,因此不能用它直接得到 P99。Summary 说明
Q:多进程模式的指标文件要清理吗?
A:要区分重启前清理和 worker 退出处理。PROMETHEUS_MULTIPROC_DIR 应在整组进程重新启动前清空,不要在运行中定期删除所谓“孤儿文件”。Gunicorn 可在 child_exit 中调用 multiprocess.mark_process_dead(worker.pid);它只清理该进程的 live* Gauge 文件,其他指标文件仍需保留。官方多进程指南
[1]: 观测云产品《应用性能监控(APM)》https://www.guance.com/product/application-performance-monitoring
[2]: 观测云文档《DataKit Prometheus 集成》https://docs.guance.com/integrations/prom/
[3]: 观测云文档《监控器》https://docs.guance.com/monitoring/