mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-14 09:03:16 +00:00
Merge 93046930bf into 08f2a98250
This commit is contained in:
commit
9e1a09922a
2 changed files with 79 additions and 4 deletions
|
|
@ -75,6 +75,7 @@ from litellm.proxy.db.db_lookup_gate import db_lookup_stall_tracker
|
|||
from litellm.proxy.db.exception_handler import PrismaDBExceptionHandler
|
||||
from litellm.proxy.db.health_check_latest import (
|
||||
LatestHealthCheckRow,
|
||||
latest_by_model_name,
|
||||
query_latest_health_checks,
|
||||
)
|
||||
from litellm.proxy.db.proxy_worker_heartbeat import count_live_proxy_workers
|
||||
|
|
@ -1803,20 +1804,34 @@ async def latest_health_checks_endpoint(
|
|||
|
||||
Returns the most recent health check result for each model.
|
||||
"""
|
||||
from litellm.proxy.proxy_server import llm_router
|
||||
|
||||
prisma_client: Final = _check_prisma_client()
|
||||
|
||||
try:
|
||||
latest_checks: Final = await prisma_client.get_all_latest_health_checks()
|
||||
|
||||
# Convert to dict format for JSON response using helper function
|
||||
checks_by_id: Final = {(check.model_id or check.model_name): check for check in latest_checks}
|
||||
checks_by_name: Final = latest_by_model_name(latest_checks)
|
||||
aliases: Final = await _caller_aliases(user_api_key_dict)
|
||||
alias_names: Final = await _names_key_may_request(
|
||||
_alias_names_caller_may_request(aliases, llm_router),
|
||||
aliases,
|
||||
user_api_key_dict,
|
||||
await _key_owner(user_api_key_dict),
|
||||
llm_router,
|
||||
)
|
||||
alias_targets: Final = {
|
||||
alias: checks_by_name.get(_served_group(alias, aliases, llm_router)) for alias in alias_names
|
||||
}
|
||||
alias_checks: Final = {alias: check for alias, check in alias_targets.items() if check is not None}
|
||||
checks_data: Final = {
|
||||
(check.model_id if check.model_id else check.model_name): convert_health_check_to_dict(check)
|
||||
for check in latest_checks
|
||||
name: convert_health_check_to_dict(check) for name, check in {**alias_checks, **checks_by_id}.items()
|
||||
}
|
||||
|
||||
return {
|
||||
"latest_health_checks": checks_data,
|
||||
"total_models": len(checks_data),
|
||||
"total_models": len(checks_by_id),
|
||||
}
|
||||
except Exception as e:
|
||||
verbose_proxy_logger.error("Error getting latest health checks: %s", e)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ from litellm.proxy.health_endpoints._health_endpoints import (
|
|||
from litellm.proxy.health_endpoints._health_endpoints import (
|
||||
test_model_connection as health_test_model_connection,
|
||||
)
|
||||
from litellm.proxy.utils import PrismaClient
|
||||
from litellm.router import Router
|
||||
from litellm.types.router import RouterModelGroupAliasItem
|
||||
from litellm.types.utils import oauth_token_exchange_litellm_params
|
||||
|
|
@ -47,6 +48,7 @@ from tests._master_key import MASTER_KEY
|
|||
|
||||
# Import shared proxy test helpers from conftest
|
||||
from tests.unit.proxy.conftest import create_proxy_test_client
|
||||
from tests.unit.proxy.db.fake_prisma_engine import engine_call
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
@ -6252,3 +6254,61 @@ async def test_unsaved_chatgpt_account_probe_requires_proxy_admin(
|
|||
await call
|
||||
assert error.value.code == "403"
|
||||
assert len(upstream.calls) == 0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("alias_layer", ["router", "key", "team", "hierarchical-router"])
|
||||
async def test_latest_health_alias_mirrors_the_targets_latest_record(monkeypatch, alias_layer):
|
||||
from litellm.proxy import proxy_server
|
||||
|
||||
llm_router: Final = Router(
|
||||
model_list=[
|
||||
{"model_name": name, "litellm_params": {"model": "openai/gpt-5.6"}, "model_info": {"id": name}}
|
||||
for name in ("chat", "unchecked", "private")
|
||||
],
|
||||
model_group_alias={
|
||||
**({"default": "chat"} if alias_layer == "router" else {}),
|
||||
"uncached": "unchecked",
|
||||
"restricted": "private",
|
||||
"old-deployment": "chat",
|
||||
},
|
||||
)
|
||||
rows: Final = [
|
||||
{
|
||||
"health_check_id": model_id,
|
||||
"model_name": model_name,
|
||||
"model_id": model_id,
|
||||
"status": status,
|
||||
"healthy_count": int(status == "healthy"),
|
||||
"unhealthy_count": int(status == "unhealthy"),
|
||||
"checked_at": checked_at,
|
||||
"created_at": checked_at,
|
||||
"updated_at": checked_at,
|
||||
}
|
||||
for model_id, model_name, status, checked_at in (
|
||||
("new-deployment", "chat", "healthy", "2026-10-31T12:00:00+00:00"),
|
||||
("old-deployment", "chat", "unhealthy", "2026-10-30T12:00:00+00:00"),
|
||||
("private", "private", "healthy", "2026-10-31T12:00:00+00:00"),
|
||||
)
|
||||
]
|
||||
prisma: Final = PrismaClient(
|
||||
database_url="postgresql://localhost/test", proxy_logging_obj=proxy_server.proxy_logging_obj
|
||||
)
|
||||
monkeypatch.setattr(prisma, "db", SimpleNamespace(query_raw=engine_call(rows)))
|
||||
caller: Final = UserAPIKeyAuth(
|
||||
models=["chat", "unchecked"],
|
||||
aliases={"default": "chat"} if alias_layer == "key" else {},
|
||||
team_model_aliases={"default": "chat"} if alias_layer == "team" else {},
|
||||
router_settings={"model_group_alias": {"default": "chat"}} if alias_layer == "hierarchical-router" else {},
|
||||
)
|
||||
|
||||
with _proxy_health_globals([], llm_router, prisma_client=prisma):
|
||||
result: Final = await _health_endpoints_module.latest_health_checks_endpoint(user_api_key_dict=caller)
|
||||
|
||||
checks: Final = result["latest_health_checks"]
|
||||
assert set(checks) == {"new-deployment", "old-deployment", "private", "default"}
|
||||
assert checks["default"] == checks["new-deployment"]
|
||||
assert checks["default"]["status"] == "healthy"
|
||||
assert checks["default"]["checked_at"] == "2026-10-31T12:00:00+00:00"
|
||||
assert checks["old-deployment"]["status"] == "unhealthy"
|
||||
assert result["total_models"] == 3
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue