155 lines
4.8 KiB
Python
155 lines
4.8 KiB
Python
import uuid
|
|
|
|
from django.apps import apps
|
|
from django.contrib.auth.models import AbstractUser
|
|
from django.db import models
|
|
from django.db.utils import NotSupportedError
|
|
from django.utils import timezone
|
|
|
|
|
|
def _default_uuid():
|
|
return str(uuid.uuid4())
|
|
|
|
|
|
class User(AbstractUser):
|
|
username = models.TextField(default=_default_uuid, unique=True)
|
|
email = models.EmailField(unique=True)
|
|
|
|
def __str__(self):
|
|
return self.email
|
|
|
|
|
|
class Service(models.Model):
|
|
ACTIVE = "AC"
|
|
ARCHIVED = "AR"
|
|
SERVICE_STATUSES = [(ACTIVE, "Active"), (ARCHIVED, "Archived")]
|
|
|
|
uuid = models.UUIDField(default=_default_uuid, primary_key=True)
|
|
name = models.TextField(max_length=64)
|
|
owner = models.ForeignKey(
|
|
User, on_delete=models.CASCADE, related_name="owning_services"
|
|
)
|
|
collaborators = models.ManyToManyField(
|
|
User, related_name="collaborating_services", blank=True
|
|
)
|
|
created = models.DateTimeField(auto_now_add=True)
|
|
link = models.URLField(blank=True)
|
|
origins = models.TextField(default="*")
|
|
status = models.CharField(
|
|
max_length=2, choices=SERVICE_STATUSES, default=ACTIVE, db_index=True
|
|
)
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
def get_daily_stats(self):
|
|
return self.get_core_stats(
|
|
start_time=timezone.now() - timezone.timedelta(days=1)
|
|
)
|
|
|
|
def get_core_stats(self, start_time=None, end_time=None):
|
|
if start_time is None:
|
|
start_time = timezone.now() - timezone.timedelta(days=30)
|
|
if end_time is None:
|
|
end_time = timezone.now()
|
|
|
|
Session = apps.get_model("analytics", "Session")
|
|
Hit = apps.get_model("analytics", "Hit")
|
|
|
|
currently_online = Session.objects.filter(
|
|
service=self, start_time__gt=timezone.now() - timezone.timedelta(seconds=10)
|
|
).count()
|
|
|
|
sessions = (
|
|
Session.objects.filter(
|
|
service=self, start_time__gt=start_time, start_time__lt=end_time
|
|
)
|
|
.order_by("-start_time")
|
|
)
|
|
session_count = sessions.count()
|
|
|
|
hits = Hit.objects.filter(
|
|
session__service=self, start_time__lt=end_time, start_time__gt=start_time
|
|
)
|
|
hit_count = hits.count()
|
|
|
|
bounces = sessions.annotate(hit_count=models.Count("hit")).filter(hit_count=1)
|
|
bounce_count = bounces.count()
|
|
|
|
locations = (
|
|
hits.values("location")
|
|
.annotate(count=models.Count("location"))
|
|
.order_by("-count")
|
|
)
|
|
|
|
referrers = (
|
|
hits.filter(initial=True)
|
|
.values("referrer")
|
|
.annotate(count=models.Count("referrer"))
|
|
.order_by("-count")
|
|
)
|
|
|
|
operating_systems = (
|
|
sessions.values("os").annotate(count=models.Count("os")).order_by("-count")
|
|
)
|
|
|
|
browsers = (
|
|
sessions.values("browser")
|
|
.annotate(count=models.Count("browser"))
|
|
.order_by("-count")
|
|
)
|
|
|
|
device_types = (
|
|
sessions.values("device_type")
|
|
.annotate(count=models.Count("device_type"))
|
|
.order_by("-count")
|
|
)
|
|
|
|
devices = (
|
|
sessions.values("device")
|
|
.annotate(count=models.Count("device"))
|
|
.order_by("-count")
|
|
)
|
|
|
|
device_types = (
|
|
sessions.values("device_type")
|
|
.annotate(count=models.Count("device_type"))
|
|
.order_by("-count")
|
|
)
|
|
|
|
avg_load_time = hits.aggregate(load_time__avg=models.Avg("load_time"))[
|
|
"load_time__avg"
|
|
]
|
|
|
|
avg_hits_per_session = hit_count / max(session_count, 1)
|
|
|
|
try:
|
|
avg_session_duration = sessions.annotate(
|
|
duration=models.F("last_seen") - models.F("start_time")
|
|
).aggregate(duration=models.Avg("duration"))["duration"]
|
|
except NotSupportedError:
|
|
avg_session_duration = sum(
|
|
[
|
|
(session.last_seen - session.start_time).total_seconds()
|
|
for session in sessions
|
|
]
|
|
) / max(session_count, 1)
|
|
|
|
return {
|
|
"currently_online": currently_online,
|
|
"session_count": session_count,
|
|
"hit_count": hit_count,
|
|
"avg_hits_per_session": hit_count / (max(session_count, 1)),
|
|
"bounce_rate_pct": bounce_count * 100 / (max(session_count, 1)),
|
|
"avg_session_duration": avg_session_duration,
|
|
"avg_load_time": avg_load_time,
|
|
"avg_hits_per_session": avg_hits_per_session,
|
|
"locations": locations,
|
|
"referrers": referrers,
|
|
"operating_systems": operating_systems,
|
|
"browsers": browsers,
|
|
"devices": devices,
|
|
"device_types": device_types,
|
|
"online": True,
|
|
}
|