因django-prometheus默认仅暴露请求计数器,未采集响应时间直方图;中间件顺序错误、时区配置异常、多进程未启用MultiProcessCollector等,均会导致P95延迟为0或指标丢失。

为什么直接用 django-prometheus 会漏掉关键请求延迟指标?
因为默认配置下,django-prometheus 只暴露 django_http_requests_total 和 django_http_exceptions_total 这类计数器,但不采集每个请求的响应时间直方图(django_http_request_duration_seconds)。你看到的 P95 延迟为 0 或空,大概率是中间件加载顺序错了。
实操建议:
- 确保
PrometheusBeforeMiddleware在最外层(即MIDDLEWARE列表首位),PrometheusAfterMiddleware在最末位;顺序颠倒会导致 duration 指标无法打点 - 检查是否误启用了
USE_TZ = True且未配置时区感知日志——这不会报错,但会使django_http_request_duration_seconds的 bucket 边界计算异常,表现为 histogram 数据稀疏或全为 0 - 确认
settings.py中已显式启用:PROMETHEUS_METRICS_EXPORT_PORT = 8001(非必须,但若用多进程部署,必须设,否则子进程抢端口导致指标丢失)
如何让 django_prometheus.metrics 正确统计数据库查询耗时?
默认的 django_prometheus 不自动监控 ORM 查询延迟,它只跟踪 HTTP 请求生命周期。要捕获 SELECT/UPDATE/INSERT 的执行时间,必须手动注入 metrics 实例到 Django 的数据库后端钩子中。
实操建议:
- 在
settings.py的DATABASES配置里,为每个 DB 引擎添加'OPTIONS': {'metrics': True}(仅支持 PostgreSQL 和 MySQL) - 若用 SQLite 或自定义 backend,需重写
DatabaseWrapper的make_debug_cursor方法,在返回 cursor 前 wrap 一层计时逻辑 - 注意:
django_db_query_duration_seconds是直方图,不是计数器;它的 labeloperation值为select/update等,不是 SQL 模板名——别指望靠它查慢查询语句,那是django_db_queries_total的职责
/metrics 接口返回 404 或权限拒绝怎么办?
这不是 Prometheus 客户端问题,而是 Django URL 路由和权限控制没对齐。常见于使用 django-auth 或 django-guardian 的项目。
实操建议:
- 路由必须显式声明:
path('metrics/', django_prometheus.exports.ExportToDjangoView, name='prometheus-django-metrics'),不能依赖自动发现 - 如果用了
django.contrib.auth.middleware.AuthenticationMiddleware,需确保该 view 不触发 login_required——可在 settings 中加:PROMETHEUS_DISABLE_ADMIN_ACCESS = True,或自定义 view 并绕过认证中间件 - 生产环境 Nginx 反向代理时,确认 header
X-Forwarded-For和X-Real-IP未被 strip,否则ExportToDjangoView可能因 IP 白名单校验失败返回 403
为什么 django_http_requests_total 的 method label 总是 GET?
这是中间件未覆盖全部请求入口导致的。Django Admin、staticfiles、APIView、DRF 的 APIView 子类,甚至某些异步视图(ASGI)都可能绕过默认中间件链。
实操建议:
- 检查是否在
urls.py中用了re_path(r'^admin/', admin.site.urls)—— 这种写法会让 admin 请求跳过中间件;应改用path('admin/', admin.site.urls) - 若用 DRF,确认
DEFAULT_RENDERER_CLASSES里没有禁用BrowsableAPIRenderer,否则浏览器调试时 POST 请求会被转成 GET,造成 label 失真 - ASGI 模式下,
django-prometheus的同步中间件不生效,必须换用prometheus-async+ 自定义 ASGI middleware,并在scope['type'] == 'http'时才打点
真正难调的是并发场景下的指标抖动——比如 Gunicorn 多 worker 共享同一端口却各自维护内存指标,这时必须用 prometheus-client 的 MultiProcessCollector,且确保 PROMETHEUS_MULTIPROC_DIR 路径可写、被所有 worker 进程共享。漏掉这个,P95 延迟就永远不准。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











