feat: custom telemetry configuration

This commit is contained in:
Abhishek Kumar 2026-03-23 11:36:39 +05:30
parent 1967a71935
commit affb39e57f
23 changed files with 927 additions and 139 deletions

View file

@ -365,13 +365,22 @@ class CampaignClient(BaseDBClient):
result = await session.execute(query)
return list(result.scalars().all())
async def get_completed_runs_for_report(
self, campaign_id: int
) -> list[WorkflowRunModel]:
"""Get completed workflow runs with call duration for campaign report CSV."""
async def get_completed_runs_for_report(self, campaign_id: int) -> list:
"""Get completed workflow runs for campaign report CSV.
Returns rows with only the columns needed for report generation.
"""
async with self.async_session() as session:
query = (
select(WorkflowRunModel)
select(
WorkflowRunModel.id,
WorkflowRunModel.created_at,
WorkflowRunModel.initial_context,
WorkflowRunModel.gathered_context,
WorkflowRunModel.cost_info,
WorkflowRunModel.logs,
WorkflowRunModel.public_access_token,
)
.where(
WorkflowRunModel.campaign_id == campaign_id,
WorkflowRunModel.is_completed.is_(True),
@ -379,14 +388,10 @@ class CampaignClient(BaseDBClient):
.as_string()
.isnot(None),
)
.order_by(
WorkflowRunModel.cost_info["call_duration_seconds"]
.as_float()
.desc()
)
.order_by(WorkflowRunModel.created_at.desc())
)
result = await session.execute(query)
return list(result.scalars().all())
return list(result.all())
async def create_queued_run(
self,

View file

@ -95,6 +95,26 @@ class OrganizationConfigurationClient(BaseDBClient):
config = await self.get_configuration(organization_id, key)
return config.value if config else default
async def get_all_configurations_by_key(self, key: str) -> list[dict[str, Any]]:
"""Get all organization configurations for a given key.
Returns a list of dicts with organization_id and the config value.
"""
async with self.async_session() as session:
result = await session.execute(
select(OrganizationConfigurationModel).where(
OrganizationConfigurationModel.key == key,
)
)
return [
{
"organization_id": config.organization_id,
"value": config.value,
}
for config in result.scalars().all()
if config.value
]
async def get_configurations_by_provider(
self, key: str, provider: str
) -> List[Dict[str, Any]]:

View file

@ -2,6 +2,7 @@ import hashlib
import json
from typing import Optional
from loguru import logger
from sqlalchemy import func, update
from sqlalchemy.future import select
from sqlalchemy.orm import load_only, selectinload
@ -174,6 +175,16 @@ class WorkflowClient(BaseDBClient):
return counts
async def get_workflow_organization_id(self, workflow_id: int) -> int | None:
"""Fetch only the organization_id for a workflow. Lightweight query."""
async with self.async_session() as session:
result = await session.execute(
select(WorkflowModel.organization_id).where(
WorkflowModel.id == workflow_id
)
)
return result.scalar_one_or_none()
async def get_workflow(
self, workflow_id: int, user_id: int = None, organization_id: int = None
) -> WorkflowModel | None:
@ -434,3 +445,38 @@ class WorkflowClient(BaseDBClient):
counts[workflow_id] = run_count
return counts
async def add_call_disposition_code(
self, workflow_id: int, disposition_code: str
) -> None:
"""Add a disposition code to the workflow's call_disposition_codes if not already present.
The codes are stored as {"disposition_codes": ["code1", "code2", ...]}.
"""
if not disposition_code:
return
async with self.async_session() as session:
result = await session.execute(
select(WorkflowModel).where(WorkflowModel.id == workflow_id)
)
workflow = result.scalars().first()
if not workflow:
return
existing = workflow.call_disposition_codes or {}
codes = existing.get("disposition_codes", [])
if disposition_code in codes:
return
codes.append(disposition_code)
workflow.call_disposition_codes = {"disposition_codes": codes}
try:
await session.commit()
except Exception as e:
await session.rollback()
logger.error(
f"Failed to add disposition code '{disposition_code}' "
f"to workflow {workflow_id}: {e}"
)