fix(slack-alerting): use top-level metadata for hanging-request alias

At pre-call time litellm_params has not been constructed yet, so
get_litellm_metadata_from_kwargs returns {} and the hanging-request
alert reports empty key_alias/team_alias. Fall back to the top-level
request metadata when the resolved metadata is empty, so the alert
still identifies the responsible key/team. A populated
litellm_params.metadata is always preferred (guard on emptiness).

Fixes #34708
This commit is contained in:
yryzhan-vitech 2026-07-26 14:24:33 +02:00
parent 6f84c468d4
commit 2e931db15b
2 changed files with 93 additions and 1 deletions

View file

@ -57,7 +57,11 @@ class AlertingHangingRequestCheck:
if request_data is None:
return
request_metadata: Final = get_litellm_metadata_from_kwargs(kwargs=request_data)
request_metadata: Final = (
get_litellm_metadata_from_kwargs(kwargs=request_data)
or request_data.get("metadata", {})
or {}
)
model: Final = request_data.get("model", "")
api_base: str | None = None

View file

@ -338,3 +338,91 @@ class TestAlertingHangingRequestCheck:
# Should not crash and should not send any alerts
hanging_request_checker.slack_alerting_object.send_alert.assert_not_called()
@pytest.mark.asyncio
async def test_add_request_uses_top_level_metadata_when_litellm_params_absent(
self, hanging_request_checker
):
"""Fall back to top-level metadata when litellm_params is absent."""
request_data = {
"litellm_call_id": "precall_request_001",
"model": "gpt-4",
"metadata": {
"user_api_key_alias": "my-key-alias",
"user_api_key_team_alias": "my-team-alias",
},
}
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="precall_request_001"
)
)
assert cached_data is not None
assert cached_data.key_alias == "my-key-alias"
assert cached_data.team_alias == "my-team-alias"
@pytest.mark.asyncio
async def test_add_request_prefers_litellm_params_metadata_when_present(
self, hanging_request_checker
):
"""Prefer litellm_params.metadata over top-level metadata when present."""
request_data = {
"litellm_call_id": "postcall_request_002",
"model": "gpt-4",
"litellm_params": {
"metadata": {
"user_api_key_alias": "lp-key-alias",
"user_api_key_team_alias": "lp-team-alias",
},
},
"metadata": {
"user_api_key_alias": "should-not-use-this",
"user_api_key_team_alias": "should-not-use-this-either",
},
}
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="postcall_request_002"
)
)
assert cached_data is not None
assert cached_data.key_alias == "lp-key-alias"
assert cached_data.team_alias == "lp-team-alias"
@pytest.mark.asyncio
async def test_add_request_preserves_team_alias_without_key_alias(
self, hanging_request_checker
):
"""Keep litellm_params team alias when key alias is absent (no overwrite)."""
request_data = {
"litellm_call_id": "team_only_request_003",
"model": "gpt-4",
"litellm_params": {
"metadata": {
"user_api_key_team_alias": "lp-team-alias",
},
},
"metadata": {
"user_api_key_team_alias": "should-not-use-this",
},
}
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="team_only_request_003"
)
)
assert cached_data is not None
assert cached_data.key_alias == ""
assert cached_data.team_alias == "lp-team-alias"