diff options
author | S. Solomon Darnell | 2025-03-28 21:52:21 -0500 |
---|---|---|
committer | S. Solomon Darnell | 2025-03-28 21:52:21 -0500 |
commit | 4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch) | |
tree | ee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/litellm/integrations/prometheus_helpers/prometheus_api.py | |
parent | cc961e04ba734dd72309fb548a2f97d67d578813 (diff) | |
download | gn-ai-4a52a71956a8d46fcb7294ac71734504bb09bcc2.tar.gz |
Diffstat (limited to '.venv/lib/python3.12/site-packages/litellm/integrations/prometheus_helpers/prometheus_api.py')
-rw-r--r-- | .venv/lib/python3.12/site-packages/litellm/integrations/prometheus_helpers/prometheus_api.py | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/litellm/integrations/prometheus_helpers/prometheus_api.py b/.venv/lib/python3.12/site-packages/litellm/integrations/prometheus_helpers/prometheus_api.py new file mode 100644 index 00000000..b25da577 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/litellm/integrations/prometheus_helpers/prometheus_api.py @@ -0,0 +1,137 @@ +""" +Helper functions to query prometheus API +""" + +import time +from datetime import datetime, timedelta +from typing import Optional + +from litellm import get_secret +from litellm._logging import verbose_logger +from litellm.llms.custom_httpx.http_handler import ( + get_async_httpx_client, + httpxSpecialProvider, +) + +PROMETHEUS_URL: Optional[str] = get_secret("PROMETHEUS_URL") # type: ignore +PROMETHEUS_SELECTED_INSTANCE: Optional[str] = get_secret("PROMETHEUS_SELECTED_INSTANCE") # type: ignore +async_http_handler = get_async_httpx_client( + llm_provider=httpxSpecialProvider.LoggingCallback +) + + +async def get_metric_from_prometheus( + metric_name: str, +): + # Get the start of the current day in Unix timestamp + if PROMETHEUS_URL is None: + raise ValueError( + "PROMETHEUS_URL not set please set 'PROMETHEUS_URL=<>' in .env" + ) + + query = f"{metric_name}[24h]" + now = int(time.time()) + response = await async_http_handler.get( + f"{PROMETHEUS_URL}/api/v1/query", params={"query": query, "time": now} + ) # End of the day + _json_response = response.json() + verbose_logger.debug("json response from prometheus /query api %s", _json_response) + results = response.json()["data"]["result"] + return results + + +async def get_fallback_metric_from_prometheus(): + """ + Gets fallback metrics from prometheus for the last 24 hours + """ + response_message = "" + relevant_metrics = [ + "litellm_deployment_successful_fallbacks_total", + "litellm_deployment_failed_fallbacks_total", + ] + for metric in relevant_metrics: + response_json = await get_metric_from_prometheus( + metric_name=metric, + ) + + if response_json: + verbose_logger.debug("response json %s", response_json) + for result in response_json: + verbose_logger.debug("result= %s", result) + metric = result["metric"] + metric_values = result["values"] + most_recent_value = metric_values[0] + + if PROMETHEUS_SELECTED_INSTANCE is not None: + if metric.get("instance") != PROMETHEUS_SELECTED_INSTANCE: + continue + + value = int(float(most_recent_value[1])) # Convert value to integer + primary_model = metric.get("primary_model", "Unknown") + fallback_model = metric.get("fallback_model", "Unknown") + response_message += f"`{value} successful fallback requests` with primary model=`{primary_model}` -> fallback model=`{fallback_model}`" + response_message += "\n" + verbose_logger.debug("response message %s", response_message) + return response_message + + +def is_prometheus_connected() -> bool: + if PROMETHEUS_URL is not None: + return True + return False + + +async def get_daily_spend_from_prometheus(api_key: Optional[str]): + """ + Expected Response Format: + [ + { + "date": "2024-08-18T00:00:00+00:00", + "spend": 1.001818099998933 + }, + ...] + """ + if PROMETHEUS_URL is None: + raise ValueError( + "PROMETHEUS_URL not set please set 'PROMETHEUS_URL=<>' in .env" + ) + + # Calculate the start and end dates for the last 30 days + end_date = datetime.utcnow() + start_date = end_date - timedelta(days=30) + + # Format dates as ISO 8601 strings with UTC offset + start_str = start_date.isoformat() + "+00:00" + end_str = end_date.isoformat() + "+00:00" + + url = f"{PROMETHEUS_URL}/api/v1/query_range" + + if api_key is None: + query = "sum(delta(litellm_spend_metric_total[1d]))" + else: + query = ( + f'sum(delta(litellm_spend_metric_total{{hashed_api_key="{api_key}"}}[1d]))' + ) + + params = { + "query": query, + "start": start_str, + "end": end_str, + "step": "86400", # Step size of 1 day in seconds + } + + response = await async_http_handler.get(url, params=params) + _json_response = response.json() + verbose_logger.debug("json response from prometheus /query api %s", _json_response) + results = response.json()["data"]["result"] + formatted_results = [] + + for result in results: + metric_data = result["values"] + for timestamp, value in metric_data: + # Convert timestamp to ISO 8601 string with UTC offset + date = datetime.fromtimestamp(float(timestamp)).isoformat() + "+00:00" + spend = float(value) + formatted_results.append({"date": date, "spend": spend}) + + return formatted_results |