[Feat-Proxy] Slack Alerting - allow using os.environ/ vars for alert to webhook url (#5726)

* allow using os.environ for slack urls

* use env vars for webhook urls

* fix types for get_secret

* fix linting

* fix linting

* fix linting

* linting fixes

* linting fix

* docs alerting slack

* fix get data
This commit is contained in:
Ishaan Jaff 2024-09-16 18:03:37 -07:00 committed by GitHub
parent 703fd9395f
commit 0d027b22fd
23 changed files with 286 additions and 84 deletions

View file

@ -93,6 +93,7 @@ def safe_deep_copy(data):
return data
# Step 1: Remove the litellm_parent_otel_span
litellm_parent_otel_span = None
if isinstance(data, dict):
# remove litellm_parent_otel_span since this is not picklable
if "metadata" in data and "litellm_parent_otel_span" in data["metadata"]:
@ -519,13 +520,7 @@ class ProxyLogging:
self,
message: str,
level: Literal["Low", "Medium", "High"],
alert_type: Literal[
"llm_exceptions",
"llm_too_slow",
"llm_requests_hanging",
"budget_alerts",
"db_exceptions",
],
alert_type: AlertType,
request_data: Optional[dict] = None,
):
"""
@ -1302,6 +1297,7 @@ class PrismaClient:
table_name is not None and table_name == "key"
):
# check if plain text or hash
hashed_token = None
if token is not None:
if isinstance(token, str):
hashed_token = token
@ -1712,7 +1708,7 @@ class PrismaClient:
updated_table_row = self.db.litellm_config.upsert(
where={"param_name": k},
data={
"create": {"param_name": k, "param_value": updated_data},
"create": {"param_name": k, "param_value": updated_data}, # type: ignore
"update": {"param_value": updated_data},
},
)
@ -2265,11 +2261,15 @@ class DBClient:
"""
For closing connection on server shutdown
"""
return await self.db.disconnect()
if self.db is not None:
return await self.db.disconnect() # type: ignore
return asyncio.sleep(0) # Return a dummy coroutine if self.db is None
### CUSTOM FILE ###
def get_instance_fn(value: str, config_file_path: Optional[str] = None) -> Any:
module_name = value
instance_name = None
try:
print_verbose(f"value: {value}")
# Split the path by dots to separate module from instance
@ -2363,6 +2363,15 @@ async def send_email(receiver_email, subject, html):
"sending email from %s to %s", sender_email, receiver_email
)
if smtp_host is None:
raise ValueError("Trying to use SMTP, but SMTP_HOST is not set")
if smtp_username is None:
raise ValueError("Trying to use SMTP, but SMTP_USERNAME is not set")
if smtp_password is None:
raise ValueError("Trying to use SMTP, but SMTP_PASSWORD is not set")
# Attach the body to the email
email_message.attach(MIMEText(html, "html"))
@ -2555,6 +2564,7 @@ async def update_spend(
spend_logs: list,
"""
n_retry_times = 3
i = None
### UPDATE USER TABLE ###
if len(prisma_client.user_list_transactons.keys()) > 0:
for i in range(n_retry_times + 1):
@ -2930,6 +2940,8 @@ async def update_spend(
)
break
except httpx.ReadTimeout:
if i is None:
i = 0
if i >= n_retry_times: # If we've reached the maximum number of retries
raise # Re-raise the last exception
# Optionally, sleep for a bit before retrying
@ -3044,10 +3056,11 @@ def get_error_message_str(e: Exception) -> str:
elif isinstance(e.detail, dict):
error_message = json.dumps(e.detail)
elif hasattr(e, "message"):
if isinstance(e.message, "str"):
error_message = e.message
elif isinstance(e.message, dict):
error_message = json.dumps(e.message)
_error = getattr(e, "message", None)
if isinstance(_error, str):
error_message = _error
elif isinstance(_error, dict):
error_message = json.dumps(_error)
else:
error_message = str(e)
else: