Skip to content

Commit

Permalink
Alternate approach
Browse files Browse the repository at this point in the history
  • Loading branch information
bmispelon committed Dec 10, 2024
1 parent f69cc41 commit 14e2b13
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 19 deletions.
22 changes: 20 additions & 2 deletions dashboard/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import ast
import calendar
import datetime
import operator
from functools import reduce

import requests
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
Expand Down Expand Up @@ -105,7 +107,6 @@ def _gather_data_periodic(self, since, period):
scale but works for now.
"""
OFFSET = "2 hours" # HACK!
ctid = ContentType.objects.get_for_model(self).id

c = connections["default"].cursor()
c.execute(
Expand All @@ -117,10 +118,14 @@ def _gather_data_periodic(self, since, period):
AND object_id = %s
AND timestamp >= %s
GROUP BY 1;""",
[period, OFFSET, ctid, self.id, since],
[period, OFFSET, self.content_type.id, self.id, since],
)
return [(calendar.timegm(t.timetuple()), float(m)) for (t, m) in c.fetchall()]

@property
def content_type(self):
return ContentType.objects.get_for_model(self)


class TracTicketMetric(Metric):
query = models.TextField()
Expand Down Expand Up @@ -249,6 +254,17 @@ def link(self):
return self.urljoin(self.jenkins_root_url, "job", self.build_name)


class DatumQuerySet(models.QuerySet):
def metrics(self, *metrics):
"""
Return only the data from the given metrics.
"""
if not metrics:
return self.none()
qobjs = [models.Q(content_type=m.content_type, object_id=m.pk) for m in metrics]
return self.filter(reduce(operator.or_, qobjs))


class Datum(models.Model):
metric = GenericForeignKey()
content_type = models.ForeignKey(
Expand All @@ -258,6 +274,8 @@ class Datum(models.Model):
timestamp = models.DateTimeField(default=datetime.datetime.now)
measurement = models.BigIntegerField()

objects = DatumQuerySet.as_manager()

class Meta:
ordering = ["-timestamp"]
get_latest_by = "timestamp"
Expand Down
30 changes: 13 additions & 17 deletions dashboard/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import datetime
import operator

from django.contrib.contenttypes.models import ContentType
from django.core.cache import cache
from django.forms.models import model_to_dict
from django.http.response import Http404, JsonResponse
Expand All @@ -22,25 +22,21 @@ def index(request):
metrics.extend(
MC.objects.filter(show_on_dashboard=True).select_related("category")
)

content_types = ContentType.objects.get_for_models(*metrics)
datum_queryset = Datum.objects.none()
for metric, content_type in content_types.items():
datum_queryset = datum_queryset.union(
Datum.objects.filter(
content_type_id=content_type.id, object_id=metric.id
).order_by("-timestamp")[0:1]
)

latest_datums = {
(datum.object_id, datum.content_type_id): datum for datum in datum_queryset
metrics = sorted(metrics, key=operator.attrgetter("display_position"))

metric_latest_querysets = [
Datum.objects.metrics(metric).order_by("-timestamp")[0:1]
for metric in metrics
]
data_latest = Datum.objects.none().union(*metric_latest_querysets)
latest_by_metric = {
(datum.content_type_id, datum.object_id): datum for datum in data_latest
}

data = []
for metric, content_type in content_types.items():
if latest := latest_datums.get((metric.id, content_type.id)):
data.append({"metric": metric, "latest": latest})
data = sorted(data, key=lambda elem: elem["metric"].display_position)
for metric in metrics:
latest = latest_by_metric.get((metric.content_type.pk, metric.pk))
data.append({"metric": metric, "latest": latest})
cache.set(key, data, 60 * 60, version=generation)

return render(request, "dashboard/index.html", {"data": data})
Expand Down

0 comments on commit 14e2b13

Please sign in to comment.