pounce/backend/app/services/telemetry.py
Yves Gugger bb7ce97330
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
Deploy: referral rewards antifraud + legal contact updates
2025-12-15 13:56:43 +01:00

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)