Skip to content

Commit

Permalink
(fix) don't block proxy startup if license check fails & using promet…
Browse files Browse the repository at this point in the history
…heus (#6839)

* fix - don't block proxy startup if not a premium user

* test_litellm_proxy_server_config_with_prometheus

* add test for proxy startup

* fix remove unused test

* fix startup test

* add comment on bad-license
  • Loading branch information
ishaan-jaff authored Nov 21, 2024
1 parent cc1f8ff commit ddfe687
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 1 deletion.
42 changes: 42 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,48 @@ jobs:
ls
python -m pytest -vv tests/otel_tests -x --junitxml=test-results/junit.xml --durations=5
no_output_timeout: 120m
# Clean up first container
- run:
name: Stop and remove first container
command: |
docker stop my-app
docker rm my-app
# Second Docker Container Run with Different Config
# NOTE: We intentionally pass a "bad" license here. We need to ensure proxy starts and serves request even with bad license
- run:
name: Run Second Docker container
command: |
docker run -d \
-p 4000:4000 \
-e DATABASE_URL=$PROXY_DATABASE_URL \
-e REDIS_HOST=$REDIS_HOST \
-e REDIS_PASSWORD=$REDIS_PASSWORD \
-e REDIS_PORT=$REDIS_PORT \
-e LITELLM_MASTER_KEY="sk-1234" \
-e OPENAI_API_KEY=$OPENAI_API_KEY \
-e LITELLM_LICENSE="bad-license" \
--name my-app-3 \
-v $(pwd)/litellm/proxy/example_config_yaml/enterprise_config.yaml:/app/config.yaml \
my-app:latest \
--config /app/config.yaml \
--port 4000 \
--detailed_debug
- run:
name: Start outputting logs for second container
command: docker logs -f my-app-2
background: true

- run:
name: Wait for second app to be ready
command: dockerize -wait http://localhost:4000 -timeout 5m

- run:
name: Run second round of tests
command: |
python -m pytest -vv tests/basic_proxy_startup_tests -x --junitxml=test-results/junit-2.xml --durations=5
no_output_timeout: 120m

# Store test results
- store_test_results:
Expand Down
4 changes: 3 additions & 1 deletion litellm/proxy/common_utils/callback_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,9 @@ def initialize_callbacks_on_proxy( # noqa: PLR0915

if "prometheus" in value:
if premium_user is not True:
raise Exception(CommonProxyErrors.not_premium_user.value)
verbose_proxy_logger.warning(

This comment has been minimized.

Copy link
@krrishdholakia

krrishdholakia Nov 21, 2024

Contributor

hey @ishaan-jaff does this check make sure prometheus metrics do not work for free users ?

f"Prometheus metrics are only available for premium users. {CommonProxyErrors.not_premium_user.value}"
)
from litellm.proxy.proxy_server import app

verbose_proxy_logger.debug("Starting Prometheus Metrics on /metrics")
Expand Down
17 changes: 17 additions & 0 deletions litellm/proxy/example_config_yaml/enterprise_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
model_list:
- model_name: gpt-4
litellm_params:
model: openai/fake
api_key: fake-key
api_base: https://exampleopenaiendpoint-production.up.railway.app/
tags: ["teamA"]
model_info:
id: "team-a-model"

litellm_settings:
cache: true
callbacks: ["prometheus"]

router_settings:
enable_tag_filtering: True # 👈 Key Change

51 changes: 51 additions & 0 deletions tests/basic_proxy_startup_tests/test_basic_proxy_startup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
This test ensures that the proxy starts and serves requests even with a bad license.
in ci/cd config.yml, we set the license to "bad-license"
"""

import pytest
import aiohttp
from typing import Optional


@pytest.mark.asyncio
async def test_health_and_chat_completion():
"""
Test health endpoints and chat completion:
1. Check /health/readiness
2. Check /health/liveness
3. Make a chat completion call
"""
async with aiohttp.ClientSession() as session:
# Test readiness endpoint
async with session.get("http://0.0.0.0:4000/health/readiness") as response:
assert response.status == 200
readiness_response = await response.json()
assert readiness_response["status"] == "connected"

# Test liveness endpoint
async with session.get("http://0.0.0.0:4000/health/liveness") as response:
assert response.status == 200
liveness_response = await response.json()
print("liveness_response", liveness_response)

# Make a chat completion call
url = "http://0.0.0.0:4000/chat/completions"
headers = {
"Authorization": "Bearer sk-1234",
"Content-Type": "application/json",
}
data = {
"model": "gpt-4",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"},
],
}

async with session.post(url, headers=headers, json=data) as response:
assert response.status == 200
completion_response = await response.json()
assert "choices" in completion_response

0 comments on commit ddfe687

Please sign in to comment.