mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-21 00:21:49 +00:00
fix(health-check-routing): properly isolate exceptions from health response
Return exceptions_by_model_id as a separate third value from _perform_health_check / perform_health_check so exception objects (which contain non-JSON-serializable httpx URL types) never appear in the endpoint dicts that get serialized by the /health response. Callers updated: _health_endpoints.py, shared_health_check_manager.py, proxy_server.py background loop. All use the exceptions dict only for cooldown integration, not for display. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5850b1130e
commit
a756424192
4 changed files with 28 additions and 7 deletions
|
|
@ -211,6 +211,10 @@ async def _perform_health_check(
|
|||
|
||||
healthy_endpoints = []
|
||||
unhealthy_endpoints = []
|
||||
# Exceptions keyed by model_id; returned separately so callers can use
|
||||
# them for cooldown integration without risking JSON-serialization errors
|
||||
# in the /health response.
|
||||
exceptions_by_model_id: dict = {}
|
||||
|
||||
for is_healthy, model in zip(results, model_list):
|
||||
litellm_params = model["litellm_params"]
|
||||
|
|
@ -225,14 +229,18 @@ async def _perform_health_check(
|
|||
cleaned = _clean_endpoint_data({**litellm_params, **is_healthy}, details)
|
||||
if _model_id:
|
||||
cleaned["model_id"] = _model_id
|
||||
if "exception" in is_healthy:
|
||||
exceptions_by_model_id[_model_id] = is_healthy["exception"]
|
||||
unhealthy_endpoints.append(cleaned)
|
||||
else:
|
||||
cleaned = _clean_endpoint_data(litellm_params, details)
|
||||
if _model_id:
|
||||
cleaned["model_id"] = _model_id
|
||||
if isinstance(is_healthy, Exception):
|
||||
exceptions_by_model_id[_model_id] = is_healthy
|
||||
unhealthy_endpoints.append(cleaned)
|
||||
|
||||
return healthy_endpoints, unhealthy_endpoints
|
||||
return healthy_endpoints, unhealthy_endpoints, exceptions_by_model_id
|
||||
|
||||
|
||||
def build_deployment_health_states(
|
||||
|
|
@ -413,7 +421,11 @@ async def perform_health_check(
|
|||
)
|
||||
|
||||
try:
|
||||
healthy_endpoints, unhealthy_endpoints = await _perform_health_check(
|
||||
(
|
||||
healthy_endpoints,
|
||||
unhealthy_endpoints,
|
||||
exceptions_by_model_id,
|
||||
) = await _perform_health_check(
|
||||
model_list,
|
||||
details,
|
||||
max_concurrency=max_concurrency,
|
||||
|
|
@ -445,4 +457,4 @@ async def perform_health_check(
|
|||
_rss_mb_for_log(),
|
||||
)
|
||||
|
||||
return healthy_endpoints, unhealthy_endpoints
|
||||
return healthy_endpoints, unhealthy_endpoints, exceptions_by_model_id
|
||||
|
|
|
|||
|
|
@ -231,7 +231,11 @@ class SharedHealthCheckManager:
|
|||
len(model_list),
|
||||
)
|
||||
|
||||
healthy_endpoints, unhealthy_endpoints = await perform_health_check(
|
||||
(
|
||||
healthy_endpoints,
|
||||
unhealthy_endpoints,
|
||||
exceptions_by_model_id,
|
||||
) = await perform_health_check(
|
||||
model_list=model_list,
|
||||
details=details,
|
||||
max_concurrency=max_concurrency,
|
||||
|
|
@ -242,7 +246,7 @@ class SharedHealthCheckManager:
|
|||
healthy_endpoints, unhealthy_endpoints
|
||||
)
|
||||
|
||||
return healthy_endpoints, unhealthy_endpoints
|
||||
return healthy_endpoints, unhealthy_endpoints, exceptions_by_model_id
|
||||
|
||||
finally:
|
||||
# Always release the lock
|
||||
|
|
|
|||
|
|
@ -771,7 +771,7 @@ async def _perform_health_check_and_save(
|
|||
max_concurrency=None,
|
||||
):
|
||||
"""Helper function to perform health check and save results to database"""
|
||||
healthy_endpoints, unhealthy_endpoints = await perform_health_check(
|
||||
healthy_endpoints, unhealthy_endpoints, _ = await perform_health_check(
|
||||
model_list=model_list,
|
||||
cli_model=cli_model,
|
||||
model=target_model,
|
||||
|
|
|
|||
|
|
@ -2287,6 +2287,7 @@ async def _run_background_health_check():
|
|||
(
|
||||
healthy_endpoints,
|
||||
unhealthy_endpoints,
|
||||
_exceptions_by_model_id,
|
||||
) = await shared_health_manager.perform_shared_health_check(
|
||||
model_list=_llm_model_list,
|
||||
details=details_bool,
|
||||
|
|
@ -2300,6 +2301,7 @@ async def _run_background_health_check():
|
|||
(
|
||||
healthy_endpoints,
|
||||
unhealthy_endpoints,
|
||||
_exceptions_by_model_id,
|
||||
) = await _run_direct_health_check_with_instrumentation(
|
||||
_llm_model_list,
|
||||
health_check_details,
|
||||
|
|
@ -2310,6 +2312,7 @@ async def _run_background_health_check():
|
|||
(
|
||||
healthy_endpoints,
|
||||
unhealthy_endpoints,
|
||||
_exceptions_by_model_id,
|
||||
) = await _run_direct_health_check_with_instrumentation(
|
||||
_llm_model_list,
|
||||
health_check_details,
|
||||
|
|
@ -2352,7 +2355,9 @@ async def _run_background_health_check():
|
|||
)
|
||||
|
||||
# Write health state to router cache for health-check-driven routing
|
||||
_write_health_state_to_router_cache(healthy_endpoints, unhealthy_endpoints)
|
||||
_write_health_state_to_router_cache(
|
||||
healthy_endpoints, unhealthy_endpoints, _exceptions_by_model_id
|
||||
)
|
||||
|
||||
await asyncio.sleep(health_check_interval)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue