Files
fangke/server/tracker/services/stats.py
T

39 lines
2.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from datetime import datetime, time, timedelta
from django.utils import timezone
from tracker.models import DailyStat, Event, VisitSession, Visitor
def daily_counts(site, date) -> dict:
"""四指标共享口径(site=None 聚合全部站点)。所有指标排除爬虫。
日界取 TIME_ZONE(Asia/Shanghai)自然日:make_aware(datetime.combine(date, time.min))。
口径:pv/uv 均从事件表统计(排除 is_bot):pv 只计 event_name=page_view
(SDK 0.2.0 每 15s 一条的 page_stay 增量与 sdk_loaded 不并计,防 PV 随停留时长灌倍),
uv=distinct visitor(任意事件即计);
sessions 按会话 started_at 落入当日且访客非爬虫;new_visitors 按 Visitor.first_seen_at 落入当日。
refresh_daily 落库与 dashboard 今日实时位共用此函数,防两处口径漂移(Task8 审查结论)。
"""
day_start = timezone.make_aware(datetime.combine(date, time.min))
day_end = day_start + timedelta(days=1)
ev = Event.objects.filter(is_bot=False,
occurred_at__gte=day_start, occurred_at__lt=day_end)
vs = VisitSession.objects.filter(visitor__is_bot=False,
started_at__gte=day_start, started_at__lt=day_end)
vis = Visitor.objects.filter(is_bot=False,
first_seen_at__gte=day_start, first_seen_at__lt=day_end)
if site is not None:
ev = ev.filter(site=site)
vs = vs.filter(site=site)
vis = vis.filter(site=site)
return {"pv": ev.filter(event_name="page_view").count(),
"uv": ev.values("visitor").distinct().count(),
"sessions": vs.count(),
"new_visitors": vis.count()}
def refresh_daily(site, date) -> DailyStat:
"""重算某站点某自然日的聚合(幂等,update_or_create)。指标口径见 daily_counts。"""
obj, _ = DailyStat.objects.update_or_create(site=site, date=date,
defaults=daily_counts(site, date))
return obj