Files
openswarm/backend/apps/analytics/collector.py
T

124 lines
3.2 KiB
Python

"""PostHog-only analytics collector.
All events go directly to PostHog. No local SQLite storage.
Usage from any module:
from backend.apps.analytics.collector import record
record("session.started", {"model": "opus"}, session_id="abc123")
"""
import logging
import platform
from uuid import uuid4
from posthog import Posthog
logger = logging.getLogger(__name__)
POSTHOG_API_KEY = "phc_KdVLvAdjCuHeacFoDm1CM1Gb23XikewRqlX67Mj6TNB"
POSTHOG_HOST = "https://us.i.posthog.com"
_posthog: Posthog | None = None
_installation_id: str | None = None
def init():
"""Initialise PostHog. Called once at app startup."""
global _posthog
if _posthog is None:
_posthog = Posthog(
project_api_key=POSTHOG_API_KEY,
host=POSTHOG_HOST,
)
return _posthog
def shutdown():
"""Flush and close. Called at app shutdown."""
global _posthog
if _posthog:
try:
_posthog.shutdown()
except Exception:
pass
_posthog = None
def _get_installation_id() -> str:
"""Get or create a stable anonymous installation ID."""
global _installation_id
if _installation_id:
return _installation_id
try:
from backend.apps.settings.settings import load_settings, _save_settings
settings = load_settings()
iid = getattr(settings, "installation_id", None)
if not iid:
iid = uuid4().hex
settings.installation_id = iid
_save_settings(settings)
_installation_id = iid
except Exception:
_installation_id = uuid4().hex
return _installation_id
def _is_opted_in() -> bool:
"""Check if user has opted in to analytics."""
try:
from backend.apps.settings.settings import load_settings
return getattr(load_settings(), "analytics_opt_in", True)
except Exception:
return True
def record(
event_type: str,
properties: dict | None = None,
session_id: str | None = None,
dashboard_id: str | None = None,
):
"""Record an analytics event to PostHog."""
if not _posthog:
return
props = {**(properties or {})}
if session_id:
props["session_id"] = session_id
if dashboard_id:
props["dashboard_id"] = dashboard_id
props["os"] = platform.system()
props["platform"] = platform.platform()
try:
_posthog.capture(
event_type,
distinct_id=_get_installation_id(),
properties=props,
)
except Exception as e:
logger.debug(f"PostHog capture failed (non-critical): {e}")
def identify(extra_properties: dict | None = None):
"""Identify the current installation with properties."""
if not _posthog:
return
try:
_posthog.identify(
_get_installation_id(),
properties={
"os": platform.system(),
"platform": platform.platform(),
**(extra_properties or {}),
},
)
except Exception as e:
logger.debug(f"PostHog identify failed (non-critical): {e}")
def get_collector():
"""Backward compat — returns None since we no longer have a local collector."""
return None