diff --git a/litellm/caching.py b/litellm/caching.py index f39e4235ed..66f030098c 100644 --- a/litellm/caching.py +++ b/litellm/caching.py @@ -13,6 +13,7 @@ import json, traceback, ast, hashlib from typing import Optional, Literal, List, Union, Any, BinaryIO from openai._models import BaseModel as OpenAIObject from litellm._logging import verbose_logger +import traceback def print_verbose(print_statement): @@ -158,6 +159,7 @@ class RedisCache(BaseCache): print_verbose( f"LiteLLM Redis Caching: async set() - Got exception from REDIS : {str(e)}" ) + traceback.print_exc() async def async_set_cache_pipeline(self, cache_list, ttl=None): """ @@ -262,6 +264,21 @@ class RedisCache(BaseCache): print_verbose(f"Error occurred in pipeline read - {str(e)}") return key_value_dict + async def ping(self): + _redis_client = self.init_async_client() + async with _redis_client as redis_client: + print_verbose(f"Pinging Async Redis Cache") + try: + response = await redis_client.ping() + print_verbose(f"Redis Cache PING: {response}") + except Exception as e: + # NON blocking - notify users Redis is throwing an exception + print_verbose( + f"LiteLLM Redis Cache PING: - Got exception from REDIS : {str(e)}" + ) + traceback.print_exc() + raise e + def flush_cache(self): self.redis_client.flushall() @@ -1254,6 +1271,11 @@ class Cache: print_verbose(f"LiteLLM Cache: Excepton add_cache: {str(e)}") traceback.print_exc() + async def ping(self): + if hasattr(self.cache, "ping"): + return await self.cache.ping() + return None + async def disconnect(self): if hasattr(self.cache, "disconnect"): await self.cache.disconnect() diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 24a4ca8e34..dfaa991621 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -7561,6 +7561,71 @@ async def health_liveliness(): return "I'm alive!" +@router.get( + "/cache/ping", + tags=["caching"], + dependencies=[Depends(user_api_key_auth)], +) +async def cache_ping(): + """ + Endpoint for checking if cache can be pinged + """ + try: + litellm_cache_params = {} + specific_cache_params = {} + + if litellm.cache is None: + raise HTTPException( + status_code=503, detail="Cache not initialized. litellm.cache is None" + ) + + for k, v in vars(litellm.cache).items(): + try: + if k == "cache": + continue + litellm_cache_params[k] = str(copy.deepcopy(v)) + except Exception: + litellm_cache_params[k] = "" + for k, v in vars(litellm.cache.cache).items(): + try: + specific_cache_params[k] = str(v) + except Exception: + specific_cache_params[k] = "" + if litellm.cache.type == "redis": + # ping the redis cache + ping_response = await litellm.cache.ping() + verbose_proxy_logger.debug( + "/cache/ping: ping_response: " + str(ping_response) + ) + # making a set cache call + # add cache does not return anything + await litellm.cache.async_add_cache( + result="test_key", + model="test-model", + messages=[{"role": "user", "content": "test from litellm"}], + ) + verbose_proxy_logger.debug("/cache/ping: done with set_cache()") + return { + "status": "healthy", + "cache_type": litellm.cache.type, + "ping_response": True, + "set_cache_response": "success", + "litellm_cache_params": litellm_cache_params, + "redis_cache_params": specific_cache_params, + } + else: + return { + "status": "healthy", + "cache_type": litellm.cache.type, + "litellm_cache_params": litellm_cache_params, + } + except Exception as e: + raise HTTPException( + status_code=503, + detail=f"Service Unhealthy ({str(e)}).Cache parameters: {litellm_cache_params}.specific_cache_params: {specific_cache_params}", + ) + + @router.get("/", dependencies=[Depends(user_api_key_auth)]) async def home(request: Request): return "LiteLLM: RUNNING"