From d89990e0c5e4ecfbef9c4997c455e6498be3d5f4 Mon Sep 17 00:00:00 2001 From: Andrew Bernat <31580217+bernata@users.noreply.github.com> Date: Tue, 28 Oct 2025 19:21:54 -0700 Subject: [PATCH] Add license metadata to health/readiness endpoint. (#15997) * health: expose license metadata (available & expiration) in /health/readiness endpoint * test: add health readiness license metadata coverage * test: ensure /health/readiness response includes license metadata * chore: remove standalone license metadata test as requested; existing test covers codepath --------- Co-authored-by: Plan42.ai --- .../health_endpoints/_health_endpoints.py | 24 +++++++++++++++++++ .../test_basic_proxy_startup.py | 4 ++++ 2 files changed, 28 insertions(+) diff --git a/litellm/proxy/health_endpoints/_health_endpoints.py b/litellm/proxy/health_endpoints/_health_endpoints.py index c59e91aa1e..b42f800734 100644 --- a/litellm/proxy/health_endpoints/_health_endpoints.py +++ b/litellm/proxy/health_endpoints/_health_endpoints.py @@ -831,6 +831,28 @@ async def health_readiness(): index_info = "index does not exist - error: " + str(e) cache_type = {"type": cache_type, "index_info": index_info} + # build license metadata + try: + from litellm.proxy.proxy_server import _license_check # type: ignore + + license_available: bool = _license_check.is_premium() if _license_check else False + license_expiration: Optional[str] = None + + if getattr(_license_check, "airgapped_license_data", None): + license_expiration = _license_check.airgapped_license_data.get( # type: ignore[arg-type] + "expiration_date" + ) + + license_metadata = { + "license": { + "has_license": license_available, + "expiration_date": license_expiration, + } + } + except Exception: + # fail closed: don't let license check break readiness + license_metadata = {"license": {"has_license": False, "expiration_date": None}} + # check DB if prisma_client is not None: # if db passed in, check if it's connected db_health_status = await _db_health_readiness_check() @@ -841,6 +863,7 @@ async def health_readiness(): "litellm_version": version, "success_callbacks": success_callback_names, "use_aiohttp_transport": AsyncHTTPHandler._should_use_aiohttp_transport(), + **license_metadata, **db_health_status, } else: @@ -851,6 +874,7 @@ async def health_readiness(): "litellm_version": version, "success_callbacks": success_callback_names, "use_aiohttp_transport": AsyncHTTPHandler._should_use_aiohttp_transport(), + **license_metadata, } except Exception as e: raise HTTPException(status_code=503, detail=f"Service Unhealthy ({str(e)})") diff --git a/tests/basic_proxy_startup_tests/test_basic_proxy_startup.py b/tests/basic_proxy_startup_tests/test_basic_proxy_startup.py index db09e38ea9..ef6e337a7a 100644 --- a/tests/basic_proxy_startup_tests/test_basic_proxy_startup.py +++ b/tests/basic_proxy_startup_tests/test_basic_proxy_startup.py @@ -25,6 +25,10 @@ async def test_health_and_chat_completion(): readiness_response = await response.json() assert readiness_response["status"] == "connected" + # New assertion: license metadata is present + assert "license" in readiness_response + assert "has_license" in readiness_response["license"] + # Test liveness endpoint async with session.get("http://0.0.0.0:4000/health/liveness") as response: assert response.status == 200