diff --git a/litellm/integrations/otel/model/spans.py b/litellm/integrations/otel/model/spans.py index c50d985b29e..8828fab6aa5 100644 --- a/litellm/integrations/otel/model/spans.py +++ b/litellm/integrations/otel/model/spans.py @@ -261,6 +261,7 @@ _PRISMA_VIEWS: Final[frozenset[str]] = frozenset( _PRISMA_MODELS: Final[frozenset[str]] = frozenset( ( "LiteLLM_Alert", + "LiteLLM_PerformanceAlertState", "LiteLLM_BudgetTable", "LiteLLM_CredentialsTable", "LiteLLM_ProxyModelTable", diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 4651b5f9f94..b4a4ded6be5 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -11877,7 +11877,25 @@ class ProxyStartupEvent: read_general_settings=_current_general_settings, ) - cls._initialize_performance_alerts_job(scheduler=scheduler, prisma_client=prisma_client) + from litellm.proxy.spend_tracking.performance_alerts import RUN_INTERVAL, run_performance_alerts + from litellm.repositories.performance_alert_repository import PerformanceAlertRepository + + performance_alert_repository: Final = PerformanceAlertRepository(prisma_client) + + async def run_performance_alerts_job() -> None: + if _current_general_settings().get("performance_alerts_enabled") is True: + await run_performance_alerts(performance_alert_repository) + + scheduler.add_job( # pyright: ignore[reportUnknownMemberType] # APScheduler does not provide typed job methods + run_performance_alerts_job, + "interval", + seconds=RUN_INTERVAL.total_seconds(), + id="performance_alerts", + replace_existing=True, + max_instances=1, + coalesce=True, + misfire_grace_time=APSCHEDULER_MISFIRE_GRACE_TIME, + ) ### PTU DAILY ROLLUP ### from litellm.proxy.spend_tracking.ptu_feature_flag import ( @@ -12255,28 +12273,6 @@ class ProxyStartupEvent: "LITELLM_EXPIRED_UI_SESSION_KEY_CLEANUP_ENABLED=true to enable)" ) - @classmethod - def _initialize_performance_alerts_job(cls, scheduler: AsyncIOScheduler, prisma_client: PrismaClient) -> None: - from litellm.proxy.spend_tracking.performance_alerts import RUN_INTERVAL, run_performance_alerts - from litellm.repositories.performance_alert_repository import PerformanceAlertRepository - - repository: Final = PerformanceAlertRepository(prisma_client) - - async def run() -> None: - if _current_general_settings().get("performance_alerts_enabled") is True: - await run_performance_alerts(repository) - - scheduler.add_job( # pyright: ignore[reportUnknownMemberType] # APScheduler does not provide typed job methods - run, - "interval", - seconds=RUN_INTERVAL.total_seconds(), - id="performance_alerts", - replace_existing=True, - max_instances=1, - coalesce=True, - misfire_grace_time=APSCHEDULER_MISFIRE_GRACE_TIME, - ) - @classmethod def _initialize_spend_capture_rate_check_job( cls, diff --git a/tests/unit/proxy/management_endpoints/test_model_insights_endpoints.py b/tests/unit/proxy/management_endpoints/test_model_insights_endpoints.py index 40b0cbe11c5..ac6714bc5df 100644 --- a/tests/unit/proxy/management_endpoints/test_model_insights_endpoints.py +++ b/tests/unit/proxy/management_endpoints/test_model_insights_endpoints.py @@ -253,6 +253,7 @@ async def test_model_insights_reads_back_what_the_rollup_wrote() -> None: "request_tags": '["task:debugging"]', "custom_llm_provider": "openai", "status": "success", + "request_duration_ms": None, } transactions = ( diff --git a/tests/unit/proxy/test_proxy_server_endpoints_and_startup.py b/tests/unit/proxy/test_proxy_server_endpoints_and_startup.py index 1cfb14e6bf9..bd5b754bda0 100644 --- a/tests/unit/proxy/test_proxy_server_endpoints_and_startup.py +++ b/tests/unit/proxy/test_proxy_server_endpoints_and_startup.py @@ -1656,6 +1656,7 @@ class MockPrisma: self.database_url = database_url self.proxy_logging_obj = proxy_logging_obj self.http_client = http_client + self.writer_db = MagicMock() async def connect(self): pass diff --git a/ui/litellm-dashboard/src/lib/http/schema.d.ts b/ui/litellm-dashboard/src/lib/http/schema.d.ts index e926dbf2511..8349818eb8a 100644 --- a/ui/litellm-dashboard/src/lib/http/schema.d.ts +++ b/ui/litellm-dashboard/src/lib/http/schema.d.ts @@ -31397,6 +31397,12 @@ export interface components { * @description If True (default), a locally-managed user's password must contain an uppercase letter. */ password_policy_require_uppercase?: boolean | null; + /** + * Performance Alerts Enabled + * @description Check yesterday's usage for the gateway, models, teams, users and keys against the week before, and save unusual spend, traffic, response time and failure rate changes as alerts. Off by default. + * @default false + */ + performance_alerts_enabled: boolean; /** * Plugins * @description external services registered as embeddable UI plugins