Last active
October 14, 2024 17:43
-
-
Save mosi-kha/c40275ae77017d3f7c7624ba92809b15 to your computer and use it in GitHub Desktop.
prometheus exporter for Django Q
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from datetime import timedelta | |
from django.conf import settings | |
from django.http import HttpResponse, HttpResponseNotFound | |
from django.utils import timezone | |
from django_q import models | |
from django_q.monitor import Stat | |
from django_redis import get_redis_connection | |
from prometheus_client import Gauge, generate_latest | |
# Env moved from settings to here | |
ENABLE_EXPORTER = True | |
DJANGO_Q_REDIS_DB_NAME = "1" | |
DJANGO_Q_EXPORTER_INTERVAL = 30 # seconds | |
CONTENT_TYPE_LATEST = str("text/plain; version=0.0.4; charset=utf-8") | |
django_q_state_metric = Gauge( | |
"django_q_state", | |
"State of Django Q Cluster: Starting: 0, Idle: 1, Working: 2, Stopping: 3, Stopped: 4", | |
["env", "cluster_id", "state"], | |
) | |
django_q_uptime_metric = Gauge( | |
"django_q_uptime_seconds", "Django Q Uptime Seconds", ["env", "cluster_id", "state"] | |
) | |
django_q_task_q_size_metric = Gauge( | |
"django_q_task_q_size", "Django Q Task Q Size", ["env", "cluster_id", "state"] | |
) | |
django_q_task_successes_metric = Gauge( | |
"django_q_task_successes", | |
"Successes tasks in Django Q", | |
[ | |
"env", | |
], | |
) | |
django_q_task_successes_relative_time_metric = Gauge( | |
"django_q_task_successes_relative_time_metric", | |
"Successes task in Django Q in relative time", | |
["env", "interval"], | |
) | |
django_q_task_failures_metric = Gauge( | |
"django_q_task_failures", | |
"Failures tasks in Django Q", | |
[ | |
"env", | |
], | |
) | |
django_q_task_failures_relative_time_metric = Gauge( | |
"django_q_task_failures_relative_time_metric", | |
"Failures task in Django Q in relative time", | |
["env", "interval"], | |
) | |
django_q_task_schedule_metric = Gauge( | |
"django_q_task_schedule", | |
"Schedule tasks in Django Q", | |
[ | |
"env", | |
], | |
) | |
django_q_clusters_metric = Gauge( | |
"django_q_clusters", | |
"Number of Clusters in Django Q", | |
[ | |
"env", | |
], | |
) | |
django_q_workers_metric = Gauge( | |
"django_q_workers", | |
"Number of Workers in Django Q", | |
[ | |
"env", | |
], | |
) | |
django_q_task_per_houre_metric = Gauge( | |
"django_q_tasks_per_hour", | |
"Tasks Per last Hour in Django Q", | |
[ | |
"env", | |
], | |
) | |
django_q_task_per_day_metric = Gauge( | |
"django_q_tasks_per_day", | |
"Tasks Per last 24 Hours in Django Q", | |
[ | |
"env", | |
], | |
) | |
django_q_redis_connections_metric = Gauge( | |
"django_q_redis_connections", | |
" Django Q Redis Connections", | |
[ | |
"env", | |
], | |
) | |
django_q_states = {"Starting": 0, "Idle": 1, "Working": 2, "Stopping": 3, "Stopped": 4} | |
def get_django_q_redis_connections(django_q_redis_db_name: str = "1"): | |
redis_connections = 0 | |
redis_con = get_redis_connection("django_q") | |
# filter django_q redis connections | |
for c in redis_con.client_list(): | |
if c["db"] == django_q_redis_db_name: | |
redis_connections += 1 | |
redis_con.close() | |
return redis_connections | |
def get_metrics(*args, **kwargs): | |
if ENABLE_EXPORTER: | |
workers = 0 | |
# cluster(s) metrics | |
for stat in Stat.get_all(): | |
workers += len(stat.workers) | |
django_q_state_metric.labels( | |
f"{settings.ENV}", str(stat.cluster_id), stat.status | |
).set(django_q_states.get(stat.status)) | |
django_q_uptime_metric.labels( | |
f"{settings.ENV}", str(stat.cluster_id), stat.status | |
).set(stat.uptime()) | |
django_q_task_q_size_metric.labels( | |
f"{settings.ENV}", str(stat.cluster_id), stat.status | |
).set(float(stat.task_q_size)) | |
# general metrics | |
django_q_task_successes_metric.labels( | |
f"{settings.ENV}", | |
).set(models.Success.objects.count()) | |
django_q_task_successes_relative_time_metric.labels( | |
f"{settings.ENV}", f"{DJANGO_Q_EXPORTER_INTERVAL}" | |
).set( | |
models.Success.objects.filter( | |
stopped__gte=timezone.now() - timedelta(seconds=30) | |
).count() | |
) | |
django_q_task_failures_metric.labels( | |
f"{settings.ENV}", | |
).set(models.Failure.objects.count()) | |
django_q_task_failures_relative_time_metric.labels( | |
f"{settings.ENV}", f"{DJANGO_Q_EXPORTER_INTERVAL}" | |
).set( | |
models.Failure.objects.filter( | |
stopped__gte=timezone.now() - timedelta(seconds=30) | |
).count() | |
) | |
django_q_task_schedule_metric.labels( | |
f"{settings.ENV}", | |
).set(models.Schedule.objects.count()) | |
django_q_clusters_metric.labels( | |
f"{settings.ENV}", | |
).set(len(Stat.get_all())) | |
django_q_workers_metric.labels( | |
f"{settings.ENV}", | |
).set(workers) | |
django_q_task_per_houre_metric.labels( | |
f"{settings.ENV}", | |
).set( | |
models.Success.objects.filter( | |
stopped__gte=timezone.now() - timedelta(hours=1) | |
).count() | |
) | |
django_q_task_per_day_metric.labels( | |
f"{settings.ENV}", | |
).set( | |
models.Success.objects.filter( | |
stopped__gte=timezone.now() - timedelta(hours=24) | |
).count() | |
) | |
django_q_redis_connections_metric.labels( | |
f"{settings.ENV}", | |
).set( | |
get_django_q_redis_connections( | |
django_q_redis_db_name=DJANGO_Q_REDIS_DB_NAME | |
) | |
) | |
return HttpResponse(generate_latest(), content_type=CONTENT_TYPE_LATEST) | |
else: | |
return HttpResponseNotFound( | |
""" | |
<!doctype html> | |
<html lang="en"> | |
<head> | |
<title>Not Found</title> | |
</head> | |
<body> | |
<h1>Not Found</h1><p>The requested resource was not found on this server.</p> | |
</body> | |
</html> | |
""" | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment