61 lines
2.7 KiB
Python
61 lines
2.7 KiB
Python
|
|
from django.db import transaction
|
||
|
|
|
||
|
|
from apps.account.models import User
|
||
|
|
from apps.telemetry.models import AppSession, ClickEvent, ClientErrorLog, PageView
|
||
|
|
|
||
|
|
|
||
|
|
class TelemetryIngestService:
|
||
|
|
@staticmethod
|
||
|
|
@transaction.atomic
|
||
|
|
def ingest(user: User, ip_address: str | None, data: dict) -> None:
|
||
|
|
session, _created = AppSession.objects.get_or_create(
|
||
|
|
id=data["session_id"],
|
||
|
|
defaults={
|
||
|
|
"user": user,
|
||
|
|
"platform": data.get("platform", ""),
|
||
|
|
"app_version": data.get("app_version", ""),
|
||
|
|
"ip_address": ip_address,
|
||
|
|
"started_at": data["events"][0]["at"],
|
||
|
|
},
|
||
|
|
)
|
||
|
|
# اگر آیپی از قبل ثبت نشده یا عوض شده، آخرین مقدار را نگه میداریم —
|
||
|
|
# همان چیزی که «لیست آیپیهایی که کاربر باهاش اومده» را میسازد (از
|
||
|
|
# طریق تجمیعِ همهی session های همان کاربر، نه فقط این یکی).
|
||
|
|
if ip_address and session.ip_address != ip_address:
|
||
|
|
session.ip_address = ip_address
|
||
|
|
session.save(update_fields=["ip_address"])
|
||
|
|
|
||
|
|
for event in data["events"]:
|
||
|
|
event_type = event["type"]
|
||
|
|
if event_type == "session_start":
|
||
|
|
if session.started_at != event["at"]:
|
||
|
|
session.started_at = min(session.started_at, event["at"])
|
||
|
|
session.save(update_fields=["started_at"])
|
||
|
|
elif event_type == "session_end":
|
||
|
|
session.ended_at = event["at"]
|
||
|
|
session.save(update_fields=["ended_at"])
|
||
|
|
elif event_type == "page_view":
|
||
|
|
PageView.objects.create(
|
||
|
|
session=session,
|
||
|
|
screen_name=event.get("screen", ""),
|
||
|
|
entered_at=event["at"],
|
||
|
|
duration_seconds=event.get("duration_seconds"),
|
||
|
|
)
|
||
|
|
elif event_type == "click":
|
||
|
|
ClickEvent.objects.create(
|
||
|
|
session=session,
|
||
|
|
screen_name=event.get("screen", ""),
|
||
|
|
element=event.get("element", ""),
|
||
|
|
x=event.get("x"),
|
||
|
|
y=event.get("y"),
|
||
|
|
created_at=event["at"],
|
||
|
|
)
|
||
|
|
elif event_type == "error":
|
||
|
|
ClientErrorLog.objects.create(
|
||
|
|
session=session,
|
||
|
|
screen_name=event.get("screen", ""),
|
||
|
|
message=event.get("message", ""),
|
||
|
|
stack_trace=event.get("stack", ""),
|
||
|
|
created_at=event["at"],
|
||
|
|
)
|