Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled
80 lines
2.2 KiB
Python
80 lines
2.2 KiB
Python
"""
|
|
Telemetry service (4A).
|
|
|
|
Single entry-point for writing canonical product events.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import json
|
|
from typing import Any, Optional
|
|
|
|
from fastapi import Request
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.config import get_settings
|
|
from app.models.telemetry import TelemetryEvent
|
|
|
|
|
|
settings = get_settings()
|
|
|
|
|
|
def _hash_ip(ip: str) -> str:
|
|
return hashlib.sha256(f"{ip}|{settings.secret_key}".encode()).hexdigest()[:32]
|
|
|
|
|
|
def _get_client_ip(request: Request) -> Optional[str]:
|
|
xff = request.headers.get("x-forwarded-for")
|
|
if xff:
|
|
ip = xff.split(",")[0].strip()
|
|
if ip:
|
|
return ip
|
|
cf_ip = request.headers.get("cf-connecting-ip")
|
|
if cf_ip:
|
|
return cf_ip.strip()
|
|
return request.client.host if request.client else None
|
|
|
|
|
|
async def track_event(
|
|
db: AsyncSession,
|
|
*,
|
|
event_name: str,
|
|
request: Optional[Request] = None,
|
|
user_id: Optional[int] = None,
|
|
is_authenticated: Optional[bool] = None,
|
|
source: Optional[str] = None,
|
|
domain: Optional[str] = None,
|
|
listing_id: Optional[int] = None,
|
|
inquiry_id: Optional[int] = None,
|
|
yield_domain_id: Optional[int] = None,
|
|
click_id: Optional[str] = None,
|
|
referrer: Optional[str] = None,
|
|
user_agent: Optional[str] = None,
|
|
metadata: Optional[dict[str, Any]] = None,
|
|
) -> None:
|
|
ip_hash = None
|
|
if request is not None:
|
|
ip = _get_client_ip(request)
|
|
ip_hash = _hash_ip(ip) if ip else None
|
|
user_agent = user_agent or request.headers.get("user-agent")
|
|
referrer = referrer or request.headers.get("referer")
|
|
|
|
row = TelemetryEvent(
|
|
user_id=user_id,
|
|
event_name=event_name,
|
|
listing_id=listing_id,
|
|
inquiry_id=inquiry_id,
|
|
yield_domain_id=yield_domain_id,
|
|
click_id=click_id[:64] if click_id else None,
|
|
domain=domain,
|
|
source=source,
|
|
ip_hash=ip_hash,
|
|
user_agent=user_agent[:500] if user_agent else None,
|
|
referrer=referrer[:500] if referrer else None,
|
|
metadata_json=json.dumps(metadata or {}, ensure_ascii=False) if metadata else None,
|
|
is_authenticated=is_authenticated,
|
|
)
|
|
db.add(row)
|
|
|