From 565592a80abf5b96f88067ea7d7ba95572f58ae9 Mon Sep 17 00:00:00 2001 From: Alessandro Benoit Date: Tue, 3 Nov 2026 12:40:37 +0100 Subject: [PATCH] fix(alerting): populate key and team alias in hanging request alerts The proxy registers a request for the hanging check in pre_call_hook, before litellm_params exists, so get_litellm_metadata_from_kwargs always returned {} and every llm_requests_hanging alert showed empty Key Alias and Team Alias. Fall back to the top-level litellm_metadata / metadata that add_litellm_data_to_request has already populated. Co-Authored-By: Claude Opus 5.5 --- .../SlackAlerting/hanging_request_check.py | 11 +++++-- .../test_hanging_request_check.py | 30 +++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/litellm/integrations/SlackAlerting/hanging_request_check.py b/litellm/integrations/SlackAlerting/hanging_request_check.py index 87baee91780..7acaa32a1c6 100644 --- a/litellm/integrations/SlackAlerting/hanging_request_check.py +++ b/litellm/integrations/SlackAlerting/hanging_request_check.py @@ -52,7 +52,7 @@ class AlertingHangingRequestCheck: async def add_request_to_hanging_request_check( self, - request_data: dict | None = None, + request_data: dict[str, Any] | None = None, ): """ Add a request to the hanging request cache. This is the list of request_ids that gets periodicall checked for hanging requests @@ -60,7 +60,14 @@ class AlertingHangingRequestCheck: if request_data is None: return - request_metadata: Final = get_litellm_metadata_from_kwargs(kwargs=request_data) + # The proxy registers the request before the call, so the key metadata is + # still at the top level of the request body, not under `litellm_params`. + request_metadata: Final = ( + get_litellm_metadata_from_kwargs(kwargs=request_data) + or request_data.get("litellm_metadata") + or request_data.get("metadata") + or {} + ) model: Final = request_data.get("model", "") api_base: str | None = None diff --git a/tests/unit/integrations/SlackAlerting/test_hanging_request_check.py b/tests/unit/integrations/SlackAlerting/test_hanging_request_check.py index 4b579dfe82f..aff84c15107 100644 --- a/tests/unit/integrations/SlackAlerting/test_hanging_request_check.py +++ b/tests/unit/integrations/SlackAlerting/test_hanging_request_check.py @@ -78,6 +78,36 @@ class TestAlertingHangingRequestCheck: assert cached_data.request_id == "test_request_123" assert cached_data.model == "gpt-4" assert cached_data.api_base == "https://api.openai.com/v1" + assert cached_data.key_alias == "test_key" + assert cached_data.team_alias == "test_team" + + @pytest.mark.asyncio + async def test_add_request_to_hanging_request_check_reads_litellm_metadata( + self, hanging_request_checker + ): + """ + Routes that store proxy metadata under `litellm_metadata` (e.g. /v1/messages) + must still populate the key and team alias of the alert. + """ + request_data = { + "litellm_call_id": "litellm_metadata_request", + "model": "claude-sonnet", + "litellm_metadata": { + "user_api_key_alias": "test_key", + "user_api_key_team_alias": "test_team", + }, + } + + await hanging_request_checker.add_request_to_hanging_request_check(request_data) + + cached_data = ( + await hanging_request_checker.hanging_request_cache.async_get_cache( + key="litellm_metadata_request" + ) + ) + + assert cached_data.key_alias == "test_key" + assert cached_data.team_alias == "test_team" @pytest.mark.asyncio async def test_add_request_to_hanging_request_check_none_request_data(