Skip to content

Commit 288bbf5

Browse files
committed
export RQ status as prometheus metrics
fixes: #503
1 parent 87dd8cf commit 288bbf5

File tree

4 files changed

+73
-1
lines changed

4 files changed

+73
-1
lines changed

django_rq/apps.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,48 @@
11
from django.apps import AppConfig
22

3+
from .queues import filter_connection_params, get_connection, get_queue_class, get_unique_connection_configs
4+
from .workers import get_worker_class
5+
6+
import logging
7+
8+
log = logging.getLogger(__name__)
9+
10+
try:
11+
import prometheus_client
12+
13+
from rq_exporter.collector import RQCollector
14+
except ImportError:
15+
RQCollector = None
16+
317

418
class DjangoRqAdminConfig(AppConfig):
519
default_auto_field = "django.db.models.AutoField"
620
name = "django_rq"
21+
22+
def ready(self):
23+
if RQCollector is None:
24+
return
25+
26+
from .settings import QUEUES
27+
28+
worker_class = get_worker_class()
29+
collector_args = {}
30+
collector_counts = {}
31+
unique_configs = get_unique_connection_configs()
32+
for name, config in QUEUES.items():
33+
index = unique_configs.index(filter_connection_params(config))
34+
queue_class = get_queue_class(config)
35+
key = index, queue_class
36+
if key not in collector_args:
37+
collector_args[key] = [name, worker_class, queue_class]
38+
collector_counts[key] = 1
39+
else:
40+
collector_counts[key] += 1
41+
42+
if len(collector_args) > 1:
43+
log.warning('RQCollector can only log metrics for one unique connection and queue class')
44+
45+
if collector_args:
46+
key = sorted(collector_counts.items(), key=lambda x: x[1], reverse=True)[0]
47+
name, worker_class, queue_class = collector_args[key]
48+
prometheus_client.REGISTRY.register(RQCollector(get_connection(name), worker_class, queue_class))

django_rq/urls.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,19 @@
22

33
from . import views
44

5+
try:
6+
import rq_exporter
7+
8+
metrics_view = [
9+
re_path(r'^metrics/?$', views.prometheus_metrics, name='rq_metrics'),
10+
]
11+
except ImportError:
12+
metrics_view = []
13+
514
urlpatterns = [
615
re_path(r'^$', views.stats, name='rq_home'),
716
re_path(r'^stats.json/(?P<token>[\w]+)?/?$', views.stats_json, name='rq_home_json'),
17+
*metrics_view,
818
re_path(r'^queues/(?P<queue_index>[\d]+)/$', views.jobs, name='rq_jobs'),
919
re_path(r'^workers/(?P<queue_index>[\d]+)/$', views.workers, name='rq_workers'),
1020
re_path(r'^workers/(?P<queue_index>[\d]+)/(?P<key>[-\w\.\:\$]+)/$', views.worker_details, name='rq_worker_details'),

django_rq/views.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from django.contrib import admin, messages
66
from django.contrib.admin.views.decorators import staff_member_required
7-
from django.http import Http404, JsonResponse
7+
from django.http import Http404, HttpResponse, JsonResponse
88
from django.shortcuts import redirect, render
99
from django.urls import reverse
1010
from django.views.decorators.cache import never_cache
@@ -27,6 +27,11 @@
2727
from .settings import API_TOKEN, QUEUES_MAP
2828
from .utils import get_jobs, get_scheduler_statistics, get_statistics, stop_jobs
2929

30+
try:
31+
import prometheus_client
32+
except ImportError:
33+
prometheus_client = None
34+
3035

3136
@never_cache
3237
@staff_member_required
@@ -48,6 +53,20 @@ def stats_json(request, token=None):
4853
)
4954

5055

56+
@never_cache
57+
@staff_member_required
58+
def prometheus_metrics(request):
59+
if not prometheus_client:
60+
raise Http404
61+
62+
registry = prometheus_client.REGISTRY
63+
encoder, content_type = prometheus_client.exposition.choose_encoder(request.META.get('HTTP_ACCEPT', ''))
64+
if 'name[]' in request.GET:
65+
registry = registry.restricted_registry(request.GET.getlist('name[]'))
66+
67+
return HttpResponse(encoder(registry), headers={'Content-Type': content_type})
68+
69+
5170
@never_cache
5271
@staff_member_required
5372
def jobs(request, queue_index):

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package_data={'': ['README.rst']},
1717
install_requires=['django>=3.2', 'rq>=1.14', 'redis>=3'],
1818
extras_require={
19+
'prometheus-metrics': ['prometheus_client>=0.4.0', 'rq-exporter'],
1920
'Sentry': ['sentry-sdk>=1.0.0'],
2021
'testing': [],
2122
},

0 commit comments

Comments
 (0)