feat: emit usage_concurrent_call_limit_reached PostHog event

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Abhishek Kumar 2026-07-09 17:39:21 +05:30
parent 6f977cf6d9
commit 6a48207999
5 changed files with 63 additions and 2 deletions

View file

@ -14,6 +14,7 @@ from api.services.auth.stack_auth import stackauth
from api.services.configuration.registry import ServiceProviders
from api.services.mps_billing import ensure_hosted_mps_billing_account_v2
from api.services.posthog_client import (
POSTHOG_ORGANIZATION_GROUP_TYPE,
capture_event,
group_identify,
set_person_properties,
@ -33,7 +34,6 @@ async def require_local_auth() -> None:
raise HTTPException(status_code=404, detail="Not found")
POSTHOG_ORGANIZATION_GROUP_TYPE = "organization"
POSTHOG_ORGANIZATION_USES_MPS_BILLING_V2_PROPERTY = "uses_mps_billing_v2"

View file

@ -6,8 +6,13 @@ from loguru import logger
from api.constants import DEFAULT_ORG_CONCURRENCY_LIMIT
from api.db import db_client
from api.enums import OrganizationConfigurationKey
from api.enums import OrganizationConfigurationKey, PostHogEvent
from api.services.campaign.rate_limiter import rate_limiter
from api.services.posthog_client import (
POSTHOG_ORGANIZATION_GROUP_TYPE,
POSTHOG_SERVER_EVENT_DISTINCT_ID,
capture_event,
)
@dataclass(frozen=True)
@ -128,6 +133,22 @@ class CallConcurrencyService:
f"source={source}, active_calls={current_count}/{max_concurrent}"
f"{scope_note}, waited={wait_time:.1f}s"
)
properties = {
"organization_id": organization_id,
"source": source,
"max_concurrent": max_concurrent,
"active_calls": current_count,
"waited_seconds": round(wait_time, 1),
}
if scope_key:
properties["scope_key"] = scope_key
properties["scope_max_concurrent"] = scope_max_concurrent
capture_event(
distinct_id=POSTHOG_SERVER_EVENT_DISTINCT_ID,
event=PostHogEvent.USAGE_CONCURRENT_CALL_LIMIT_REACHED,
properties=properties,
groups={POSTHOG_ORGANIZATION_GROUP_TYPE: str(organization_id)},
)
raise CallConcurrencyLimitError(
organization_id=organization_id,
source=source,

View file

@ -7,6 +7,12 @@ from api.constants import POSTHOG_API_KEY, POSTHOG_HOST
_posthog_client: Posthog | None = None
POSTHOG_SERVER_GROUP_IDENTIFY_DISTINCT_ID = "server-group-identify"
POSTHOG_ORGANIZATION_GROUP_TYPE = "organization"
# Stable distinct_id for server-originated events with no acting user.
# Group-linked events must stay identified (setting $process_person_profile
# to False would unlink them from the organization group), so a single shared
# "server" person absorbs them instead of minting one person per org.
POSTHOG_SERVER_EVENT_DISTINCT_ID = "server"
def get_posthog() -> Posthog | None: