NetBox 原生 Prometheus 指标(/metrics)接入指南:配置、指标类型与多进程部署
【免费下载链接】netboxThe premier source of truth powering network automation. Open source under Apache 2. Try NetBox Cloud free: https://netboxlabs.com/products/free-netbox-cloud/项目地址: https://gitcode.com/gh_mirrors/ne/netbox
本文围绕 NetBox 自带的 Prometheus 监控指标能力展开:如何通过METRICS_ENABLED配置在/metrics端点暴露应用指标,NetBox 默认采集哪些维度的监控数据,以及以多进程(多 Gunicorn worker)方式部署时如何正确配置共享指标目录。读完本文,你将掌握从配置开启、指标链路梳理到生产环境落地采集的一整套实操方案。
概述:NetBox 为什么内置 Prometheus 指标
Prometheus 是当前主流的时序指标平台,广泛用于应用与基础设施监控。NetBox 作为网络自动化的事实数据源(source of truth),在应用层内置了可选的 Prometheus 指标暴露能力:开启后,应用会在 HTTP 端点/metrics(例如https://netbox.local/metrics)以 Prometheus 文本格式输出指标,供 Prometheus Server 定时抓取。
该能力的开关由配置项METRICS_ENABLED控制,默认关闭——指标不会未经配置就对外暴露。这一设计兼顾了"开箱即用"与"按需开启"两种诉求。
NetBox 的指标体系基于 Python 生态中成熟的 django-prometheus):
django-prometheus>=2.4.0,<2.5.0,!=2.4.1django-prometheus 通过 Django 中间件、数据库后端替换等手段,把模型操作、视图请求、数据库、缓存等维度的埋点自动挂接到请求处理链路中,NetBox 在此基础上又扩展了 REST API 与 GraphQL 的自定义计数器。
第一步:用 METRICS_ENABLED 开启指标暴露
配置方式很简单:在 NetBox 的配置文件configuration.py中将METRICS_ENABLED设为True。仓库自带的配置示例(netbox/netbox/configuration_example.py)中明确注释了这一用途:
# Expose Prometheus monitoring metrics at the HTTP endpoint '/metrics' METRICS_ENABLED = False对应的默认值定义在 settings.py:
METRICS_ENABLED = getattr(configuration, 'METRICS_ENABLED', False)即:若configuration.py中未定义该参数,则默认False(不暴露)。设置为True并重启 WSGI 服务后,访问https://<netbox域名>/metrics即可看到指标输出。
值得说明的是,METRICS_ENABLED并非只在 URL 层面生效,它同时驱动了多项底层行为(详见下文"源码视角"小节),因此开启它相当于一次性接通整套监控埋点链路,而不是简单地挂载一个视图。
指标类型总览
得益于 django-prometheus 的自动埋点,开启后 NetBox 会暴露以下几类指标(信息继承自 docs/integrations/prometheus-metrics.md):
| 指标类别 | 说明 |
|---|---|
| 模型操作计数器 | 每个模型(Model)的 insert / update / delete 操作计数 |
| 视图请求计数器 | 每个视图(View)的请求次数计数 |
| 视图请求延迟直方图 | 每个视图的请求耗时分布(histogram) |
| REST API 请求指标 | 按端点与请求方法(method)统计的请求计数 |
| GraphQL API 请求指标 | GraphQL API 请求计数 |
| 请求体大小直方图 | 请求体(request body)字节数分布 |
| 响应体大小直方图 | 响应体(response body)字节数分布 |
| 响应码计数器 | HTTP 响应状态码计数 |
| 数据库指标 | 数据库连接、执行次数与错误计数器 |
| 缓存指标 | 缓存命中(hit)、未命中(miss)与失效(invalidation)计数器 |
| 中间件延迟直方图 | Django 中间件处理耗时分布 |
| Django 元数据指标 | 其他与 Django 运行时相关的元数据指标 |
要获取当前实例完整、权威的指标清单,最直接的办法就是开启后访问本实例的/metrics端点——该端点输出的正是 Prometheus 实际抓取的全部指标名称与当前值,天然与部署版本保持同步,无需依赖任何文档清单。
源码视角:从配置到指标暴露的完整链路
只改一个配置项背后,NetBox 实际做了四件事,阅读源码可以完整还原这条链路:
1. 注册 django_prometheus 应用
当METRICS_ENABLED为真时,django_prometheus始终位于 INSTALLED_APPS 中,为指标采集提供应用级支持。
2. 替换数据库后端以采集数据库指标
settings.py 中会根据开关动态选择数据库引擎:
if 'ENGINE' not in DATABASES['default']: DATABASES['default'].update({ 'ENGINE': 'django_prometheus.db.backends.postgresql' if METRICS_ENABLED else 'django.db.backends.postgresql' })也就是说,开启指标后 PostgreSQL 后端会被替换为 django-prometheus 提供的包装后端,从而在数据库连接、查询执行层面产生计数器与直方图——这就是上文"数据库连接、执行、错误计数器"的来源。
3. 注入前后置 Prometheus 中间件
settings.py 中,开启后会在中间件链的最前端和最末端分别插入两个中间件:
if METRICS_ENABLED: # If metrics are enabled, add the before & after Prometheus middleware MIDDLEWARE = [ 'netbox.middleware.PrometheusBeforeMiddleware', *MIDDLEWARE, 'netbox.middleware.PrometheusAfterMiddleware', ]这两个中间件定义在 middleware.py,分别继承 django-prometheus 的同名基类,并指定自定义的metrics_cls = Metrics:
class PrometheusBeforeMiddleware(middleware.PrometheusBeforeMiddleware): metrics_cls = Metrics class PrometheusAfterMiddleware(middleware.PrometheusAfterMiddleware): metrics_cls = Metrics它们一前一后包住整个请求周期,前者在请求进入时打点(如记录开始时间),后者在响应返回时统计耗时、响应码、响应体大小等,从而生成"按视图的请求计数与延迟直方图"“响应码计数器”等指标。
4. 挂载 /metrics 路由
urls.py 中按开关条件挂载 django-prometheus 自带的路由:
# Prometheus metrics if settings.METRICS_ENABLED: _patterns.append(path('', include('django_prometheus.urls')))这就是/metrics端点的来源。需要注意的是,这些路由最终统一置于BASE_PATH前缀之下(urls.py),如果你的 NetBox 配置了自定义BASE_PATH,实际访问地址会相应变为https://<域名>/<BASE_PATH>/metrics。
深入:NetBox 自定义的 REST API 与 GraphQL 指标
除了 django-prometheus 的通用指标外,NetBox 还通过自定义中间件类扩展了三个 API 相关计数器,定义在 metrics.py 中:
class Metrics(middleware.Metrics): """ Expand the stock Metrics class from django_prometheus to add our own counters. """ def register(self): super().register() # REST API metrics self.rest_api_requests = self.register_metric( Counter, "rest_api_requests_total_by_method", "Count of total REST API requests by method", ["method"], namespace=NAMESPACE, ) self.rest_api_requests_by_view_method = self.register_metric( Counter, "rest_api_requests_total_by_view_method", "Count of REST API requests by view & method", ["view", "method"], namespace=NAMESPACE, ) # GraphQL API metrics self.graphql_api_requests = self.register_metric( Counter, "graphql_api_requests_total", "Count of total GraphQL API requests", namespace=NAMESPACE, )rest_api_requests_total_by_method:按 HTTP 方法(GET/POST/PATCH/DELETE 等)统计的 REST API 请求总数;rest_api_requests_total_by_view_method:按"视图 + 方法"组合统计的 REST API 请求数,可精确到具体 API 端点;graphql_api_requests_total:GraphQL API 请求总数。
这些计数器的触发逻辑位于 middleware.py 的PrometheusAfterMiddleware.process_response:
def process_response(self, request, response): response = super().process_response(request, response) # Increment REST API request counters if is_api_request(request): method = self._method(request) name = self._get_view_name(request) self.label_metric(self.metrics.rest_api_requests, request, method=method).inc() self.label_metric(self.metrics.rest_api_requests_by_view_method, request, method=method, view=name).inc() # Increment GraphQL API request counters elif is_graphql_request(request): self.metrics.graphql_api_requests.inc() return response其中is_api_request与is_graphql_request由 utilities/api.py 提供,用于在中间件层面区分 REST 与 GraphQL 请求(GraphQL 端点/graphql本身也是 Django 视图,仅靠视图名无法与普通页面区分)。这解释了为何文档中"REST API 请求(按端点与方法)"和"GraphQL API 请求"被单列为两类指标——它们是 NetBox 在 django-prometheus 之上专门补充的、面向 API 可观测性的差异化能力。
多进程部署注意事项(Multi Processing Notes)
当 NetBox 以多进程方式部署(例如 Gunicorn 启动多个 worker)时,Prometheus 客户端库要求使用共享目录来汇聚所有 worker 进程的指标文件。配置步骤如下:
- 创建或指定一个本地目录,确保所有 worker 进程对该目录拥有读写权限;
- 在 WSGI 服务(如 Gunicorn)的启动环境中,将该目录路径定义为环境变量
prometheus_multiproc_dir。
以仓库自带的 Gunicorn 配置为例(contrib/gunicorn.py 默认workers = 5、threads = 3),多 worker 场景下需要在启动命令中注入该环境变量,例如:
prometheus_multiproc_dir=/var/run/prometheus_metrics gunicorn --config /opt/netbox/gunicorn.py netbox.wsgi(具体路径可自行指定,只要满足"所有 worker 可读写"这一前提即可。)
重要警告:如果多进程环境下长期指标的准确性对部署至关重要,官方文档建议优先使用uwsgi库而非gunicorn。原因在于二者对 worker 进程的跟踪机制不同——gunicorn 对 worker 进程的跟踪方式,会影响上述配置所生成的指标文件的管理与清理(例如 worker 退出后遗留的指标文件可能导致数据错乱或重复计数),而 uwsgi 的跟踪机制更有利于维护这些文件。针对这一问题的更详细讨论可参考 NetBox 社区 issue #3779。
不过,有一个重要的例外场景:如果你使用容器化方式部署 NetBox,并遵循"每个容器内仅运行单个进程(one-process-per-container)"的实践,那么每个容器只有一个 worker 进程,天然不存在跨进程指标文件冲突问题,通常无需为此切换到 uwsgi。换言之:
- 裸机/虚拟机多 worker 部署且看重长期指标准确性→ 评估使用 uwsgi;
- 容器化、单容器单进程部署→ 保持 gunicorn 即可。
接入 Prometheus:抓取配置与查询示例
开启/metrics后,即可在 Prometheus Server 的抓取配置(prometheus.yml)中加入该目标。以下是一个典型的 scrape job 配置(以官方 NetBox 容器/服务部署为例,域名按实际替换):
scrape_configs: - job_name: 'netbox' scheme: https static_configs: - targets: ['netbox.local'] metrics_path: /metrics抓取到数据后,可在 Prometheus / Grafana 中按指标名称与标签进行查询与告警,例如:
- 查看 NetBox 近 5 分钟 REST API 请求速率:
rate(rest_api_requests_total_by_method[5m]) - 按视图拆分的 API 请求量:
sum by (view, method) (rate(rest_api_requests_total_by_view_method[5m])) - GraphQL 请求总量:
graphql_api_requests_total
注意:实际可用的指标名以你实例
/metrics端点的输出为准——指标清单与 django-prometheus 版本、NetBox 版本强相关,不同版本之间可能存在增删。上述示例中 REST/GraphQL 相关名称来自 metrics.py 的定义,可作为查询起点。
小结
| 要点 | 结论 |
|---|---|
| 开启方式 | configuration.py中设置METRICS_ENABLED = True,默认关闭(configuration_example.py) |
| 暴露端点 | /metrics(受BASE_PATH前缀影响),路由见 urls.py |
| 指标来源 | django-prometheus 自动埋点 + NetBox 自定义 REST/GraphQL 计数器(metrics.py) |
| 开启的副作用 | 自动替换 PostgreSQL 后端、注入前后置中间件(settings.py、settings.py) |
| 多进程部署 | 必须设置prometheus_multiproc_dir共享目录;看重长期指标准确性建议评估 uwsgi |
| 容器化部署 | 单容器单进程时无需特殊处理,gunicorn 即可 |
通过本文的配置步骤与源码级链路梳理,你可以为 NetBox 实例快速建立起完整的 Prometheus 可观测性:从模型操作、页面与 API 请求,到数据库、缓存与中间件性能,全部纳入统一监控体系。
【免费下载链接】netboxThe premier source of truth powering network automation. Open source under Apache 2. Try NetBox Cloud free: https://netboxlabs.com/products/free-netbox-cloud/项目地址: https://gitcode.com/gh_mirrors/ne/netbox
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考