Skip to content

Commit 427a415

Browse files
peterbeYour Name
andauthored
AnalyticsRollupCommentsReferrerDaily (#2802)
Co-authored-by: Your Name <[email protected]>
1 parent 6d64381 commit 427a415

File tree

4 files changed

+105
-4
lines changed

4 files changed

+105
-4
lines changed

peterbecom/api/analytics.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ def query(request):
7272
q,
7373
)
7474

75+
elif table == "analyticsrollupcommentsreferrerdaily":
76+
q = re.sub(
77+
r"\banalyticsrollupcommentsreferrerdaily\b",
78+
"base_analyticsrollupcommentsreferrerdaily",
79+
q,
80+
)
81+
7582
elif table == "requestlog":
7683
q = re.sub(r"\brequestlog\b", "base_requestlog", q)
7784

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Generated by Django 5.2.7 on 2025-10-26 00:47
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('base', '0026_requestlogrollupsbotagentstatuscodedaily'),
10+
]
11+
12+
operations = [
13+
migrations.CreateModel(
14+
name='AnalyticsRollupCommentsReferrerDaily',
15+
fields=[
16+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17+
('day', models.DateTimeField(db_index=True)),
18+
('count', models.IntegerField()),
19+
('referrer', models.URLField()),
20+
('pathname', models.CharField(max_length=300)),
21+
('is_bot', models.BooleanField()),
22+
('created', models.DateTimeField(auto_now_add=True)),
23+
],
24+
options={
25+
'verbose_name': 'Analytics Rollup Comments by Referrer and Pathname daily',
26+
},
27+
),
28+
]

peterbecom/base/models.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,65 @@ def rollup(cls, day=None):
291291
cls.objects.bulk_create(bulk)
292292

293293

294+
class AnalyticsRollupCommentsReferrerDaily(models.Model):
295+
day = models.DateTimeField(db_index=True)
296+
count = models.IntegerField()
297+
referrer = models.URLField()
298+
pathname = models.CharField(max_length=300)
299+
is_bot = models.BooleanField()
300+
created = models.DateTimeField(auto_now_add=True)
301+
302+
class Meta:
303+
verbose_name = "Analytics Rollup Comments by Referrer and Pathname daily"
304+
305+
@classmethod
306+
def rollup(cls, day=None):
307+
if not day:
308+
# Use yesterday
309+
day = timezone.now() - datetime.timedelta(days=1)
310+
311+
start_of_day = day.replace(hour=0, minute=0, second=0, microsecond=0)
312+
end_of_day = start_of_day + datetime.timedelta(days=1)
313+
314+
day = start_of_day
315+
print(f" ROLLUP BY PATHNAME DAY: {day.isoformat()} ".center(80, "-"))
316+
with transaction.atomic():
317+
cls.objects.filter(day=day).delete()
318+
319+
agg_query = (
320+
AnalyticsEvent.objects.filter(
321+
created__gte=start_of_day,
322+
created__lt=end_of_day,
323+
type="pageview",
324+
data__is_comment=True,
325+
# data__referrer__isnull=False,
326+
data__pathname__isnull=False,
327+
data__is_bot__isnull=False,
328+
)
329+
.values("data__referrer", "data__pathname", "data__is_bot")
330+
.annotate(count=Count("id"))
331+
.order_by("-count")
332+
)
333+
bulk = []
334+
for agg in agg_query:
335+
print(
336+
f"{agg['count']:>5} {agg['data__referrer'] or '':<12} {agg['data__pathname']:<12} is_bot={agg['data__is_bot']}"
337+
)
338+
bulk.append(
339+
cls(
340+
day=day,
341+
count=agg["count"],
342+
referrer=agg["data__referrer"] or "",
343+
is_bot=agg["data__is_bot"],
344+
pathname=agg["data__pathname"],
345+
)
346+
)
347+
if len(bulk) > 100:
348+
cls.objects.bulk_create(bulk)
349+
bulk = []
350+
cls.objects.bulk_create(bulk)
351+
352+
294353
class AnalyticsGeoEvent(models.Model):
295354
event = models.OneToOneField(AnalyticsEvent, on_delete=models.CASCADE)
296355
ip_address = models.GenericIPAddressField()

peterbecom/base/tasks.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from peterbecom.base.cdn import purge_cdn_urls
2020
from peterbecom.base.models import (
2121
AnalyticsEvent,
22+
AnalyticsRollupCommentsReferrerDaily,
2223
AnalyticsRollupsDaily,
2324
AnalyticsRollupsPathnameDaily,
2425
CDNPurgeURL,
@@ -221,24 +222,30 @@ def delete_old_analyticsevents():
221222
AnalyticsEvent.objects.filter(created__lt=old).delete()
222223

223224
# The publicapi-pageview ones are much more numerous and less
224-
# useful and use up a lot of space
225+
# useful and use up a lot of spacecd
225226
old = timezone.now() - datetime.timedelta(days=60)
226227
AnalyticsEvent.objects.filter(created__lt=old, type="publicapi-pageview").delete()
227228

228229

229-
@periodic_task(crontab(hour="*/15") if settings.DEBUG else crontab(hour=0, minute=1))
230+
@periodic_task(crontab(minute="*/15") if settings.DEBUG else crontab(hour=0, minute=1))
230231
@log_task_run
231232
def analytics_rollups_daily():
232233
AnalyticsRollupsDaily.rollup()
233234

234235

235-
@periodic_task(crontab(hour="*/15") if settings.DEBUG else crontab(hour=0, minute=0))
236+
@periodic_task(crontab(minute="*/15") if settings.DEBUG else crontab(hour=0, minute=0))
236237
@log_task_run
237238
def analytics_rollups_pathname_daily():
238239
AnalyticsRollupsPathnameDaily.rollup()
239240

240241

241-
@periodic_task(crontab(hour="*/15") if settings.DEBUG else crontab(hour=10))
242+
@periodic_task(crontab(minute="*/15") if settings.DEBUG else crontab(hour="*/12"))
243+
@log_task_run
244+
def analytics_rollup_comments_referrer_pathname_daily():
245+
AnalyticsRollupCommentsReferrerDaily.rollup()
246+
247+
248+
@periodic_task(crontab(minute="*/15") if settings.DEBUG else crontab(hour=10))
242249
@log_task_run
243250
def requestlog_rollups_bot_agent_status_code_daily():
244251
RequestLogRollupsBotAgentStatusCodeDaily.rollup()

0 commit comments

Comments
 (0)