Skip to content

Instantly share code, notes, and snippets.

@mosi-kha
Last active October 14, 2024 17:43
Show Gist options
  • Save mosi-kha/c40275ae77017d3f7c7624ba92809b15 to your computer and use it in GitHub Desktop.
Save mosi-kha/c40275ae77017d3f7c7624ba92809b15 to your computer and use it in GitHub Desktop.
prometheus exporter for Django Q
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