mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
perf: build log messages lazily so filtered-out log records cost nothing (#35703)
This commit is contained in:
parent
2039981210
commit
c9887a1f94
419 changed files with 3919 additions and 3140 deletions
|
|
@ -651,7 +651,9 @@ def get_redis_async_client(
|
|||
if arg in args:
|
||||
url_kwargs[arg] = redis_kwargs[arg]
|
||||
else:
|
||||
verbose_logger.debug(f"REDIS: ignoring argument: {arg}. Not an allowed async_redis.Redis.from_url arg.")
|
||||
verbose_logger.debug(
|
||||
"REDIS: ignoring argument: %s. Not an allowed async_redis.Redis.from_url arg.", arg
|
||||
)
|
||||
return async_redis.Redis.from_url(**url_kwargs)
|
||||
|
||||
# Check for Redis Sentinel
|
||||
|
|
@ -805,6 +807,6 @@ def _pretty_print_redis_config(redis_kwargs: dict) -> None:
|
|||
# Fallback to simple logging if rich is not available
|
||||
masker = SensitiveDataMasker()
|
||||
masked_redis_kwargs = masker.mask_dict(redis_kwargs)
|
||||
verbose_logger.info(f"Redis configuration: {masked_redis_kwargs}")
|
||||
verbose_logger.info("Redis configuration: %s", masked_redis_kwargs)
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"Error pretty printing Redis configuration: {e}")
|
||||
verbose_logger.error("Error pretty printing Redis configuration: %s", e)
|
||||
|
|
|
|||
|
|
@ -148,13 +148,13 @@ class LiteLLMA2ACardResolver(_A2ACardResolver): # type: ignore[misc]
|
|||
last_error = None
|
||||
for path in paths:
|
||||
try:
|
||||
verbose_logger.debug(f"Attempting to fetch agent card from {self.base_url}{path}")
|
||||
verbose_logger.debug("Attempting to fetch agent card from %s%s", self.base_url, path)
|
||||
return await super().get_agent_card(
|
||||
relative_card_path=path,
|
||||
http_kwargs=http_kwargs,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Failed to fetch agent card from {self.base_url}{path}: {e}")
|
||||
verbose_logger.debug("Failed to fetch agent card from %s%s: %s", self.base_url, path, e)
|
||||
last_error = e
|
||||
continue
|
||||
|
||||
|
|
|
|||
|
|
@ -192,9 +192,11 @@ async def handle_a2a_localhost_retry(
|
|||
|
||||
request_type = "streaming " if is_streaming else ""
|
||||
verbose_logger.warning(
|
||||
f"A2A {request_type}request to '{error.localhost_url}' failed: {error.original_error}. "
|
||||
f"Agent card contains localhost/internal URL. "
|
||||
f"Retrying with base_url '{error.base_url}'."
|
||||
"A2A %srequest to '%s' failed: %s. Agent card contains localhost/internal URL. Retrying with base_url '%s'.",
|
||||
request_type,
|
||||
error.localhost_url,
|
||||
error.original_error,
|
||||
error.base_url,
|
||||
)
|
||||
|
||||
# Fix the agent card URL
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class A2ACompletionBridgeHandler:
|
|||
)
|
||||
|
||||
if a2a_provider_config is not None:
|
||||
verbose_logger.info(f"A2A: Using provider config for {custom_llm_provider}")
|
||||
verbose_logger.info("A2A: Using provider config for %s", custom_llm_provider)
|
||||
|
||||
return await a2a_provider_config.handle_non_streaming(
|
||||
request_id=request_id,
|
||||
|
|
@ -103,7 +103,7 @@ class A2ACompletionBridgeHandler:
|
|||
else:
|
||||
full_model = model
|
||||
|
||||
verbose_logger.info(f"A2A completion bridge: model={full_model}, api_base={api_base}")
|
||||
verbose_logger.info("A2A completion bridge: model=%s, api_base=%s", full_model, api_base)
|
||||
|
||||
# Build completion params dict
|
||||
completion_params: dict[str, Any] = {
|
||||
|
|
@ -143,7 +143,7 @@ class A2ACompletionBridgeHandler:
|
|||
request_id=request_id,
|
||||
)
|
||||
|
||||
verbose_logger.info(f"A2A completion bridge completed: request_id={request_id}")
|
||||
verbose_logger.info("A2A completion bridge completed: request_id=%s", request_id)
|
||||
|
||||
return a2a_response
|
||||
|
||||
|
|
@ -185,7 +185,7 @@ class A2ACompletionBridgeHandler:
|
|||
)
|
||||
|
||||
if a2a_provider_config is not None:
|
||||
verbose_logger.info(f"A2A: Using provider config for {custom_llm_provider} (streaming)")
|
||||
verbose_logger.info("A2A: Using provider config for %s (streaming)", custom_llm_provider)
|
||||
|
||||
async for chunk in a2a_provider_config.handle_streaming(
|
||||
request_id=request_id,
|
||||
|
|
@ -221,7 +221,7 @@ class A2ACompletionBridgeHandler:
|
|||
else:
|
||||
full_model = model
|
||||
|
||||
verbose_logger.info(f"A2A completion bridge streaming: model={full_model}, api_base={api_base}")
|
||||
verbose_logger.info("A2A completion bridge streaming: model=%s, api_base=%s", full_model, api_base)
|
||||
|
||||
# Build completion params dict
|
||||
completion_params: dict[str, Any] = {
|
||||
|
|
@ -300,7 +300,9 @@ class A2ACompletionBridgeHandler:
|
|||
)
|
||||
yield completed_event
|
||||
|
||||
verbose_logger.info(f"A2A completion bridge streaming completed: request_id={request_id}, chunks={chunk_count}")
|
||||
verbose_logger.info(
|
||||
"A2A completion bridge streaming completed: request_id=%s, chunks=%s", request_id, chunk_count
|
||||
)
|
||||
|
||||
|
||||
# Convenience functions that delegate to the class methods
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ class A2ACompletionBridgeTransformation:
|
|||
extra_body = {**extra_body, "metadata": merged_metadata}
|
||||
completion_params["extra_body"] = extra_body
|
||||
|
||||
verbose_logger.debug(f"A2A -> completion forward metadata keys={list(forward_metadata.keys())}")
|
||||
verbose_logger.debug("A2A -> completion forward metadata keys=%s", list(forward_metadata.keys()))
|
||||
|
||||
@staticmethod
|
||||
def a2a_message_to_openai_messages(
|
||||
|
|
@ -145,7 +145,9 @@ class A2ACompletionBridgeTransformation:
|
|||
# once at run level via extra_body.metadata (LangGraph POST /runs/wait shape).
|
||||
openai_message: dict[str, Any] = {"role": openai_role, "content": content}
|
||||
|
||||
verbose_logger.debug(f"A2A -> OpenAI transform: role={role} -> {openai_role}, content_length={len(content)}")
|
||||
verbose_logger.debug(
|
||||
"A2A -> OpenAI transform: role=%s -> %s, content_length=%s", role, openai_role, len(content)
|
||||
)
|
||||
|
||||
return [openai_message]
|
||||
|
||||
|
|
@ -186,7 +188,7 @@ class A2ACompletionBridgeTransformation:
|
|||
"result": a2a_message,
|
||||
}
|
||||
|
||||
verbose_logger.debug(f"OpenAI -> A2A transform: content_length={len(content)}")
|
||||
verbose_logger.debug("OpenAI -> A2A transform: content_length=%s", len(content))
|
||||
|
||||
return a2a_response
|
||||
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ async def _send_message_via_completion_bridge(
|
|||
|
||||
Requires request; api_base is optional for providers that derive endpoint from model.
|
||||
"""
|
||||
verbose_logger.info(f"A2A using completion bridge: provider={custom_llm_provider}, api_base={api_base}")
|
||||
verbose_logger.info("A2A using completion bridge: provider=%s, api_base=%s", custom_llm_provider, api_base)
|
||||
|
||||
from litellm.a2a_protocol.litellm_completion_bridge.handler import (
|
||||
A2ACompletionBridgeHandler,
|
||||
|
|
@ -463,7 +463,7 @@ async def asend_message(
|
|||
|
||||
agent_name = _get_a2a_model_info(a2a_client, kwargs)
|
||||
|
||||
verbose_logger.info(f"A2A send_message request_id={request.id}, agent={agent_name}")
|
||||
verbose_logger.info("A2A send_message request_id=%s, agent=%s", request.id, agent_name)
|
||||
|
||||
# Get agent card URL for localhost retry logic
|
||||
agent_card = _get_a2a_client_agent_card(a2a_client)
|
||||
|
|
@ -478,7 +478,7 @@ async def asend_message(
|
|||
agent_name=agent_name,
|
||||
)
|
||||
|
||||
verbose_logger.info(f"A2A send_message completed, request_id={request.id}")
|
||||
verbose_logger.info("A2A send_message completed, request_id=%s", request.id)
|
||||
|
||||
# Wrap in LiteLLM response type for _hidden_params support
|
||||
response = LiteLLMSendMessageResponse.from_a2a_response(a2a_response, request_id=str(request.id))
|
||||
|
|
@ -640,7 +640,7 @@ async def asend_message_streaming(
|
|||
raise ValueError("request is required for completion bridge")
|
||||
# api_base is optional for providers that derive endpoint from model (e.g., bedrock/agentcore)
|
||||
|
||||
verbose_logger.info(f"A2A streaming using completion bridge: provider={custom_llm_provider}")
|
||||
verbose_logger.info("A2A streaming using completion bridge: provider=%s", custom_llm_provider)
|
||||
|
||||
from litellm.a2a_protocol.litellm_completion_bridge.handler import (
|
||||
A2ACompletionBridgeHandler,
|
||||
|
|
@ -697,7 +697,7 @@ async def asend_message_streaming(
|
|||
proxy_server_request=proxy_server_request,
|
||||
)
|
||||
|
||||
verbose_logger.info(f"A2A send_message_streaming request_id={request.id}, agent={agent_name}")
|
||||
verbose_logger.info("A2A send_message_streaming request_id=%s, agent=%s", request.id, agent_name)
|
||||
|
||||
agent_card = _get_a2a_client_agent_card(a2a_client)
|
||||
card_url = get_agent_card_url(agent_card) if agent_card else None
|
||||
|
|
@ -759,7 +759,7 @@ async def create_a2a_client(
|
|||
"The 'a2a' package is required for A2A agent invocation. Install it with: pip install a2a-sdk"
|
||||
)
|
||||
|
||||
verbose_logger.info(f"Creating A2A client for {base_url}")
|
||||
verbose_logger.info("Creating A2A client for %s", base_url)
|
||||
|
||||
# Use get_async_httpx_client with per-agent params so that different agents
|
||||
# (with different extra_headers) get separate cached clients. The params
|
||||
|
|
@ -781,7 +781,7 @@ async def create_a2a_client(
|
|||
httpx_client = _async_handler.client
|
||||
if extra_headers:
|
||||
httpx_client.headers.update(extra_headers)
|
||||
verbose_proxy_logger.debug(f"A2A client created with extra_headers={list(extra_headers.keys())}")
|
||||
verbose_proxy_logger.debug("A2A client created with extra_headers=%s", list(extra_headers.keys()))
|
||||
|
||||
a2a_client = await create_client( # pyright: ignore[reportOptionalCall]
|
||||
base_url,
|
||||
|
|
@ -798,7 +798,7 @@ async def create_a2a_client(
|
|||
if agent_card is not None:
|
||||
a2a_client._litellm_agent_card = agent_card # type: ignore[attr-defined]
|
||||
|
||||
verbose_logger.info(f"A2A client created for {base_url}")
|
||||
verbose_logger.info("A2A client created for %s", base_url)
|
||||
|
||||
return a2a_client
|
||||
|
||||
|
|
@ -824,7 +824,7 @@ async def aget_agent_card(
|
|||
"The 'a2a' package is required for A2A agent invocation. Install it with: pip install a2a-sdk"
|
||||
)
|
||||
|
||||
verbose_logger.info(f"Fetching agent card from {base_url}")
|
||||
verbose_logger.info("Fetching agent card from %s", base_url)
|
||||
|
||||
# Use LiteLLM's cached httpx client
|
||||
http_handler = get_async_httpx_client(
|
||||
|
|
@ -839,5 +839,5 @@ async def aget_agent_card(
|
|||
)
|
||||
agent_card = await resolver.get_agent_card()
|
||||
|
||||
verbose_logger.info(f"Fetched agent card: {agent_card.name if hasattr(agent_card, 'name') else 'unknown'}")
|
||||
verbose_logger.info("Fetched agent card: %s", agent_card.name if hasattr(agent_card, "name") else "unknown")
|
||||
return agent_card
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class BedrockAgentCoreA2AHandler:
|
|||
agent_extra_headers=agent_extra_headers,
|
||||
)
|
||||
|
||||
verbose_logger.info(f"BedrockAgentCore A2A: Sending non-streaming request to {url}")
|
||||
verbose_logger.info("BedrockAgentCore A2A: Sending non-streaming request to %s", url)
|
||||
|
||||
client = get_async_httpx_client(
|
||||
llm_provider=cast(Any, httpxSpecialProvider.A2AProvider),
|
||||
|
|
@ -67,7 +67,7 @@ class BedrockAgentCoreA2AHandler:
|
|||
response_data = response.json()
|
||||
|
||||
if "error" in response_data:
|
||||
verbose_logger.warning(f"BedrockAgentCore A2A: Agent returned error: {response_data['error']}")
|
||||
verbose_logger.warning("BedrockAgentCore A2A: Agent returned error: %s", response_data["error"])
|
||||
|
||||
return response_data
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ class BedrockAgentCoreA2AHandler:
|
|||
agent_extra_headers=agent_extra_headers,
|
||||
)
|
||||
|
||||
verbose_logger.info(f"BedrockAgentCore A2A: Sending streaming request to {url}")
|
||||
verbose_logger.info("BedrockAgentCore A2A: Sending streaming request to %s", url)
|
||||
|
||||
client = get_async_httpx_client(
|
||||
llm_provider=cast(Any, httpxSpecialProvider.A2AProvider),
|
||||
|
|
|
|||
|
|
@ -195,5 +195,5 @@ class BedrockAgentCoreA2ATransformation:
|
|||
event = json.loads(data_str)
|
||||
yield event
|
||||
except json.JSONDecodeError:
|
||||
verbose_logger.debug(f"BedrockAgentCore A2A: Skipping non-JSON SSE line: {data_str[:100]}")
|
||||
verbose_logger.debug("BedrockAgentCore A2A: Skipping non-JSON SSE line: %s", data_str[:100])
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ class PydanticAIHandler:
|
|||
"""
|
||||
if api_base is None:
|
||||
raise ValueError("api_base is required for Pydantic AI agents")
|
||||
verbose_logger.info(f"Pydantic AI: Routing to Pydantic AI agent at {api_base}")
|
||||
verbose_logger.info("Pydantic AI: Routing to Pydantic AI agent at %s", api_base)
|
||||
|
||||
# Send request directly to Pydantic AI agent
|
||||
response_data = await PydanticAITransformation.send_non_streaming_request(
|
||||
|
|
@ -92,7 +92,7 @@ class PydanticAIHandler:
|
|||
"""
|
||||
if api_base is None:
|
||||
raise ValueError("api_base is required for Pydantic AI agents")
|
||||
verbose_logger.info(f"Pydantic AI: Faking streaming for Pydantic AI agent at {api_base}")
|
||||
verbose_logger.info("Pydantic AI: Faking streaming for Pydantic AI agent at %s", api_base)
|
||||
|
||||
# Get raw task response first (not the transformed A2A format)
|
||||
raw_response = await PydanticAITransformation.send_and_get_raw_response(
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ class PydanticAITransformation:
|
|||
status = result.get("status", {})
|
||||
state = status.get("state", "")
|
||||
|
||||
verbose_logger.debug(f"Pydantic AI: Poll attempt {attempt + 1}/{max_attempts}, state={state}")
|
||||
verbose_logger.debug("Pydantic AI: Poll attempt %s/%s, state=%s", attempt + 1, max_attempts, state)
|
||||
|
||||
if state == "completed":
|
||||
return poll_data
|
||||
|
|
@ -173,7 +173,7 @@ class PydanticAITransformation:
|
|||
# FastA2A uses root endpoint (/) not /messages
|
||||
endpoint = api_base.rstrip("/")
|
||||
|
||||
verbose_logger.info(f"Pydantic AI: Sending non-streaming request to {endpoint}")
|
||||
verbose_logger.info("Pydantic AI: Sending non-streaming request to %s", endpoint)
|
||||
|
||||
# Send request to Pydantic AI agent using shared async HTTP client
|
||||
client = get_async_httpx_client(
|
||||
|
|
@ -200,7 +200,7 @@ class PydanticAITransformation:
|
|||
# Need to poll for completion
|
||||
task_id = result.get("id")
|
||||
if task_id:
|
||||
verbose_logger.info(f"Pydantic AI: Task {task_id} submitted, polling for completion...")
|
||||
verbose_logger.info("Pydantic AI: Task %s submitted, polling for completion...", task_id)
|
||||
response_data = await PydanticAITransformation._poll_for_completion(
|
||||
client=client,
|
||||
endpoint=endpoint,
|
||||
|
|
@ -209,7 +209,7 @@ class PydanticAITransformation:
|
|||
agent_extra_headers=agent_extra_headers,
|
||||
)
|
||||
|
||||
verbose_logger.info(f"Pydantic AI: Received completed response for request_id={request_id}")
|
||||
verbose_logger.info("Pydantic AI: Received completed response for request_id=%s", request_id)
|
||||
|
||||
return response_data
|
||||
|
||||
|
|
@ -518,4 +518,4 @@ class PydanticAITransformation:
|
|||
}
|
||||
yield completed_event
|
||||
|
||||
verbose_logger.info(f"Pydantic AI: Fake streaming completed for request_id={request_id}")
|
||||
verbose_logger.info("Pydantic AI: Fake streaming completed for request_id=%s", request_id)
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ class WatsonxOrchestrateHandler:
|
|||
response.raise_for_status()
|
||||
result: dict[str, Any] = response.json()
|
||||
status = result.get("status", "")
|
||||
verbose_logger.debug(f"WXO: Poll {attempt + 1}/{max_attempts} run='{run_id}' status='{status}'")
|
||||
verbose_logger.debug("WXO: Poll %s/%s run='%s' status='%s'", attempt + 1, max_attempts, run_id, status)
|
||||
if status in WatsonxOrchestrateTransformation.TERMINAL_STATES:
|
||||
return result
|
||||
|
||||
|
|
@ -297,8 +297,8 @@ class WatsonxOrchestrateHandler:
|
|||
response.raise_for_status()
|
||||
except httpx.TransportError as exc:
|
||||
verbose_logger.warning(
|
||||
f"WXO: Streaming request failed before a run was submitted "
|
||||
f"({exc!r}), falling back to non-streaming + fake streaming",
|
||||
"WXO: Streaming request failed before a run was submitted (%r), falling back to non-streaming + fake streaming",
|
||||
exc,
|
||||
exc_info=True,
|
||||
)
|
||||
result = await WatsonxOrchestrateHandler.handle_non_streaming(
|
||||
|
|
|
|||
|
|
@ -214,4 +214,4 @@ class WatsonxOrchestrateTransformation:
|
|||
},
|
||||
}
|
||||
|
||||
verbose_logger.debug(f"WXO: Fake streaming completed for request_id={request_id}")
|
||||
verbose_logger.debug("WXO: Fake streaming completed for request_id=%s", request_id)
|
||||
|
|
|
|||
|
|
@ -138,13 +138,15 @@ class A2AStreamingIterator:
|
|||
)
|
||||
|
||||
verbose_logger.info(
|
||||
f"A2A streaming completed: prompt_tokens={prompt_tokens}, "
|
||||
f"completion_tokens={completion_tokens}, total_tokens={total_tokens}, "
|
||||
f"response_cost={response_cost}"
|
||||
"A2A streaming completed: prompt_tokens=%s, completion_tokens=%s, total_tokens=%s, response_cost=%s",
|
||||
prompt_tokens,
|
||||
completion_tokens,
|
||||
total_tokens,
|
||||
response_cost,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Error in A2A streaming completion handler: {e}")
|
||||
verbose_logger.debug("Error in A2A streaming completion handler: %s", e)
|
||||
|
||||
def _build_logging_result(self, usage: litellm.Usage) -> dict[str, Any]:
|
||||
"""Build a result dict for logging."""
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class GetAnthropicBetaHeadersConfig:
|
|||
)
|
||||
return content
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"Failed to load local beta headers config: {e}")
|
||||
verbose_logger.error("Failed to load local beta headers config: %s", e)
|
||||
# Return empty config as fallback
|
||||
return {
|
||||
"anthropic": {},
|
||||
|
|
@ -246,7 +246,9 @@ def filter_and_transform_beta_headers(
|
|||
|
||||
# Check if header is in the mapping
|
||||
if header not in provider_mapping:
|
||||
verbose_logger.debug(f"Dropping unknown beta header '{header}' for provider '{provider}' (not in mapping)")
|
||||
verbose_logger.debug(
|
||||
"Dropping unknown beta header '%s' for provider '%s' (not in mapping)", header, provider
|
||||
)
|
||||
continue
|
||||
|
||||
# Get the mapped header value
|
||||
|
|
@ -254,7 +256,7 @@ def filter_and_transform_beta_headers(
|
|||
|
||||
# Skip if header is unsupported (null value)
|
||||
if mapped_header is None:
|
||||
verbose_logger.debug(f"Dropping unsupported beta header '{header}' for provider '{provider}'")
|
||||
verbose_logger.debug("Dropping unsupported beta header '%s' for provider '%s'", header, provider)
|
||||
continue
|
||||
|
||||
# Add the mapped header
|
||||
|
|
|
|||
|
|
@ -258,10 +258,10 @@ async def _fetch_batch_output_file_content(
|
|||
if is_base64_unified_file_id:
|
||||
try:
|
||||
file_id = is_base64_unified_file_id.split("llm_output_file_id,")[1].split(";")[0]
|
||||
verbose_logger.debug(f"Extracted LLM output file ID from unified file ID: {file_id}")
|
||||
verbose_logger.debug("Extracted LLM output file ID from unified file ID: %s", file_id)
|
||||
except (IndexError, AttributeError) as e:
|
||||
verbose_logger.error(
|
||||
f"Failed to extract LLM output file ID from unified file ID: {batch.output_file_id}, error: {e}"
|
||||
"Failed to extract LLM output file ID from unified file ID: %s, error: %s", batch.output_file_id, e
|
||||
)
|
||||
|
||||
# Build kwargs for afile_content with credentials from litellm_params
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ def create_batch(
|
|||
)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(
|
||||
f"litellm.batches.main.py::create_batch() - Error inferring custom_llm_provider - {e}"
|
||||
"litellm.batches.main.py::create_batch() - Error inferring custom_llm_provider - %s", e
|
||||
)
|
||||
|
||||
_is_async = kwargs.pop("acreate_batch", False) is True
|
||||
|
|
@ -890,7 +890,7 @@ def cancel_batch(
|
|||
)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(
|
||||
f"litellm.batches.main.py::cancel_batch() - Error inferring custom_llm_provider - {e}"
|
||||
"litellm.batches.main.py::cancel_batch() - Error inferring custom_llm_provider - %s", e
|
||||
)
|
||||
optional_params = GenericLiteLLMParams(**kwargs)
|
||||
litellm_params = get_litellm_params(
|
||||
|
|
|
|||
|
|
@ -67,7 +67,10 @@ class AzureBlobCache(BaseCache):
|
|||
cached_response = json.loads(as_str)
|
||||
|
||||
verbose_logger.debug(
|
||||
f"Got Azure Blob Cache: key: {key}, cached_response {cached_response}. Type Response {type(cached_response)}"
|
||||
"Got Azure Blob Cache: key: %s, cached_response %s. Type Response %s",
|
||||
key,
|
||||
cached_response,
|
||||
type(cached_response),
|
||||
)
|
||||
|
||||
return cached_response
|
||||
|
|
@ -84,7 +87,10 @@ class AzureBlobCache(BaseCache):
|
|||
as_str = as_bytes.decode("utf-8")
|
||||
cached_response = json.loads(as_str)
|
||||
verbose_logger.debug(
|
||||
f"Got Azure Blob Cache: key: {key}, cached_response {cached_response}. Type Response {type(cached_response)}"
|
||||
"Got Azure Blob Cache: key: %s, cached_response %s. Type Response %s",
|
||||
key,
|
||||
cached_response,
|
||||
type(cached_response),
|
||||
)
|
||||
return cached_response
|
||||
except ResourceNotFoundError:
|
||||
|
|
|
|||
|
|
@ -676,7 +676,7 @@ class Cache:
|
|||
cache_key, cached_data, kwargs = self._add_cache_logic(result=result, **kwargs)
|
||||
self.cache.set_cache(cache_key, cached_data, **kwargs)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"LiteLLM Cache: Excepton add_cache: {e}")
|
||||
verbose_logger.exception("LiteLLM Cache: Excepton add_cache: %s", e)
|
||||
|
||||
async def async_add_cache(self, result, dynamic_cache_object: BaseCache | None = None, **kwargs):
|
||||
"""
|
||||
|
|
@ -695,7 +695,7 @@ class Cache:
|
|||
else:
|
||||
await self.cache.async_set_cache(cache_key, cached_data, **kwargs)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"LiteLLM Cache: Excepton add_cache: {e}")
|
||||
verbose_logger.exception("LiteLLM Cache: Excepton add_cache: %s", e)
|
||||
|
||||
def _convert_to_cached_embedding(
|
||||
self,
|
||||
|
|
@ -874,7 +874,7 @@ class Cache:
|
|||
else:
|
||||
await self.cache.async_set_cache_pipeline(cache_list=cache_list, **kwargs)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"LiteLLM Cache: Excepton add_cache: {e}")
|
||||
verbose_logger.exception("LiteLLM Cache: Excepton add_cache: %s", e)
|
||||
|
||||
def should_use_cache(self, **kwargs):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ class LLMCachingHandler:
|
|||
embedding_all_elements_cache_hit=embedding_all_elements_cache_hit,
|
||||
)
|
||||
|
||||
verbose_logger.debug(f"CACHE RESULT: {cached_result}")
|
||||
verbose_logger.debug("CACHE RESULT: %s", cached_result)
|
||||
return CachingHandlerResponse(
|
||||
cached_result=cached_result,
|
||||
final_embedding_cached_response=final_embedding_cached_response,
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ class DualCache(BaseCache):
|
|||
|
||||
return result
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"LiteLLM Cache: Excepton async add_cache: {e}")
|
||||
verbose_logger.error("LiteLLM Cache: Excepton async add_cache: %s", e)
|
||||
raise e
|
||||
|
||||
def get_cache(
|
||||
|
|
@ -347,7 +347,7 @@ class DualCache(BaseCache):
|
|||
if self.redis_cache is not None and local_only is False:
|
||||
await self.redis_cache.async_set_cache(key, value, **kwargs)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"LiteLLM Cache: Excepton async add_cache: {e}")
|
||||
verbose_logger.exception("LiteLLM Cache: Excepton async add_cache: %s", e)
|
||||
|
||||
# async_batch_set_cache
|
||||
async def async_set_cache_pipeline(self, cache_list: list, local_only: bool = False, **kwargs):
|
||||
|
|
@ -366,7 +366,7 @@ class DualCache(BaseCache):
|
|||
cache_list=cache_list, ttl=kwargs.pop("ttl", None), **kwargs
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"LiteLLM Cache: Excepton async add_cache: {e}")
|
||||
verbose_logger.exception("LiteLLM Cache: Excepton async add_cache: %s", e)
|
||||
|
||||
async def async_increment_cache(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -71,12 +71,15 @@ class GCSCache(BaseCache):
|
|||
if response.status_code == 200:
|
||||
cached_response = json.loads(response.text)
|
||||
verbose_logger.debug(
|
||||
f"Got GCS Cache: key: {key}, cached_response {cached_response}. Type Response {type(cached_response)}"
|
||||
"Got GCS Cache: key: %s, cached_response %s. Type Response %s",
|
||||
key,
|
||||
cached_response,
|
||||
type(cached_response),
|
||||
)
|
||||
return cached_response
|
||||
return None
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"GCS Caching: get_cache() - Got exception from GCS: {e}")
|
||||
verbose_logger.error("GCS Caching: get_cache() - Got exception from GCS: %s", e)
|
||||
|
||||
async def async_get_cache(self, key, **kwargs):
|
||||
try:
|
||||
|
|
@ -89,7 +92,7 @@ class GCSCache(BaseCache):
|
|||
return json.loads(response.text)
|
||||
return None
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"GCS Caching: async_get_cache() - Got exception from GCS: {e}")
|
||||
verbose_logger.error("GCS Caching: async_get_cache() - Got exception from GCS: %s", e)
|
||||
|
||||
def flush_cache(self):
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -346,7 +346,8 @@ class RedisCache(BaseCache):
|
|||
verbose_logger.debug("Ignoring async redis ping. No running event loop.")
|
||||
else:
|
||||
verbose_logger.error(
|
||||
f"Error connecting to Async Redis client - {e}",
|
||||
"Error connecting to Async Redis client - %s",
|
||||
e,
|
||||
extra={"error": str(e)},
|
||||
)
|
||||
self._handle_async_ping_error(e)
|
||||
|
|
@ -1139,7 +1140,7 @@ class RedisCache(BaseCache):
|
|||
|
||||
return decoded_results
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"Error occurred in batch get cache - {e}")
|
||||
verbose_logger.error("Error occurred in batch get cache - %s", e)
|
||||
return key_value_dict
|
||||
|
||||
@_redis_circuit_breaker_guard
|
||||
|
|
@ -1257,7 +1258,7 @@ class RedisCache(BaseCache):
|
|||
parent_otel_span=parent_otel_span,
|
||||
)
|
||||
)
|
||||
verbose_logger.error(f"Error occurred in async batch get cache - {e}")
|
||||
verbose_logger.error("Error occurred in async batch get cache - %s", e)
|
||||
_record_swallowed_redis_failure(self._circuit_breaker, e)
|
||||
return key_value_dict
|
||||
|
||||
|
|
@ -1292,7 +1293,7 @@ class RedisCache(BaseCache):
|
|||
error=e,
|
||||
call_type=f"sync_ping <- {_get_call_stack_info()}",
|
||||
)
|
||||
verbose_logger.error(f"LiteLLM Redis Cache PING: - Got exception from REDIS : {e}")
|
||||
verbose_logger.error("LiteLLM Redis Cache PING: - Got exception from REDIS : %s", e)
|
||||
raise e
|
||||
|
||||
async def ping(self) -> bool:
|
||||
|
|
@ -1326,7 +1327,7 @@ class RedisCache(BaseCache):
|
|||
call_type=f"async_ping <- {_get_call_stack_info()}",
|
||||
)
|
||||
)
|
||||
verbose_logger.error(f"LiteLLM Redis Cache PING: - Got exception from REDIS : {e}")
|
||||
verbose_logger.error("LiteLLM Redis Cache PING: - Got exception from REDIS : %s", e)
|
||||
raise e
|
||||
|
||||
@_redis_circuit_breaker_guard
|
||||
|
|
@ -1388,7 +1389,7 @@ class RedisCache(BaseCache):
|
|||
else:
|
||||
return {"status": "failed", "message": "Redis ping returned False"}
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"Redis connection test failed: {e}")
|
||||
verbose_logger.error("Redis connection test failed: %s", e)
|
||||
return {
|
||||
"status": "failed",
|
||||
"message": f"Redis connection failed: {e}",
|
||||
|
|
@ -1426,7 +1427,7 @@ class RedisCache(BaseCache):
|
|||
# Execute the pipeline and return results
|
||||
results = await pipe.execute()
|
||||
# only return float values
|
||||
verbose_logger.debug(f"Increment ASYNC Redis Cache PIPELINE: results: {results}")
|
||||
verbose_logger.debug("Increment ASYNC Redis Cache PIPELINE: results: %s", results)
|
||||
return [r for r in results if isinstance(r, float)]
|
||||
|
||||
@_redis_circuit_breaker_guard
|
||||
|
|
@ -1513,7 +1514,7 @@ class RedisCache(BaseCache):
|
|||
return None
|
||||
return ttl
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Redis TTL Error: {e}")
|
||||
verbose_logger.debug("Redis TTL Error: %s", e)
|
||||
_record_swallowed_redis_failure(self._circuit_breaker, e)
|
||||
return None
|
||||
|
||||
|
|
@ -1565,7 +1566,7 @@ class RedisCache(BaseCache):
|
|||
call_type=f"async_rpush <- {_get_call_stack_info()}",
|
||||
)
|
||||
)
|
||||
verbose_logger.error(f"LiteLLM Redis Cache RPUSH: - Got exception from REDIS : {e}")
|
||||
verbose_logger.error("LiteLLM Redis Cache RPUSH: - Got exception from REDIS : %s", e)
|
||||
raise e
|
||||
|
||||
async def _pipeline_rpush_helper(
|
||||
|
|
@ -1711,7 +1712,7 @@ class RedisCache(BaseCache):
|
|||
call_type=f"async_lpop <- {_get_call_stack_info()}",
|
||||
)
|
||||
)
|
||||
verbose_logger.error(f"LiteLLM Redis Cache LPOP: - Got exception from REDIS : {e}")
|
||||
verbose_logger.error("LiteLLM Redis Cache LPOP: - Got exception from REDIS : %s", e)
|
||||
raise e
|
||||
|
||||
async def _pipeline_lpop_helper(
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ class RedisClusterCache(RedisCache):
|
|||
except Exception as e:
|
||||
from litellm._logging import verbose_logger
|
||||
|
||||
verbose_logger.error(f"Redis Cluster connection test failed: {e}")
|
||||
verbose_logger.error("Redis Cluster connection test failed: %s", e)
|
||||
return {
|
||||
"status": "failed",
|
||||
"message": f"Redis Cluster connection failed: {e}",
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ class RedisSemanticCache(BaseCache):
|
|||
cache_vectorizer=cache_vectorizer,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"Redis semantic-cache index build failed: {e}")
|
||||
verbose_logger.error("Redis semantic-cache index build failed: %s", e)
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
|
|
|
|||
|
|
@ -104,12 +104,12 @@ class S3Cache(BaseCache):
|
|||
Compatible with Python 3.8+.
|
||||
"""
|
||||
try:
|
||||
verbose_logger.debug(f"Set ASYNC S3 Cache: Key={key}. Value={value}")
|
||||
verbose_logger.debug("Set ASYNC S3 Cache: Key=%s. Value=%s", key, value)
|
||||
loop = asyncio.get_event_loop()
|
||||
func = partial(self.set_cache, key, value, **kwargs)
|
||||
await loop.run_in_executor(None, func)
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"S3 Caching: async_set_cache() - Got exception from S3: {e}")
|
||||
verbose_logger.error("S3 Caching: async_set_cache() - Got exception from S3: %s", e)
|
||||
|
||||
def get_cache(self, key, **kwargs):
|
||||
import botocore
|
||||
|
|
@ -138,17 +138,20 @@ class S3Cache(BaseCache):
|
|||
if not isinstance(cached_response, dict):
|
||||
cached_response = dict(cached_response)
|
||||
verbose_logger.debug(
|
||||
f"Got S3 Cache: key: {key}, cached_response {cached_response}. Type Response {type(cached_response)}"
|
||||
"Got S3 Cache: key: %s, cached_response %s. Type Response %s",
|
||||
key,
|
||||
cached_response,
|
||||
type(cached_response),
|
||||
)
|
||||
|
||||
return cached_response
|
||||
except botocore.exceptions.ClientError as e: # type: ignore
|
||||
if e.response["Error"]["Code"] == "NoSuchKey":
|
||||
verbose_logger.debug(f"S3 Cache: The specified key '{key}' does not exist in the S3 bucket.")
|
||||
verbose_logger.debug("S3 Cache: The specified key '%s' does not exist in the S3 bucket.", key)
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"S3 Caching: get_cache() - Got exception from S3: {e}")
|
||||
verbose_logger.error("S3 Caching: get_cache() - Got exception from S3: %s", e)
|
||||
|
||||
async def async_get_cache(self, key, **kwargs):
|
||||
"""
|
||||
|
|
@ -156,13 +159,13 @@ class S3Cache(BaseCache):
|
|||
Compatible with Python 3.8+.
|
||||
"""
|
||||
try:
|
||||
verbose_logger.debug(f"Get ASYNC S3 Cache: key: {key}")
|
||||
verbose_logger.debug("Get ASYNC S3 Cache: key: %s", key)
|
||||
loop = asyncio.get_event_loop()
|
||||
func = partial(self.get_cache, key, **kwargs)
|
||||
result = await loop.run_in_executor(None, func)
|
||||
return result
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"S3 Caching: async_get_cache() - Got exception from S3: {e}")
|
||||
verbose_logger.error("S3 Caching: async_get_cache() - Got exception from S3: %s", e)
|
||||
return None
|
||||
|
||||
def flush_cache(self):
|
||||
|
|
|
|||
|
|
@ -408,7 +408,7 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge):
|
|||
self._map_optional_params_to_responses_api_request(optional_params, responses_api_request)
|
||||
|
||||
stream = optional_params.get("stream") or litellm_params.get("stream", False)
|
||||
verbose_logger.debug(f"Chat provider: Stream parameter: {stream}")
|
||||
verbose_logger.debug("Chat provider: Stream parameter: %s", stream)
|
||||
|
||||
# Ensure stream is properly set in the request
|
||||
if stream:
|
||||
|
|
@ -418,7 +418,7 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge):
|
|||
previous_response_id = optional_params.get("previous_response_id")
|
||||
if previous_response_id:
|
||||
# Use the existing session handler for responses API
|
||||
verbose_logger.debug(f"Chat provider: Warning ignoring previous response ID: {previous_response_id}")
|
||||
verbose_logger.debug("Chat provider: Warning ignoring previous response ID: %s", previous_response_id)
|
||||
|
||||
# Convert back to responses API format for the actual request
|
||||
|
||||
|
|
@ -438,7 +438,7 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge):
|
|||
"client": client,
|
||||
}
|
||||
|
||||
verbose_logger.debug(f"Chat provider: Final request model={api_model}, input_items={len(input_items)}")
|
||||
verbose_logger.debug("Chat provider: Final request model=%s, input_items=%s", api_model, len(input_items))
|
||||
|
||||
self._merge_responses_api_request_into_request_data(request_data, responses_api_request, instructions)
|
||||
|
||||
|
|
@ -776,29 +776,29 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge):
|
|||
"""Convert chat completion content to responses API format"""
|
||||
from litellm.types.llms.openai import ChatCompletionImageObject
|
||||
|
||||
verbose_logger.debug(f"Chat provider: Converting content to responses format - input type: {type(content)}")
|
||||
verbose_logger.debug("Chat provider: Converting content to responses format - input type: %s", type(content))
|
||||
|
||||
if content is None:
|
||||
return [self._convert_content_str_to_input_text("", role)]
|
||||
elif isinstance(content, str):
|
||||
result = [self._convert_content_str_to_input_text(content, role)]
|
||||
verbose_logger.debug(f"Chat provider: String content -> {result}")
|
||||
verbose_logger.debug("Chat provider: String content -> %s", result)
|
||||
return result
|
||||
elif isinstance(content, list):
|
||||
result = []
|
||||
for i, item in enumerate(content):
|
||||
verbose_logger.debug(f"Chat provider: Processing content item {i}: {type(item)} = {item}")
|
||||
verbose_logger.debug("Chat provider: Processing content item %s: %s = %s", i, type(item), item)
|
||||
if isinstance(item, str):
|
||||
converted = self._convert_content_str_to_input_text(item, role)
|
||||
result.append(converted)
|
||||
verbose_logger.debug(f"Chat provider: -> {converted}")
|
||||
verbose_logger.debug("Chat provider: -> %s", converted)
|
||||
elif isinstance(item, dict):
|
||||
# Handle multimodal content
|
||||
original_type = item.get("type")
|
||||
if original_type == "text":
|
||||
converted = self._convert_content_str_to_input_text(item.get("text", ""), role)
|
||||
result.append(converted)
|
||||
verbose_logger.debug(f"Chat provider: text -> {converted}")
|
||||
verbose_logger.debug("Chat provider: text -> %s", converted)
|
||||
elif original_type == "image_url":
|
||||
# Map to responses API image format
|
||||
converted = cast(
|
||||
|
|
@ -808,14 +808,14 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge):
|
|||
),
|
||||
)
|
||||
result.append(converted)
|
||||
verbose_logger.debug(f"Chat provider: image_url -> {converted}")
|
||||
verbose_logger.debug("Chat provider: image_url -> %s", converted)
|
||||
else:
|
||||
# Try to map other types to responses API format
|
||||
item_type = original_type or "input_text"
|
||||
if item_type == "image":
|
||||
converted = {"type": "input_image", **item}
|
||||
result.append(converted)
|
||||
verbose_logger.debug(f"Chat provider: image -> {converted}")
|
||||
verbose_logger.debug("Chat provider: image -> %s", converted)
|
||||
elif item_type == "file":
|
||||
# Map Chat Completion file to Responses API input_file
|
||||
# {"type": "file", "file": {"file_data": "...", "filename": "..."}}
|
||||
|
|
@ -827,7 +827,7 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge):
|
|||
if key in file_data:
|
||||
converted[key] = file_data[key]
|
||||
result.append(converted)
|
||||
verbose_logger.debug(f"Chat provider: file -> {converted}")
|
||||
verbose_logger.debug("Chat provider: file -> %s", converted)
|
||||
elif item_type in [
|
||||
"input_text",
|
||||
"input_image",
|
||||
|
|
@ -839,17 +839,17 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge):
|
|||
]:
|
||||
# Already in responses API format
|
||||
result.append(item)
|
||||
verbose_logger.debug(f"Chat provider: passthrough -> {item}")
|
||||
verbose_logger.debug("Chat provider: passthrough -> %s", item)
|
||||
else:
|
||||
# Default to input_text for unknown types
|
||||
converted = self._convert_content_str_to_input_text(str(item.get("text", item)), role)
|
||||
result.append(converted)
|
||||
verbose_logger.debug(f"Chat provider: unknown({original_type}) -> {converted}")
|
||||
verbose_logger.debug(f"Chat provider: Final converted content: {result}")
|
||||
verbose_logger.debug("Chat provider: unknown(%s) -> %s", original_type, converted)
|
||||
verbose_logger.debug("Chat provider: Final converted content: %s", result)
|
||||
return result
|
||||
else:
|
||||
result = [self._convert_content_str_to_input_text(str(content), role)]
|
||||
verbose_logger.debug(f"Chat provider: Other content type -> {result}")
|
||||
verbose_logger.debug("Chat provider: Other content type -> %s", result)
|
||||
return result
|
||||
|
||||
def _convert_tools_to_responses_format(self, tools: list[dict[str, Any]]) -> list["ALL_RESPONSES_API_TOOL_PARAMS"]:
|
||||
|
|
@ -1032,13 +1032,13 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge):
|
|||
annotation_dict = annotation
|
||||
else:
|
||||
# Skip unsupported annotation types
|
||||
verbose_logger.debug(f"Skipping unsupported annotation type: {type(annotation)}")
|
||||
verbose_logger.debug("Skipping unsupported annotation type: %s", type(annotation))
|
||||
continue
|
||||
|
||||
result.append(annotation_dict) # type: ignore
|
||||
except Exception as e:
|
||||
# Skip malformed annotations
|
||||
verbose_logger.debug(f"Skipping malformed annotation: {annotation}, error: {e}")
|
||||
verbose_logger.debug("Skipping malformed annotation: %s, error: %s", annotation, e)
|
||||
continue
|
||||
|
||||
return result if result else None
|
||||
|
|
@ -1122,11 +1122,11 @@ class OpenAiResponsesToChatCompletionStreamIterator(BaseModelResponseIterator):
|
|||
):
|
||||
return ModelResponseStream(**parsed_chunk)
|
||||
|
||||
verbose_logger.debug(f"Chat provider: Processing event type: {event_type}")
|
||||
verbose_logger.debug("Chat provider: Processing event type: %s", event_type)
|
||||
|
||||
if event_type == "response.created":
|
||||
# Initial response creation event
|
||||
verbose_logger.debug(f"Chat provider: response.created -> {parsed_chunk}")
|
||||
verbose_logger.debug("Chat provider: response.created -> %s", parsed_chunk)
|
||||
return ModelResponseStream(
|
||||
choices=[
|
||||
StreamingChoices(
|
||||
|
|
@ -1345,7 +1345,7 @@ class OpenAiResponsesToChatCompletionStreamIterator(BaseModelResponseIterator):
|
|||
else:
|
||||
pass
|
||||
# For any unhandled event types, create a minimal valid chunk or skip
|
||||
verbose_logger.debug(f"Chat provider: Unhandled event type '{event_type}', creating empty chunk")
|
||||
verbose_logger.debug("Chat provider: Unhandled event type '%s', creating empty chunk", event_type)
|
||||
|
||||
# Return a minimal valid chunk for unknown events
|
||||
return ModelResponseStream(
|
||||
|
|
@ -1368,7 +1368,7 @@ class OpenAiResponsesToChatCompletionStreamIterator(BaseModelResponseIterator):
|
|||
Returns:
|
||||
ModelResponseStream: OpenAI-formatted streaming chunk
|
||||
"""
|
||||
verbose_logger.debug(f"Chat provider: transform_streaming_response called with chunk: {chunk}")
|
||||
verbose_logger.debug("Chat provider: transform_streaming_response called with chunk: %s", chunk)
|
||||
return self._with_stream_scoped_id(
|
||||
OpenAiResponsesToChatCompletionStreamIterator.translate_responses_chunk_to_openai_stream(chunk)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ def _get_additional_costs(
|
|||
completion_tokens=completion_tokens,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Error calculating additional costs: {e}")
|
||||
verbose_logger.debug("Error calculating additional costs: %s", e)
|
||||
|
||||
return None
|
||||
|
||||
|
|
@ -715,7 +715,7 @@ def _get_provider_for_cost_calc(
|
|||
_, custom_llm_provider, _, _ = litellm.get_llm_provider(model=model)
|
||||
except Exception as e:
|
||||
verbose_logger.debug(
|
||||
f"litellm.cost_calculator.py::_get_provider_for_cost_calc() - Error inferring custom_llm_provider - {e}"
|
||||
"litellm.cost_calculator.py::_get_provider_for_cost_calc() - Error inferring custom_llm_provider - %s", e
|
||||
)
|
||||
return None
|
||||
|
||||
|
|
@ -896,7 +896,7 @@ def _get_usage_object(
|
|||
elif isinstance(usage_obj, BaseModel):
|
||||
return Usage(**usage_obj.model_dump())
|
||||
else:
|
||||
verbose_logger.debug(f"Unknown usage object type: {type(usage_obj)}, usage_obj: {usage_obj}")
|
||||
verbose_logger.debug("Unknown usage object type: %s, usage_obj: %s", type(usage_obj), usage_obj)
|
||||
return None
|
||||
|
||||
|
||||
|
|
@ -994,16 +994,17 @@ def _apply_cost_margin(
|
|||
if custom_llm_provider and custom_llm_provider in litellm.cost_margin_config:
|
||||
margin_config = litellm.cost_margin_config[custom_llm_provider]
|
||||
if verbose_logger.isEnabledFor(logging.DEBUG):
|
||||
verbose_logger.debug(f"Found provider-specific margin config for {custom_llm_provider}: {margin_config}")
|
||||
verbose_logger.debug("Found provider-specific margin config for %s: %s", custom_llm_provider, margin_config)
|
||||
elif "global" in litellm.cost_margin_config:
|
||||
margin_config = litellm.cost_margin_config["global"]
|
||||
if verbose_logger.isEnabledFor(logging.DEBUG):
|
||||
verbose_logger.debug(f"Using global margin config: {margin_config}")
|
||||
verbose_logger.debug("Using global margin config: %s", margin_config)
|
||||
else:
|
||||
if verbose_logger.isEnabledFor(logging.DEBUG):
|
||||
verbose_logger.debug(
|
||||
f"No margin config found. Provider: {custom_llm_provider}, "
|
||||
f"Available configs: {list(litellm.cost_margin_config.keys())}"
|
||||
"No margin config found. Provider: %s, Available configs: %s",
|
||||
custom_llm_provider,
|
||||
list(litellm.cost_margin_config.keys()),
|
||||
)
|
||||
|
||||
if margin_config is not None:
|
||||
|
|
@ -1098,7 +1099,7 @@ def _store_cost_breakdown_in_logging_obj(
|
|||
)
|
||||
|
||||
except Exception as breakdown_error:
|
||||
verbose_logger.debug(f"Error storing cost breakdown: {breakdown_error}")
|
||||
verbose_logger.debug("Error storing cost breakdown: %s", breakdown_error)
|
||||
# Don't fail the main cost calculation if breakdown storage fails
|
||||
|
||||
|
||||
|
|
@ -1225,7 +1226,7 @@ def completion_cost(
|
|||
for idx, model in enumerate(potential_model_names):
|
||||
try:
|
||||
if verbose_logger.isEnabledFor(logging.DEBUG):
|
||||
verbose_logger.debug(f"selected model name for cost calculation: {model}")
|
||||
verbose_logger.debug("selected model name for cost calculation: %s", model)
|
||||
|
||||
if completion_response is not None and (
|
||||
isinstance(completion_response, BaseModel) or isinstance(completion_response, dict)
|
||||
|
|
@ -1321,7 +1322,8 @@ def completion_cost(
|
|||
) # strip the llm provider from the model name -> for image gen cost calculation
|
||||
except Exception as e:
|
||||
verbose_logger.debug(
|
||||
f"litellm.cost_calculator.py::completion_cost() - Error inferring custom_llm_provider - {e}"
|
||||
"litellm.cost_calculator.py::completion_cost() - Error inferring custom_llm_provider - %s",
|
||||
e,
|
||||
)
|
||||
if CostCalculatorUtils._call_type_has_image_response(call_type) and isinstance(
|
||||
completion_response, ImageResponse
|
||||
|
|
@ -1672,7 +1674,7 @@ def completion_cost(
|
|||
return _final_cost
|
||||
except Exception as e:
|
||||
verbose_logger.debug(
|
||||
f"litellm.cost_calculator.py::completion_cost() - Error calculating cost for model={model} - {e}"
|
||||
"litellm.cost_calculator.py::completion_cost() - Error calculating cost for model=%s - %s", model, e
|
||||
)
|
||||
if idx == len(potential_model_names) - 1:
|
||||
raise e
|
||||
|
|
@ -1888,7 +1890,7 @@ def vector_store_search_cost(
|
|||
)
|
||||
|
||||
if config is None:
|
||||
verbose_logger.debug(f"Vector store search is not supported for {custom_llm_provider}")
|
||||
verbose_logger.debug("Vector store search is not supported for %s", custom_llm_provider)
|
||||
return 0.0, 0.0
|
||||
|
||||
return config.calculate_vector_store_cost(
|
||||
|
|
@ -1976,7 +1978,7 @@ def default_image_cost_calculator(
|
|||
# gpt-image-1 models use low, medium, high quality. If user did not specify quality, use medium fot gpt-image-1 model family
|
||||
model_name_with_v2_quality = f"{ImageGenerationRequestQuality.HIGH.value}/{base_model_name}"
|
||||
|
||||
verbose_logger.debug(f"Looking up cost for models: {model_name_with_quality}, {base_model_name}")
|
||||
verbose_logger.debug("Looking up cost for models: %s, %s", model_name_with_quality, base_model_name)
|
||||
|
||||
model_without_provider = f"{size_str}/{model.split('/')[-1]}"
|
||||
model_with_quality_without_provider = f"{quality}/{model_without_provider}" if quality else model_without_provider
|
||||
|
|
@ -2046,7 +2048,7 @@ def default_video_cost_calculator(
|
|||
model_name_without_custom_llm_provider = model.replace(f"{custom_llm_provider}/", "")
|
||||
base_model_name = f"{custom_llm_provider}/{model_name_without_custom_llm_provider}"
|
||||
|
||||
verbose_logger.debug(f"Looking up cost for video model: {base_model_name}")
|
||||
verbose_logger.debug("Looking up cost for video model: %s", base_model_name)
|
||||
|
||||
model_without_provider = model.split("/")[-1]
|
||||
|
||||
|
|
@ -2082,7 +2084,8 @@ def default_video_cost_calculator(
|
|||
|
||||
# If no cost information found, return 0
|
||||
verbose_logger.info(
|
||||
f"No cost information found for video model {model}. Please add pricing to model_prices_and_context_window.json"
|
||||
"No cost information found for video model %s. Please add pricing to model_prices_and_context_window.json",
|
||||
model,
|
||||
)
|
||||
return 0.0
|
||||
|
||||
|
|
|
|||
|
|
@ -364,7 +364,7 @@ class MCPClient:
|
|||
try:
|
||||
await session_ctx.__aexit__(None, None, None)
|
||||
except BaseException as e:
|
||||
verbose_logger.debug(f"Error during session context exit: {e}")
|
||||
verbose_logger.debug("Error during session context exit: %s", e)
|
||||
except BaseException as e:
|
||||
in_flight_error = e
|
||||
raise
|
||||
|
|
@ -372,7 +372,7 @@ class MCPClient:
|
|||
try:
|
||||
await transport_ctx.__aexit__(None, None, None)
|
||||
except BaseException as exit_error:
|
||||
verbose_logger.debug(f"Error during transport context exit: {exit_error}")
|
||||
verbose_logger.debug("Error during transport context exit: %s", exit_error)
|
||||
root_cause = _first_non_cancelled_cause(exit_error)
|
||||
if root_cause is not None and isinstance(in_flight_error, asyncio.CancelledError):
|
||||
raise root_cause from in_flight_error
|
||||
|
|
@ -402,7 +402,7 @@ class MCPClient:
|
|||
try:
|
||||
await http_client.aclose()
|
||||
except BaseException as e:
|
||||
verbose_logger.debug(f"Error during http_client cleanup: {e}")
|
||||
verbose_logger.debug("Error during http_client cleanup: %s", e)
|
||||
|
||||
def update_auth_value(self, mcp_auth_value: str | dict[str, str]):
|
||||
"""
|
||||
|
|
@ -464,7 +464,7 @@ class MCPClient:
|
|||
"""Create an httpx.AsyncClient with LiteLLM's SSL configuration."""
|
||||
# Get unified SSL configuration using the same logic as http_handler.py
|
||||
ssl_config = get_ssl_configuration(self.ssl_verify)
|
||||
verbose_logger.debug(f"MCP client using SSL configuration: {type(ssl_config).__name__}")
|
||||
verbose_logger.debug("MCP client using SSL configuration: %s", type(ssl_config).__name__)
|
||||
# The MCP SDK's sse_client and streamable_http_client call this factory without
|
||||
# passing auth=, so the fallback is used: a v2-resolved auth if present, else the
|
||||
# SigV4 aws_auth. Both are None for the common case — no behavior change.
|
||||
|
|
@ -490,7 +490,7 @@ class MCPClient:
|
|||
MCP client (triggering the upstream OAuth flow) rather than
|
||||
masking them as "connected, no tools".
|
||||
"""
|
||||
verbose_logger.debug(f"MCP client listing tools from {self.server_url or 'stdio'}")
|
||||
verbose_logger.debug("MCP client listing tools from %s", self.server_url or "stdio")
|
||||
|
||||
async def _list_tools_operation(session: ClientSession):
|
||||
return await session.list_tools()
|
||||
|
|
@ -499,7 +499,9 @@ class MCPClient:
|
|||
result = await self.run_with_session(_list_tools_operation, quiet_on_error=raise_on_error)
|
||||
tool_count = len(result.tools)
|
||||
tool_names = [tool.name for tool in result.tools]
|
||||
verbose_logger.info(f"MCP client listed {tool_count} tools from {self.server_url or 'stdio'}: {tool_names}")
|
||||
verbose_logger.info(
|
||||
"MCP client listed %s tools from %s: %s", tool_count, self.server_url or "stdio", tool_names
|
||||
)
|
||||
return result.tools
|
||||
except asyncio.CancelledError:
|
||||
verbose_logger.warning("MCP client list_tools was cancelled")
|
||||
|
|
@ -555,7 +557,7 @@ class MCPClient:
|
|||
an upstream 401 so it can re-mint the exchanged token and retry once; every other
|
||||
caller keeps the default and gets graceful ``isError`` degradation.
|
||||
"""
|
||||
verbose_logger.info(f"MCP client calling tool '{call_tool_request_params.name}'")
|
||||
verbose_logger.info("MCP client calling tool '%s'", call_tool_request_params.name)
|
||||
|
||||
async def on_progress(progress: float, total: float | None, message: str | None):
|
||||
percentage = (progress / total * 100) if total else 0
|
||||
|
|
@ -568,7 +570,7 @@ class MCPClient:
|
|||
try:
|
||||
await host_progress_callback(progress, total)
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Failed to forward to Host: {e}")
|
||||
verbose_logger.warning("Failed to forward to Host: %s", e)
|
||||
|
||||
async def _call_tool_operation(session: ClientSession):
|
||||
verbose_logger.debug("MCP client sending tool call to session")
|
||||
|
|
@ -580,16 +582,16 @@ class MCPClient:
|
|||
|
||||
try:
|
||||
tool_result = await self.run_with_session(_call_tool_operation, quiet_on_error=raise_on_error)
|
||||
verbose_logger.info(f"MCP client tool call '{call_tool_request_params.name}' completed successfully")
|
||||
verbose_logger.info("MCP client tool call '%s' completed successfully", call_tool_request_params.name)
|
||||
return tool_result
|
||||
except asyncio.CancelledError:
|
||||
verbose_logger.warning(f"MCP client tool call timed out after {self.timeout}s for {self.server_url}")
|
||||
verbose_logger.warning("MCP client tool call timed out after %ss for %s", self.timeout, self.server_url)
|
||||
raise
|
||||
except Exception as e:
|
||||
import traceback
|
||||
|
||||
error_trace = traceback.format_exc()
|
||||
verbose_logger.debug(f"MCP client tool call traceback:\n{error_trace}")
|
||||
verbose_logger.debug("MCP client tool call traceback:\n%s", error_trace)
|
||||
# Log detailed error information
|
||||
error_type = type(e).__name__
|
||||
# When the caller opted into raise_on_error it owns the exception and logs it at the
|
||||
|
|
@ -619,7 +621,7 @@ class MCPClient:
|
|||
|
||||
async def list_prompts(self) -> list[Prompt]:
|
||||
"""List available prompts from the server."""
|
||||
verbose_logger.debug(f"MCP client listing tools from {self.server_url or 'stdio'}")
|
||||
verbose_logger.debug("MCP client listing tools from %s", self.server_url or "stdio")
|
||||
|
||||
async def _list_prompts_operation(session: ClientSession):
|
||||
return await session.list_prompts()
|
||||
|
|
@ -629,7 +631,7 @@ class MCPClient:
|
|||
prompt_count = len(result.prompts)
|
||||
prompt_names = [prompt.name for prompt in result.prompts]
|
||||
verbose_logger.info(
|
||||
f"MCP client listed {prompt_count} tools from {self.server_url or 'stdio'}: {prompt_names}"
|
||||
"MCP client listed %s tools from %s: %s", prompt_count, self.server_url or "stdio", prompt_names
|
||||
)
|
||||
return result.prompts
|
||||
except asyncio.CancelledError:
|
||||
|
|
@ -638,11 +640,11 @@ class MCPClient:
|
|||
except Exception as e:
|
||||
error_type = type(e).__name__
|
||||
verbose_logger.error(
|
||||
f"MCP client list_prompts failed - "
|
||||
f"Error Type: {error_type}, "
|
||||
f"Error: {e}, "
|
||||
f"Server: {self.server_url or 'stdio'}, "
|
||||
f"Transport: {self.transport_type}"
|
||||
"MCP client list_prompts failed - Error Type: %s, Error: %s, Server: %s, Transport: %s",
|
||||
error_type,
|
||||
e,
|
||||
self.server_url or "stdio",
|
||||
self.transport_type,
|
||||
)
|
||||
# Check if it's a stream/connection error
|
||||
if "BrokenResourceError" in error_type or "Broken" in error_type:
|
||||
|
|
@ -655,7 +657,7 @@ class MCPClient:
|
|||
|
||||
async def get_prompt(self, get_prompt_request_params: GetPromptRequestParams) -> GetPromptResult:
|
||||
"""Fetch a prompt definition from the MCP server."""
|
||||
verbose_logger.info(f"MCP client fetching prompt '{get_prompt_request_params.name}'")
|
||||
verbose_logger.info("MCP client fetching prompt '%s'", get_prompt_request_params.name)
|
||||
|
||||
async def _get_prompt_operation(session: ClientSession):
|
||||
verbose_logger.debug("MCP client sending get_prompt request to session")
|
||||
|
|
@ -666,7 +668,7 @@ class MCPClient:
|
|||
|
||||
try:
|
||||
get_prompt_result = await self.run_with_session(_get_prompt_operation)
|
||||
verbose_logger.info(f"MCP client get_prompt '{get_prompt_request_params.name}' completed successfully")
|
||||
verbose_logger.info("MCP client get_prompt '%s' completed successfully", get_prompt_request_params.name)
|
||||
return get_prompt_result
|
||||
except asyncio.CancelledError:
|
||||
verbose_logger.warning("MCP client get_prompt was cancelled")
|
||||
|
|
@ -675,16 +677,16 @@ class MCPClient:
|
|||
import traceback
|
||||
|
||||
error_trace = traceback.format_exc()
|
||||
verbose_logger.debug(f"MCP client get_prompt traceback:\n{error_trace}")
|
||||
verbose_logger.debug("MCP client get_prompt traceback:\n%s", error_trace)
|
||||
# Log detailed error information
|
||||
error_type = type(e).__name__
|
||||
verbose_logger.error(
|
||||
f"MCP client get_prompt failed - "
|
||||
f"Error Type: {error_type}, "
|
||||
f"Error: {e}, "
|
||||
f"Prompt: {get_prompt_request_params.name}, "
|
||||
f"Server: {self.server_url or 'stdio'}, "
|
||||
f"Transport: {self.transport_type}"
|
||||
"MCP client get_prompt failed - Error Type: %s, Error: %s, Prompt: %s, Server: %s, Transport: %s",
|
||||
error_type,
|
||||
e,
|
||||
get_prompt_request_params.name,
|
||||
self.server_url or "stdio",
|
||||
self.transport_type,
|
||||
)
|
||||
# Check if it's a stream/connection error
|
||||
if "BrokenResourceError" in error_type or "Broken" in error_type:
|
||||
|
|
@ -696,7 +698,7 @@ class MCPClient:
|
|||
|
||||
async def list_resources(self) -> list[Resource]:
|
||||
"""List available resources from the server."""
|
||||
verbose_logger.debug(f"MCP client listing resources from {self.server_url or 'stdio'}")
|
||||
verbose_logger.debug("MCP client listing resources from %s", self.server_url or "stdio")
|
||||
|
||||
async def _list_resources_operation(session: ClientSession):
|
||||
return await session.list_resources()
|
||||
|
|
@ -706,7 +708,7 @@ class MCPClient:
|
|||
resource_count = len(result.resources)
|
||||
resource_names = [resource.name for resource in result.resources]
|
||||
verbose_logger.info(
|
||||
f"MCP client listed {resource_count} resources from {self.server_url or 'stdio'}: {resource_names}"
|
||||
"MCP client listed %s resources from %s: %s", resource_count, self.server_url or "stdio", resource_names
|
||||
)
|
||||
return result.resources
|
||||
except asyncio.CancelledError:
|
||||
|
|
@ -715,11 +717,11 @@ class MCPClient:
|
|||
except Exception as e:
|
||||
error_type = type(e).__name__
|
||||
verbose_logger.error(
|
||||
f"MCP client list_resources failed - "
|
||||
f"Error Type: {error_type}, "
|
||||
f"Error: {e}, "
|
||||
f"Server: {self.server_url or 'stdio'}, "
|
||||
f"Transport: {self.transport_type}"
|
||||
"MCP client list_resources failed - Error Type: %s, Error: %s, Server: %s, Transport: %s",
|
||||
error_type,
|
||||
e,
|
||||
self.server_url or "stdio",
|
||||
self.transport_type,
|
||||
)
|
||||
# Check if it's a stream/connection error
|
||||
if "BrokenResourceError" in error_type or "Broken" in error_type:
|
||||
|
|
@ -732,7 +734,7 @@ class MCPClient:
|
|||
|
||||
async def list_resource_templates(self) -> list[ResourceTemplate]:
|
||||
"""List available resource templates from the server."""
|
||||
verbose_logger.debug(f"MCP client listing resource templates from {self.server_url or 'stdio'}")
|
||||
verbose_logger.debug("MCP client listing resource templates from %s", self.server_url or "stdio")
|
||||
|
||||
async def _list_resource_templates_operation(session: ClientSession):
|
||||
return await session.list_resource_templates()
|
||||
|
|
@ -742,7 +744,10 @@ class MCPClient:
|
|||
resource_template_count = len(result.resourceTemplates)
|
||||
resource_template_names = [resourceTemplate.name for resourceTemplate in result.resourceTemplates]
|
||||
verbose_logger.info(
|
||||
f"MCP client listed {resource_template_count} resource templates from {self.server_url or 'stdio'}: {resource_template_names}"
|
||||
"MCP client listed %s resource templates from %s: %s",
|
||||
resource_template_count,
|
||||
self.server_url or "stdio",
|
||||
resource_template_names,
|
||||
)
|
||||
return result.resourceTemplates
|
||||
except asyncio.CancelledError:
|
||||
|
|
@ -751,11 +756,11 @@ class MCPClient:
|
|||
except Exception as e:
|
||||
error_type = type(e).__name__
|
||||
verbose_logger.error(
|
||||
f"MCP client list_resource_templates failed - "
|
||||
f"Error Type: {error_type}, "
|
||||
f"Error: {e}, "
|
||||
f"Server: {self.server_url or 'stdio'}, "
|
||||
f"Transport: {self.transport_type}"
|
||||
"MCP client list_resource_templates failed - Error Type: %s, Error: %s, Server: %s, Transport: %s",
|
||||
error_type,
|
||||
e,
|
||||
self.server_url or "stdio",
|
||||
self.transport_type,
|
||||
)
|
||||
# Check if it's a stream/connection error
|
||||
if "BrokenResourceError" in error_type or "Broken" in error_type:
|
||||
|
|
@ -768,7 +773,7 @@ class MCPClient:
|
|||
|
||||
async def read_resource(self, url: AnyUrl) -> ReadResourceResult:
|
||||
"""Fetch resource contents from the MCP server."""
|
||||
verbose_logger.info(f"MCP client fetching resource '{url}'")
|
||||
verbose_logger.info("MCP client fetching resource '%s'", url)
|
||||
|
||||
async def _read_resource_operation(session: ClientSession):
|
||||
verbose_logger.debug("MCP client sending read_resource request to session")
|
||||
|
|
@ -776,7 +781,7 @@ class MCPClient:
|
|||
|
||||
try:
|
||||
read_resource_result = await self.run_with_session(_read_resource_operation)
|
||||
verbose_logger.info(f"MCP client read_resource '{url}' completed successfully")
|
||||
verbose_logger.info("MCP client read_resource '%s' completed successfully", url)
|
||||
return read_resource_result
|
||||
except asyncio.CancelledError:
|
||||
verbose_logger.warning("MCP client read_resource was cancelled")
|
||||
|
|
@ -785,16 +790,16 @@ class MCPClient:
|
|||
import traceback
|
||||
|
||||
error_trace = traceback.format_exc()
|
||||
verbose_logger.debug(f"MCP client read_resource traceback:\n{error_trace}")
|
||||
verbose_logger.debug("MCP client read_resource traceback:\n%s", error_trace)
|
||||
# Log detailed error information
|
||||
error_type = type(e).__name__
|
||||
verbose_logger.error(
|
||||
f"MCP client read_resource failed - "
|
||||
f"Error Type: {error_type}, "
|
||||
f"Error: {e}, "
|
||||
f"Url: {url}, "
|
||||
f"Server: {self.server_url or 'stdio'}, "
|
||||
f"Transport: {self.transport_type}"
|
||||
"MCP client read_resource failed - Error Type: %s, Error: %s, Url: %s, Server: %s, Transport: %s",
|
||||
error_type,
|
||||
e,
|
||||
url,
|
||||
self.server_url or "stdio",
|
||||
self.transport_type,
|
||||
)
|
||||
# Check if it's a stream/connection error
|
||||
if "BrokenResourceError" in error_type or "Broken" in error_type:
|
||||
|
|
|
|||
|
|
@ -104,9 +104,10 @@ class GoogleGenAIStreamWrapper(AdapterCompletionStreamWrapper):
|
|||
except json.JSONDecodeError:
|
||||
# This can happen if the stream is abruptly cut off mid-argument string.
|
||||
verbose_logger.warning(
|
||||
f"Could not parse tool call arguments at end of stream for index {tool_call_index}. "
|
||||
f"Name: {tool_call_data['name']}. "
|
||||
f"Partial args: {tool_call_data['arguments']}"
|
||||
"Could not parse tool call arguments at end of stream for index %s. Name: %s. Partial args: %s",
|
||||
tool_call_index,
|
||||
tool_call_data["name"],
|
||||
tool_call_data["arguments"],
|
||||
)
|
||||
if parts:
|
||||
final_chunk = {
|
||||
|
|
@ -662,7 +663,7 @@ class GoogleGenAIAdapter:
|
|||
|
||||
# Optimization: Skip chunks that have no new data
|
||||
if not function_name and not args_chunk:
|
||||
verbose_logger.debug(f"Skipping empty tool call chunk for index: {tool_call_index}")
|
||||
verbose_logger.debug("Skipping empty tool call chunk for index: %s", tool_call_index)
|
||||
continue
|
||||
|
||||
if function_name:
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ async def send_to_webhook(slackAlertingInstance: SlackAlertingType, item, count)
|
|||
data=json.dumps(payload),
|
||||
)
|
||||
if response.status_code != 200:
|
||||
verbose_proxy_logger.debug(f"Error sending slack alert to url={item['url']}. Error={response.text}")
|
||||
verbose_proxy_logger.debug("Error sending slack alert to url=%s. Error=%s", item["url"], response.text)
|
||||
except Exception as e:
|
||||
verbose_proxy_logger.debug(f"Error sending slack alert: {e}")
|
||||
verbose_proxy_logger.debug("Error sending slack alert: %s", e)
|
||||
finally:
|
||||
_print_alerting_payload_warning(payload, slackAlertingInstance=slackAlertingInstance)
|
||||
|
|
|
|||
|
|
@ -1467,7 +1467,7 @@ Model Info:
|
|||
try:
|
||||
await self._flush_digest_buckets()
|
||||
except Exception as e:
|
||||
verbose_proxy_logger.debug(f"Error flushing digest buckets: {e}")
|
||||
verbose_proxy_logger.debug("Error flushing digest buckets: %s", e)
|
||||
await self.flush_queue()
|
||||
|
||||
async def async_log_success_event(self, kwargs, response_obj, start_time, end_time):
|
||||
|
|
@ -1502,7 +1502,7 @@ Model Info:
|
|||
)
|
||||
except Exception as e:
|
||||
verbose_proxy_logger.error(
|
||||
f"[Non-Blocking Error] Slack Alerting: Got error in logging LLM deployment latency: {e}"
|
||||
"[Non-Blocking Error] Slack Alerting: Got error in logging LLM deployment latency: %s", e
|
||||
)
|
||||
|
||||
async def async_log_failure_event(self, kwargs, response_obj, start_time, end_time):
|
||||
|
|
@ -1522,7 +1522,7 @@ Model Info:
|
|||
)
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Exception raises -{e}")
|
||||
verbose_logger.debug("Exception raises -%s", e)
|
||||
|
||||
if isinstance(kwargs.get("exception", ""), APIError):
|
||||
if "outage_alerts" in self.alert_types:
|
||||
|
|
@ -1662,9 +1662,9 @@ Model Info:
|
|||
)
|
||||
|
||||
except ValueError as ve:
|
||||
verbose_proxy_logger.error(f"Invalid time range format: {ve}")
|
||||
verbose_proxy_logger.error("Invalid time range format: %s", ve)
|
||||
except Exception as e:
|
||||
verbose_proxy_logger.error(f"Error sending spend report: {e}")
|
||||
verbose_proxy_logger.error("Error sending spend report: %s", e)
|
||||
|
||||
async def send_monthly_spend_report(self):
|
||||
""" """
|
||||
|
|
|
|||
|
|
@ -143,8 +143,8 @@ class AnthropicCacheControlHook(CustomPromptManagement):
|
|||
|
||||
if limit_reached:
|
||||
verbose_logger.warning(
|
||||
f"AnthropicCacheControlHook: Reached the Anthropic limit of "
|
||||
f"{MAX_CACHE_CONTROL_BLOCKS} cache_control blocks. Skipping further injection."
|
||||
"AnthropicCacheControlHook: Reached the Anthropic limit of %s cache_control blocks. Skipping further injection.",
|
||||
MAX_CACHE_CONTROL_BLOCKS,
|
||||
)
|
||||
|
||||
return messages
|
||||
|
|
@ -174,8 +174,10 @@ class AnthropicCacheControlHook(CustomPromptManagement):
|
|||
return [targetted_index]
|
||||
|
||||
verbose_logger.warning(
|
||||
f"AnthropicCacheControlHook: Provided index {original_index} is out of bounds for message list of length {len(messages)}. "
|
||||
f"Targeted index was {targetted_index}. Skipping cache control injection for this point."
|
||||
"AnthropicCacheControlHook: Provided index %s is out of bounds for message list of length %s. Targeted index was %s. Skipping cache control injection for this point.",
|
||||
original_index,
|
||||
len(messages),
|
||||
targetted_index,
|
||||
)
|
||||
return []
|
||||
|
||||
|
|
|
|||
|
|
@ -185,9 +185,9 @@ class ArgillaLogger(CustomBatchLogger):
|
|||
)
|
||||
|
||||
if response.status_code >= 300:
|
||||
verbose_logger.error(f"Argilla Error: {response.status_code} - {response.text}")
|
||||
verbose_logger.error("Argilla Error: %s - %s", response.status_code, response.text)
|
||||
else:
|
||||
verbose_logger.debug(f"Batch of {len(self.log_queue)} runs successfully created")
|
||||
verbose_logger.debug("Batch of %s runs successfully created", len(self.log_queue))
|
||||
|
||||
self.log_queue.clear()
|
||||
except Exception:
|
||||
|
|
@ -204,7 +204,7 @@ class ArgillaLogger(CustomBatchLogger):
|
|||
random_sample = random.random()
|
||||
if random_sample > sampling_rate:
|
||||
verbose_logger.info(
|
||||
f"Skipping Langsmith logging. Sampling rate={sampling_rate}, random_sample={random_sample}"
|
||||
"Skipping Langsmith logging. Sampling rate=%s, random_sample=%s", sampling_rate, random_sample
|
||||
)
|
||||
return # Skip logging
|
||||
verbose_logger.debug(
|
||||
|
|
@ -217,7 +217,7 @@ class ArgillaLogger(CustomBatchLogger):
|
|||
return
|
||||
|
||||
self.log_queue.append(data)
|
||||
verbose_logger.debug(f"Langsmith, event added to queue. Will flush in {self.flush_interval} seconds...")
|
||||
verbose_logger.debug("Langsmith, event added to queue. Will flush in %s seconds...", self.flush_interval)
|
||||
|
||||
if len(self.log_queue) >= self.batch_size:
|
||||
self._send_batch()
|
||||
|
|
@ -231,7 +231,7 @@ class ArgillaLogger(CustomBatchLogger):
|
|||
random_sample = random.random()
|
||||
if random_sample > sampling_rate:
|
||||
verbose_logger.info(
|
||||
f"Skipping Langsmith logging. Sampling rate={sampling_rate}, random_sample={random_sample}"
|
||||
"Skipping Langsmith logging. Sampling rate=%s, random_sample=%s", sampling_rate, random_sample
|
||||
)
|
||||
return # Skip logging
|
||||
verbose_logger.debug(
|
||||
|
|
@ -272,7 +272,7 @@ class ArgillaLogger(CustomBatchLogger):
|
|||
random_sample = random.random()
|
||||
if random_sample > sampling_rate:
|
||||
verbose_logger.info(
|
||||
f"Skipping Langsmith logging. Sampling rate={sampling_rate}, random_sample={random_sample}"
|
||||
"Skipping Langsmith logging. Sampling rate=%s, random_sample=%s", sampling_rate, random_sample
|
||||
)
|
||||
return # Skip logging
|
||||
verbose_logger.info("Langsmith Failure Event Logging!")
|
||||
|
|
@ -325,7 +325,7 @@ class ArgillaLogger(CustomBatchLogger):
|
|||
response.raise_for_status()
|
||||
|
||||
if response.status_code >= 300:
|
||||
verbose_logger.error(f"Argilla Error: {response.status_code} - {response.text}")
|
||||
verbose_logger.error("Argilla Error: %s - %s", response.status_code, response.text)
|
||||
else:
|
||||
verbose_logger.debug("Batch of %s runs successfully created", len(self.log_queue))
|
||||
except httpx.HTTPStatusError:
|
||||
|
|
|
|||
|
|
@ -461,7 +461,7 @@ def set_attributes(span: "Span", kwargs, response_obj, attributes: type[BaseLLMO
|
|||
_set_response_attributes(span=span, response_obj=response_obj_for_attrs)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"[Arize/Phoenix] Failed to set OpenInference span attributes: {e}")
|
||||
verbose_logger.error("[Arize/Phoenix] Failed to set OpenInference span attributes: %s", e)
|
||||
if hasattr(span, "record_exception"):
|
||||
span.record_exception(e)
|
||||
|
||||
|
|
|
|||
|
|
@ -425,7 +425,7 @@ class ArizePhoenixLogger(OpenTelemetry): # type: ignore
|
|||
endpoint = "http://localhost:6006/v1/traces"
|
||||
protocol = "otlp_http"
|
||||
verbose_logger.debug(
|
||||
f"No PHOENIX_COLLECTOR_ENDPOINT found, using default local Phoenix endpoint: {endpoint}"
|
||||
"No PHOENIX_COLLECTOR_ENDPOINT found, using default local Phoenix endpoint: %s", endpoint
|
||||
)
|
||||
|
||||
otlp_auth_headers = None
|
||||
|
|
|
|||
|
|
@ -339,7 +339,7 @@ class ArizePhoenixPromptManager(CustomPromptManagement):
|
|||
# Log error but don't fail the call
|
||||
import litellm
|
||||
|
||||
litellm._logging.verbose_proxy_logger.error(f"Error in Arize Phoenix prompt pre_call_hook: {e}")
|
||||
litellm._logging.verbose_proxy_logger.error("Error in Arize Phoenix prompt pre_call_hook: %s", e)
|
||||
return messages, litellm_params
|
||||
|
||||
def get_available_prompts(self) -> list[str]:
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ class AzureSentinelLogger(CustomBatchLogger):
|
|||
await self.async_send_batch()
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Azure Sentinel Layer Error - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("Azure Sentinel Layer Error - %s\n%s", e, traceback.format_exc())
|
||||
|
||||
async def async_log_failure_event(self, kwargs, response_obj, start_time, end_time):
|
||||
"""
|
||||
|
|
@ -233,7 +233,7 @@ class AzureSentinelLogger(CustomBatchLogger):
|
|||
await self.async_send_batch()
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Azure Sentinel Layer Error - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("Azure Sentinel Layer Error - %s\n%s", e, traceback.format_exc())
|
||||
|
||||
async def async_log_audit_log_event(self, audit_log: StandardAuditLogPayload) -> None:
|
||||
"""
|
||||
|
|
@ -256,7 +256,7 @@ class AzureSentinelLogger(CustomBatchLogger):
|
|||
await self.async_send_audit_batch()
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Azure Sentinel Audit Log Layer Error - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("Azure Sentinel Audit Log Layer Error - %s\n%s", e, traceback.format_exc())
|
||||
|
||||
async def async_send_batch(self):
|
||||
"""
|
||||
|
|
@ -323,7 +323,7 @@ class AzureSentinelLogger(CustomBatchLogger):
|
|||
)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Azure Sentinel Error sending batch API - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("Azure Sentinel Error sending batch API - %s\n%s", e, traceback.format_exc())
|
||||
finally:
|
||||
log_queue.clear()
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,9 @@ class AzureBlobStorageLogger(CustomBatchLogger):
|
|||
self.log_queue: list[StandardLoggingPayload] = []
|
||||
super().__init__(**kwargs, flush_lock=self.flush_lock)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"AzureBlobStorageLogger: Got exception on init AzureBlobStorageLogger client {e}")
|
||||
verbose_logger.exception(
|
||||
"AzureBlobStorageLogger: Got exception on init AzureBlobStorageLogger client %s", e
|
||||
)
|
||||
raise e
|
||||
|
||||
async def async_log_success_event(self, kwargs, response_obj, start_time, end_time):
|
||||
|
|
@ -77,7 +79,7 @@ class AzureBlobStorageLogger(CustomBatchLogger):
|
|||
self.log_queue.append(standard_logging_payload)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"AzureBlobStorageLogger Layer Error - {e}")
|
||||
verbose_logger.exception("AzureBlobStorageLogger Layer Error - %s", e)
|
||||
|
||||
async def async_log_failure_event(self, kwargs, response_obj, start_time, end_time):
|
||||
"""
|
||||
|
|
@ -99,7 +101,7 @@ class AzureBlobStorageLogger(CustomBatchLogger):
|
|||
|
||||
self.log_queue.append(standard_logging_payload)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"AzureBlobStorageLogger Layer Error - {e}")
|
||||
verbose_logger.exception("AzureBlobStorageLogger Layer Error - %s", e)
|
||||
|
||||
async def async_send_batch(self):
|
||||
"""
|
||||
|
|
@ -122,7 +124,7 @@ class AzureBlobStorageLogger(CustomBatchLogger):
|
|||
await self.async_upload_payload_to_azure_blob_storage(payload=payload)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"AzureBlobStorageLogger Error sending batch API - {e}")
|
||||
verbose_logger.exception("AzureBlobStorageLogger Error sending batch API - %s", e)
|
||||
|
||||
async def async_upload_payload_to_azure_blob_storage(self, payload: StandardLoggingPayload):
|
||||
"""
|
||||
|
|
@ -148,16 +150,16 @@ class AzureBlobStorageLogger(CustomBatchLogger):
|
|||
await self._append_data(async_client, base_url, json_payload)
|
||||
await self._flush_data(async_client, base_url, len(payload_bytes))
|
||||
|
||||
verbose_logger.debug(f"Successfully uploaded log to Azure Blob Storage: {filename}")
|
||||
verbose_logger.debug("Successfully uploaded log to Azure Blob Storage: %s", filename)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error uploading to Azure Blob Storage: {e}")
|
||||
verbose_logger.exception("Error uploading to Azure Blob Storage: %s", e)
|
||||
raise e
|
||||
|
||||
async def _create_file(self, client: AsyncHTTPHandler, base_url: str):
|
||||
"""Helper method to create the file resource"""
|
||||
try:
|
||||
verbose_logger.debug(f"Creating file resource at: {base_url}")
|
||||
verbose_logger.debug("Creating file resource at: %s", base_url)
|
||||
headers = {
|
||||
"x-ms-version": AZURE_STORAGE_MSFT_VERSION,
|
||||
"Content-Length": "0",
|
||||
|
|
@ -167,13 +169,13 @@ class AzureBlobStorageLogger(CustomBatchLogger):
|
|||
response.raise_for_status()
|
||||
verbose_logger.debug("Successfully created file resource")
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error creating file resource: {e}")
|
||||
verbose_logger.exception("Error creating file resource: %s", e)
|
||||
raise
|
||||
|
||||
async def _append_data(self, client: AsyncHTTPHandler, base_url: str, json_payload: str):
|
||||
"""Helper method to append data to the file"""
|
||||
try:
|
||||
verbose_logger.debug(f"Appending data to file: {base_url}")
|
||||
verbose_logger.debug("Appending data to file: %s", base_url)
|
||||
headers = {
|
||||
"x-ms-version": AZURE_STORAGE_MSFT_VERSION,
|
||||
"Content-Type": "application/json",
|
||||
|
|
@ -187,13 +189,13 @@ class AzureBlobStorageLogger(CustomBatchLogger):
|
|||
response.raise_for_status()
|
||||
verbose_logger.debug("Successfully appended data")
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error appending data: {e}")
|
||||
verbose_logger.exception("Error appending data: %s", e)
|
||||
raise
|
||||
|
||||
async def _flush_data(self, client: AsyncHTTPHandler, base_url: str, position: int):
|
||||
"""Helper method to flush the data"""
|
||||
try:
|
||||
verbose_logger.debug(f"Flushing data at position {position}")
|
||||
verbose_logger.debug("Flushing data at position %s", position)
|
||||
headers = {
|
||||
"x-ms-version": AZURE_STORAGE_MSFT_VERSION,
|
||||
"Content-Length": "0",
|
||||
|
|
@ -203,7 +205,7 @@ class AzureBlobStorageLogger(CustomBatchLogger):
|
|||
response.raise_for_status()
|
||||
verbose_logger.debug("Successfully flushed data")
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error flushing data: {e}")
|
||||
verbose_logger.exception("Error flushing data: %s", e)
|
||||
raise
|
||||
|
||||
####### Helper methods to managing Authentication to Azure Storage #######
|
||||
|
|
@ -227,7 +229,7 @@ class AzureBlobStorageLogger(CustomBatchLogger):
|
|||
)
|
||||
# Token typically expires in 1 hour
|
||||
self.token_expiry = datetime.now() + timedelta(hours=1)
|
||||
verbose_logger.debug(f"New token will expire at {self.token_expiry}")
|
||||
verbose_logger.debug("New token will expire at %s", self.token_expiry)
|
||||
|
||||
def get_azure_ad_token_from_azure_storage(
|
||||
self,
|
||||
|
|
@ -322,7 +324,7 @@ class AzureBlobStorageLogger(CustomBatchLogger):
|
|||
# check if the directory exists
|
||||
if not await directory_client.exists():
|
||||
await directory_client.create_directory()
|
||||
verbose_logger.debug(f"Created directory: {today}")
|
||||
verbose_logger.debug("Created directory: %s", today)
|
||||
|
||||
# Create a file client
|
||||
file_name = f"{payload.get('id') or str(uuid.uuid4())}.json"
|
||||
|
|
@ -340,7 +342,7 @@ class AzureBlobStorageLogger(CustomBatchLogger):
|
|||
# Flush the content to finalize the file
|
||||
await file_client.flush_data(position=len(content), offset=0)
|
||||
|
||||
verbose_logger.debug(f"Successfully uploaded and wrote to {today}/{file_name}")
|
||||
verbose_logger.debug("Successfully uploaded and wrote to %s/%s", today, file_name)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error occurred: {e}")
|
||||
verbose_logger.exception("Error occurred: %s", e)
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ class BitBucketPromptManager(CustomPromptManagement):
|
|||
# Log error but don't fail the call
|
||||
import litellm
|
||||
|
||||
litellm._logging.verbose_proxy_logger.error(f"Error in BitBucket prompt pre_call_hook: {e}")
|
||||
litellm._logging.verbose_proxy_logger.error("Error in BitBucket prompt pre_call_hook: %s", e)
|
||||
return messages, litellm_params
|
||||
|
||||
def _parse_prompt_to_messages(self, prompt_content: str) -> list[AllMessageValues]:
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ def _mock_http_handler_post(
|
|||
"""Monkey-patched HTTPHandler.post that intercepts Braintrust calls with endpoint-specific responses."""
|
||||
# Only mock Braintrust API calls
|
||||
if isinstance(url, str) and _is_braintrust_url(url):
|
||||
verbose_logger.info(f"[BRAINTRUST MOCK] POST to {url}")
|
||||
verbose_logger.info("[BRAINTRUST MOCK] POST to %s", url)
|
||||
time.sleep(_MOCK_LATENCY_SECONDS)
|
||||
# Return appropriate mock response based on endpoint
|
||||
if "/project" in url:
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class CloudZeroLogger(CustomLogger):
|
|||
self.connection_id = connection_id or os.getenv("CLOUDZERO_CONNECTION_ID")
|
||||
self.timezone = timezone or os.getenv("CLOUDZERO_TIMEZONE", "UTC")
|
||||
verbose_logger.debug(
|
||||
f"CloudZero Logger initialized with connection ID: {self.connection_id}, timezone: {self.timezone}"
|
||||
"CloudZero Logger initialized with connection ID: %s, timezone: %s", self.connection_id, self.timezone
|
||||
)
|
||||
|
||||
async def initialize_cloudzero_export_job(self):
|
||||
|
|
@ -130,7 +130,7 @@ class CloudZeroLogger(CustomLogger):
|
|||
verbose_logger.debug("CloudZero Logger: No usage data found to export")
|
||||
return
|
||||
|
||||
verbose_logger.debug(f"CloudZero Logger: Processing {len(data)} records")
|
||||
verbose_logger.debug("CloudZero Logger: Processing %s records", len(data))
|
||||
|
||||
# Transform data to CloudZero CBF format
|
||||
transformer = CBFTransformer()
|
||||
|
|
@ -147,13 +147,13 @@ class CloudZeroLogger(CustomLogger):
|
|||
user_timezone=self.timezone,
|
||||
)
|
||||
|
||||
verbose_logger.debug(f"CloudZero Logger: Transmitting {len(cbf_data)} records to CloudZero")
|
||||
verbose_logger.debug("CloudZero Logger: Transmitting %s records to CloudZero", len(cbf_data))
|
||||
streamer.send_batched(cbf_data, operation=operation)
|
||||
|
||||
verbose_logger.debug(f"CloudZero Logger: Successfully exported {len(cbf_data)} records to CloudZero")
|
||||
verbose_logger.debug("CloudZero Logger: Successfully exported %s records to CloudZero", len(cbf_data))
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"CloudZero Logger: Error exporting usage data: {e}")
|
||||
verbose_logger.error("CloudZero Logger: Error exporting usage data: %s", e)
|
||||
raise
|
||||
|
||||
async def dry_run_export_usage_data(self, limit: int | None = 10000):
|
||||
|
|
@ -191,7 +191,7 @@ class CloudZeroLogger(CustomLogger):
|
|||
},
|
||||
}
|
||||
|
||||
verbose_logger.debug(f"CloudZero Dry Run: Processing {len(data)} records...")
|
||||
verbose_logger.debug("CloudZero Dry Run: Processing %s records...", len(data))
|
||||
|
||||
# Convert usage data to dict format for response
|
||||
usage_data_sample = data.head(50).to_dicts() # Return first 50 rows
|
||||
|
|
@ -229,7 +229,7 @@ class CloudZeroLogger(CustomLogger):
|
|||
)
|
||||
total_tokens = sum(record.get("usage/amount", 0) for record in cbf_data_dict)
|
||||
|
||||
verbose_logger.debug(f"CloudZero Logger: Dry run completed for {len(cbf_data)} records")
|
||||
verbose_logger.debug("CloudZero Logger: Dry run completed for %s records", len(cbf_data))
|
||||
|
||||
return {
|
||||
"usage_data": usage_data_sample,
|
||||
|
|
@ -244,8 +244,8 @@ class CloudZeroLogger(CustomLogger):
|
|||
}
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"CloudZero Logger: Error in dry run export: {e}")
|
||||
verbose_logger.error(f"CloudZero Dry Run Error: {e}")
|
||||
verbose_logger.error("CloudZero Logger: Error in dry run export: %s", e)
|
||||
verbose_logger.error("CloudZero Dry Run Error: %s", e)
|
||||
raise
|
||||
|
||||
def _display_cbf_data_on_screen(self, cbf_data):
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ class CustomBatchLogger(CustomLogger):
|
|||
async def periodic_flush(self):
|
||||
while True:
|
||||
await asyncio.sleep(self.flush_interval)
|
||||
verbose_logger.debug(f"CustomLogger periodic flush after {self.flush_interval} seconds")
|
||||
verbose_logger.debug("CustomLogger periodic flush after %s seconds", self.flush_interval)
|
||||
await self.flush_queue()
|
||||
|
||||
async def flush_queue(self):
|
||||
|
|
|
|||
|
|
@ -864,7 +864,7 @@ class CustomGuardrail(CustomLogger):
|
|||
|
||||
if premium_user is not True:
|
||||
verbose_logger.warning(
|
||||
f"Trying to use premium guardrail without premium user {CommonProxyErrors.not_premium_user.value}"
|
||||
"Trying to use premium guardrail without premium user %s", CommonProxyErrors.not_premium_user.value
|
||||
)
|
||||
return False
|
||||
return True
|
||||
|
|
@ -1028,7 +1028,7 @@ class CustomGuardrail(CustomLogger):
|
|||
else:
|
||||
guardrail_response = "allow"
|
||||
|
||||
verbose_logger.debug(f"Guardrail response: {response}")
|
||||
verbose_logger.debug("Guardrail response: %s", response)
|
||||
|
||||
self.add_standard_logging_guardrail_information_to_request_data(
|
||||
guardrail_json_response=guardrail_response,
|
||||
|
|
|
|||
|
|
@ -915,19 +915,19 @@ class CustomLogger: # https://docs.litellm.ai/docs/observability/custom_callbac
|
|||
|
||||
for callback_obj in all_callbacks:
|
||||
if hasattr(callback_obj, "increment_callback_logging_failure"):
|
||||
verbose_logger.debug(f"Incrementing callback failure metric for {callback_name}")
|
||||
verbose_logger.debug("Incrementing callback failure metric for %s", callback_name)
|
||||
callback_obj.increment_callback_logging_failure(callback_name=callback_name) # type: ignore
|
||||
return
|
||||
|
||||
verbose_logger.debug(
|
||||
f"No callback with increment_callback_logging_failure method found for {callback_name}. "
|
||||
"Ensure 'prometheus' is in your callbacks config."
|
||||
"No callback with increment_callback_logging_failure method found for %s. Ensure 'prometheus' is in your callbacks config.",
|
||||
callback_name,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
from litellm._logging import verbose_logger
|
||||
|
||||
verbose_logger.debug(f"Error in handle_callback_failure for {callback_name}: {e}")
|
||||
verbose_logger.debug("Error in handle_callback_failure for %s: %s", callback_name, e)
|
||||
|
||||
async def _strip_base64_from_messages(
|
||||
self,
|
||||
|
|
@ -946,7 +946,7 @@ class CustomLogger: # https://docs.litellm.ai/docs/observability/custom_callbac
|
|||
"""
|
||||
raw_messages: Any = payload.get("messages", [])
|
||||
messages: list[Any] = raw_messages if isinstance(raw_messages, list) else []
|
||||
verbose_logger.debug(f"[CustomLogger] Stripping base64 from {len(messages)} messages")
|
||||
verbose_logger.debug("[CustomLogger] Stripping base64 from %s messages", len(messages))
|
||||
|
||||
if messages:
|
||||
payload["messages"] = self._process_messages(messages=messages, max_depth=max_depth)
|
||||
|
|
@ -958,7 +958,7 @@ class CustomLogger: # https://docs.litellm.ai/docs/observability/custom_callbac
|
|||
if isinstance(content, list):
|
||||
total_items += len(content)
|
||||
|
||||
verbose_logger.debug(f"[CustomLogger] Completed base64 strip; retained {total_items} content items")
|
||||
verbose_logger.debug("[CustomLogger] Completed base64 strip; retained %s content items", total_items)
|
||||
return payload
|
||||
|
||||
def _strip_base64_from_messages_sync(
|
||||
|
|
@ -978,7 +978,7 @@ class CustomLogger: # https://docs.litellm.ai/docs/observability/custom_callbac
|
|||
"""
|
||||
raw_messages: Any = payload.get("messages", [])
|
||||
messages: list[Any] = raw_messages if isinstance(raw_messages, list) else []
|
||||
verbose_logger.debug(f"[CustomLogger] Stripping base64 from {len(messages)} messages")
|
||||
verbose_logger.debug("[CustomLogger] Stripping base64 from %s messages", len(messages))
|
||||
|
||||
if messages:
|
||||
payload["messages"] = self._process_messages(messages=messages, max_depth=max_depth)
|
||||
|
|
@ -990,7 +990,7 @@ class CustomLogger: # https://docs.litellm.ai/docs/observability/custom_callbac
|
|||
if isinstance(content, list):
|
||||
total_items += len(content)
|
||||
|
||||
verbose_logger.debug(f"[CustomLogger] Completed base64 strip; retained {total_items} content items")
|
||||
verbose_logger.debug("[CustomLogger] Completed base64 strip; retained %s content items", total_items)
|
||||
return payload
|
||||
|
||||
def _redact_base64(
|
||||
|
|
@ -1001,12 +1001,12 @@ class CustomLogger: # https://docs.litellm.ai/docs/observability/custom_callbac
|
|||
) -> Any:
|
||||
"""Recursively redact inline base64 from any nested structure with a max recursion depth limit."""
|
||||
if depth > max_depth:
|
||||
verbose_logger.warning(f"[CustomLogger] Max recursion depth {max_depth} reached while redacting base64")
|
||||
verbose_logger.warning("[CustomLogger] Max recursion depth %s reached while redacting base64", max_depth)
|
||||
return "[MAX_DEPTH_REACHED]"
|
||||
|
||||
if isinstance(value, str):
|
||||
if _BASE64_INLINE_PATTERN.search(value):
|
||||
verbose_logger.debug(f"[CustomLogger] Redacted inline base64 string: {value[:40]}...")
|
||||
verbose_logger.debug("[CustomLogger] Redacted inline base64 string: %s...", value[:40])
|
||||
return _BASE64_INLINE_PATTERN.sub("[BASE64_REDACTED]", value)
|
||||
return value
|
||||
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ class CustomSecretManager(BaseSecretManager):
|
|||
Returns:
|
||||
True if the secret manager is healthy, False otherwise
|
||||
"""
|
||||
verbose_logger.debug(f"Health check not implemented for {self.secret_manager_name}")
|
||||
verbose_logger.debug("Health check not implemented for %s", self.secret_manager_name)
|
||||
return True
|
||||
|
||||
def __repr__(self) -> str:
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ class DataDogLogger(
|
|||
batch_size=_resolve_dd_batch_size(),
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Datadog: Got exception on init Datadog client {e}")
|
||||
verbose_logger.exception("Datadog: Got exception on init Datadog client %s", e)
|
||||
raise e
|
||||
|
||||
def _get_datadog_params(self) -> dict:
|
||||
|
|
@ -210,7 +210,7 @@ class DataDogLogger(
|
|||
self.DD_API_KEY = dd_api_key or (
|
||||
os.getenv("DD_API_KEY") if allow_env_credentials else None
|
||||
) # Optional when using agent
|
||||
verbose_logger.debug(f"Datadog: Using DD Agent at {self.intake_url}")
|
||||
verbose_logger.debug("Datadog: Using DD Agent at %s", self.intake_url)
|
||||
|
||||
def _configure_dd_direct_api(
|
||||
self,
|
||||
|
|
@ -257,7 +257,7 @@ class DataDogLogger(
|
|||
await self._log_async_event(kwargs, response_obj, start_time, end_time)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Datadog Layer Error - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("Datadog Layer Error - %s\n%s", e, traceback.format_exc())
|
||||
|
||||
async def async_log_failure_event(self, kwargs, response_obj, start_time, end_time):
|
||||
try:
|
||||
|
|
@ -265,7 +265,7 @@ class DataDogLogger(
|
|||
await self._log_async_event(kwargs, response_obj, start_time, end_time)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Datadog Layer Error - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("Datadog Layer Error - %s\n%s", e, traceback.format_exc())
|
||||
|
||||
async def async_post_call_failure_hook(
|
||||
self,
|
||||
|
|
@ -340,7 +340,7 @@ class DataDogLogger(
|
|||
if len(self.log_queue) >= self.batch_size:
|
||||
await self.flush_queue()
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Datadog: async_post_call_failure_hook - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("Datadog: async_post_call_failure_hook - %s\n%s", e, traceback.format_exc())
|
||||
return None
|
||||
|
||||
async def async_send_batch(self):
|
||||
|
|
@ -376,11 +376,11 @@ class DataDogLogger(
|
|||
self.log_queue = undelivered + self.log_queue
|
||||
|
||||
if self.is_mock_mode:
|
||||
verbose_logger.debug(f"[DATADOG MOCK] Batch of {len(batch_to_send)} events successfully mocked")
|
||||
verbose_logger.debug("[DATADOG MOCK] Batch of %s events successfully mocked", len(batch_to_send))
|
||||
|
||||
except Exception as e:
|
||||
self.log_queue = batch_to_send + self.log_queue
|
||||
verbose_logger.exception(f"Datadog Error sending batch API - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("Datadog Error sending batch API - %s\n%s", e, traceback.format_exc())
|
||||
|
||||
async def _send_with_413_split(self, batch: list) -> list:
|
||||
"""
|
||||
|
|
@ -411,7 +411,7 @@ class DataDogLogger(
|
|||
if isinstance(e, MaskedHTTPStatusError) and e.status_code == 413:
|
||||
response = e.response
|
||||
else:
|
||||
verbose_logger.exception(f"Datadog Error sending batch API - {e}")
|
||||
verbose_logger.exception("Datadog Error sending batch API - %s", e)
|
||||
return self._undelivered(chunk, pending)
|
||||
|
||||
if response.status_code == 413:
|
||||
|
|
@ -515,7 +515,7 @@ class DataDogLogger(
|
|||
)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Datadog Layer Error - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("Datadog Layer Error - %s\n%s", e, traceback.format_exc())
|
||||
|
||||
async def _log_async_event(self, kwargs, response_obj, start_time, end_time):
|
||||
dd_payload = self.create_datadog_logging_payload(
|
||||
|
|
@ -526,7 +526,7 @@ class DataDogLogger(
|
|||
)
|
||||
|
||||
self.log_queue.append(dd_payload)
|
||||
verbose_logger.debug(f"Datadog, event added to queue. Will flush in {self.flush_interval} seconds...")
|
||||
verbose_logger.debug("Datadog, event added to queue. Will flush in %s seconds...", self.flush_interval)
|
||||
|
||||
if len(self.log_queue) >= self.batch_size:
|
||||
await self.flush_queue()
|
||||
|
|
@ -653,7 +653,7 @@ class DataDogLogger(
|
|||
self.log_queue.append(_dd_payload)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Datadog: Logger - Exception in async_service_failure_hook: {e}")
|
||||
verbose_logger.exception("Datadog: Logger - Exception in async_service_failure_hook: %s", e)
|
||||
|
||||
async def async_service_success_hook(
|
||||
self,
|
||||
|
|
@ -692,7 +692,7 @@ class DataDogLogger(
|
|||
self.log_queue.append(_dd_payload)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Datadog: Logger - Exception in async_service_failure_hook: {e}")
|
||||
verbose_logger.exception("Datadog: Logger - Exception in async_service_failure_hook: %s", e)
|
||||
|
||||
def _create_v0_logging_payload(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ class DatadogCostManagementLogger(CustomBatchLogger):
|
|||
await self.async_send_batch()
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Datadog Cost Management: Error in async_log_success_event: {e}")
|
||||
verbose_logger.exception("Datadog Cost Management: Error in async_log_success_event: %s", e)
|
||||
|
||||
async def async_send_batch(self):
|
||||
if not self.log_queue:
|
||||
|
|
@ -104,7 +104,7 @@ class DatadogCostManagementLogger(CustomBatchLogger):
|
|||
await self._upload_to_datadog(aggregated_entries)
|
||||
except Exception as e:
|
||||
self.log_queue = batch_to_send + self.log_queue
|
||||
verbose_logger.exception(f"Datadog Cost Management: Error in async_send_batch: {e}")
|
||||
verbose_logger.exception("Datadog Cost Management: Error in async_send_batch: %s", e)
|
||||
|
||||
def _aggregate_costs(self, logs: list[StandardLoggingPayload]) -> list[DatadogFOCUSCostEntry]:
|
||||
"""
|
||||
|
|
@ -159,7 +159,7 @@ class DatadogCostManagementLogger(CustomBatchLogger):
|
|||
aggregator[key]["BilledCost"] += cost
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Error processing log for cost aggregation: {e}")
|
||||
verbose_logger.warning("Error processing log for cost aggregation: %s", e)
|
||||
continue
|
||||
|
||||
return list(aggregator.values())
|
||||
|
|
@ -254,5 +254,5 @@ class DatadogCostManagementLogger(CustomBatchLogger):
|
|||
response.raise_for_status()
|
||||
|
||||
verbose_logger.debug(
|
||||
f"Datadog Cost Management: Uploaded {len(payload)} cost entries. Status: {response.status_code}"
|
||||
"Datadog Cost Management: Uploaded %s cost entries. Status: %s", len(payload), response.status_code
|
||||
)
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ class DataDogLLMObsLogger(CustomBatchLogger):
|
|||
kwargs.update(dict_datadog_llm_obs_params)
|
||||
CustomBatchLogger.__init__(self, **kwargs, flush_lock=self.flush_lock)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"DataDogLLMObs: Error initializing - {e}")
|
||||
verbose_logger.exception("DataDogLLMObs: Error initializing - %s", e)
|
||||
raise e
|
||||
|
||||
def _configure_dd_agent(self, dd_agent_host: str):
|
||||
|
|
@ -103,7 +103,7 @@ class DataDogLLMObsLogger(CustomBatchLogger):
|
|||
agent_port = os.getenv("LITELLM_DD_LLM_OBS_PORT", "8126")
|
||||
self.DD_SITE = "localhost" # Not used for URL construction in agent mode
|
||||
self.intake_url = f"http://{dd_agent_host}:{agent_port}/api/intake/llm-obs/v1/trace/spans"
|
||||
verbose_logger.debug(f"DataDogLLMObs: Using DD Agent at {self.intake_url}")
|
||||
verbose_logger.debug("DataDogLLMObs: Using DD Agent at %s", self.intake_url)
|
||||
|
||||
def _configure_dd_direct_api(self):
|
||||
"""
|
||||
|
|
@ -137,34 +137,34 @@ class DataDogLLMObsLogger(CustomBatchLogger):
|
|||
|
||||
async def async_log_success_event(self, kwargs, response_obj, start_time, end_time):
|
||||
try:
|
||||
verbose_logger.debug(f"DataDogLLMObs: Logging success event for model {kwargs.get('model', 'unknown')}")
|
||||
verbose_logger.debug("DataDogLLMObs: Logging success event for model %s", kwargs.get("model", "unknown"))
|
||||
payload = self.create_llm_obs_payload(kwargs, start_time, end_time)
|
||||
verbose_logger.debug(f"DataDogLLMObs: Payload: {payload}")
|
||||
verbose_logger.debug("DataDogLLMObs: Payload: %s", payload)
|
||||
self.log_queue.append(payload)
|
||||
|
||||
if len(self.log_queue) >= self.batch_size:
|
||||
await self.async_send_batch()
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"DataDogLLMObs: Error logging success event - {e}")
|
||||
verbose_logger.exception("DataDogLLMObs: Error logging success event - %s", e)
|
||||
|
||||
async def async_log_failure_event(self, kwargs, response_obj, start_time, end_time):
|
||||
try:
|
||||
verbose_logger.debug(f"DataDogLLMObs: Logging failure event for model {kwargs.get('model', 'unknown')}")
|
||||
verbose_logger.debug("DataDogLLMObs: Logging failure event for model %s", kwargs.get("model", "unknown"))
|
||||
payload = self.create_llm_obs_payload(kwargs, start_time, end_time)
|
||||
verbose_logger.debug(f"DataDogLLMObs: Payload: {payload}")
|
||||
verbose_logger.debug("DataDogLLMObs: Payload: %s", payload)
|
||||
self.log_queue.append(payload)
|
||||
|
||||
if len(self.log_queue) >= self.batch_size:
|
||||
await self.async_send_batch()
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"DataDogLLMObs: Error logging failure event - {e}")
|
||||
verbose_logger.exception("DataDogLLMObs: Error logging failure event - %s", e)
|
||||
|
||||
async def async_send_batch(self):
|
||||
try:
|
||||
if not self.log_queue:
|
||||
return
|
||||
|
||||
verbose_logger.debug(f"DataDogLLMObs: Flushing {len(self.log_queue)} events")
|
||||
verbose_logger.debug("DataDogLLMObs: Flushing %s events", len(self.log_queue))
|
||||
|
||||
if self.is_mock_mode:
|
||||
verbose_logger.debug("[DATADOG MOCK] Mock mode enabled - API calls will be intercepted")
|
||||
|
|
@ -207,14 +207,14 @@ class DataDogLLMObsLogger(CustomBatchLogger):
|
|||
)
|
||||
|
||||
if self.is_mock_mode:
|
||||
verbose_logger.debug(f"[DATADOG MOCK] Batch of {len(self.log_queue)} events successfully mocked")
|
||||
verbose_logger.debug("[DATADOG MOCK] Batch of %s events successfully mocked", len(self.log_queue))
|
||||
else:
|
||||
verbose_logger.debug(f"DataDogLLMObs: Successfully sent batch - status_code: {response.status_code}")
|
||||
verbose_logger.debug("DataDogLLMObs: Successfully sent batch - status_code: %s", response.status_code)
|
||||
self.log_queue.clear()
|
||||
except httpx.HTTPStatusError as e:
|
||||
verbose_logger.exception(f"DataDogLLMObs: Error sending batch - {e.response.text}")
|
||||
verbose_logger.exception("DataDogLLMObs: Error sending batch - %s", e.response.text)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"DataDogLLMObs: Error sending batch - {e}")
|
||||
verbose_logger.exception("DataDogLLMObs: Error sending batch - %s", e)
|
||||
|
||||
def create_llm_obs_payload(self, kwargs: dict, start_time: datetime, end_time: datetime) -> LLMObsPayload:
|
||||
standard_logging_payload: StandardLoggingPayload | None = kwargs.get("standard_logging_object")
|
||||
|
|
@ -613,7 +613,7 @@ class DataDogLLMObsLogger(CustomBatchLogger):
|
|||
try:
|
||||
spend_metrics["user_api_key_spend"] = float(user_api_key_spend)
|
||||
except (ValueError, TypeError):
|
||||
verbose_logger.debug(f"Invalid user_api_key_spend value: {user_api_key_spend}")
|
||||
verbose_logger.debug("Invalid user_api_key_spend value: %s", user_api_key_spend)
|
||||
|
||||
# API key budget reset datetime
|
||||
user_api_key_budget_reset_at = metadata.get("user_api_key_budget_reset_at")
|
||||
|
|
@ -640,10 +640,10 @@ class DataDogLLMObsLogger(CustomBatchLogger):
|
|||
spend_metrics["user_api_key_budget_reset_at"] = iso_string
|
||||
|
||||
# Debug logging to verify the conversion
|
||||
verbose_logger.debug(f"Converted budget_reset_at to ISO format: {iso_string}")
|
||||
verbose_logger.debug("Converted budget_reset_at to ISO format: %s", iso_string)
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Error processing budget reset datetime: {e}")
|
||||
verbose_logger.debug(f"Original value: {user_api_key_budget_reset_at}")
|
||||
verbose_logger.debug("Error processing budget reset datetime: %s", e)
|
||||
verbose_logger.debug("Original value: %s", user_api_key_budget_reset_at)
|
||||
|
||||
return spend_metrics
|
||||
|
||||
|
|
@ -707,7 +707,7 @@ class DataDogLLMObsLogger(CustomBatchLogger):
|
|||
|
||||
kv_pairs[f"tool_calls.{idx}.function.arguments"] = json.dumps(function_arguments)
|
||||
except (KeyError, TypeError, ValueError) as e:
|
||||
verbose_logger.debug(f"DataDogLLMObs: Error processing tool call {idx}: {e}")
|
||||
verbose_logger.debug("DataDogLLMObs: Error processing tool call %s: %s", idx, e)
|
||||
continue
|
||||
|
||||
return kv_pairs
|
||||
|
|
@ -747,6 +747,6 @@ class DataDogLLMObsLogger(CustomBatchLogger):
|
|||
tool_call_metadata[f"output_{key}"] = value
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"DataDogLLMObs: Error extracting tool call metadata: {e}")
|
||||
verbose_logger.debug("DataDogLLMObs: Error extracting tool call metadata: %s", e)
|
||||
|
||||
return tool_call_metadata
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ class DatadogMetricsLogger(CustomBatchLogger):
|
|||
await self.flush_queue()
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Datadog Metrics: Error in async_log_success_event: {e}")
|
||||
verbose_logger.exception("Datadog Metrics: Error in async_log_success_event: %s", e)
|
||||
|
||||
async def async_log_failure_event(self, kwargs, response_obj, start_time, end_time):
|
||||
try:
|
||||
|
|
@ -202,7 +202,7 @@ class DatadogMetricsLogger(CustomBatchLogger):
|
|||
await self.flush_queue()
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Datadog Metrics: Error in async_log_failure_event: {e}")
|
||||
verbose_logger.exception("Datadog Metrics: Error in async_log_failure_event: %s", e)
|
||||
|
||||
async def async_send_batch(self):
|
||||
if not self.log_queue:
|
||||
|
|
@ -214,7 +214,7 @@ class DatadogMetricsLogger(CustomBatchLogger):
|
|||
try:
|
||||
await self._upload_to_datadog(payload_data)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Datadog Metrics: Error in async_send_batch: {e}")
|
||||
verbose_logger.exception("Datadog Metrics: Error in async_send_batch: %s", e)
|
||||
raise
|
||||
|
||||
async def _upload_to_datadog(self, payload: DatadogMetricsPayload):
|
||||
|
|
@ -242,7 +242,7 @@ class DatadogMetricsLogger(CustomBatchLogger):
|
|||
response.raise_for_status()
|
||||
|
||||
verbose_logger.debug(
|
||||
f"Datadog Metrics: Uploaded {len(payload['series'])} metric points. Status: {response.status_code}"
|
||||
"Datadog Metrics: Uploaded %s metric points. Status: %s", len(payload["series"]), response.status_code
|
||||
)
|
||||
|
||||
async def async_health_check(self) -> IntegrationHealthCheckStatus:
|
||||
|
|
|
|||
|
|
@ -23,9 +23,9 @@ def log_retry_error(details):
|
|||
exception = details.get("exception")
|
||||
tries = details.get("tries")
|
||||
if exception:
|
||||
logging.error(f"Confident AI Error: {exception}. Retrying: {tries} time(s)...")
|
||||
logging.error("Confident AI Error: %s. Retrying: %s time(s)...", exception, tries)
|
||||
else:
|
||||
logging.error(f"Retrying: {tries} time(s)...")
|
||||
logging.error("Retrying: %s time(s)...", tries)
|
||||
|
||||
|
||||
class HttpMethods(Enum):
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class GCSBucketLogger(GCSBucketBase, AdditionalLoggingUtils):
|
|||
await self.log_queue.put(GCSLogQueueItem(payload=logging_payload, kwargs=kwargs, response_obj=response_obj))
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"GCS Bucket logging error: {e}")
|
||||
verbose_logger.exception("GCS Bucket logging error: %s", e)
|
||||
|
||||
async def async_log_failure_event(self, kwargs, response_obj, start_time, end_time):
|
||||
try:
|
||||
|
|
@ -95,7 +95,7 @@ class GCSBucketLogger(GCSBucketBase, AdditionalLoggingUtils):
|
|||
await self.log_queue.put(GCSLogQueueItem(payload=logging_payload, kwargs=kwargs, response_obj=response_obj))
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"GCS Bucket logging error: {e}")
|
||||
verbose_logger.exception("GCS Bucket logging error: %s", e)
|
||||
|
||||
def _drain_queue_batch(self) -> list[GCSLogQueueItem]:
|
||||
"""
|
||||
|
|
@ -218,7 +218,7 @@ class GCSBucketLogger(GCSBucketBase, AdditionalLoggingUtils):
|
|||
except Exception as e:
|
||||
success_count = 0
|
||||
error_count = len(items)
|
||||
verbose_logger.exception(f"GCS Bucket error logging batch payload to GCS bucket: {e}")
|
||||
verbose_logger.exception("GCS Bucket error logging batch payload to GCS bucket: %s", e)
|
||||
return (success_count, error_count)
|
||||
|
||||
async def _send_individual_logs(self, items: list[GCSLogQueueItem]) -> None:
|
||||
|
|
@ -255,7 +255,7 @@ class GCSBucketLogger(GCSBucketBase, AdditionalLoggingUtils):
|
|||
logging_payload=item["payload"],
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"GCS Bucket error logging individual payload to GCS bucket: {e}")
|
||||
verbose_logger.exception("GCS Bucket error logging individual payload to GCS bucket: %s", e)
|
||||
|
||||
async def async_send_batch(self):
|
||||
"""
|
||||
|
|
@ -336,7 +336,7 @@ class GCSBucketLogger(GCSBucketBase, AdditionalLoggingUtils):
|
|||
loaded_response = json.loads(response)
|
||||
return loaded_response
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Failed to fetch payload for date {date_str}: {e}")
|
||||
verbose_logger.debug("Failed to fetch payload for date %s: %s", date_str, e)
|
||||
continue
|
||||
|
||||
return None
|
||||
|
|
@ -370,7 +370,7 @@ class GCSBucketLogger(GCSBucketBase, AdditionalLoggingUtils):
|
|||
"""
|
||||
while True:
|
||||
await asyncio.sleep(self.flush_interval)
|
||||
verbose_logger.debug(f"GCS Bucket periodic flush after {self.flush_interval} seconds")
|
||||
verbose_logger.debug("GCS Bucket periodic flush after %s seconds", self.flush_interval)
|
||||
await self.flush_queue()
|
||||
|
||||
async def async_health_check(self) -> IntegrationHealthCheckStatus:
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ async def _mock_async_handler_get(self, url, params=None, headers=None, follow_r
|
|||
"""Monkey-patched AsyncHTTPHandler.get that intercepts GCS calls."""
|
||||
# Only mock GCS API calls
|
||||
if isinstance(url, str) and "storage.googleapis.com" in url:
|
||||
verbose_logger.info(f"[GCS MOCK] GET to {url}")
|
||||
verbose_logger.info("[GCS MOCK] GET to %s", url)
|
||||
await asyncio.sleep(_MOCK_LATENCY_SECONDS)
|
||||
# Return a minimal but valid StandardLoggingPayload JSON string as bytes
|
||||
# This matches what GCS returns when downloading with ?alt=media
|
||||
|
|
@ -117,7 +117,7 @@ async def _mock_async_handler_delete(
|
|||
"""Monkey-patched AsyncHTTPHandler.delete that intercepts GCS calls."""
|
||||
# Only mock GCS API calls
|
||||
if isinstance(url, str) and "storage.googleapis.com" in url:
|
||||
verbose_logger.info(f"[GCS MOCK] DELETE to {url}")
|
||||
verbose_logger.info("[GCS MOCK] DELETE to %s", url)
|
||||
await asyncio.sleep(_MOCK_LATENCY_SECONDS)
|
||||
# DELETE returns 204 No Content with empty body (not JSON)
|
||||
return MockResponse(
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ class GcsPubSubLogger(CustomBatchLogger):
|
|||
await self.async_send_batch()
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"PubSub Layer Error - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("PubSub Layer Error - %s\n%s", e, traceback.format_exc())
|
||||
|
||||
async def async_send_batch(self):
|
||||
"""
|
||||
|
|
@ -142,13 +142,13 @@ class GcsPubSubLogger(CustomBatchLogger):
|
|||
if not self.log_queue:
|
||||
return
|
||||
|
||||
verbose_logger.debug(f"PubSub - about to flush {len(self.log_queue)} events")
|
||||
verbose_logger.debug("PubSub - about to flush %s events", len(self.log_queue))
|
||||
|
||||
for message in self.log_queue:
|
||||
await self.publish_message(message)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"PubSub Error sending batch - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("PubSub Error sending batch - %s\n%s", e, traceback.format_exc())
|
||||
finally:
|
||||
self.log_queue.clear()
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ def load_compatible_callbacks() -> dict:
|
|||
with open(json_path, "r") as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Error loading generic_api_compatible_callbacks.json: {e}")
|
||||
verbose_logger.warning("Error loading generic_api_compatible_callbacks.json: %s", e)
|
||||
return {}
|
||||
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ class GenericAPILogger(CustomBatchLogger):
|
|||
#########################################################
|
||||
if callback_name:
|
||||
if is_callback_compatible(callback_name):
|
||||
verbose_logger.debug(f"Loading configuration for callback: {callback_name}")
|
||||
verbose_logger.debug("Loading configuration for callback: %s", callback_name)
|
||||
callback_config = get_callback_config(callback_name)
|
||||
|
||||
# Use config from JSON if not explicitly provided
|
||||
|
|
@ -145,7 +145,7 @@ class GenericAPILogger(CustomBatchLogger):
|
|||
log_format = callback_config["log_format"]
|
||||
else:
|
||||
verbose_logger.warning(
|
||||
f"callback_name '{callback_name}' not found in generic_api_compatible_callbacks.json"
|
||||
"callback_name '%s' not found in generic_api_compatible_callbacks.json", callback_name
|
||||
)
|
||||
|
||||
#########################################################
|
||||
|
|
@ -177,7 +177,12 @@ class GenericAPILogger(CustomBatchLogger):
|
|||
self.log_format: LOG_FORMAT_TYPES = log_format or "json_array"
|
||||
|
||||
verbose_logger.debug(
|
||||
f"in init GenericAPILogger, callback_name: {self.callback_name}, endpoint {self.endpoint}, headers {self.headers}, event_types: {self.event_types}, log_format: {self.log_format}"
|
||||
"in init GenericAPILogger, callback_name: %s, endpoint %s, headers %s, event_types: %s, log_format: %s",
|
||||
self.callback_name,
|
||||
self.endpoint,
|
||||
self.headers,
|
||||
self.event_types,
|
||||
self.log_format,
|
||||
)
|
||||
|
||||
#########################################################
|
||||
|
|
@ -214,7 +219,7 @@ class GenericAPILogger(CustomBatchLogger):
|
|||
key, value = item.split("=", 1)
|
||||
headers_dict[key.strip()] = value.strip()
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Error parsing headers from environment variables: {e}")
|
||||
verbose_logger.warning("Error parsing headers from environment variables: %s", e)
|
||||
|
||||
# 2. Update with litellm generic headers if available
|
||||
if litellm.generic_logger_headers:
|
||||
|
|
@ -308,7 +313,7 @@ class GenericAPILogger(CustomBatchLogger):
|
|||
await self.async_send_batch()
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Generic API Logger Error - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("Generic API Logger Error - %s\n%s", e, traceback.format_exc())
|
||||
|
||||
async def async_log_failure_event(self, kwargs, response_obj, start_time, end_time):
|
||||
"""
|
||||
|
|
@ -339,7 +344,7 @@ class GenericAPILogger(CustomBatchLogger):
|
|||
await self.async_send_batch()
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Generic API Logger Error - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("Generic API Logger Error - %s\n%s", e, traceback.format_exc())
|
||||
|
||||
async def async_send_batch(self):
|
||||
"""
|
||||
|
|
@ -355,7 +360,7 @@ class GenericAPILogger(CustomBatchLogger):
|
|||
return
|
||||
|
||||
verbose_logger.debug(
|
||||
f"Generic API Logger - about to flush {len(self.log_queue)} events in '{self.log_format}' format"
|
||||
"Generic API Logger - about to flush %s events in '%s' format", len(self.log_queue), self.log_format
|
||||
)
|
||||
|
||||
if self.log_format == "single":
|
||||
|
|
@ -371,11 +376,13 @@ class GenericAPILogger(CustomBatchLogger):
|
|||
# Log results
|
||||
for idx, result in enumerate(responses):
|
||||
if isinstance(result, Exception):
|
||||
verbose_logger.exception(f"Generic API Logger - Error sending log {idx}: {result}")
|
||||
verbose_logger.exception("Generic API Logger - Error sending log %s: %s", idx, result)
|
||||
else:
|
||||
# result is a Response object
|
||||
verbose_logger.debug(
|
||||
f"Generic API Logger - sent log {idx}, status: {result.status_code}" # type: ignore
|
||||
"Generic API Logger - sent log %s, status: %s",
|
||||
idx,
|
||||
result.status_code, # type: ignore
|
||||
)
|
||||
else:
|
||||
# Format the payload based on log_format
|
||||
|
|
@ -390,12 +397,14 @@ class GenericAPILogger(CustomBatchLogger):
|
|||
response = await self._post_with_retries(data=data)
|
||||
|
||||
verbose_logger.debug(
|
||||
f"Generic API Logger - sent batch to {self.endpoint}, "
|
||||
f"status: {response.status_code}, format: {self.log_format}"
|
||||
"Generic API Logger - sent batch to %s, status: %s, format: %s",
|
||||
self.endpoint,
|
||||
response.status_code,
|
||||
self.log_format,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Generic API Logger Error sending batch - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("Generic API Logger Error sending batch - %s\n%s", e, traceback.format_exc())
|
||||
finally:
|
||||
self.log_queue.clear()
|
||||
|
||||
|
|
@ -405,7 +414,7 @@ class GenericAPILogger(CustomBatchLogger):
|
|||
|
||||
Returns a dict of the payload to send to the Generic API Endpoint
|
||||
"""
|
||||
verbose_logger.debug(f"GenericAPILogger Logging - Enters logging function for model {kwargs}")
|
||||
verbose_logger.debug("GenericAPILogger Logging - Enters logging function for model %s", kwargs)
|
||||
|
||||
# construct payload to send custom logger
|
||||
# follows the same params as langfuse.py
|
||||
|
|
|
|||
|
|
@ -379,7 +379,7 @@ class GitLabPromptManager(CustomPromptManagement):
|
|||
except Exception as e:
|
||||
import litellm
|
||||
|
||||
litellm._logging.verbose_proxy_logger.error(f"Error in GitLab prompt pre_call_hook: {e}")
|
||||
litellm._logging.verbose_proxy_logger.error("Error in GitLab prompt pre_call_hook: %s", e)
|
||||
return messages, litellm_params
|
||||
|
||||
def _parse_prompt_to_messages(self, prompt_content: str) -> list[AllMessageValues]:
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ class LagoLogger(CustomLogger):
|
|||
}
|
||||
}
|
||||
|
||||
verbose_logger.debug(f"\033[91mLogged Lago Object:\n{returned_val}\033[0m\n")
|
||||
verbose_logger.debug("\x1b[91mLogged Lago Object:\n%s\x1b[0m\n", returned_val)
|
||||
return returned_val
|
||||
|
||||
def log_success_event(self, kwargs, response_obj, start_time, end_time):
|
||||
|
|
@ -149,7 +149,7 @@ class LagoLogger(CustomLogger):
|
|||
except Exception as e:
|
||||
error_response = getattr(e, "response", None)
|
||||
if error_response is not None and hasattr(error_response, "text"):
|
||||
verbose_logger.debug(f"\nError Message: {error_response.text}")
|
||||
verbose_logger.debug("\nError Message: %s", error_response.text)
|
||||
raise e
|
||||
|
||||
async def async_log_success_event(self, kwargs, response_obj, start_time, end_time):
|
||||
|
|
@ -184,8 +184,8 @@ class LagoLogger(CustomLogger):
|
|||
|
||||
response.raise_for_status()
|
||||
|
||||
verbose_logger.debug(f"Logged Lago Object: {response.text}")
|
||||
verbose_logger.debug("Logged Lago Object: %s", response.text)
|
||||
except Exception as e:
|
||||
if response is not None and hasattr(response, "text"):
|
||||
verbose_logger.debug(f"\nError Message: {response.text}")
|
||||
verbose_logger.debug("\nError Message: %s", response.text)
|
||||
raise e
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ class LangFuseLogger:
|
|||
)
|
||||
langfuse_client = Langfuse(**parameters)
|
||||
litellm.initialized_langfuse_clients += 1
|
||||
verbose_logger.debug(f"Created langfuse client number {litellm.initialized_langfuse_clients}")
|
||||
verbose_logger.debug("Created langfuse client number %s", litellm.initialized_langfuse_clients)
|
||||
return langfuse_client
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -226,9 +226,9 @@ class LangFuseLogger:
|
|||
if metadata_param_key.startswith("langfuse_"):
|
||||
trace_param_key = metadata_param_key.replace("langfuse_", "", 1)
|
||||
if trace_param_key in metadata:
|
||||
verbose_logger.warning(f"Overwriting Langfuse `{trace_param_key}` from request header")
|
||||
verbose_logger.warning("Overwriting Langfuse `%s` from request header", trace_param_key)
|
||||
else:
|
||||
verbose_logger.debug(f"Found Langfuse `{trace_param_key}` in request header")
|
||||
verbose_logger.debug("Found Langfuse `%s` in request header", trace_param_key)
|
||||
metadata[trace_param_key] = proxy_headers.get(metadata_param_key)
|
||||
|
||||
return metadata
|
||||
|
|
@ -256,7 +256,7 @@ class LangFuseLogger:
|
|||
Logs a success or error event on Langfuse
|
||||
"""
|
||||
try:
|
||||
verbose_logger.debug(f"Langfuse Logging - Enters logging function for model {kwargs}")
|
||||
verbose_logger.debug("Langfuse Logging - Enters logging function for model %s", kwargs)
|
||||
|
||||
# set default values for input/output for langfuse logging
|
||||
input = None
|
||||
|
|
@ -295,7 +295,7 @@ class LangFuseLogger:
|
|||
level=level,
|
||||
status_message=status_message,
|
||||
)
|
||||
verbose_logger.debug(f"OUTPUT IN LANGFUSE: {output}; original: {response_obj}")
|
||||
verbose_logger.debug("OUTPUT IN LANGFUSE: %s; original: %s", output, response_obj)
|
||||
trace_id = None
|
||||
generation_id = None
|
||||
if self._is_langfuse_v2():
|
||||
|
|
@ -325,12 +325,12 @@ class LangFuseLogger:
|
|||
input=input,
|
||||
response_obj=response_obj,
|
||||
)
|
||||
verbose_logger.debug(f"Langfuse Layer Logging - final response object: {response_obj}")
|
||||
verbose_logger.debug("Langfuse Layer Logging - final response object: %s", response_obj)
|
||||
verbose_logger.info("Langfuse Layer Logging - logging success")
|
||||
|
||||
return {"trace_id": trace_id, "generation_id": generation_id}
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Langfuse Layer Error(): Exception occured - {e}")
|
||||
verbose_logger.exception("Langfuse Layer Error(): Exception occured - %s", e)
|
||||
return {"trace_id": None, "generation_id": None}
|
||||
|
||||
def _get_langfuse_input_output_content(
|
||||
|
|
@ -625,7 +625,7 @@ class LangFuseLogger:
|
|||
trace_params["metadata"] = {"metadata_passed_to_litellm": metadata}
|
||||
|
||||
cost = kwargs.get("response_cost", None)
|
||||
verbose_logger.debug(f"trace: {cost}")
|
||||
verbose_logger.debug("trace: %s", cost)
|
||||
|
||||
clean_metadata["litellm_response_cost"] = cost
|
||||
if standard_logging_object is not None:
|
||||
|
|
@ -780,12 +780,13 @@ class LangFuseLogger:
|
|||
if hasattr(generation_client, "trace_id") and generation_client.trace_id:
|
||||
if generation_client.trace_id != trace_id:
|
||||
verbose_logger.warning(
|
||||
f"Langfuse trace_id mismatch: set {trace_id}, but langfuse returned {generation_client.trace_id}. "
|
||||
"Using our intended trace_id for consistency."
|
||||
"Langfuse trace_id mismatch: set %s, but langfuse returned %s. Using our intended trace_id for consistency.",
|
||||
trace_id,
|
||||
generation_client.trace_id,
|
||||
)
|
||||
return trace_id, generation_id
|
||||
except Exception:
|
||||
verbose_logger.error(f"Langfuse Layer Error - {traceback.format_exc()}")
|
||||
verbose_logger.error("Langfuse Layer Error - %s", traceback.format_exc())
|
||||
return None, None
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -902,7 +903,7 @@ class LangFuseLogger:
|
|||
# For other types, try to apply the function directly
|
||||
return masking_function(data)
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Failed to apply masking function: {e}. Returning original data.")
|
||||
verbose_logger.warning("Failed to apply masking function: %s. Returning original data.", e)
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -966,7 +967,7 @@ class LangFuseLogger:
|
|||
end_time=guardrail_entry.get("end_time", None), # type: ignore
|
||||
)
|
||||
|
||||
verbose_logger.debug(f"Logged guardrail information as span: {span}")
|
||||
verbose_logger.debug("Logged guardrail information as span: %s", span)
|
||||
span.end()
|
||||
|
||||
|
||||
|
|
@ -1035,7 +1036,7 @@ def _add_prompt_to_generation_params(
|
|||
try:
|
||||
generation_params["prompt"] = langfuse_client.get_prompt(prompt_management_metadata["prompt_id"])
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"[Non-blocking] Langfuse Logger: Error getting prompt client for logging: {e}")
|
||||
verbose_logger.debug("[Non-blocking] Langfuse Logger: Error getting prompt client for logging: %s", e)
|
||||
|
||||
else:
|
||||
generation_params["prompt"] = user_prompt
|
||||
|
|
|
|||
|
|
@ -315,10 +315,10 @@ class LangfuseOtelLogger(OpenTelemetry):
|
|||
if langfuse_host:
|
||||
normalized_host = langfuse_host if langfuse_host.startswith("http") else f"https://{langfuse_host}"
|
||||
endpoint = f"{normalized_host.rstrip('/')}/api/public/otel"
|
||||
verbose_logger.debug(f"Using Langfuse OTEL endpoint from host: {endpoint}")
|
||||
verbose_logger.debug("Using Langfuse OTEL endpoint from host: %s", endpoint)
|
||||
else:
|
||||
endpoint = LANGFUSE_CLOUD_US_ENDPOINT
|
||||
verbose_logger.debug(f"Using Langfuse US cloud endpoint: {endpoint}")
|
||||
verbose_logger.debug("Using Langfuse US cloud endpoint: %s", endpoint)
|
||||
|
||||
auth_header = LangfuseOtelLogger._get_langfuse_authorization_header(
|
||||
public_key=public_key, secret_key=secret_key
|
||||
|
|
|
|||
|
|
@ -317,7 +317,7 @@ class LangfusePromptManagement(LangFuseLogger, PromptManagementBase, CustomLogge
|
|||
except Exception as e:
|
||||
from litellm._logging import verbose_logger
|
||||
|
||||
verbose_logger.exception(f"Langfuse Layer Error - Exception occurred while logging success event: {e}")
|
||||
verbose_logger.exception("Langfuse Layer Error - Exception occurred while logging success event: %s", e)
|
||||
self.handle_callback_failure(callback_name="langfuse")
|
||||
|
||||
async def async_log_failure_event(self, kwargs, response_obj, start_time, end_time):
|
||||
|
|
@ -347,5 +347,5 @@ class LangfusePromptManagement(LangFuseLogger, PromptManagementBase, CustomLogge
|
|||
except Exception as e:
|
||||
from litellm._logging import verbose_logger
|
||||
|
||||
verbose_logger.exception(f"Langfuse Layer Error - Exception occurred while logging failure event: {e}")
|
||||
verbose_logger.exception("Langfuse Layer Error - Exception occurred while logging failure event: %s", e)
|
||||
self.handle_callback_failure(callback_name="langfuse")
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ class LangsmithLogger(CustomBatchLogger):
|
|||
|
||||
fields = self._extract_metadata_fields(metadata, credentials)
|
||||
verbose_logger.debug(
|
||||
f"Langsmith Logging - project_name: {fields['project_name']}, run_name {fields['run_name']}"
|
||||
"Langsmith Logging - project_name: %s, run_name %s", fields["project_name"], fields["run_name"]
|
||||
)
|
||||
|
||||
payload: StandardLoggingPayload | None = kwargs.get("standard_logging_object", None)
|
||||
|
|
@ -244,7 +244,7 @@ class LangsmithLogger(CustomBatchLogger):
|
|||
random_sample = random.random()
|
||||
if random_sample > sampling_rate:
|
||||
verbose_logger.info(
|
||||
f"Skipping Langsmith logging. Sampling rate={sampling_rate}, random_sample={random_sample}"
|
||||
"Skipping Langsmith logging. Sampling rate=%s, random_sample=%s", sampling_rate, random_sample
|
||||
)
|
||||
return # Skip logging
|
||||
verbose_logger.debug(
|
||||
|
|
@ -267,7 +267,7 @@ class LangsmithLogger(CustomBatchLogger):
|
|||
credentials=credentials,
|
||||
)
|
||||
)
|
||||
verbose_logger.debug(f"Langsmith, event added to queue. Will flush in {self.flush_interval} seconds...")
|
||||
verbose_logger.debug("Langsmith, event added to queue. Will flush in %s seconds...", self.flush_interval)
|
||||
|
||||
if len(self.log_queue) >= self.batch_size:
|
||||
self._send_batch()
|
||||
|
|
@ -282,7 +282,7 @@ class LangsmithLogger(CustomBatchLogger):
|
|||
random_sample = random.random()
|
||||
if random_sample > sampling_rate:
|
||||
verbose_logger.info(
|
||||
f"Skipping Langsmith logging. Sampling rate={sampling_rate}, random_sample={random_sample}"
|
||||
"Skipping Langsmith logging. Sampling rate=%s, random_sample=%s", sampling_rate, random_sample
|
||||
)
|
||||
return # Skip logging
|
||||
verbose_logger.debug(
|
||||
|
|
@ -321,7 +321,7 @@ class LangsmithLogger(CustomBatchLogger):
|
|||
random_sample = random.random()
|
||||
if random_sample > sampling_rate:
|
||||
verbose_logger.info(
|
||||
f"Skipping Langsmith logging. Sampling rate={sampling_rate}, random_sample={random_sample}"
|
||||
"Skipping Langsmith logging. Sampling rate=%s, random_sample=%s", sampling_rate, random_sample
|
||||
)
|
||||
return # Skip logging
|
||||
verbose_logger.info("Langsmith Failure Event Logging!")
|
||||
|
|
@ -422,16 +422,16 @@ class LangsmithLogger(CustomBatchLogger):
|
|||
response.raise_for_status()
|
||||
|
||||
if response.status_code >= 300:
|
||||
verbose_logger.error(f"Langsmith Error: {response.status_code} - {response.text}")
|
||||
verbose_logger.error("Langsmith Error: %s - %s", response.status_code, response.text)
|
||||
else:
|
||||
if self.is_mock_mode:
|
||||
verbose_logger.debug(f"[LANGSMITH MOCK] Batch of {len(elements_to_log)} runs successfully mocked")
|
||||
verbose_logger.debug("[LANGSMITH MOCK] Batch of %s runs successfully mocked", len(elements_to_log))
|
||||
else:
|
||||
verbose_logger.debug(f"Batch of {len(self.log_queue)} runs successfully created")
|
||||
verbose_logger.debug("Batch of %s runs successfully created", len(self.log_queue))
|
||||
except httpx.HTTPStatusError as e:
|
||||
verbose_logger.exception(f"Langsmith HTTP Error: {e.response.status_code} - {e.response.text}")
|
||||
verbose_logger.exception("Langsmith HTTP Error: %s - %s", e.response.status_code, e.response.text)
|
||||
except Exception:
|
||||
verbose_logger.exception(f"Langsmith Layer Error - {traceback.format_exc()}")
|
||||
verbose_logger.exception("Langsmith Layer Error - %s", traceback.format_exc())
|
||||
|
||||
def _group_batches_by_credentials(self) -> dict[CredentialsKey, BatchGroup]:
|
||||
"""Groups queue objects by credentials using a proper key structure"""
|
||||
|
|
|
|||
|
|
@ -94,9 +94,9 @@ class LiteralAILogger(CustomBatchLogger):
|
|||
)
|
||||
|
||||
if response.status_code >= 300:
|
||||
verbose_logger.error(f"Literal AI Error: {response.status_code} - {response.text}")
|
||||
verbose_logger.error("Literal AI Error: %s - %s", response.status_code, response.text)
|
||||
else:
|
||||
verbose_logger.debug(f"Batch of {len(self.log_queue)} runs successfully created")
|
||||
verbose_logger.debug("Batch of %s runs successfully created", len(self.log_queue))
|
||||
except Exception:
|
||||
verbose_logger.exception("Literal AI Layer Error")
|
||||
|
||||
|
|
@ -152,11 +152,11 @@ class LiteralAILogger(CustomBatchLogger):
|
|||
headers=self.headers,
|
||||
)
|
||||
if response.status_code >= 300:
|
||||
verbose_logger.error(f"Literal AI Error: {response.status_code} - {response.text}")
|
||||
verbose_logger.error("Literal AI Error: %s - %s", response.status_code, response.text)
|
||||
else:
|
||||
verbose_logger.debug(f"Batch of {len(self.log_queue)} runs successfully created")
|
||||
verbose_logger.debug("Batch of %s runs successfully created", len(self.log_queue))
|
||||
except httpx.HTTPStatusError as e:
|
||||
verbose_logger.exception(f"Literal AI HTTP Error: {e.response.status_code} - {e.response.text}")
|
||||
verbose_logger.exception("Literal AI HTTP Error: %s - %s", e.response.status_code, e.response.text)
|
||||
except Exception:
|
||||
verbose_logger.exception("Literal AI Layer Error")
|
||||
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ class LogfireLogger:
|
|||
try:
|
||||
import logfire
|
||||
|
||||
verbose_logger.debug(f"logfire Logging - Enters logging function for model {kwargs}")
|
||||
verbose_logger.debug("logfire Logging - Enters logging function for model %s", kwargs)
|
||||
|
||||
if not response_obj:
|
||||
response_obj = {}
|
||||
|
|
@ -159,4 +159,4 @@ class LogfireLogger:
|
|||
|
||||
print_verbose(f"Logfire Layer Logging - final response object: {response_obj}")
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Logfire Layer Error - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.debug("Logfire Layer Error - %s\n%s", e, traceback.format_exc())
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ class MlflowLogger(CustomLogger):
|
|||
)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"MLflow Logging Error - {e}", stack_info=True)
|
||||
verbose_logger.debug("MLflow Logging Error - %s", e, stack_info=True)
|
||||
|
||||
def _handle_stream_event(self, kwargs, response_obj, start_time, end_time):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ def create_mock_client_factory(config: MockClientConfig):
|
|||
):
|
||||
"""Monkey-patched AsyncHTTPHandler.post that intercepts API calls."""
|
||||
if isinstance(url, str) and _is_mock_url(url):
|
||||
verbose_logger.info(f"[{config.name} MOCK] POST to {url}")
|
||||
verbose_logger.info("[%s MOCK] POST to %s", config.name, url)
|
||||
await asyncio.sleep(_MOCK_LATENCY_SECONDS)
|
||||
return MockResponse(
|
||||
status_code=config.default_status_code,
|
||||
|
|
@ -172,7 +172,7 @@ def create_mock_client_factory(config: MockClientConfig):
|
|||
def _mock_sync_client_post(self, url, **kwargs):
|
||||
"""Monkey-patched httpx.Client.post that intercepts API calls."""
|
||||
if _is_mock_url(url):
|
||||
verbose_logger.info(f"[{config.name} MOCK] POST to {url} (sync)")
|
||||
verbose_logger.info("[%s MOCK] POST to %s (sync)", config.name, url)
|
||||
return MockResponse(
|
||||
status_code=config.default_status_code,
|
||||
json_data=config.default_json_data,
|
||||
|
|
@ -198,7 +198,7 @@ def create_mock_client_factory(config: MockClientConfig):
|
|||
):
|
||||
"""Monkey-patched HTTPHandler.post that intercepts API calls."""
|
||||
if isinstance(url, str) and _is_mock_url(url):
|
||||
verbose_logger.info(f"[{config.name} MOCK] POST to {url}")
|
||||
verbose_logger.info("[%s MOCK] POST to %s", config.name, url)
|
||||
import time
|
||||
|
||||
time.sleep(_MOCK_LATENCY_SECONDS)
|
||||
|
|
@ -236,29 +236,29 @@ def create_mock_client_factory(config: MockClientConfig):
|
|||
if _mocks_initialized:
|
||||
return
|
||||
|
||||
verbose_logger.debug(f"[{config.name} MOCK] Initializing {config.name} mock client...")
|
||||
verbose_logger.debug("[%s MOCK] Initializing %s mock client...", config.name, config.name)
|
||||
|
||||
if config.patch_async_handler and _original_async_handler_post is None:
|
||||
from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler
|
||||
|
||||
_original_async_handler_post = AsyncHTTPHandler.post
|
||||
AsyncHTTPHandler.post = _mock_async_handler_post # type: ignore
|
||||
verbose_logger.debug(f"[{config.name} MOCK] Patched AsyncHTTPHandler.post")
|
||||
verbose_logger.debug("[%s MOCK] Patched AsyncHTTPHandler.post", config.name)
|
||||
|
||||
if config.patch_sync_client and _original_sync_client_post is None:
|
||||
_original_sync_client_post = httpx.Client.post
|
||||
httpx.Client.post = _mock_sync_client_post # type: ignore
|
||||
verbose_logger.debug(f"[{config.name} MOCK] Patched httpx.Client.post")
|
||||
verbose_logger.debug("[%s MOCK] Patched httpx.Client.post", config.name)
|
||||
|
||||
if config.patch_http_handler and _original_http_handler_post is None:
|
||||
from litellm.llms.custom_httpx.http_handler import HTTPHandler
|
||||
|
||||
_original_http_handler_post = HTTPHandler.post
|
||||
HTTPHandler.post = _mock_http_handler_post # type: ignore
|
||||
verbose_logger.debug(f"[{config.name} MOCK] Patched HTTPHandler.post")
|
||||
verbose_logger.debug("[%s MOCK] Patched HTTPHandler.post", config.name)
|
||||
|
||||
verbose_logger.debug(f"[{config.name} MOCK] Mock latency set to {_MOCK_LATENCY_SECONDS * 1000:.0f}ms")
|
||||
verbose_logger.debug(f"[{config.name} MOCK] {config.name} mock client initialization complete")
|
||||
verbose_logger.debug("[%s MOCK] %s mock client initialization complete", config.name, config.name)
|
||||
|
||||
_mocks_initialized = True
|
||||
|
||||
|
|
@ -274,7 +274,7 @@ def create_mock_client_factory(config: MockClientConfig):
|
|||
result = bool(result) if result is not None else False
|
||||
|
||||
if result:
|
||||
verbose_logger.info(f"{config.name} Mock Mode: ENABLED - API calls will be mocked")
|
||||
verbose_logger.info("%s Mock Mode: ENABLED - API calls will be mocked", config.name)
|
||||
|
||||
return result
|
||||
|
||||
|
|
|
|||
|
|
@ -116,11 +116,12 @@ class NewRelicLogger(CustomLogger):
|
|||
|
||||
self.enabled = True
|
||||
verbose_logger.info(
|
||||
f"New Relic AI Monitoring initialized for app: {self.app_name}, "
|
||||
f"content recording: {self.record_content}"
|
||||
"New Relic AI Monitoring initialized for app: %s, content recording: %s",
|
||||
self.app_name,
|
||||
self.record_content,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"Failed to initialize New Relic agent: {e}. Integration will be disabled.")
|
||||
verbose_logger.error("Failed to initialize New Relic agent: %s. Integration will be disabled.", e)
|
||||
self.enabled = False
|
||||
|
||||
def _get_newrelic_params(self) -> dict:
|
||||
|
|
@ -170,9 +171,10 @@ class NewRelicLogger(CustomLogger):
|
|||
if value in ("0", "false", "no", "off"):
|
||||
return False
|
||||
verbose_logger.warning(
|
||||
f"{var_name}={raw!r} is not a recognised boolean "
|
||||
f"(accepts true/false, 1/0, yes/no, on/off). "
|
||||
f"Falling back to default ({default})."
|
||||
"%s=%r is not a recognised boolean (accepts true/false, 1/0, yes/no, on/off). Falling back to default (%s).",
|
||||
var_name,
|
||||
raw,
|
||||
default,
|
||||
)
|
||||
return default
|
||||
|
||||
|
|
@ -188,7 +190,7 @@ class NewRelicLogger(CustomLogger):
|
|||
|
||||
return version("litellm")
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Unable to determine litellm version: {e}")
|
||||
verbose_logger.warning("Unable to determine litellm version: %s", e)
|
||||
return "unknown"
|
||||
|
||||
def _emit_supportability_metric(self):
|
||||
|
|
@ -216,12 +218,12 @@ class NewRelicLogger(CustomLogger):
|
|||
|
||||
if app and app.enabled:
|
||||
app.record_custom_metric(metric_name, 1)
|
||||
verbose_logger.info(f"Emitted New Relic supportability metric: {metric_name}")
|
||||
verbose_logger.info("Emitted New Relic supportability metric: %s", metric_name)
|
||||
else:
|
||||
verbose_logger.info("New Relic application is not enabled; skipping metric recording.")
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Failed to emit supportability metric: {e}")
|
||||
verbose_logger.warning("Failed to emit supportability metric: %s", e)
|
||||
|
||||
def _check_and_emit_periodic_metric(self):
|
||||
"""
|
||||
|
|
@ -294,14 +296,13 @@ class NewRelicLogger(CustomLogger):
|
|||
trace_id = slo_trace_id
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Unable to parse New Relic trace context from upstream sources: {e}")
|
||||
verbose_logger.warning("Unable to parse New Relic trace context from upstream sources: %s", e)
|
||||
|
||||
if not trace_id:
|
||||
trace_id = uuid.uuid4().hex
|
||||
verbose_logger.debug(
|
||||
f"New Relic trace_id not available from distributed tracing headers or "
|
||||
f"StandardLoggingPayload. Generated trace_id={trace_id} for AI monitoring "
|
||||
f"event grouping."
|
||||
"New Relic trace_id not available from distributed tracing headers or StandardLoggingPayload. Generated trace_id=%s for AI monitoring event grouping.",
|
||||
trace_id,
|
||||
)
|
||||
|
||||
return trace_id
|
||||
|
|
@ -638,7 +639,7 @@ class NewRelicLogger(CustomLogger):
|
|||
verbose_logger.warning("New Relic application is not enabled; skipping summary event recording.")
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Failed to record New Relic summary event: {e}")
|
||||
verbose_logger.warning("Failed to record New Relic summary event: %s", e)
|
||||
self.handle_callback_failure("newrelic")
|
||||
|
||||
def _record_message_events(
|
||||
|
|
@ -699,7 +700,7 @@ class NewRelicLogger(CustomLogger):
|
|||
app.record_custom_event("LlmChatCompletionMessage", event_data)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Failed to record New Relic message events: {e}")
|
||||
verbose_logger.warning("Failed to record New Relic message events: %s", e)
|
||||
self.handle_callback_failure("newrelic")
|
||||
|
||||
def _record_error_metric(self):
|
||||
|
|
@ -714,7 +715,7 @@ class NewRelicLogger(CustomLogger):
|
|||
if app and app.enabled:
|
||||
app.record_custom_metric("LLM/LiteLLM/Error", 1)
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Failed to record New Relic error metric: {e}")
|
||||
verbose_logger.warning("Failed to record New Relic error metric: %s", e)
|
||||
self.handle_callback_failure("newrelic")
|
||||
|
||||
def _process_success(
|
||||
|
|
@ -846,7 +847,7 @@ class NewRelicLogger(CustomLogger):
|
|||
try:
|
||||
self._process_success(kwargs, response_obj, start_time, end_time)
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Error in New Relic log_success_event: {e}")
|
||||
verbose_logger.warning("Error in New Relic log_success_event: %s", e)
|
||||
self.handle_callback_failure("newrelic")
|
||||
|
||||
async def async_log_success_event(self, kwargs, response_obj, start_time, end_time):
|
||||
|
|
@ -859,7 +860,7 @@ class NewRelicLogger(CustomLogger):
|
|||
try:
|
||||
self._process_success(kwargs, response_obj, start_time, end_time)
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Error in New Relic async_log_success_event: {e}")
|
||||
verbose_logger.warning("Error in New Relic async_log_success_event: %s", e)
|
||||
self.handle_callback_failure("newrelic")
|
||||
|
||||
def log_failure_event(self, kwargs, response_obj, start_time, end_time):
|
||||
|
|
@ -872,7 +873,7 @@ class NewRelicLogger(CustomLogger):
|
|||
self._record_error_metric()
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Error in New Relic log_failure_event: {e}")
|
||||
verbose_logger.warning("Error in New Relic log_failure_event: %s", e)
|
||||
self.handle_callback_failure("newrelic")
|
||||
|
||||
async def async_log_failure_event(self, kwargs, response_obj, start_time, end_time):
|
||||
|
|
@ -885,5 +886,5 @@ class NewRelicLogger(CustomLogger):
|
|||
self._record_error_metric()
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Error in New Relic async_log_failure_event: {e}")
|
||||
verbose_logger.warning("Error in New Relic async_log_failure_event: %s", e)
|
||||
self.handle_callback_failure("newrelic")
|
||||
|
|
|
|||
|
|
@ -2688,7 +2688,8 @@ class OpenTelemetry(OTELGenAISemconvMixin, CustomLogger):
|
|||
)
|
||||
except json.JSONDecodeError:
|
||||
verbose_logger.debug(
|
||||
f"litellm.integrations.opentelemetry.py::set_raw_request_attributes() - raw_response not json string - {_raw_response}"
|
||||
"litellm.integrations.opentelemetry.py::set_raw_request_attributes() - raw_response not json string - %s",
|
||||
_raw_response,
|
||||
)
|
||||
|
||||
self.safe_set_attribute(
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ class OpikLogger(CustomBatchLogger):
|
|||
self.flush_lock: asyncio.Lock | None = asyncio.Lock()
|
||||
except Exception as e:
|
||||
verbose_logger.exception(
|
||||
f"OpikLogger - Asynchronous processing not initialized as we are not running in an async context {e}"
|
||||
"OpikLogger - Asynchronous processing not initialized as we are not running in an async context %s", e
|
||||
)
|
||||
self.flush_lock = None
|
||||
|
||||
|
|
@ -154,14 +154,14 @@ class OpikLogger(CustomBatchLogger):
|
|||
self.log_queue.append(span_payload.__dict__)
|
||||
|
||||
verbose_logger.debug(
|
||||
f"OpikLogger added event to log_queue - Will flush in {self.flush_interval} seconds..."
|
||||
"OpikLogger added event to log_queue - Will flush in %s seconds...", self.flush_interval
|
||||
)
|
||||
|
||||
if len(self.log_queue) >= self.batch_size:
|
||||
verbose_logger.debug("OpikLogger - Flushing batch")
|
||||
await self.flush_queue()
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"OpikLogger failed to log success event - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("OpikLogger failed to log success event - %s\n%s", e, traceback.format_exc())
|
||||
|
||||
def _sync_send(self, url: str, headers: dict[str, str], batch: dict[str, Any]) -> None:
|
||||
try:
|
||||
|
|
@ -174,7 +174,7 @@ class OpikLogger(CustomBatchLogger):
|
|||
if response.status_code != 204:
|
||||
raise Exception(f"Response from opik API status_code: {response.status_code}, text: {response.text}")
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"OpikLogger failed to send batch - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("OpikLogger failed to send batch - %s\n%s", e, traceback.format_exc())
|
||||
|
||||
def log_success_event(
|
||||
self,
|
||||
|
|
@ -245,7 +245,7 @@ class OpikLogger(CustomBatchLogger):
|
|||
batch={"spans": [span_payload.__dict__]},
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"OpikLogger failed to log success event - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("OpikLogger failed to log success event - %s\n%s", e, traceback.format_exc())
|
||||
|
||||
async def _submit_batch(self, url: str, headers: dict[str, str], batch: dict[str, Any]) -> None:
|
||||
try:
|
||||
|
|
@ -257,11 +257,11 @@ class OpikLogger(CustomBatchLogger):
|
|||
response.raise_for_status()
|
||||
|
||||
if response.status_code >= 300:
|
||||
verbose_logger.error(f"OpikLogger - Error: {response.status_code} - {response.text}")
|
||||
verbose_logger.error("OpikLogger - Error: %s - %s", response.status_code, response.text)
|
||||
else:
|
||||
verbose_logger.info(f"OpikLogger - {len(self.log_queue)} Opik events submitted")
|
||||
verbose_logger.info("OpikLogger - %s Opik events submitted", len(self.log_queue))
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"OpikLogger failed to send batch - {e}")
|
||||
verbose_logger.exception("OpikLogger failed to send batch - %s", e)
|
||||
|
||||
def _create_opik_headers(self) -> dict[str, str]:
|
||||
headers: dict[str, str] = {}
|
||||
|
|
@ -283,7 +283,7 @@ class OpikLogger(CustomBatchLogger):
|
|||
# Send trace batch
|
||||
if len(traces) > 0:
|
||||
await self._submit_batch(url=self.trace_url, headers=self.headers, batch={"traces": traces})
|
||||
verbose_logger.info(f"Sent {len(traces)} traces")
|
||||
verbose_logger.info("Sent %s traces", len(traces))
|
||||
if len(spans) > 0:
|
||||
await self._submit_batch(url=self.span_url, headers=self.headers, batch={"spans": spans})
|
||||
verbose_logger.info(f"Sent {len(spans)} spans")
|
||||
verbose_logger.info("Sent %s spans", len(spans))
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ def extract_opik_metadata(
|
|||
if requester_opik:
|
||||
opik_meta.update(requester_opik)
|
||||
|
||||
_logging.verbose_logger.debug(f"litellm_opik_metadata - {json.dumps(opik_meta, default=str)}")
|
||||
_logging.verbose_logger.debug("litellm_opik_metadata - %s", json.dumps(opik_meta, default=str))
|
||||
|
||||
return opik_meta
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ def extract_span_identifiers(
|
|||
try:
|
||||
return current_span_data.trace_id, current_span_data.id
|
||||
except AttributeError:
|
||||
_logging.verbose_logger.warning(f"Unexpected current_span_data format: {type(current_span_data)}")
|
||||
_logging.verbose_logger.warning("Unexpected current_span_data format: %s", type(current_span_data))
|
||||
return None, None
|
||||
|
||||
|
||||
|
|
@ -152,7 +152,7 @@ def apply_proxy_header_overrides(
|
|||
if isinstance(parsed_tags, list):
|
||||
tags.extend(parsed_tags)
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
_logging.verbose_logger.warning(f"Failed to parse tags from header: {value}")
|
||||
_logging.verbose_logger.warning("Failed to parse tags from header: %s", value)
|
||||
|
||||
return project_name, tags, thread_id
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ def build_span_payload(
|
|||
created = response_obj.get("created", 0)
|
||||
span_name = f"{model}_{obj_type}_{created}"
|
||||
|
||||
_logging.verbose_logger.debug(f"OpikLogger creating span with id {span_id} for trace {trace_id}")
|
||||
_logging.verbose_logger.debug("OpikLogger creating span with id %s for trace %s", span_id, trace_id)
|
||||
|
||||
return types.SpanPayload(
|
||||
id=span_id,
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ class PostHogLogger(CustomBatchLogger):
|
|||
super().__init__(**kwargs, flush_lock=None, batch_size=POSTHOG_MAX_BATCH_SIZE)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"PostHog: Got exception on init PostHog client {e}")
|
||||
verbose_logger.exception("PostHog: Got exception on init PostHog client %s", e)
|
||||
raise e
|
||||
|
||||
def log_success_event(self, kwargs, response_obj, start_time, end_time):
|
||||
|
|
@ -107,7 +107,7 @@ class PostHogLogger(CustomBatchLogger):
|
|||
verbose_logger.debug("PostHog: Sync event successfully sent")
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"PostHog Sync Layer Error - {e}")
|
||||
verbose_logger.exception("PostHog Sync Layer Error - %s", e)
|
||||
|
||||
async def async_log_success_event(self, kwargs, response_obj, start_time, end_time):
|
||||
try:
|
||||
|
|
@ -115,7 +115,7 @@ class PostHogLogger(CustomBatchLogger):
|
|||
self._ensure_async_setup() # Lazy initialization
|
||||
await self._log_async_event(kwargs, response_obj, start_time, end_time)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"PostHog Layer Error - {e}")
|
||||
verbose_logger.exception("PostHog Layer Error - %s", e)
|
||||
|
||||
async def async_log_failure_event(self, kwargs, response_obj, start_time, end_time):
|
||||
try:
|
||||
|
|
@ -123,7 +123,7 @@ class PostHogLogger(CustomBatchLogger):
|
|||
self._ensure_async_setup() # Lazy initialization
|
||||
await self._log_async_event(kwargs, response_obj, start_time, end_time)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"PostHog Layer Error - {e}")
|
||||
verbose_logger.exception("PostHog Layer Error - %s", e)
|
||||
|
||||
async def _log_async_event(self, kwargs, response_obj=None, start_time=0.0, end_time=0.0):
|
||||
# Note: response_obj, start_time, end_time not used - all data comes from kwargs
|
||||
|
|
@ -132,7 +132,7 @@ class PostHogLogger(CustomBatchLogger):
|
|||
|
||||
# Store event with its credentials for batch sending
|
||||
self.log_queue.append({"event": event_payload, "api_key": api_key, "api_url": api_url})
|
||||
verbose_logger.debug(f"PostHog, event added to queue. Will flush in {self.flush_interval} seconds...")
|
||||
verbose_logger.debug("PostHog, event added to queue. Will flush in %s seconds...", self.flush_interval)
|
||||
|
||||
if len(self.log_queue) >= self.batch_size:
|
||||
await self.flush_queue()
|
||||
|
|
@ -328,7 +328,7 @@ class PostHogLogger(CustomBatchLogger):
|
|||
if not self.log_queue:
|
||||
return
|
||||
|
||||
verbose_logger.debug(f"PostHog: Sending batch of {len(self.log_queue)} events")
|
||||
verbose_logger.debug("PostHog: Sending batch of %s events", len(self.log_queue))
|
||||
|
||||
if self.is_mock_mode:
|
||||
verbose_logger.debug("[POSTHOG MOCK] Mock mode enabled - API calls will be intercepted")
|
||||
|
|
@ -363,11 +363,11 @@ class PostHogLogger(CustomBatchLogger):
|
|||
)
|
||||
|
||||
if self.is_mock_mode:
|
||||
verbose_logger.debug(f"[POSTHOG MOCK] Batch of {len(self.log_queue)} events successfully mocked")
|
||||
verbose_logger.debug("[POSTHOG MOCK] Batch of %s events successfully mocked", len(self.log_queue))
|
||||
else:
|
||||
verbose_logger.debug(f"PostHog: Batch of {len(self.log_queue)} events successfully sent")
|
||||
verbose_logger.debug("PostHog: Batch of %s events successfully sent", len(self.log_queue))
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"PostHog Error sending batch API - {e}")
|
||||
verbose_logger.exception("PostHog Error sending batch API - %s", e)
|
||||
|
||||
def _ensure_async_setup(self):
|
||||
if not self._async_initialized:
|
||||
|
|
@ -377,7 +377,7 @@ class PostHogLogger(CustomBatchLogger):
|
|||
self._async_initialized = True
|
||||
verbose_logger.debug("PostHog: Async components initialized")
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"PostHog: Failed to initialize async components: {e}")
|
||||
verbose_logger.error("PostHog: Failed to initialize async components: %s", e)
|
||||
raise
|
||||
|
||||
def _extract_metadata(self, kwargs: dict[str, Any]) -> dict[str, Any]:
|
||||
|
|
@ -408,7 +408,7 @@ class PostHogLogger(CustomBatchLogger):
|
|||
if not self.log_queue:
|
||||
return
|
||||
|
||||
verbose_logger.debug(f"PostHog: Flushing {len(self.log_queue)} remaining events on exit")
|
||||
verbose_logger.debug("PostHog: Flushing %s remaining events on exit", len(self.log_queue))
|
||||
|
||||
try:
|
||||
# Group events by credentials (same logic as async_send_batch)
|
||||
|
|
@ -436,13 +436,13 @@ class PostHogLogger(CustomBatchLogger):
|
|||
response.raise_for_status()
|
||||
|
||||
if response.status_code != 200:
|
||||
verbose_logger.error(f"PostHog: Failed to flush on exit - status {response.status_code}")
|
||||
verbose_logger.error("PostHog: Failed to flush on exit - status %s", response.status_code)
|
||||
|
||||
if self.is_mock_mode:
|
||||
verbose_logger.debug(f"[POSTHOG MOCK] Successfully flushed {len(self.log_queue)} events on exit")
|
||||
verbose_logger.debug("[POSTHOG MOCK] Successfully flushed %s events on exit", len(self.log_queue))
|
||||
else:
|
||||
verbose_logger.debug(f"PostHog: Successfully flushed {len(self.log_queue)} events on exit")
|
||||
verbose_logger.debug("PostHog: Successfully flushed %s events on exit", len(self.log_queue))
|
||||
self.log_queue.clear()
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"PostHog: Error flushing events on exit: {e}")
|
||||
verbose_logger.error("PostHog: Error flushing events on exit: %s", e)
|
||||
|
|
|
|||
|
|
@ -697,7 +697,7 @@ class PrometheusLogger(CustomLogger):
|
|||
if not config:
|
||||
return {}
|
||||
|
||||
verbose_logger.debug(f"prometheus config: {config}")
|
||||
verbose_logger.debug("prometheus config: %s", config)
|
||||
|
||||
# Parse and validate all configuration groups
|
||||
parsed_configs = []
|
||||
|
|
@ -963,7 +963,10 @@ class PrometheusLogger(CustomLogger):
|
|||
except ImportError:
|
||||
# Fallback to simple logging if rich is not available
|
||||
verbose_logger.error(
|
||||
f"Invalid labels for metric '{metric_name}': {invalid_labels}. Valid labels: {sorted(valid_labels)}"
|
||||
"Invalid labels for metric '%s': %s. Valid labels: %s",
|
||||
metric_name,
|
||||
invalid_labels,
|
||||
sorted(valid_labels),
|
||||
)
|
||||
|
||||
def _pretty_print_invalid_metric_error(self, invalid_metric_name: str, valid_metrics: tuple) -> None:
|
||||
|
|
@ -1003,7 +1006,9 @@ class PrometheusLogger(CustomLogger):
|
|||
|
||||
except ImportError:
|
||||
# Fallback to simple logging if rich is not available
|
||||
verbose_logger.error(f"Invalid metric name: {invalid_metric_name}. Valid metrics: {sorted(valid_metrics)}")
|
||||
verbose_logger.error(
|
||||
"Invalid metric name: %s. Valid metrics: %s", invalid_metric_name, sorted(valid_metrics)
|
||||
)
|
||||
|
||||
#########################################################
|
||||
# End of pretty print functions
|
||||
|
|
@ -1078,9 +1083,10 @@ class PrometheusLogger(CustomLogger):
|
|||
except ImportError:
|
||||
# Fallback to simple logging if rich is not available
|
||||
verbose_logger.info(
|
||||
f"Enabled metrics: {sorted(self.enabled_metrics) if hasattr(self, 'enabled_metrics') else 'All metrics'}"
|
||||
"Enabled metrics: %s",
|
||||
sorted(self.enabled_metrics) if hasattr(self, "enabled_metrics") else "All metrics",
|
||||
)
|
||||
verbose_logger.info(f"Label filters: {label_filters}")
|
||||
verbose_logger.info("Label filters: %s", label_filters)
|
||||
|
||||
def _is_metric_enabled(self, metric_name: str) -> bool:
|
||||
"""Check if a metric is enabled based on configuration"""
|
||||
|
|
@ -1866,7 +1872,9 @@ class PrometheusLogger(CustomLogger):
|
|||
for i, r in enumerate(results):
|
||||
if isinstance(r, Exception):
|
||||
verbose_logger.debug(
|
||||
f"[Non-Blocking] Prometheus: Budget metric lookup {['key', 'team', 'user', 'org'][i]} failed: {r}"
|
||||
"[Non-Blocking] Prometheus: Budget metric lookup %s failed: %s",
|
||||
["key", "team", "user", "org"][i],
|
||||
r,
|
||||
)
|
||||
|
||||
def _increment_top_level_request_and_spend_metrics(
|
||||
|
|
@ -2132,7 +2140,7 @@ class PrometheusLogger(CustomLogger):
|
|||
response_cost=0,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"prometheus Layer Error(): Exception occured - {e}")
|
||||
verbose_logger.exception("prometheus Layer Error(): Exception occured - %s", e)
|
||||
|
||||
def _extract_status_code(
|
||||
self,
|
||||
|
|
@ -2262,8 +2270,9 @@ class PrometheusLogger(CustomLogger):
|
|||
|
||||
if self._is_invalid_api_key_request(status_code, exception=exception):
|
||||
verbose_logger.debug(
|
||||
"Skipping Prometheus metrics for invalid API key request: "
|
||||
f"status_code={status_code}, exception={type(exception).__name__ if exception else None}"
|
||||
"Skipping Prometheus metrics for invalid API key request: status_code=%s, exception=%s",
|
||||
status_code,
|
||||
type(exception).__name__ if exception else None,
|
||||
)
|
||||
return True
|
||||
|
||||
|
|
@ -2383,7 +2392,7 @@ class PrometheusLogger(CustomLogger):
|
|||
)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"prometheus Layer Error(): Exception occured - {e}")
|
||||
verbose_logger.exception("prometheus Layer Error(): Exception occured - %s", e)
|
||||
|
||||
async def async_post_call_success_hook(self, data: dict, user_api_key_dict: UserAPIKeyAuth, response):
|
||||
"""
|
||||
|
|
@ -2608,7 +2617,7 @@ class PrometheusLogger(CustomLogger):
|
|||
)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Prometheus Error: set_llm_deployment_failure_metrics. Exception occured - {e}")
|
||||
verbose_logger.debug("Prometheus Error: set_llm_deployment_failure_metrics. Exception occured - %s", e)
|
||||
|
||||
def _set_deployment_tpm_rpm_limit_metrics(
|
||||
self,
|
||||
|
|
@ -2722,7 +2731,7 @@ class PrometheusLogger(CustomLogger):
|
|||
)
|
||||
self.litellm_remaining_requests_metric.labels(**_labels).set(remaining_requests)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Prometheus Error: _async_set_router_remaining_metrics. Exception occured - {e}")
|
||||
verbose_logger.exception("Prometheus Error: _async_set_router_remaining_metrics. Exception occured - %s", e)
|
||||
|
||||
def set_llm_deployment_success_metrics(
|
||||
self,
|
||||
|
|
@ -2865,7 +2874,7 @@ class PrometheusLogger(CustomLogger):
|
|||
self.litellm_deployment_latency_per_output_token.labels(**_labels).observe(latency_per_token)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Prometheus Error: set_llm_deployment_success_metrics. Exception occured - {e}")
|
||||
verbose_logger.exception("Prometheus Error: set_llm_deployment_success_metrics. Exception occured - %s", e)
|
||||
return
|
||||
|
||||
def _record_guardrail_metrics(
|
||||
|
|
@ -2910,7 +2919,7 @@ class PrometheusLogger(CustomLogger):
|
|||
hook_type=hook_type,
|
||||
).inc()
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Error recording guardrail metrics: {e}")
|
||||
verbose_logger.debug("Error recording guardrail metrics: %s", e)
|
||||
|
||||
########################################
|
||||
# Managed Batch Metric Recording Methods
|
||||
|
|
@ -2933,7 +2942,7 @@ class PrometheusLogger(CustomLogger):
|
|||
api_key_alias=api_key_alias,
|
||||
).inc()
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Error recording batch created metric: {e}")
|
||||
verbose_logger.warning("Error recording batch created metric: %s", e)
|
||||
|
||||
def record_managed_file_size(
|
||||
self,
|
||||
|
|
@ -2954,7 +2963,7 @@ class PrometheusLogger(CustomLogger):
|
|||
user=user or "",
|
||||
).set(size_bytes)
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Error recording file size metric: {e}")
|
||||
verbose_logger.warning("Error recording file size metric: %s", e)
|
||||
|
||||
def record_managed_batch_duration(
|
||||
self,
|
||||
|
|
@ -2968,7 +2977,7 @@ class PrometheusLogger(CustomLogger):
|
|||
api_provider=api_provider or "",
|
||||
).observe(duration_seconds)
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Error recording batch duration metric: {e}")
|
||||
verbose_logger.warning("Error recording batch duration metric: %s", e)
|
||||
|
||||
def record_managed_file_created(
|
||||
self,
|
||||
|
|
@ -2987,14 +2996,14 @@ class PrometheusLogger(CustomLogger):
|
|||
api_key_alias=api_key_alias,
|
||||
).inc()
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Error recording file created metric: {e}")
|
||||
verbose_logger.warning("Error recording file created metric: %s", e)
|
||||
|
||||
def record_managed_file_deleted(self, result: str):
|
||||
"""Record a managed file deletion attempt. result is 'success' or 'blocked'."""
|
||||
try:
|
||||
self.litellm_managed_file_deleted_total.labels(result=result).inc()
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Error recording file deleted metric: {e}")
|
||||
verbose_logger.warning("Error recording file deleted metric: %s", e)
|
||||
|
||||
def record_check_batch_cost_run(
|
||||
self,
|
||||
|
|
@ -3021,7 +3030,7 @@ class PrometheusLogger(CustomLogger):
|
|||
api_provider=api_provider or "",
|
||||
).inc()
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Error recording check batch cost metrics: {e}")
|
||||
verbose_logger.warning("Error recording check batch cost metrics: %s", e)
|
||||
|
||||
def record_check_batch_cost_error(self, error_type: str):
|
||||
try:
|
||||
|
|
@ -3029,7 +3038,7 @@ class PrometheusLogger(CustomLogger):
|
|||
error_type=error_type,
|
||||
).inc()
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Error recording check batch cost error metric: {e}")
|
||||
verbose_logger.warning("Error recording check batch cost error metric: %s", e)
|
||||
|
||||
@staticmethod
|
||||
def _get_exception_class_name(exception: Exception) -> str:
|
||||
|
|
@ -3313,7 +3322,7 @@ class PrometheusLogger(CustomLogger):
|
|||
await set_metrics_function(data)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error initializing {data_type} budget metrics: {e}")
|
||||
verbose_logger.exception("Error initializing %s budget metrics: %s", data_type, e)
|
||||
|
||||
async def _initialize_team_budget_metrics(self):
|
||||
"""
|
||||
|
|
@ -3493,18 +3502,18 @@ class PrometheusLogger(CustomLogger):
|
|||
# Get total user count
|
||||
total_users = await UserRepository(prisma_client).table.count()
|
||||
self.litellm_total_users_metric.set(total_users)
|
||||
verbose_logger.debug(f"Prometheus: set litellm_total_users to {total_users}")
|
||||
verbose_logger.debug("Prometheus: set litellm_total_users to %s", total_users)
|
||||
|
||||
billable_users = await UserRepository(prisma_client).count_billable_users()
|
||||
self.litellm_active_users_metric.set(billable_users)
|
||||
verbose_logger.debug(f"Prometheus: set litellm_active_users to {billable_users}")
|
||||
verbose_logger.debug("Prometheus: set litellm_active_users to %s", billable_users)
|
||||
|
||||
# Get total team count
|
||||
total_teams = await TeamRepository(prisma_client).table.count()
|
||||
self.litellm_teams_count_metric.set(total_teams)
|
||||
verbose_logger.debug(f"Prometheus: set litellm_teams_count to {total_teams}")
|
||||
verbose_logger.debug("Prometheus: set litellm_teams_count to %s", total_teams)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error initializing user/team count metrics: {e}")
|
||||
verbose_logger.exception("Error initializing user/team count metrics: %s", e)
|
||||
|
||||
async def _set_key_list_budget_metrics(self, keys: list[str | UserAPIKeyAuth]):
|
||||
"""Helper function to set budget metrics for a list of keys"""
|
||||
|
|
@ -3595,7 +3604,7 @@ class PrometheusLogger(CustomLogger):
|
|||
user_api_key_cache=user_api_key_cache,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"[Non-Blocking] Prometheus: Error getting team info: {e}")
|
||||
verbose_logger.debug("[Non-Blocking] Prometheus: Error getting team info: %s", e)
|
||||
return team_object
|
||||
|
||||
if team_info:
|
||||
|
|
@ -3693,7 +3702,7 @@ class PrometheusLogger(CustomLogger):
|
|||
include_budget_table=True,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"[Non-Blocking] Prometheus: Error getting org info: {e}")
|
||||
verbose_logger.debug("[Non-Blocking] Prometheus: Error getting org info: %s", e)
|
||||
return
|
||||
|
||||
if org_info is None:
|
||||
|
|
@ -3850,7 +3859,7 @@ class PrometheusLogger(CustomLogger):
|
|||
if key_object:
|
||||
user_api_key_dict.budget_reset_at = key_object.budget_reset_at
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"[Non-Blocking] Prometheus: Error getting key info: {e}")
|
||||
verbose_logger.debug("[Non-Blocking] Prometheus: Error getting key info: %s", e)
|
||||
|
||||
return user_api_key_dict
|
||||
|
||||
|
|
@ -3915,7 +3924,7 @@ class PrometheusLogger(CustomLogger):
|
|||
check_db_only=False,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"[Non-Blocking] Prometheus: Error getting user info: {e}")
|
||||
verbose_logger.debug("[Non-Blocking] Prometheus: Error getting user info: %s", e)
|
||||
return user_object
|
||||
|
||||
if user_info:
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ class PrometheusServicesLogger:
|
|||
|
||||
metrics = DEFAULT_SERVICE_CONFIGS.get(service, {}).get("metrics", [])
|
||||
if not metrics:
|
||||
verbose_logger.debug(f"No metrics found for service {service}")
|
||||
verbose_logger.debug("No metrics found for service %s", service)
|
||||
return DEFAULT_METRICS
|
||||
return metrics
|
||||
|
||||
|
|
|
|||
|
|
@ -163,9 +163,9 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
|
|||
parsed_rate = float(rbrk_sampling_rate.strip())
|
||||
self.sampling_rate = max(0.0, min(1.0, parsed_rate))
|
||||
if parsed_rate != self.sampling_rate:
|
||||
verbose_logger.warning(f"RUBRIK_SAMPLING_RATE={parsed_rate} clamped to {self.sampling_rate}")
|
||||
verbose_logger.warning("RUBRIK_SAMPLING_RATE=%s clamped to %s", parsed_rate, self.sampling_rate)
|
||||
except ValueError:
|
||||
verbose_logger.warning(f"Invalid RUBRIK_SAMPLING_RATE: {rbrk_sampling_rate!r}, using 1.0")
|
||||
verbose_logger.warning("Invalid RUBRIK_SAMPLING_RATE: %r, using 1.0", rbrk_sampling_rate)
|
||||
|
||||
def _parse_batch_size(self) -> None:
|
||||
_batch_size = os.getenv("RUBRIK_BATCH_SIZE")
|
||||
|
|
@ -173,11 +173,11 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
|
|||
try:
|
||||
parsed_size = int(_batch_size)
|
||||
if parsed_size <= 0:
|
||||
verbose_logger.warning(f"RUBRIK_BATCH_SIZE={_batch_size!r} must be > 0, using default")
|
||||
verbose_logger.warning("RUBRIK_BATCH_SIZE=%r must be > 0, using default", _batch_size)
|
||||
else:
|
||||
self.batch_size = parsed_size
|
||||
except ValueError:
|
||||
verbose_logger.warning(f"Invalid RUBRIK_BATCH_SIZE: {_batch_size!r}, using default")
|
||||
verbose_logger.warning("Invalid RUBRIK_BATCH_SIZE: %r, using default", _batch_size)
|
||||
|
||||
def _setup_clients(self, webhook_url: str) -> None:
|
||||
self.response_moderation_endpoint = f"{webhook_url}{_WEBHOOK_PATH_RESPONSE_MODERATION}"
|
||||
|
|
@ -279,7 +279,9 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
|
|||
return inputs
|
||||
except Exception as e:
|
||||
verbose_logger.error(
|
||||
f"{label} hook failed: {e}. Returning original inputs unchanged.",
|
||||
"%s hook failed: %s. Returning original inputs unchanged.",
|
||||
label,
|
||||
e,
|
||||
exc_info=True,
|
||||
)
|
||||
return inputs
|
||||
|
|
@ -388,8 +390,9 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
|
|||
if logging_obj is None:
|
||||
verbose_logger.error(
|
||||
"Rubrik: moderation block fired with logging_obj=None for "
|
||||
f"litellm_call_id={request_data.get('litellm_call_id')}; "
|
||||
"cannot suppress success event or attach failure payload."
|
||||
"litellm_call_id=%s; "
|
||||
"cannot suppress success event or attach failure payload.",
|
||||
request_data.get("litellm_call_id"),
|
||||
)
|
||||
request_data["_rubrik_logging_obj"] = None
|
||||
return
|
||||
|
|
@ -650,14 +653,15 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
|
|||
payload["messages"] = (system_scaffold, messages)
|
||||
except Exception as e:
|
||||
verbose_logger.warning(
|
||||
f"Rubrik: failed to prepend system prompt: {e}",
|
||||
"Rubrik: failed to prepend system prompt: %s",
|
||||
e,
|
||||
exc_info=True,
|
||||
)
|
||||
|
||||
async def _prepare_log_payload(self, kwargs: Mapping[str, Any], event_type: str) -> StandardLoggingPayload | None:
|
||||
"""Shared logic for success logging (sampled)."""
|
||||
if random.random() > self.sampling_rate:
|
||||
verbose_logger.debug(f"Skipping Rubrik {event_type} logging (sampling_rate={self.sampling_rate})")
|
||||
verbose_logger.debug("Skipping Rubrik %s logging (sampling_rate=%s)", event_type, self.sampling_rate)
|
||||
return None
|
||||
|
||||
# Deep-copy so mutations don't affect other callbacks sharing this object
|
||||
|
|
@ -701,7 +705,9 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
|
|||
await self._append_and_maybe_flush(payload)
|
||||
except Exception as e:
|
||||
verbose_logger.error(
|
||||
f"Rubrik {event_type} logging hook failed: {e}. Skipping logging for this event.",
|
||||
"Rubrik %s logging hook failed: %s. Skipping logging for this event.",
|
||||
event_type,
|
||||
e,
|
||||
exc_info=True,
|
||||
)
|
||||
|
||||
|
|
@ -710,7 +716,8 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
|
|||
# skip here to avoid double-logging the pre-block response.
|
||||
if kwargs.get("_rubrik_blocked"):
|
||||
verbose_logger.debug(
|
||||
f"Rubrik: skipping success event for blocked request litellm_call_id={kwargs.get('litellm_call_id')}"
|
||||
"Rubrik: skipping success event for blocked request litellm_call_id=%s",
|
||||
kwargs.get("litellm_call_id"),
|
||||
)
|
||||
return
|
||||
await self._enqueue_log_event(kwargs, "success")
|
||||
|
|
@ -755,11 +762,14 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
|
|||
# way we cannot build the payload.
|
||||
verbose_logger.warning(
|
||||
"Rubrik: block exception without stashed logging_obj. "
|
||||
f"litellm_call_id={request_data.get('litellm_call_id')}, "
|
||||
f"model={request_data.get('model')}, "
|
||||
f"user_id={user_api_key_dict.user_id}, "
|
||||
f"raising_guardrail="
|
||||
f"{getattr(original_exception, 'guardrail_name', None)}"
|
||||
"litellm_call_id=%s, "
|
||||
"model=%s, "
|
||||
"user_id=%s, "
|
||||
"raising_guardrail=%s",
|
||||
request_data.get("litellm_call_id"),
|
||||
request_data.get("model"),
|
||||
user_api_key_dict.user_id,
|
||||
getattr(original_exception, "guardrail_name", None),
|
||||
)
|
||||
return
|
||||
|
||||
|
|
@ -786,8 +796,9 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
|
|||
payload = self._prepare_block_failure_payload(logging_obj, exception, user_api_key_dict)
|
||||
except (AttributeError, ImportError, KeyError, TypeError) as e:
|
||||
verbose_logger.error(
|
||||
f"Rubrik: failed to build blocked-tool payload for "
|
||||
f"litellm_call_id={call_id}: {e}. Event will NOT be logged.",
|
||||
"Rubrik: failed to build blocked-tool payload for litellm_call_id=%s: %s. Event will NOT be logged.",
|
||||
call_id,
|
||||
e,
|
||||
exc_info=True,
|
||||
)
|
||||
return
|
||||
|
|
@ -796,7 +807,9 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
|
|||
await self._append_and_maybe_flush(payload)
|
||||
except Exception as e:
|
||||
verbose_logger.error(
|
||||
f"Rubrik: failed to enqueue blocked-tool event for litellm_call_id={call_id}: {e}.",
|
||||
"Rubrik: failed to enqueue blocked-tool event for litellm_call_id=%s: %s.",
|
||||
call_id,
|
||||
e,
|
||||
exc_info=True,
|
||||
)
|
||||
|
||||
|
|
@ -853,8 +866,9 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
|
|||
else:
|
||||
verbose_logger.debug(
|
||||
"Rubrik: standard_logging_object not yet on model_call_details "
|
||||
f"for litellm_call_id={call_details.get('litellm_call_id')}; "
|
||||
"using best-effort fallback payload."
|
||||
"for litellm_call_id=%s; "
|
||||
"using best-effort fallback payload.",
|
||||
call_details.get("litellm_call_id"),
|
||||
)
|
||||
payload = self._build_fallback_payload(call_details, user_api_key_dict)
|
||||
|
||||
|
|
@ -932,7 +946,7 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
|
|||
)
|
||||
response.raise_for_status()
|
||||
except httpx.HTTPStatusError as e:
|
||||
verbose_logger.exception(f"Rubrik HTTP Error: {e.response.status_code} - {e.response.text}")
|
||||
verbose_logger.exception("Rubrik HTTP Error: %s - %s", e.response.status_code, e.response.text)
|
||||
raise
|
||||
except Exception:
|
||||
verbose_logger.exception("Rubrik Layer Error")
|
||||
|
|
@ -989,7 +1003,7 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
|
|||
Exception: If the service is unavailable or returns an error.
|
||||
TypeError: If the response JSON is not a dict.
|
||||
"""
|
||||
verbose_logger.debug(f"Sending request to {service_name}: {endpoint}")
|
||||
verbose_logger.debug("Sending request to %s: %s", service_name, endpoint)
|
||||
http_response = await self.moderation_client.post(
|
||||
endpoint,
|
||||
json=payload,
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class S3Logger:
|
|||
import boto3
|
||||
|
||||
try:
|
||||
verbose_logger.debug(f"in init s3 logger - s3_callback_params {litellm.s3_callback_params}")
|
||||
verbose_logger.debug("in init s3 logger - s3_callback_params %s", litellm.s3_callback_params)
|
||||
|
||||
s3_use_team_prefix = False
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ class S3Logger:
|
|||
self.s3_server_side_encryption, self.s3_sse_kms_key_id = resolve_sse_params(
|
||||
s3_server_side_encryption, s3_sse_kms_key_id
|
||||
)
|
||||
verbose_logger.debug(f"s3 logger using endpoint url {s3_endpoint_url}")
|
||||
verbose_logger.debug("s3 logger using endpoint url %s", s3_endpoint_url)
|
||||
# Create an S3 client with custom endpoint URL
|
||||
self.s3_client = boto3.client(
|
||||
"s3",
|
||||
|
|
@ -86,7 +86,7 @@ class S3Logger:
|
|||
|
||||
def log_event(self, kwargs, response_obj, start_time, end_time, print_verbose):
|
||||
try:
|
||||
verbose_logger.debug(f"s3 Logging - Enters logging function for model {kwargs}")
|
||||
verbose_logger.debug("s3 Logging - Enters logging function for model %s", kwargs)
|
||||
|
||||
# construct payload to send to s3
|
||||
# follows the same params as langfuse.py
|
||||
|
|
@ -168,14 +168,14 @@ class S3Logger:
|
|||
print_verbose(f"s3 Layer Logging - final response object: {response_obj}")
|
||||
return response
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"s3 Layer Error - {e}")
|
||||
verbose_logger.exception("s3 Layer Error - %s", e)
|
||||
|
||||
|
||||
def _validated_sse_value(name: str, value: str | None) -> str | None:
|
||||
if value is None or isinstance(value, str):
|
||||
return value
|
||||
verbose_logger.warning(
|
||||
f"s3 logging: ignoring {name} because it has invalid type {type(value).__name__}; expected a string"
|
||||
"s3 logging: ignoring %s because it has invalid type %s; expected a string", name, type(value).__name__
|
||||
)
|
||||
return None
|
||||
|
||||
|
|
@ -191,8 +191,8 @@ def resolve_sse_params(
|
|||
return None, None
|
||||
if valid_key_id and not algorithm.startswith("aws:kms"):
|
||||
verbose_logger.warning(
|
||||
f"s3 logging: ignoring s3_sse_kms_key_id because s3_server_side_encryption is {algorithm}; "
|
||||
"set it to aws:kms to encrypt with the KMS key"
|
||||
"s3 logging: ignoring s3_sse_kms_key_id because s3_server_side_encryption is %s; set it to aws:kms to encrypt with the KMS key",
|
||||
algorithm,
|
||||
)
|
||||
return algorithm, None
|
||||
return algorithm, valid_key_id
|
||||
|
|
|
|||
|
|
@ -64,12 +64,12 @@ class S3Logger(CustomBatchLogger, BaseAWSLLM):
|
|||
_masker = SensitiveDataMasker()
|
||||
if s3_callback_params_override is not None:
|
||||
verbose_logger.debug(
|
||||
f"in init s3 logger (audit override) - {_masker.mask_dict(dict(s3_callback_params_override))}"
|
||||
"in init s3 logger (audit override) - %s", _masker.mask_dict(dict(s3_callback_params_override))
|
||||
)
|
||||
else:
|
||||
verbose_logger.debug(
|
||||
f"in init s3 logger - s3_callback_params "
|
||||
f"{_masker.mask_dict(dict(litellm.s3_callback_params or {}))}"
|
||||
"in init s3 logger - s3_callback_params %s",
|
||||
_masker.mask_dict(dict(litellm.s3_callback_params or {})),
|
||||
)
|
||||
|
||||
# Initialize S3 params first to get the correct s3_verify value
|
||||
|
|
@ -98,11 +98,11 @@ class S3Logger(CustomBatchLogger, BaseAWSLLM):
|
|||
s3_server_side_encryption=s3_server_side_encryption,
|
||||
s3_sse_kms_key_id=s3_sse_kms_key_id,
|
||||
)
|
||||
verbose_logger.debug(f"s3 logger using endpoint url {s3_endpoint_url}")
|
||||
verbose_logger.debug("s3 logger using endpoint url %s", s3_endpoint_url)
|
||||
|
||||
# IMPORTANT
|
||||
# Create httpx client AFTER _init_s3_params so we have the correct s3_verify value
|
||||
verbose_logger.debug(f"s3_v2 logger creating async httpx client with s3_verify={self.s3_verify}")
|
||||
verbose_logger.debug("s3_v2 logger creating async httpx client with s3_verify=%s", self.s3_verify)
|
||||
self.async_httpx_client = get_async_httpx_client(
|
||||
llm_provider=httpxSpecialProvider.LoggingCallback,
|
||||
params={"ssl_verify": self.s3_verify},
|
||||
|
|
@ -111,7 +111,7 @@ class S3Logger(CustomBatchLogger, BaseAWSLLM):
|
|||
asyncio.create_task(self.periodic_flush())
|
||||
self.flush_lock = asyncio.Lock()
|
||||
|
||||
verbose_logger.debug(f"s3 flush interval: {s3_flush_interval}, s3 batch size: {s3_batch_size}")
|
||||
verbose_logger.debug("s3 flush interval: %s, s3 batch size: %s", s3_flush_interval, s3_batch_size)
|
||||
# Call CustomLogger's __init__
|
||||
CustomBatchLogger.__init__(
|
||||
self,
|
||||
|
|
@ -259,7 +259,7 @@ class S3Logger(CustomBatchLogger, BaseAWSLLM):
|
|||
|
||||
async def _async_log_event_base(self, kwargs, response_obj, start_time, end_time):
|
||||
try:
|
||||
verbose_logger.debug(f"s3 Logging - Enters logging function for model {kwargs}")
|
||||
verbose_logger.debug("s3 Logging - Enters logging function for model %s", kwargs)
|
||||
|
||||
s3_batch_logging_element = self.create_s3_batch_logging_element(
|
||||
start_time=start_time,
|
||||
|
|
@ -284,7 +284,7 @@ class S3Logger(CustomBatchLogger, BaseAWSLLM):
|
|||
self.batch_size,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"s3 Layer Error - {e}")
|
||||
verbose_logger.exception("s3 Layer Error - %s", e)
|
||||
self.handle_callback_failure(callback_name="S3Logger")
|
||||
|
||||
async def async_upload_data_to_s3(self, batch_logging_element: s3BatchLoggingElement):
|
||||
|
|
@ -313,8 +313,8 @@ class S3Logger(CustomBatchLogger, BaseAWSLLM):
|
|||
aws_sts_endpoint=self.s3_aws_sts_endpoint,
|
||||
)
|
||||
|
||||
verbose_logger.debug(f"s3_v2 logger - uploading data to s3 - {batch_logging_element.s3_object_key}")
|
||||
verbose_logger.debug(f"s3_v2 logger - s3_verify setting: {self.s3_verify}")
|
||||
verbose_logger.debug("s3_v2 logger - uploading data to s3 - %s", batch_logging_element.s3_object_key)
|
||||
verbose_logger.debug("s3_v2 logger - s3_verify setting: %s", self.s3_verify)
|
||||
|
||||
# Prepare the URL
|
||||
url = f"https://{self.s3_bucket_name}.s3.{self.s3_region_name}.amazonaws.com/{batch_logging_element.s3_object_key}"
|
||||
|
|
@ -374,16 +374,19 @@ class S3Logger(CustomBatchLogger, BaseAWSLLM):
|
|||
if response.status_code in (500, 503) and attempt < max_retries - 1:
|
||||
wait_time = 2**attempt # 1s, 2s
|
||||
verbose_logger.warning(
|
||||
f"S3 upload returned {response.status_code}, retrying in {wait_time}s "
|
||||
f"(attempt {attempt + 1}/{max_retries}) "
|
||||
f"key={batch_logging_element.s3_object_key}"
|
||||
"S3 upload returned %s, retrying in %ss (attempt %s/%s) key=%s",
|
||||
response.status_code,
|
||||
wait_time,
|
||||
attempt + 1,
|
||||
max_retries,
|
||||
batch_logging_element.s3_object_key,
|
||||
)
|
||||
await asyncio.sleep(wait_time)
|
||||
continue
|
||||
response.raise_for_status()
|
||||
break
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error uploading to s3: {e}")
|
||||
verbose_logger.exception("Error uploading to s3: %s", e)
|
||||
self.handle_callback_failure(callback_name="S3Logger")
|
||||
|
||||
async def async_send_batch(self):
|
||||
|
|
@ -395,7 +398,7 @@ class S3Logger(CustomBatchLogger, BaseAWSLLM):
|
|||
|
||||
Raises: Does not raise an exception, will only verbose_logger.exception()
|
||||
"""
|
||||
verbose_logger.debug(f"s3_v2 logger - sending batch of {len(self.log_queue)}")
|
||||
verbose_logger.debug("s3_v2 logger - sending batch of %s", len(self.log_queue))
|
||||
if not self.log_queue:
|
||||
return
|
||||
|
||||
|
|
@ -447,7 +450,10 @@ class S3Logger(CustomBatchLogger, BaseAWSLLM):
|
|||
|
||||
s3_file_name = litellm.utils.get_logging_id(start_time, standard_logging_payload) or ""
|
||||
verbose_logger.debug(
|
||||
f"Creating s3 file with prefix_components={prefix_components},prefix_path={prefix_path} and {s3_file_name}"
|
||||
"Creating s3 file with prefix_components=%s,prefix_path=%s and %s",
|
||||
prefix_components,
|
||||
prefix_path,
|
||||
s3_file_name,
|
||||
)
|
||||
s3_object_key = get_s3_object_key(
|
||||
s3_path=cast(str | None, self.s3_path) or "",
|
||||
|
|
@ -455,7 +461,7 @@ class S3Logger(CustomBatchLogger, BaseAWSLLM):
|
|||
start_time=start_time,
|
||||
s3_file_name=s3_file_name,
|
||||
)
|
||||
verbose_logger.debug(f"s3_object_key={s3_object_key}")
|
||||
verbose_logger.debug("s3_object_key=%s", s3_object_key)
|
||||
|
||||
s3_object_download_filename = (
|
||||
f"time-{start_time.strftime('%Y-%m-%dT%H-%M-%S-%f')}_{standard_logging_payload['id']}.json"
|
||||
|
|
@ -479,7 +485,7 @@ class S3Logger(CustomBatchLogger, BaseAWSLLM):
|
|||
except ImportError:
|
||||
raise ImportError("Missing boto3 to call bedrock. Run 'pip install boto3'.")
|
||||
try:
|
||||
verbose_logger.debug(f"s3_v2 logger - uploading data to s3 - {batch_logging_element.s3_object_key}")
|
||||
verbose_logger.debug("s3_v2 logger - uploading data to s3 - %s", batch_logging_element.s3_object_key)
|
||||
credentials: Credentials = self.get_credentials(
|
||||
aws_access_key_id=self.s3_aws_access_key_id,
|
||||
aws_secret_access_key=self.s3_aws_secret_access_key,
|
||||
|
|
@ -548,16 +554,19 @@ class S3Logger(CustomBatchLogger, BaseAWSLLM):
|
|||
if response.status_code in (500, 503) and attempt < max_retries - 1:
|
||||
wait_time = 2**attempt # 1s, 2s
|
||||
verbose_logger.warning(
|
||||
f"S3 upload returned {response.status_code}, retrying in {wait_time}s "
|
||||
f"(attempt {attempt + 1}/{max_retries}) "
|
||||
f"key={batch_logging_element.s3_object_key}"
|
||||
"S3 upload returned %s, retrying in %ss (attempt %s/%s) key=%s",
|
||||
response.status_code,
|
||||
wait_time,
|
||||
attempt + 1,
|
||||
max_retries,
|
||||
batch_logging_element.s3_object_key,
|
||||
)
|
||||
time.sleep(wait_time)
|
||||
continue
|
||||
response.raise_for_status()
|
||||
break
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error uploading to s3: {e}")
|
||||
verbose_logger.exception("Error uploading to s3: %s", e)
|
||||
self.handle_callback_failure(callback_name="S3Logger")
|
||||
|
||||
async def _download_object_from_s3(self, s3_object_key: str) -> dict | None:
|
||||
|
|
@ -596,7 +605,7 @@ class S3Logger(CustomBatchLogger, BaseAWSLLM):
|
|||
aws_sts_endpoint=self.s3_aws_sts_endpoint,
|
||||
)
|
||||
|
||||
verbose_logger.debug(f"s3_v2 logger - downloading data from s3 - {s3_object_key}")
|
||||
verbose_logger.debug("s3_v2 logger - downloading data from s3 - %s", s3_object_key)
|
||||
|
||||
# Prepare the URL
|
||||
url = f"https://{self.s3_bucket_name}.s3.{self.s3_region_name}.amazonaws.com/{s3_object_key}"
|
||||
|
|
@ -642,7 +651,7 @@ class S3Logger(CustomBatchLogger, BaseAWSLLM):
|
|||
return response.json()
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error downloading from S3: {e}")
|
||||
verbose_logger.exception("Error downloading from S3: %s", e)
|
||||
return None
|
||||
|
||||
async def get_proxy_server_request_from_cold_storage_with_object_key(
|
||||
|
|
@ -666,5 +675,5 @@ class S3Logger(CustomBatchLogger, BaseAWSLLM):
|
|||
downloaded_object = await self._download_object_from_s3(object_key)
|
||||
return downloaded_object
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error retrieving object {object_key} from cold storage: {e}")
|
||||
verbose_logger.exception("Error retrieving object %s from cold storage: %s", object_key, e)
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class SQSLogger(CustomBatchLogger, BaseAWSLLM):
|
|||
**kwargs,
|
||||
) -> None:
|
||||
try:
|
||||
verbose_logger.debug(f"in init sqs logger - sqs_callback_params {litellm.aws_sqs_callback_params}")
|
||||
verbose_logger.debug("in init sqs logger - sqs_callback_params %s", litellm.aws_sqs_callback_params)
|
||||
|
||||
self.async_httpx_client = get_async_httpx_client(
|
||||
llm_provider=httpxSpecialProvider.LoggingCallback,
|
||||
|
|
@ -100,7 +100,7 @@ class SQSLogger(CustomBatchLogger, BaseAWSLLM):
|
|||
asyncio.create_task(self.periodic_flush())
|
||||
self.flush_lock = asyncio.Lock()
|
||||
|
||||
verbose_logger.debug(f"sqs flush interval: {sqs_flush_interval}, sqs batch size: {sqs_batch_size}")
|
||||
verbose_logger.debug("sqs flush interval: %s, sqs batch size: %s", sqs_flush_interval, sqs_batch_size)
|
||||
|
||||
CustomBatchLogger.__init__(
|
||||
self,
|
||||
|
|
@ -215,7 +215,7 @@ class SQSLogger(CustomBatchLogger, BaseAWSLLM):
|
|||
self.batch_size,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"sqs Layer Error - {e}")
|
||||
verbose_logger.exception("sqs Layer Error - %s", e)
|
||||
|
||||
async def async_log_failure_event(self, kwargs, response_obj, start_time, end_time):
|
||||
try:
|
||||
|
|
@ -233,10 +233,10 @@ class SQSLogger(CustomBatchLogger, BaseAWSLLM):
|
|||
)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Datadog Layer Error - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.exception("Datadog Layer Error - %s\n%s", e, traceback.format_exc())
|
||||
|
||||
async def async_send_batch(self) -> None:
|
||||
verbose_logger.debug(f"sqs logger - sending batch of {len(self.log_queue)}")
|
||||
verbose_logger.debug("sqs logger - sending batch of %s", len(self.log_queue))
|
||||
if not self.log_queue:
|
||||
return
|
||||
|
||||
|
|
@ -305,7 +305,7 @@ class SQSLogger(CustomBatchLogger, BaseAWSLLM):
|
|||
)
|
||||
response.raise_for_status()
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error sending to SQS: {e}")
|
||||
verbose_logger.exception("Error sending to SQS: %s", e)
|
||||
|
||||
async def async_health_check(self) -> IntegrationHealthCheckStatus:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ class TraceloopLogger:
|
|||
from traceloop.sdk.tracing.tracing import TracerWrapper
|
||||
except ModuleNotFoundError as e:
|
||||
verbose_logger.error(
|
||||
f"Traceloop not installed, try running 'pip install traceloop-sdk' to fix this error: {e}\n{traceback.format_exc()}"
|
||||
"Traceloop not installed, try running 'pip install traceloop-sdk' to fix this error: %s\n%s",
|
||||
e,
|
||||
traceback.format_exc(),
|
||||
)
|
||||
raise e
|
||||
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ class VectorStorePreCallHook(CustomLogger):
|
|||
},
|
||||
)
|
||||
|
||||
verbose_logger.debug(f"search_response: {search_response}")
|
||||
verbose_logger.debug("search_response: %s", search_response)
|
||||
|
||||
# Store search results for later use in citations
|
||||
all_search_results.append(search_response)
|
||||
|
|
@ -137,7 +137,7 @@ class VectorStorePreCallHook(CustomLogger):
|
|||
# Get the number of results for logging
|
||||
num_results = 0
|
||||
num_results = len(search_response.get("data", []) or [])
|
||||
verbose_logger.debug(f"Vector store search completed. Added context from {num_results} results")
|
||||
verbose_logger.debug("Vector store search completed. Added context from %s results", num_results)
|
||||
|
||||
# Store search results as-is (already in OpenAI-compatible format)
|
||||
if litellm_logging_obj and all_search_results:
|
||||
|
|
@ -146,7 +146,7 @@ class VectorStorePreCallHook(CustomLogger):
|
|||
return model, modified_messages, non_default_params
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error in VectorStorePreCallHook: {e}")
|
||||
verbose_logger.exception("Error in VectorStorePreCallHook: %s", e)
|
||||
# Return original parameters on error
|
||||
return model, messages, non_default_params
|
||||
|
||||
|
|
@ -243,14 +243,14 @@ class VectorStorePreCallHook(CustomLogger):
|
|||
verbose_logger.debug("No litellm_logging_obj in request_data")
|
||||
return None
|
||||
|
||||
verbose_logger.debug(f"model_call_details keys: {list(litellm_logging_obj.model_call_details.keys())}")
|
||||
verbose_logger.debug("model_call_details keys: %s", list(litellm_logging_obj.model_call_details.keys()))
|
||||
|
||||
# Get search results from model_call_details (already in OpenAI format)
|
||||
search_results: list[VectorStoreSearchResponse] | None = litellm_logging_obj.model_call_details.get(
|
||||
"search_results"
|
||||
)
|
||||
|
||||
verbose_logger.debug(f"Search results found: {search_results is not None}")
|
||||
verbose_logger.debug("Search results found: %s", search_results is not None)
|
||||
|
||||
if not search_results:
|
||||
verbose_logger.debug("No search results found")
|
||||
|
|
@ -269,13 +269,13 @@ class VectorStorePreCallHook(CustomLogger):
|
|||
# Set the provider_specific_fields
|
||||
setattr(choice.message, "provider_specific_fields", provider_fields)
|
||||
|
||||
verbose_logger.debug(f"Added {len(search_results)} search results to response")
|
||||
verbose_logger.debug("Added %s search results to response", len(search_results))
|
||||
|
||||
# Return modified response
|
||||
return response
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error adding search results to response: {e}")
|
||||
verbose_logger.exception("Error adding search results to response: %s", e)
|
||||
# Don't fail the request if search results fail to be added
|
||||
return None
|
||||
|
||||
|
|
@ -297,7 +297,7 @@ class VectorStorePreCallHook(CustomLogger):
|
|||
# Get search results from model_call_details (already in OpenAI format)
|
||||
search_results: list[VectorStoreSearchResponse] | None = request_data.get("search_results")
|
||||
|
||||
verbose_logger.debug(f"Search results found for streaming chunk: {search_results is not None}")
|
||||
verbose_logger.debug("Search results found for streaming chunk: %s", search_results is not None)
|
||||
|
||||
if not search_results:
|
||||
verbose_logger.debug("No search results found for streaming chunk")
|
||||
|
|
@ -316,12 +316,12 @@ class VectorStorePreCallHook(CustomLogger):
|
|||
# Set the provider_specific_fields
|
||||
choice.delta.provider_specific_fields = provider_fields
|
||||
|
||||
verbose_logger.debug(f"Added {len(search_results)} search results to streaming chunk")
|
||||
verbose_logger.debug("Added %s search results to streaming chunk", len(search_results))
|
||||
|
||||
# Return modified chunk
|
||||
return response_chunk
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error adding search results to streaming chunk: {e}")
|
||||
verbose_logger.exception("Error adding search results to streaming chunk: %s", e)
|
||||
# Don't fail the request if search results fail to be added
|
||||
return response_chunk
|
||||
|
|
|
|||
|
|
@ -148,10 +148,10 @@ def get_weave_otel_config() -> WeaveOtelConfig:
|
|||
host = "https://" + host
|
||||
# Self-managed instances use a different path
|
||||
endpoint = host.rstrip("/") + WEAVE_OTEL_ENDPOINT
|
||||
verbose_logger.debug(f"Using Weave OTEL endpoint from host: {endpoint}")
|
||||
verbose_logger.debug("Using Weave OTEL endpoint from host: %s", endpoint)
|
||||
else:
|
||||
endpoint = WEAVE_BASE_URL + WEAVE_OTEL_ENDPOINT
|
||||
verbose_logger.debug(f"Using Weave cloud endpoint: {endpoint}")
|
||||
verbose_logger.debug("Using Weave cloud endpoint: %s", endpoint)
|
||||
|
||||
# Weave uses Basic auth with format: api:<WANDB_API_KEY>
|
||||
auth_header = _get_weave_authorization_header(api_key=api_key)
|
||||
|
|
|
|||
|
|
@ -155,8 +155,8 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
)
|
||||
if anthropic_config is not None and anthropic_config.handles_web_search_natively():
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Skipping short-circuit for {provider_str} "
|
||||
"(provider handles web search natively via the agentic loop)"
|
||||
"WebSearchInterception: Skipping short-circuit for %s (provider handles web search natively via the agentic loop)",
|
||||
provider_str,
|
||||
)
|
||||
return None
|
||||
except (ValueError, Exception):
|
||||
|
|
@ -176,7 +176,7 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
return None
|
||||
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Short-circuit search detected (provider={provider_str}, query='{query}')"
|
||||
"WebSearchInterception: Short-circuit search detected (provider=%s, query='%s')", provider_str, query
|
||||
)
|
||||
|
||||
# Native clients (Claude Desktop / Cowork / Anthropic SDK) make a
|
||||
|
|
@ -198,7 +198,7 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
else:
|
||||
search_result_text, structured = await self._execute_search(query, kwargs=kwargs)
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"WebSearchInterception: Short-circuit search failed: {e}")
|
||||
verbose_logger.error("WebSearchInterception: Short-circuit search failed: %s", e)
|
||||
search_result_text, structured = f"Search failed: {e}", None
|
||||
|
||||
content: list[dict[str, object]] = []
|
||||
|
|
@ -235,9 +235,9 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
}
|
||||
|
||||
verbose_logger.debug(
|
||||
"WebSearchInterception: Short-circuit search completed, "
|
||||
f"returning synthetic response ({len(search_result_text)} chars, "
|
||||
f"native_blocks={native_tool is not None})"
|
||||
"WebSearchInterception: Short-circuit search completed, returning synthetic response (%s chars, native_blocks=%s)",
|
||||
len(search_result_text),
|
||||
native_tool is not None,
|
||||
)
|
||||
return response
|
||||
|
||||
|
|
@ -294,8 +294,10 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
converted_tool = get_litellm_web_search_tool_openai()
|
||||
converted_tools.append(converted_tool)
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Converted {tool.get('name', 'unknown')} "
|
||||
f"(type={tool.get('type', 'none')}) to {LITELLM_WEB_SEARCH_TOOL_NAME}"
|
||||
"WebSearchInterception: Converted %s (type=%s) to %s",
|
||||
tool.get("name", "unknown"),
|
||||
tool.get("type", "none"),
|
||||
LITELLM_WEB_SEARCH_TOOL_NAME,
|
||||
)
|
||||
else:
|
||||
# Keep other tools as-is
|
||||
|
|
@ -419,14 +421,14 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
custom_llm_provider = kwargs.get("litellm_params", {}).get("custom_llm_provider", "")
|
||||
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Pre-request hook called"
|
||||
f" - custom_llm_provider={custom_llm_provider}"
|
||||
f" - enabled_providers={self.enabled_providers or 'ALL'}"
|
||||
"WebSearchInterception: Pre-request hook called - custom_llm_provider=%s - enabled_providers=%s",
|
||||
custom_llm_provider,
|
||||
self.enabled_providers or "ALL",
|
||||
)
|
||||
|
||||
if self.enabled_providers is not None and custom_llm_provider not in self.enabled_providers:
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Skipping - provider {custom_llm_provider} not in {self.enabled_providers}"
|
||||
"WebSearchInterception: Skipping - provider %s not in %s", custom_llm_provider, self.enabled_providers
|
||||
)
|
||||
return None
|
||||
|
||||
|
|
@ -440,7 +442,7 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
if not has_websearch:
|
||||
return None
|
||||
|
||||
verbose_logger.debug(f"WebSearchInterception: Pre-request hook triggered for provider={custom_llm_provider}")
|
||||
verbose_logger.debug("WebSearchInterception: Pre-request hook triggered for provider=%s", custom_llm_provider)
|
||||
|
||||
# If the client sent an Anthropic-native web_search_* tool, mark the
|
||||
# request so the agentic loop emits native web_search_tool_result
|
||||
|
|
@ -457,15 +459,17 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
standard_tool = get_litellm_web_search_tool()
|
||||
converted_tools.append(standard_tool)
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Converted {tool.get('name', 'unknown')} "
|
||||
f"(type={tool.get('type', 'none')}) to {LITELLM_WEB_SEARCH_TOOL_NAME}"
|
||||
"WebSearchInterception: Converted %s (type=%s) to %s",
|
||||
tool.get("name", "unknown"),
|
||||
tool.get("type", "none"),
|
||||
LITELLM_WEB_SEARCH_TOOL_NAME,
|
||||
)
|
||||
else:
|
||||
converted_tools.append(tool)
|
||||
|
||||
kwargs["tools"] = converted_tools
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Tools after conversion: {[t.get('name') for t in converted_tools]}"
|
||||
"WebSearchInterception: Tools after conversion: %s", [t.get("name") for t in converted_tools]
|
||||
)
|
||||
|
||||
if "tool_choice" in kwargs:
|
||||
|
|
@ -511,15 +515,17 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
kwargs=kwargs,
|
||||
)
|
||||
|
||||
verbose_logger.debug(f"WebSearchInterception: Hook called! provider={custom_llm_provider}, stream={stream}")
|
||||
verbose_logger.debug(f"WebSearchInterception: Response type: {type(response)}")
|
||||
verbose_logger.debug("WebSearchInterception: Hook called! provider=%s, stream=%s", custom_llm_provider, stream)
|
||||
verbose_logger.debug("WebSearchInterception: Response type: %s", type(response))
|
||||
|
||||
# Check if provider should be intercepted
|
||||
# Note: custom_llm_provider is already normalized by get_llm_provider()
|
||||
# (e.g., "bedrock/invoke/..." -> "bedrock")
|
||||
if self.enabled_providers is not None and custom_llm_provider not in self.enabled_providers:
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Skipping provider {custom_llm_provider} (not in enabled list: {self.enabled_providers})"
|
||||
"WebSearchInterception: Skipping provider %s (not in enabled list: %s)",
|
||||
custom_llm_provider,
|
||||
self.enabled_providers,
|
||||
)
|
||||
return False, {}
|
||||
|
||||
|
|
@ -541,7 +547,7 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
return False, {}
|
||||
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Detected {len(tool_calls)} WebSearch tool call(s), executing agentic loop"
|
||||
"WebSearchInterception: Detected %s WebSearch tool call(s), executing agentic loop", len(tool_calls)
|
||||
)
|
||||
|
||||
# Extract thinking blocks from response content.
|
||||
|
|
@ -576,7 +582,7 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
|
||||
if thinking_blocks:
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Extracted {len(thinking_blocks)} thinking block(s) from response"
|
||||
"WebSearchInterception: Extracted %s thinking block(s) from response", len(thinking_blocks)
|
||||
)
|
||||
|
||||
# Return tools dict with tool calls and thinking blocks
|
||||
|
|
@ -606,14 +612,16 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
"""
|
||||
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Chat completion hook called! provider={custom_llm_provider}, stream={stream}"
|
||||
"WebSearchInterception: Chat completion hook called! provider=%s, stream=%s", custom_llm_provider, stream
|
||||
)
|
||||
verbose_logger.debug(f"WebSearchInterception: Response type: {type(response)}")
|
||||
verbose_logger.debug("WebSearchInterception: Response type: %s", type(response))
|
||||
|
||||
# Check if provider should be intercepted
|
||||
if self.enabled_providers is not None and custom_llm_provider not in self.enabled_providers:
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Skipping provider {custom_llm_provider} (not in enabled list: {self.enabled_providers})"
|
||||
"WebSearchInterception: Skipping provider %s (not in enabled list: %s)",
|
||||
custom_llm_provider,
|
||||
self.enabled_providers,
|
||||
)
|
||||
return False, {}
|
||||
|
||||
|
|
@ -635,7 +643,7 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
return False, {}
|
||||
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Detected {len(tool_calls)} WebSearch tool call(s), executing agentic loop"
|
||||
"WebSearchInterception: Detected %s WebSearch tool call(s), executing agentic loop", len(tool_calls)
|
||||
)
|
||||
|
||||
# Return tools dict with tool calls
|
||||
|
|
@ -659,12 +667,14 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
) -> tuple[bool, dict]:
|
||||
"""Check if WebSearch interception is needed for the Responses API."""
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Responses hook called! provider={custom_llm_provider}, stream={stream}"
|
||||
"WebSearchInterception: Responses hook called! provider=%s, stream=%s", custom_llm_provider, stream
|
||||
)
|
||||
|
||||
if self.enabled_providers is not None and custom_llm_provider not in self.enabled_providers:
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Skipping provider {custom_llm_provider} (not in enabled list: {self.enabled_providers})"
|
||||
"WebSearchInterception: Skipping provider %s (not in enabled list: %s)",
|
||||
custom_llm_provider,
|
||||
self.enabled_providers,
|
||||
)
|
||||
return False, {}
|
||||
|
||||
|
|
@ -684,7 +694,7 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
return False, {}
|
||||
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Detected {len(tool_calls)} WebSearch function_call(s), executing agentic loop"
|
||||
"WebSearchInterception: Detected %s WebSearch function_call(s), executing agentic loop", len(tool_calls)
|
||||
)
|
||||
|
||||
tools_dict = {
|
||||
|
|
@ -716,7 +726,7 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
tool_calls = tools["tool_calls"]
|
||||
thinking_blocks = tools.get("thinking_blocks", [])
|
||||
|
||||
verbose_logger.debug(f"WebSearchInterception: Executing agentic loop for {len(tool_calls)} search(es)")
|
||||
verbose_logger.debug("WebSearchInterception: Executing agentic loop for %s search(es)", len(tool_calls))
|
||||
|
||||
return await self._execute_agentic_loop(
|
||||
model=model,
|
||||
|
|
@ -853,7 +863,8 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
# Object refused write — fall through and leave the response
|
||||
# untouched rather than crash the request.
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: could not inject native blocks into response of type {type(response).__name__}"
|
||||
"WebSearchInterception: could not inject native blocks into response of type %s",
|
||||
type(response).__name__,
|
||||
)
|
||||
return response
|
||||
|
||||
|
|
@ -878,7 +889,7 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
response_format = tools.get("response_format", "openai")
|
||||
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Executing chat completion agentic loop for {len(tool_calls)} search(es)"
|
||||
"WebSearchInterception: Executing chat completion agentic loop for %s search(es)", len(tool_calls)
|
||||
)
|
||||
|
||||
return await self._execute_chat_completion_agentic_loop(
|
||||
|
|
@ -962,7 +973,7 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
for tool_call in tool_calls
|
||||
]
|
||||
|
||||
verbose_logger.debug(f"WebSearchInterception: Executing {len(search_tasks)} responses search(es) in parallel")
|
||||
verbose_logger.debug("WebSearchInterception: Executing %s responses search(es) in parallel", len(search_tasks))
|
||||
search_results = await asyncio.gather(*search_tasks, return_exceptions=True)
|
||||
|
||||
search_texts = [self._extract_search_text(result) for result in search_results]
|
||||
|
|
@ -1038,12 +1049,12 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
@staticmethod
|
||||
def _extract_search_text(result: object) -> str:
|
||||
if isinstance(result, Exception):
|
||||
verbose_logger.error(f"WebSearchInterception: Responses search failed with error: {result}")
|
||||
verbose_logger.error("WebSearchInterception: Responses search failed with error: %s", result)
|
||||
return f"Search failed: {result}"
|
||||
if isinstance(result, tuple) and len(result) == 2:
|
||||
text_value, _ = result
|
||||
return text_value if isinstance(text_value, str) else str(text_value)
|
||||
verbose_logger.debug(f"WebSearchInterception: Unexpected search result type {type(result)}")
|
||||
verbose_logger.debug("WebSearchInterception: Unexpected search result type %s", type(result))
|
||||
return str(result)
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -1176,15 +1187,15 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
for tool_call in tool_calls:
|
||||
query = tool_call["input"].get("query")
|
||||
if query:
|
||||
verbose_logger.debug(f"WebSearchInterception: Queuing search for query='{query}'")
|
||||
verbose_logger.debug("WebSearchInterception: Queuing search for query='%s'", query)
|
||||
search_tasks.append(self._execute_search(query, kwargs=kwargs))
|
||||
else:
|
||||
verbose_logger.debug(f"WebSearchInterception: Tool call {tool_call['id']} has no query")
|
||||
verbose_logger.debug("WebSearchInterception: Tool call %s has no query", tool_call["id"])
|
||||
# Add empty result for tools without query
|
||||
search_tasks.append(self._create_empty_search_result())
|
||||
|
||||
# Execute searches in parallel
|
||||
verbose_logger.debug(f"WebSearchInterception: Executing {len(search_tasks)} search(es) in parallel")
|
||||
verbose_logger.debug("WebSearchInterception: Executing %s search(es) in parallel", len(search_tasks))
|
||||
search_results = await asyncio.gather(*search_tasks, return_exceptions=True)
|
||||
|
||||
# Split the gathered (text, structured) tuples into two parallel lists.
|
||||
|
|
@ -1194,7 +1205,7 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
structured_results: list[SearchResponse | None] = []
|
||||
for i, result in enumerate(search_results):
|
||||
if isinstance(result, Exception):
|
||||
verbose_logger.error(f"WebSearchInterception: Search {i} failed with error: {result}")
|
||||
verbose_logger.error("WebSearchInterception: Search %s failed with error: %s", i, result)
|
||||
final_search_results.append(f"Search failed: {result}")
|
||||
structured_results.append(None)
|
||||
elif isinstance(result, tuple) and len(result) == 2:
|
||||
|
|
@ -1204,7 +1215,7 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
else:
|
||||
# Defensive: legacy callers / unexpected shape — preserve text,
|
||||
# drop structure.
|
||||
verbose_logger.debug(f"WebSearchInterception: Unexpected result type {type(result)} at index {i}")
|
||||
verbose_logger.debug("WebSearchInterception: Unexpected result type %s at index %s", type(result), i)
|
||||
final_search_results.append(str(result))
|
||||
structured_results.append(None)
|
||||
|
||||
|
|
@ -1224,7 +1235,7 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
|
||||
max_tokens = self._resolve_max_tokens(anthropic_messages_optional_request_params, kwargs)
|
||||
|
||||
verbose_logger.debug(f"WebSearchInterception: Using max_tokens={max_tokens} for follow-up request")
|
||||
verbose_logger.debug("WebSearchInterception: Using max_tokens=%s for follow-up request", max_tokens)
|
||||
|
||||
optional_params_without_max_tokens = {
|
||||
k: v for k, v in anthropic_messages_optional_request_params.items() if k != "max_tokens"
|
||||
|
|
@ -1286,12 +1297,12 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
if not search_provider:
|
||||
search_provider = "perplexity"
|
||||
verbose_logger.debug(
|
||||
"WebSearchInterception: No search tools configured in router, "
|
||||
f"using default provider '{search_provider}'"
|
||||
"WebSearchInterception: No search tools configured in router, using default provider '%s'",
|
||||
search_provider,
|
||||
)
|
||||
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Executing search for '{query}' using provider '{search_provider}'"
|
||||
"WebSearchInterception: Executing search for '%s' using provider '%s'", query, search_provider
|
||||
)
|
||||
search_kwargs = {
|
||||
key: value
|
||||
|
|
@ -1304,11 +1315,11 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
search_result_text = WebSearchTransformation.format_search_response(result)
|
||||
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Search completed for '{query}', got {len(search_result_text)} chars"
|
||||
"WebSearchInterception: Search completed for '%s', got %s chars", query, len(search_result_text)
|
||||
)
|
||||
return search_result_text, result
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"WebSearchInterception: Search failed for '{query}': {e}")
|
||||
verbose_logger.error("WebSearchInterception: Search failed for '%s': %s", query, e)
|
||||
raise
|
||||
|
||||
async def _authorize_search_tool(
|
||||
|
|
@ -1392,21 +1403,25 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
if matching_tools:
|
||||
search_provider = (matching_tools[0].get("litellm_params", {}) or {}).get("search_provider")
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Found search tool '{self.search_tool_name}' "
|
||||
f"from {source} with provider '{search_provider}'"
|
||||
"WebSearchInterception: Found search tool '%s' from %s with provider '%s'",
|
||||
self.search_tool_name,
|
||||
source,
|
||||
search_provider,
|
||||
)
|
||||
return matching_tools[0]
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Search tool '{self.search_tool_name}' not found in {source}, "
|
||||
"falling back to first available or perplexity"
|
||||
"WebSearchInterception: Search tool '%s' not found in %s, falling back to first available or perplexity",
|
||||
self.search_tool_name,
|
||||
source,
|
||||
)
|
||||
|
||||
if search_tools:
|
||||
first_tool = search_tools[0]
|
||||
search_provider = (first_tool.get("litellm_params", {}) or {}).get("search_provider")
|
||||
verbose_logger.debug(
|
||||
f"WebSearchInterception: Using first available search tool from {source} "
|
||||
f"with provider '{search_provider}'"
|
||||
"WebSearchInterception: Using first available search tool from %s with provider '%s'",
|
||||
source,
|
||||
search_provider,
|
||||
)
|
||||
return first_tool
|
||||
|
||||
|
|
@ -1470,15 +1485,15 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
query = args.get("query")
|
||||
|
||||
if query:
|
||||
verbose_logger.debug(f"WebSearchInterception: Queuing search for query='{query}'")
|
||||
verbose_logger.debug("WebSearchInterception: Queuing search for query='%s'", query)
|
||||
search_tasks.append(self._execute_search(query, kwargs=kwargs))
|
||||
else:
|
||||
verbose_logger.debug(f"WebSearchInterception: Tool call {tool_call.get('id')} has no query")
|
||||
verbose_logger.debug("WebSearchInterception: Tool call %s has no query", tool_call.get("id"))
|
||||
# Add empty result for tools without query
|
||||
search_tasks.append(self._create_empty_search_result())
|
||||
|
||||
# Execute searches in parallel
|
||||
verbose_logger.debug(f"WebSearchInterception: Executing {len(search_tasks)} search(es) in parallel")
|
||||
verbose_logger.debug("WebSearchInterception: Executing %s search(es) in parallel", len(search_tasks))
|
||||
search_results = await asyncio.gather(*search_tasks, return_exceptions=True)
|
||||
|
||||
# Chat-completion path only needs text — OpenAI tool_result format
|
||||
|
|
@ -1486,13 +1501,13 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
final_search_results: list[str] = []
|
||||
for i, result in enumerate(search_results):
|
||||
if isinstance(result, Exception):
|
||||
verbose_logger.error(f"WebSearchInterception: Search {i} failed with error: {result}")
|
||||
verbose_logger.error("WebSearchInterception: Search %s failed with error: %s", i, result)
|
||||
final_search_results.append(f"Search failed: {result}")
|
||||
elif isinstance(result, tuple) and len(result) == 2:
|
||||
text_value, _ = result
|
||||
final_search_results.append(cast(str, text_value) if isinstance(text_value, str) else str(text_value))
|
||||
else:
|
||||
verbose_logger.debug(f"WebSearchInterception: Unexpected result type {type(result)} at index {i}")
|
||||
verbose_logger.debug("WebSearchInterception: Unexpected result type %s at index %s", type(result), i)
|
||||
final_search_results.append(str(result))
|
||||
|
||||
# Build assistant and tool messages using transformation
|
||||
|
|
@ -1517,7 +1532,7 @@ class WebSearchInterceptionLogger(CustomLogger):
|
|||
]
|
||||
|
||||
verbose_logger.debug("WebSearchInterception: Making follow-up chat completion request with search results")
|
||||
verbose_logger.debug(f"WebSearchInterception: Follow-up messages count: {len(follow_up_messages)}")
|
||||
verbose_logger.debug("WebSearchInterception: Follow-up messages count: %s", len(follow_up_messages))
|
||||
|
||||
# Remove internal parameters that shouldn't be passed to follow-up request
|
||||
internal_params = {
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ class WebSearchTransformation:
|
|||
parsed_input = json.loads(arguments) if arguments else {}
|
||||
except json.JSONDecodeError:
|
||||
verbose_logger.warning(
|
||||
f"WebSearchInterception: Failed to parse function_call arguments: {arguments}"
|
||||
"WebSearchInterception: Failed to parse function_call arguments: %s", arguments
|
||||
)
|
||||
parsed_input = {}
|
||||
elif isinstance(arguments, dict):
|
||||
|
|
@ -122,7 +122,7 @@ class WebSearchTransformation:
|
|||
"input": parsed_input,
|
||||
}
|
||||
)
|
||||
verbose_logger.debug(f"WebSearchInterception: Found {item_name} function_call with call_id={call_id}")
|
||||
verbose_logger.debug("WebSearchInterception: Found %s function_call with call_id=%s", item_name, call_id)
|
||||
|
||||
return len(tool_calls) > 0, tool_calls
|
||||
|
||||
|
|
@ -178,7 +178,7 @@ class WebSearchTransformation:
|
|||
"input": block_input,
|
||||
}
|
||||
tool_calls.append(tool_call)
|
||||
verbose_logger.debug(f"WebSearchInterception: Found {block_name} tool_use with id={tool_call['id']}")
|
||||
verbose_logger.debug("WebSearchInterception: Found %s tool_use with id=%s", block_name, tool_call["id"])
|
||||
|
||||
return len(tool_calls) > 0, tool_calls
|
||||
|
||||
|
|
@ -255,7 +255,7 @@ class WebSearchTransformation:
|
|||
arguments = json.loads(function_arguments)
|
||||
except json.JSONDecodeError:
|
||||
verbose_logger.warning(
|
||||
f"WebSearchInterception: Failed to parse function arguments: {function_arguments}"
|
||||
"WebSearchInterception: Failed to parse function arguments: %s", function_arguments
|
||||
)
|
||||
arguments = {}
|
||||
else:
|
||||
|
|
@ -273,7 +273,7 @@ class WebSearchTransformation:
|
|||
"input": arguments, # For compatibility with Anthropic format
|
||||
}
|
||||
tool_calls.append(tool_call_dict)
|
||||
verbose_logger.debug(f"WebSearchInterception: Found {function_name} tool_call with id={tool_id}")
|
||||
verbose_logger.debug("WebSearchInterception: Found %s tool_call with id=%s", function_name, tool_id)
|
||||
|
||||
return len(tool_calls) > 0, tool_calls
|
||||
|
||||
|
|
|
|||
|
|
@ -42,9 +42,9 @@ try:
|
|||
elif response["object"] == "chat.completion":
|
||||
return self._resolve_chat_completion(request, response, time_elapsed)
|
||||
else:
|
||||
logger.debug(f"Unknown OpenAI response object: {response['object']}")
|
||||
logger.debug("Unknown OpenAI response object: %s", response["object"])
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to resolve request/response: {e}")
|
||||
logger.warning("Failed to resolve request/response: %s", e)
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ class BaseInteractionsAPIStreamingIterator:
|
|||
return None
|
||||
except json.JSONDecodeError:
|
||||
# If we can't parse the chunk, continue
|
||||
verbose_logger.debug(f"Failed to parse streaming chunk: {stripped_chunk[:200]}...")
|
||||
verbose_logger.debug("Failed to parse streaming chunk: %s...", stripped_chunk[:200])
|
||||
return None
|
||||
|
||||
def _handle_logging_completed_response(self):
|
||||
|
|
|
|||
|
|
@ -536,7 +536,7 @@ def _map_anthropic_exception(
|
|||
llm_provider="anthropic",
|
||||
)
|
||||
if hasattr(original_exception, "status_code"):
|
||||
verbose_logger.debug(f"status_code: {original_exception.status_code}")
|
||||
verbose_logger.debug("status_code: %s", original_exception.status_code)
|
||||
if original_exception.status_code == 401:
|
||||
raise AuthenticationError(
|
||||
message=f"AnthropicException - {error_str}",
|
||||
|
|
@ -1752,7 +1752,7 @@ def _map_aleph_alpha_exception(
|
|||
response=getattr(original_exception, "response", None),
|
||||
)
|
||||
elif hasattr(original_exception, "status_code"):
|
||||
verbose_logger.debug(f"status code: {original_exception.status_code}")
|
||||
verbose_logger.debug("status code: %s", original_exception.status_code)
|
||||
if original_exception.status_code == 401:
|
||||
raise AuthenticationError(
|
||||
message=f"AlephAlphaException - {original_exception.message}",
|
||||
|
|
@ -2526,7 +2526,9 @@ def exception_logging(
|
|||
model_call_details["exception"] = exception
|
||||
model_call_details["additional_args"] = additional_args
|
||||
# User Logging -> if you pass in a custom logging function or want to use sentry breadcrumbs
|
||||
verbose_logger.debug(f"Logging Details: logger_fn - {logger_fn} | callable(logger_fn) - {callable(logger_fn)}")
|
||||
verbose_logger.debug(
|
||||
"Logging Details: logger_fn - %s | callable(logger_fn) - %s", logger_fn, callable(logger_fn)
|
||||
)
|
||||
if logger_fn and callable(logger_fn):
|
||||
try:
|
||||
logger_fn(
|
||||
|
|
@ -2534,11 +2536,11 @@ def exception_logging(
|
|||
) # Expectation: any logger function passed in by the user should accept a dict object
|
||||
except Exception:
|
||||
verbose_logger.debug(
|
||||
f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while logging {traceback.format_exc()}"
|
||||
"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while logging %s", traceback.format_exc()
|
||||
)
|
||||
except Exception:
|
||||
verbose_logger.debug(
|
||||
f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while logging {traceback.format_exc()}"
|
||||
"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while logging %s", traceback.format_exc()
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ async def async_completion_with_fallbacks(**kwargs):
|
|||
)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Fallback attempt failed for model {model}: {e}")
|
||||
verbose_logger.exception("Fallback attempt failed for model %s: %s", model, e)
|
||||
most_recent_exception_str = str(e)
|
||||
continue
|
||||
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ try:
|
|||
EnterpriseStandardLoggingPayloadSetup
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"[Non-Blocking] Unable to import GenericAPILogger - LiteLLM Enterprise Feature - {e}")
|
||||
verbose_logger.debug("[Non-Blocking] Unable to import GenericAPILogger - LiteLLM Enterprise Feature - %s", e)
|
||||
GenericAPILogger = CustomLogger # type: ignore
|
||||
ResendEmailLogger = CustomLogger # type: ignore
|
||||
SendGridEmailLogger = CustomLogger # type: ignore
|
||||
|
|
@ -546,7 +546,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
self.litellm_request_debug = litellm_params.get("litellm_request_debug", False)
|
||||
self.logger_fn = litellm_params.get("logger_fn", None)
|
||||
if _is_debugging_on() or self.litellm_request_debug:
|
||||
verbose_logger.debug(f"self.optional_params: {self.optional_params}")
|
||||
verbose_logger.debug("self.optional_params: %s", self.optional_params)
|
||||
|
||||
self.model_call_details.update(
|
||||
{
|
||||
|
|
@ -981,7 +981,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
) # Expectation: any logger function passed in by the user should accept a dict object
|
||||
except Exception as e:
|
||||
verbose_logger.exception(
|
||||
f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while logging {e}"
|
||||
"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while logging %s", e
|
||||
)
|
||||
|
||||
self.model_call_details["api_call_start_time"] = datetime.datetime.now()
|
||||
|
|
@ -1001,7 +1001,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
verbose_logger.debug("reaches supabase for logging!")
|
||||
model = self.model_call_details["model"]
|
||||
messages = self.model_call_details["input"]
|
||||
verbose_logger.debug(f"supabaseClient: {supabaseClient}")
|
||||
verbose_logger.debug("supabaseClient: %s", supabaseClient)
|
||||
supabaseClient.input_log_event(
|
||||
model=model,
|
||||
messages=messages,
|
||||
|
|
@ -1041,15 +1041,15 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
callback_func=callback,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"litellm.Logging.pre_call(): Exception occured - {e}")
|
||||
verbose_logger.exception("litellm.Logging.pre_call(): Exception occured - %s", e)
|
||||
verbose_logger.debug(
|
||||
f"LiteLLM.Logging: is sentry capture exception initialized {capture_exception}"
|
||||
"LiteLLM.Logging: is sentry capture exception initialized %s", capture_exception
|
||||
)
|
||||
if capture_exception: # log this error to sentry for debugging
|
||||
capture_exception(e)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while logging {e}")
|
||||
verbose_logger.error(f"LiteLLM.Logging: is sentry capture exception initialized {capture_exception}")
|
||||
verbose_logger.exception("LiteLLM.LoggingError: [Non-Blocking] Exception occurred while logging %s", e)
|
||||
verbose_logger.error("LiteLLM.Logging: is sentry capture exception initialized %s", capture_exception)
|
||||
if capture_exception: # log this error to sentry for debugging
|
||||
capture_exception(e)
|
||||
|
||||
|
|
@ -1091,10 +1091,10 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
)
|
||||
if self.litellm_request_debug:
|
||||
verbose_logger.warning(
|
||||
f"\033[92m{curl_command}\033[0m\n"
|
||||
"\x1b[92m%s\x1b[0m\n", curl_command
|
||||
) # .warning ensures this shows up in all environments
|
||||
else:
|
||||
verbose_logger.debug(f"\033[92m{curl_command}\033[0m\n")
|
||||
verbose_logger.debug("\x1b[92m%s\x1b[0m\n", curl_command)
|
||||
|
||||
def _get_request_body(self, data: dict) -> str:
|
||||
return str(data)
|
||||
|
|
@ -1164,7 +1164,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
) # Expectation: any logger function passed in by the user should accept a dict object
|
||||
except Exception as e:
|
||||
verbose_logger.exception(
|
||||
f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while logging {e}"
|
||||
"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while logging %s", e
|
||||
)
|
||||
original_response = redact_message_input_output_from_logging(
|
||||
model_call_details=(self.model_call_details if hasattr(self, "model_call_details") else {}),
|
||||
|
|
@ -1201,15 +1201,16 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(
|
||||
f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while post-call logging with integrations {e}"
|
||||
"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while post-call logging with integrations %s",
|
||||
e,
|
||||
)
|
||||
verbose_logger.debug(
|
||||
f"LiteLLM.Logging: is sentry capture exception initialized {capture_exception}"
|
||||
"LiteLLM.Logging: is sentry capture exception initialized %s", capture_exception
|
||||
)
|
||||
if capture_exception: # log this error to sentry for debugging
|
||||
capture_exception(e)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while logging {e}")
|
||||
verbose_logger.exception("LiteLLM.LoggingError: [Non-Blocking] Exception occurred while logging %s", e)
|
||||
|
||||
async def async_post_mcp_tool_call_hook(
|
||||
self,
|
||||
|
|
@ -1249,7 +1250,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
if response is not None:
|
||||
response_obj = self._parse_post_mcp_call_hook_response(response=response)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while logging {e}")
|
||||
verbose_logger.exception("LiteLLM.LoggingError: [Non-Blocking] Exception occurred while logging %s", e)
|
||||
return response_obj
|
||||
|
||||
def _parse_post_mcp_call_hook_response(self, response: MCPPostCallResponseObject | None) -> Any:
|
||||
|
|
@ -1439,14 +1440,14 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
error_str=str(e),
|
||||
traceback_str=_get_traceback_str_for_error(str(e)),
|
||||
)
|
||||
verbose_logger.debug(f"response_cost_failure_debug_information: {debug_info}")
|
||||
verbose_logger.debug("response_cost_failure_debug_information: %s", debug_info)
|
||||
self.model_call_details["response_cost_failure_debug_information"] = debug_info
|
||||
return None
|
||||
|
||||
try:
|
||||
response_cost = litellm.response_cost_calculator(**response_cost_calculator_kwargs)
|
||||
|
||||
verbose_logger.debug(f"response_cost: {response_cost}")
|
||||
verbose_logger.debug("response_cost: %s", response_cost)
|
||||
additional_response_cost: object = self.model_call_details.get("additional_response_cost")
|
||||
if isinstance(additional_response_cost, (int, float)) and additional_response_cost > 0:
|
||||
return (response_cost or 0.0) + additional_response_cost
|
||||
|
|
@ -1462,7 +1463,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
call_type=response_cost_calculator_kwargs["call_type"],
|
||||
custom_pricing=response_cost_calculator_kwargs["custom_pricing"],
|
||||
)
|
||||
verbose_logger.debug(f"response_cost_failure_debug_information: {debug_info}")
|
||||
verbose_logger.debug("response_cost_failure_debug_information: %s", debug_info)
|
||||
self.model_call_details["response_cost_failure_debug_information"] = debug_info
|
||||
|
||||
return None
|
||||
|
|
@ -1497,7 +1498,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
raw_response=httpx.Response(status_code=200, headers={}),
|
||||
)
|
||||
except Exception as e: # noqa: BLE001 - cost normalization must never break the response path
|
||||
verbose_logger.debug(f"generate_content response cost normalization failed: {e}")
|
||||
verbose_logger.debug("generate_content response cost normalization failed: %s", e)
|
||||
return None
|
||||
|
||||
async def _response_cost_calculator_async(
|
||||
|
|
@ -1666,7 +1667,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
# proxy cost tracking cal backs should run
|
||||
|
||||
if not (isinstance(callback, CustomLogger) and "_PROXY_" in callback.__class__.__name__):
|
||||
verbose_logger.debug(f"no-log request, skipping logging for {event_hook} event")
|
||||
verbose_logger.debug("no-log request, skipping logging for %s event", event_hook)
|
||||
return False
|
||||
|
||||
# Check for dynamically disabled callbacks via headers
|
||||
|
|
@ -1676,7 +1677,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
standard_callback_dynamic_params=self.standard_callback_dynamic_params,
|
||||
):
|
||||
verbose_logger.debug(
|
||||
f"Callback {callback} disabled via x-litellm-disable-callbacks header for {event_hook} event"
|
||||
"Callback %s disabled via x-litellm-disable-callbacks header for %s event", callback, event_hook
|
||||
)
|
||||
return False
|
||||
|
||||
|
|
@ -1989,7 +1990,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
await self.async_success_handler(result=complete_streaming_response)
|
||||
|
||||
def success_handler(self, result=None, start_time=None, end_time=None, cache_hit=None, **kwargs):
|
||||
verbose_logger.debug(f"Logging Details LiteLLM-Success Call: Cache_hit={cache_hit}")
|
||||
verbose_logger.debug("Logging Details LiteLLM-Success Call: Cache_hit=%s", cache_hit)
|
||||
if not self.should_run_logging(event_type="sync_success"): # prevent double logging
|
||||
return
|
||||
start_time, end_time, result = self._success_handler_helper_fn(
|
||||
|
|
@ -2210,7 +2211,8 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
# this only logs streaming once, complete_streaming_response exists i.e when stream ends
|
||||
if self.stream:
|
||||
verbose_logger.debug(
|
||||
f"is complete_streaming_response in kwargs: {kwargs.get('complete_streaming_response', None)}"
|
||||
"is complete_streaming_response in kwargs: %s",
|
||||
kwargs.get("complete_streaming_response", None),
|
||||
)
|
||||
if complete_streaming_response is None:
|
||||
continue
|
||||
|
|
@ -2247,7 +2249,8 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
# this only logs streaming once, complete_streaming_response exists i.e when stream ends
|
||||
if self.stream:
|
||||
verbose_logger.debug(
|
||||
f"is complete_streaming_response in kwargs: {kwargs.get('complete_streaming_response', None)}"
|
||||
"is complete_streaming_response in kwargs: %s",
|
||||
kwargs.get("complete_streaming_response", None),
|
||||
)
|
||||
if complete_streaming_response is None:
|
||||
continue
|
||||
|
|
@ -2389,7 +2392,8 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
pass
|
||||
except Exception as e:
|
||||
verbose_logger.exception(
|
||||
f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while success logging {e}",
|
||||
"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while success logging %s",
|
||||
e,
|
||||
)
|
||||
|
||||
async def async_success_handler(self, result=None, start_time=None, end_time=None, cache_hit=None, **kwargs):
|
||||
|
|
@ -2483,10 +2487,10 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
result=complete_streaming_response
|
||||
)
|
||||
|
||||
verbose_logger.debug(f"Model={self.model}; cost={self.model_call_details['response_cost']}")
|
||||
verbose_logger.debug("Model=%s; cost=%s", self.model, self.model_call_details["response_cost"])
|
||||
except litellm.NotFoundError:
|
||||
verbose_logger.warning(
|
||||
f"Model={self.model} not found in completion cost map. Setting 'response_cost' to None"
|
||||
"Model=%s not found in completion cost map. Setting 'response_cost' to None", self.model
|
||||
)
|
||||
self.model_call_details["response_cost"] = None
|
||||
|
||||
|
|
@ -2681,7 +2685,8 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
)
|
||||
except Exception:
|
||||
verbose_logger.error(
|
||||
f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while success logging {traceback.format_exc()}"
|
||||
"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while success logging %s",
|
||||
traceback.format_exc(),
|
||||
)
|
||||
self._handle_callback_failure(callback=callback)
|
||||
|
||||
|
|
@ -2705,7 +2710,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
break # Only increment once
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Error in _handle_callback_failure: {e}")
|
||||
verbose_logger.debug("Error in _handle_callback_failure: %s", e)
|
||||
|
||||
def _failure_handler_helper_fn(self, exception, traceback_exception, start_time=None, end_time=None):
|
||||
if start_time is None:
|
||||
|
|
@ -2784,7 +2789,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
) # type: ignore
|
||||
|
||||
def failure_handler(self, exception, traceback_exception, start_time=None, end_time=None):
|
||||
verbose_logger.debug(f"Logging Details LiteLLM-Failure Call: {litellm.failure_callback}")
|
||||
verbose_logger.debug("Logging Details LiteLLM-Failure Call: %s", litellm.failure_callback)
|
||||
if not self.should_run_logging(event_type="sync_failure"): # prevent double logging
|
||||
return
|
||||
litellm_params = self.model_call_details.get("litellm_params", {})
|
||||
|
|
@ -2949,7 +2954,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
capture_exception(e)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(
|
||||
f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while failure logging {e}"
|
||||
"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while failure logging %s", e
|
||||
)
|
||||
|
||||
async def async_failure_handler(self, exception, traceback_exception, start_time=None, end_time=None):
|
||||
|
|
@ -3005,8 +3010,9 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(
|
||||
f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while failure \
|
||||
logging {e}\nCallback={callback}"
|
||||
"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while failure logging %s\nCallback=%s",
|
||||
e,
|
||||
callback,
|
||||
)
|
||||
# Track callback logging failures in Prometheus
|
||||
self._handle_callback_failure(callback=callback)
|
||||
|
|
@ -3134,7 +3140,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
"""
|
||||
filtered = [cb for cb in callbacks if not self._is_internal_litellm_proxy_callback(cb)]
|
||||
|
||||
verbose_logger.debug(f"Filtered callbacks: {filtered}")
|
||||
verbose_logger.debug("Filtered callbacks: %s", filtered)
|
||||
return filtered
|
||||
|
||||
def _get_callback_name(self, cb) -> str:
|
||||
|
|
@ -4149,7 +4155,7 @@ def _init_custom_logger_compatible_class(
|
|||
return newrelic_logger # type: ignore
|
||||
return None
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"[Non-Blocking Error] Error initializing custom logger: {e}")
|
||||
verbose_logger.exception("[Non-Blocking Error] Error initializing custom logger: %s", e)
|
||||
return None
|
||||
return None
|
||||
|
||||
|
|
@ -4433,7 +4439,7 @@ def get_custom_logger_compatible_class(
|
|||
return None
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"[Non-Blocking Error] Error getting custom logger: {e}")
|
||||
verbose_logger.exception("[Non-Blocking Error] Error getting custom logger: %s", e)
|
||||
return None
|
||||
|
||||
|
||||
|
|
@ -4783,7 +4789,8 @@ class StandardLoggingPayloadSetup:
|
|||
)
|
||||
except Exception:
|
||||
verbose_logger.debug( # keep in debug otherwise it will trigger on every call
|
||||
f"Model={model_cost_name} is not mapped in model cost map. Defaulting to None model_cost_information for standard_logging_payload"
|
||||
"Model=%s is not mapped in model cost map. Defaulting to None model_cost_information for standard_logging_payload",
|
||||
model_cost_name,
|
||||
)
|
||||
model_cost_information = StandardLoggingModelInformation(
|
||||
model_map_key=model_cost_name, model_map_value=None
|
||||
|
|
@ -5437,7 +5444,7 @@ def get_standard_logging_object_payload(
|
|||
|
||||
return payload
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error creating standard logging object - {e}")
|
||||
verbose_logger.exception("Error creating standard logging object - %s", e)
|
||||
return None
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -150,7 +150,8 @@ def _generic_cost_per_character(
|
|||
prompt_cost = prompt_characters * custom_prompt_cost
|
||||
except Exception as e:
|
||||
verbose_logger.exception(
|
||||
f"litellm.litellm_core_utils.llm_cost_calc.utils.py::cost_per_character(): Exception occured - {e}\nDefaulting to None"
|
||||
"litellm.litellm_core_utils.llm_cost_calc.utils.py::cost_per_character(): Exception occured - %s\nDefaulting to None",
|
||||
e,
|
||||
)
|
||||
|
||||
prompt_cost = None
|
||||
|
|
@ -165,7 +166,8 @@ def _generic_cost_per_character(
|
|||
completion_cost = completion_characters * custom_completion_cost
|
||||
except Exception as e:
|
||||
verbose_logger.exception(
|
||||
f"litellm.litellm_core_utils.llm_cost_calc.utils.py::cost_per_character(): Exception occured - {e}\nDefaulting to None"
|
||||
"litellm.litellm_core_utils.llm_cost_calc.utils.py::cost_per_character(): Exception occured - %s\nDefaulting to None",
|
||||
e,
|
||||
)
|
||||
|
||||
completion_cost = None
|
||||
|
|
@ -388,7 +390,8 @@ def _get_cost_per_unit(model_info: ModelInfo, cost_key: str, default_value: floa
|
|||
return float(cost_per_unit)
|
||||
except ValueError:
|
||||
verbose_logger.exception(
|
||||
f"litellm.litellm_core_utils.llm_cost_calc.utils.py::calculate_cost_per_component(): Exception occured - {cost_per_unit}\nDefaulting to 0.0"
|
||||
"litellm.litellm_core_utils.llm_cost_calc.utils.py::calculate_cost_per_component(): Exception occured - %s\nDefaulting to 0.0",
|
||||
cost_per_unit,
|
||||
)
|
||||
|
||||
# If the service tier key doesn't exist or is None, try to fall back to the standard key
|
||||
|
|
@ -408,7 +411,8 @@ def _get_cost_per_unit(model_info: ModelInfo, cost_key: str, default_value: floa
|
|||
return float(fallback_cost)
|
||||
except ValueError:
|
||||
verbose_logger.exception(
|
||||
f"litellm.litellm_core_utils.llm_cost_calc.utils.py::_get_cost_per_unit(): Exception occured - {fallback_cost}\nDefaulting to 0.0"
|
||||
"litellm.litellm_core_utils.llm_cost_calc.utils.py::_get_cost_per_unit(): Exception occured - %s\nDefaulting to 0.0",
|
||||
fallback_cost,
|
||||
)
|
||||
break # Only try the first matching suffix
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ def get_api_base(model: str, optional_params: dict | LiteLLM_Params) -> str | No
|
|||
api_key=_optional_params.api_key,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Error occurred in getting api base - {e}")
|
||||
verbose_logger.debug("Error occurred in getting api base - %s", e)
|
||||
custom_llm_provider = None
|
||||
dynamic_api_base = None
|
||||
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ class LoggingCallbackManager:
|
|||
if callback not in parent_list:
|
||||
parent_list.append(callback)
|
||||
else:
|
||||
verbose_logger.debug(f"Callback {callback} already exists in {parent_list}, not adding again..")
|
||||
verbose_logger.debug("Callback %s already exists in %s, not adding again..", callback, parent_list)
|
||||
|
||||
def _check_callback_list_size(self, parent_list: list[CustomLogger | Callable | str]) -> bool:
|
||||
"""
|
||||
|
|
@ -155,7 +155,9 @@ class LoggingCallbackManager:
|
|||
"""
|
||||
if len(parent_list) >= MAX_CALLBACKS:
|
||||
verbose_logger.warning(
|
||||
f"Cannot add callback - would exceed MAX_CALLBACKS limit of {MAX_CALLBACKS}. Current callbacks: {len(parent_list)}"
|
||||
"Cannot add callback - would exceed MAX_CALLBACKS limit of %s. Current callbacks: %s",
|
||||
MAX_CALLBACKS,
|
||||
len(parent_list),
|
||||
)
|
||||
return False
|
||||
return True
|
||||
|
|
@ -281,7 +283,7 @@ class LoggingCallbackManager:
|
|||
parent_list.append(callback)
|
||||
else:
|
||||
verbose_logger.debug(
|
||||
f"Callback function {callback.__name__} already exists in {parent_list}, not adding again.."
|
||||
"Callback function %s already exists in %s, not adding again..", callback.__name__, parent_list
|
||||
)
|
||||
|
||||
def _add_custom_logger_to_list(
|
||||
|
|
@ -301,7 +303,10 @@ class LoggingCallbackManager:
|
|||
and self._get_custom_logger_key(existing_logger) == custom_logger_key
|
||||
):
|
||||
verbose_logger.debug(
|
||||
f"Custom logger of type {custom_logger_type_name}, key: {custom_logger_key} already exists in {parent_list}, not adding again.."
|
||||
"Custom logger of type %s, key: %s already exists in %s, not adding again..",
|
||||
custom_logger_type_name,
|
||||
custom_logger_key,
|
||||
parent_list,
|
||||
)
|
||||
return
|
||||
parent_list.append(custom_logger)
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ def _get_parent_otel_span_from_logging_obj(
|
|||
return _get_parent_otel_span_from_kwargs(logging_obj.model_call_details)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error in _get_parent_otel_span_from_logging_obj: {e}")
|
||||
verbose_logger.exception("Error in _get_parent_otel_span_from_logging_obj: %s", e)
|
||||
return None
|
||||
|
||||
|
||||
|
|
@ -265,7 +265,7 @@ def _set_duration_in_model_call_details(
|
|||
else:
|
||||
verbose_logger.debug("`logging_obj` not found - unable to track `llm_api_duration_ms")
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Error setting `llm_api_duration_ms`: {e}")
|
||||
verbose_logger.warning("Error setting `llm_api_duration_ms`: %s", e)
|
||||
|
||||
|
||||
def track_llm_api_timing():
|
||||
|
|
@ -321,7 +321,7 @@ def track_llm_api_timing():
|
|||
)
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Error in service logging: {e}")
|
||||
verbose_logger.debug("Error in service logging: %s", e)
|
||||
|
||||
@functools.wraps(func)
|
||||
def sync_wrapper(*args, **kwargs):
|
||||
|
|
@ -366,7 +366,7 @@ def track_llm_api_timing():
|
|||
parent_otel_span=parent_otel_span,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Error in service logging: {e}")
|
||||
verbose_logger.debug("Error in service logging: %s", e)
|
||||
|
||||
# Check if the function is async or sync
|
||||
if inspect.iscoroutinefunction(func):
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ class LoggingWorker:
|
|||
timeout=self.timeout,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"LoggingWorker error: {e}")
|
||||
verbose_logger.exception("LoggingWorker error: %s", e)
|
||||
finally:
|
||||
self._queue.task_done()
|
||||
finally:
|
||||
|
|
@ -297,7 +297,7 @@ class LoggingWorker:
|
|||
if extracted_tasks:
|
||||
await self._process_extracted_tasks(extracted_tasks)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"LoggingWorker error during aggressive clear: {e}")
|
||||
verbose_logger.exception("LoggingWorker error during aggressive clear: %s", e)
|
||||
finally:
|
||||
# Always reset the flag even if an error occurs
|
||||
self._aggressive_clear_in_progress = False
|
||||
|
|
@ -383,7 +383,7 @@ class LoggingWorker:
|
|||
for _ in range(MAX_ITERATIONS_TO_CLEAR_QUEUE):
|
||||
# Check if we've exceeded the maximum time
|
||||
if asyncio.get_event_loop().time() - start_time >= MAX_TIME_TO_CLEAR_QUEUE:
|
||||
verbose_logger.warning(f"clear_queue exceeded max_time of {MAX_TIME_TO_CLEAR_QUEUE}s, stopping early")
|
||||
verbose_logger.warning("clear_queue exceeded max_time of %ss, stopping early", MAX_TIME_TO_CLEAR_QUEUE)
|
||||
break
|
||||
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -1413,7 +1413,7 @@ def convert_to_gemini_tool_call_result(
|
|||
inline_data_list.append(BlobType(data=mime_rest[1], mime_type=clean_mime))
|
||||
content_str = ""
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Failed to parse data URL in tool response: {e}")
|
||||
verbose_logger.warning("Failed to parse data URL in tool response: %s", e)
|
||||
elif isinstance(message["content"], list):
|
||||
content_list = message["content"]
|
||||
for content in content_list:
|
||||
|
|
@ -1432,7 +1432,7 @@ def convert_to_gemini_tool_call_result(
|
|||
)
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Failed to process Anthropic image block in tool response: {e}")
|
||||
verbose_logger.warning("Failed to process Anthropic image block in tool response: %s", e)
|
||||
elif content_type in ("input_image", "image_url"):
|
||||
# Extract image for inline_data (for Computer Use screenshots and tool results)
|
||||
image_url_data = content.get("image_url", "")
|
||||
|
|
@ -1449,7 +1449,7 @@ def convert_to_gemini_tool_call_result(
|
|||
)
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Failed to process image in tool response: {e}")
|
||||
verbose_logger.warning("Failed to process image in tool response: %s", e)
|
||||
elif content_type in ("file", "input_file"):
|
||||
# Extract file for inline_data (for tool results with PDF, audio, video, etc.)
|
||||
file_data = content.get("file_data", "")
|
||||
|
|
@ -1474,7 +1474,7 @@ def convert_to_gemini_tool_call_result(
|
|||
)
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Failed to process file in tool response: {e}")
|
||||
verbose_logger.warning("Failed to process file in tool response: %s", e)
|
||||
name: str | None = message.get("name", "") # type: ignore
|
||||
|
||||
# Recover name from last message with tool calls
|
||||
|
|
@ -1997,7 +1997,7 @@ def _sanitize_empty_text_content(
|
|||
message = cast(AllMessageValues, dict(message)) # Make a copy
|
||||
message["content"] = _EMPTY_TEXT_PLACEHOLDER
|
||||
verbose_logger.debug(
|
||||
f"_sanitize_empty_text_content: Replaced empty text content in {message.get('role')} message"
|
||||
"_sanitize_empty_text_content: Replaced empty text content in %s message", message.get("role")
|
||||
)
|
||||
return message
|
||||
|
||||
|
|
@ -2022,7 +2022,7 @@ def _sanitize_empty_text_content(
|
|||
message = cast(AllMessageValues, dict(message)) # Make a copy
|
||||
message["content"] = new_blocks # type: ignore
|
||||
verbose_logger.debug(
|
||||
f"_sanitize_empty_text_content: Replaced empty text block(s) in {message.get('role')} message"
|
||||
"_sanitize_empty_text_content: Replaced empty text block(s) in %s message", message.get("role")
|
||||
)
|
||||
|
||||
return message
|
||||
|
|
@ -2086,7 +2086,8 @@ def _add_missing_tool_results(
|
|||
|
||||
if missing_tool_call_ids:
|
||||
verbose_logger.debug(
|
||||
f"_add_missing_tool_results: Found {len(missing_tool_call_ids)} orphaned tool calls. Adding dummy tool results."
|
||||
"_add_missing_tool_results: Found %s orphaned tool calls. Adding dummy tool results.",
|
||||
len(missing_tool_call_ids),
|
||||
)
|
||||
|
||||
result_messages.append(current_message)
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ class RealTimeStreaming:
|
|||
# Catch-all base object so unknown/new event names never raise.
|
||||
typed_obj = OpenAIRealtimeStreamResponseBaseObject(**message_obj) # type: ignore
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Error parsing message for logging: {e}")
|
||||
verbose_logger.debug("Error parsing message for logging: %s", e)
|
||||
self.messages.append(message_obj) # type: ignore[arg-type]
|
||||
return
|
||||
self.messages.append(typed_obj)
|
||||
|
|
@ -213,7 +213,7 @@ class RealTimeStreaming:
|
|||
if tools and isinstance(tools, list):
|
||||
self.session_tools = tools
|
||||
# GA: session.type is required; log it for traceability but no action needed
|
||||
verbose_logger.debug(f"Realtime session.type: {session.get('type')}")
|
||||
verbose_logger.debug("Realtime session.type: %s", session.get("type"))
|
||||
if session.get("type") == "transcription":
|
||||
self._is_transcription_session = True
|
||||
except (json.JSONDecodeError, AttributeError, TypeError):
|
||||
|
|
@ -981,7 +981,7 @@ class RealTimeStreaming:
|
|||
try:
|
||||
await self._handle_provider_config_message(raw_response)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error processing backend message, skipping: {e}")
|
||||
verbose_logger.exception("Error processing backend message, skipping: %s", e)
|
||||
continue
|
||||
else:
|
||||
event = self._parse_backend_event(raw_response)
|
||||
|
|
@ -1008,9 +1008,9 @@ class RealTimeStreaming:
|
|||
await self.websocket.send_text(json.dumps(translated))
|
||||
|
||||
except websockets.exceptions.ConnectionClosed as e: # type: ignore
|
||||
verbose_logger.exception(f"Connection closed in backend to client send messages - {e}")
|
||||
verbose_logger.exception("Connection closed in backend to client send messages - %s", e)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"Error in backend to client send messages: {e}")
|
||||
verbose_logger.exception("Error in backend to client send messages: %s", e)
|
||||
finally:
|
||||
await self.log_messages()
|
||||
|
||||
|
|
@ -1404,7 +1404,7 @@ class RealTimeStreaming:
|
|||
self._guardrail_turn_detection_update_sent = True
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Error in client ack messages: {e}")
|
||||
verbose_logger.debug("Error in client ack messages: %s", e)
|
||||
|
||||
async def bidirectional_forward(self):
|
||||
forward_task = asyncio.create_task(self.backend_to_client_send_messages())
|
||||
|
|
|
|||
|
|
@ -618,7 +618,7 @@ class CustomStreamWrapper:
|
|||
else:
|
||||
return ""
|
||||
except Exception as e:
|
||||
verbose_logger.exception(f"litellm.CustomStreamWrapper.handle_baseten_chunk(): Exception occured - {e}")
|
||||
verbose_logger.exception("litellm.CustomStreamWrapper.handle_baseten_chunk(): Exception occured - %s", e)
|
||||
return ""
|
||||
|
||||
def handle_triton_stream(self, chunk):
|
||||
|
|
@ -1430,7 +1430,7 @@ class CustomStreamWrapper:
|
|||
model_response.choices[0].delta = Delta(**_json_delta)
|
||||
except Exception as e:
|
||||
verbose_logger.exception(
|
||||
f"litellm.CustomStreamWrapper.chunk_creator(): Exception occured - {e}"
|
||||
"litellm.CustomStreamWrapper.chunk_creator(): Exception occured - %s", e
|
||||
)
|
||||
model_response.choices[0].delta = Delta()
|
||||
elif self._has_any_special_delta_attributes(delta):
|
||||
|
|
@ -1538,7 +1538,7 @@ class CustomStreamWrapper:
|
|||
except Exception as e:
|
||||
from litellm._logging import verbose_logger
|
||||
|
||||
verbose_logger.exception(f"Error in post-call streaming deployment hook: {e}")
|
||||
verbose_logger.exception("Error in post-call streaming deployment hook: %s", e)
|
||||
return chunk
|
||||
|
||||
def _add_mcp_list_tools_to_first_chunk(self, chunk: ModelResponseStream) -> ModelResponseStream:
|
||||
|
|
@ -1578,7 +1578,7 @@ class CustomStreamWrapper:
|
|||
except Exception as e:
|
||||
from litellm._logging import verbose_logger
|
||||
|
||||
verbose_logger.exception(f"Error adding MCP list tools to first chunk: {e}")
|
||||
verbose_logger.exception("Error adding MCP list tools to first chunk: %s", e)
|
||||
|
||||
return chunk
|
||||
|
||||
|
|
@ -1615,7 +1615,7 @@ class CustomStreamWrapper:
|
|||
except Exception as e:
|
||||
from litellm._logging import verbose_logger
|
||||
|
||||
verbose_logger.exception(f"Error adding MCP metadata to final chunk: {e}")
|
||||
verbose_logger.exception("Error adding MCP metadata to final chunk: %s", e)
|
||||
|
||||
return chunk
|
||||
|
||||
|
|
|
|||
|
|
@ -80,17 +80,20 @@ def get_modified_max_tokens(
|
|||
) # give at least a 10 token buffer. token counting can be imprecise.
|
||||
|
||||
input_tokens += int(token_buffer)
|
||||
verbose_logger.debug(f"max_output_tokens: {max_output_tokens}, user_max_tokens: {user_max_tokens}")
|
||||
verbose_logger.debug("max_output_tokens: %s, user_max_tokens: %s", max_output_tokens, user_max_tokens)
|
||||
## CASE 1: model input + output can't exceed X - happens when max input = max output, e.g. gpt-3.5-turbo
|
||||
if _model_info["max_input_tokens"] == max_output_tokens:
|
||||
verbose_logger.debug(f"input_tokens: {input_tokens}, max_output_tokens: {max_output_tokens}")
|
||||
verbose_logger.debug("input_tokens: %s, max_output_tokens: %s", input_tokens, max_output_tokens)
|
||||
if input_tokens > max_output_tokens:
|
||||
pass # allow call to fail normally - don't set max_tokens to negative.
|
||||
elif (
|
||||
user_max_tokens + input_tokens > max_output_tokens
|
||||
): # we can still modify to keep it positive but below the limit
|
||||
verbose_logger.debug(
|
||||
f"MODIFYING MAX TOKENS - user_max_tokens={user_max_tokens}, input_tokens={input_tokens}, max_output_tokens={max_output_tokens}"
|
||||
"MODIFYING MAX TOKENS - user_max_tokens=%s, input_tokens=%s, max_output_tokens=%s",
|
||||
user_max_tokens,
|
||||
input_tokens,
|
||||
max_output_tokens,
|
||||
)
|
||||
user_max_tokens = int(max_output_tokens - input_tokens)
|
||||
## CASE 2: user_max_tokens> model max output tokens
|
||||
|
|
@ -98,13 +101,17 @@ def get_modified_max_tokens(
|
|||
user_max_tokens = max_output_tokens
|
||||
|
||||
verbose_logger.debug(
|
||||
f"litellm.litellm_core_utils.token_counter.py::get_modified_max_tokens() - user_max_tokens: {user_max_tokens}"
|
||||
"litellm.litellm_core_utils.token_counter.py::get_modified_max_tokens() - user_max_tokens: %s",
|
||||
user_max_tokens,
|
||||
)
|
||||
|
||||
return user_max_tokens
|
||||
except Exception as e:
|
||||
verbose_logger.debug(
|
||||
f"litellm.litellm_core_utils.token_counter.py::get_modified_max_tokens() - Error while checking max token limit: {e}\nmodel={model}, base_model={base_model}"
|
||||
"litellm.litellm_core_utils.token_counter.py::get_modified_max_tokens() - Error while checking max token limit: %s\nmodel=%s, base_model=%s",
|
||||
e,
|
||||
model,
|
||||
base_model,
|
||||
)
|
||||
return user_max_tokens
|
||||
|
||||
|
|
@ -280,7 +287,7 @@ def calculate_img_tokens(
|
|||
int: The number of tokens for the image.
|
||||
"""
|
||||
if use_default_image_token_count:
|
||||
verbose_logger.debug(f"Using default image token count: {DEFAULT_IMAGE_TOKEN_COUNT}")
|
||||
verbose_logger.debug("Using default image token count: %s", DEFAULT_IMAGE_TOKEN_COUNT)
|
||||
return DEFAULT_IMAGE_TOKEN_COUNT
|
||||
if mode == "low" or mode == "auto":
|
||||
return base_tokens
|
||||
|
|
@ -367,7 +374,7 @@ def token_counter(
|
|||
if litellm.disable_token_counter is True:
|
||||
return 0
|
||||
|
||||
verbose_logger.debug(f"messages in token_counter: {messages}, text in token_counter: {text}")
|
||||
verbose_logger.debug("messages in token_counter: %s, text in token_counter: %s", messages, text)
|
||||
if text is not None and messages is not None:
|
||||
raise ValueError("text and messages cannot both be set")
|
||||
if use_default_image_token_count is None:
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ def discover_guardrail_translation_mappings() -> dict[CallTypes, type["BaseTrans
|
|||
|
||||
try:
|
||||
# Import the module
|
||||
verbose_logger.debug(f"Discovering guardrail translations in: {module_path}")
|
||||
verbose_logger.debug("Discovering guardrail translations in: %s", module_path)
|
||||
|
||||
module = importlib.import_module(module_path)
|
||||
|
||||
|
|
@ -102,14 +102,14 @@ def discover_guardrail_translation_mappings() -> dict[CallTypes, type["BaseTrans
|
|||
if isinstance(mappings, dict):
|
||||
discovered_mappings.update(mappings)
|
||||
verbose_logger.debug(
|
||||
f"Found guardrail_translation_mappings in {module_path}: {list(mappings.keys())}"
|
||||
"Found guardrail_translation_mappings in %s: %s", module_path, list(mappings.keys())
|
||||
)
|
||||
|
||||
except ImportError as e:
|
||||
verbose_logger.error(f"Could not import {module_path}: {e}")
|
||||
verbose_logger.error("Could not import %s: %s", module_path, e)
|
||||
continue
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"Error processing {module_path}: {e}")
|
||||
verbose_logger.error("Error processing %s: %s", module_path, e)
|
||||
continue
|
||||
|
||||
try:
|
||||
|
|
@ -126,11 +126,13 @@ def discover_guardrail_translation_mappings() -> dict[CallTypes, type["BaseTrans
|
|||
verbose_logger.debug("MCP guardrail translation mappings not available; skipping")
|
||||
|
||||
verbose_logger.debug(
|
||||
f"Discovered {len(discovered_mappings)} guardrail translation mappings: {list(discovered_mappings.keys())}"
|
||||
"Discovered %s guardrail translation mappings: %s",
|
||||
len(discovered_mappings),
|
||||
list(discovered_mappings.keys()),
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"Error discovering guardrail translation mappings: {e}")
|
||||
verbose_logger.error("Error discovering guardrail translation mappings: %s", e)
|
||||
|
||||
return discovered_mappings
|
||||
|
||||
|
|
|
|||
|
|
@ -825,10 +825,10 @@ class AnthropicMessagesHandler(BaseTranslation):
|
|||
if delta.get("type") == "text_delta":
|
||||
text += delta.get("text", "")
|
||||
except json.JSONDecodeError:
|
||||
verbose_proxy_logger.warning(f"Failed to parse JSON from SSE data: {data_line}")
|
||||
verbose_proxy_logger.warning("Failed to parse JSON from SSE data: %s", data_line)
|
||||
|
||||
except Exception as e:
|
||||
verbose_proxy_logger.error(f"Error extracting text from SSE: {e}")
|
||||
verbose_proxy_logger.error("Error extracting text from SSE: %s", e)
|
||||
|
||||
return text
|
||||
|
||||
|
|
@ -889,10 +889,10 @@ class AnthropicMessagesHandler(BaseTranslation):
|
|||
if stop_reason is not None:
|
||||
return True
|
||||
except json.JSONDecodeError:
|
||||
verbose_proxy_logger.warning(f"Failed to parse JSON from SSE data: {data_line}")
|
||||
verbose_proxy_logger.warning("Failed to parse JSON from SSE data: %s", data_line)
|
||||
|
||||
except Exception as e:
|
||||
verbose_proxy_logger.error(f"Error checking streaming end in SSE: {e}")
|
||||
verbose_proxy_logger.error("Error checking streaming end in SSE: %s", e)
|
||||
|
||||
# Handle already-parsed dict format
|
||||
elif isinstance(response, dict):
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class AnthropicCountTokensHandler(AnthropicCountTokensConfig):
|
|||
# Validate the request
|
||||
self.validate_request(model, messages)
|
||||
|
||||
verbose_logger.debug(f"Processing Anthropic CountTokens request for model: {model}")
|
||||
verbose_logger.debug("Processing Anthropic CountTokens request for model: %s", model)
|
||||
|
||||
# Transform request to Anthropic format
|
||||
request_body = self.transform_request_to_count_tokens(
|
||||
|
|
@ -64,12 +64,12 @@ class AnthropicCountTokensHandler(AnthropicCountTokensConfig):
|
|||
system=system,
|
||||
)
|
||||
|
||||
verbose_logger.debug(f"Transformed request: {request_body}")
|
||||
verbose_logger.debug("Transformed request: %s", request_body)
|
||||
|
||||
# Get endpoint URL
|
||||
endpoint_url = api_base or self.get_anthropic_count_tokens_endpoint()
|
||||
|
||||
verbose_logger.debug(f"Making request to: {endpoint_url}")
|
||||
verbose_logger.debug("Making request to: %s", endpoint_url)
|
||||
|
||||
# Get required headers
|
||||
headers = self.get_required_headers(api_key)
|
||||
|
|
@ -87,11 +87,11 @@ class AnthropicCountTokensHandler(AnthropicCountTokensConfig):
|
|||
timeout=request_timeout,
|
||||
)
|
||||
|
||||
verbose_logger.debug(f"Response status: {response.status_code}")
|
||||
verbose_logger.debug("Response status: %s", response.status_code)
|
||||
|
||||
if response.status_code != 200:
|
||||
error_text = response.text
|
||||
verbose_logger.error(f"Anthropic API error: {error_text}")
|
||||
verbose_logger.error("Anthropic API error: %s", error_text)
|
||||
raise AnthropicError(
|
||||
status_code=response.status_code,
|
||||
message=error_text,
|
||||
|
|
@ -99,7 +99,7 @@ class AnthropicCountTokensHandler(AnthropicCountTokensConfig):
|
|||
|
||||
anthropic_response = response.json()
|
||||
|
||||
verbose_logger.debug(f"Anthropic response: {anthropic_response}")
|
||||
verbose_logger.debug("Anthropic response: %s", anthropic_response)
|
||||
|
||||
# Return Anthropic response directly - no transformation needed
|
||||
return anthropic_response
|
||||
|
|
@ -109,13 +109,13 @@ class AnthropicCountTokensHandler(AnthropicCountTokensConfig):
|
|||
raise
|
||||
except httpx.HTTPStatusError as e:
|
||||
# HTTP errors - preserve the actual status code
|
||||
verbose_logger.error(f"HTTP error in CountTokens handler: {e}")
|
||||
verbose_logger.error("HTTP error in CountTokens handler: %s", e)
|
||||
raise AnthropicError(
|
||||
status_code=e.response.status_code,
|
||||
message=e.response.text,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"Error in CountTokens handler: {e}")
|
||||
verbose_logger.error("Error in CountTokens handler: %s", e)
|
||||
raise AnthropicError(
|
||||
status_code=500,
|
||||
message=f"CountTokens processing error: {e}",
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ class AnthropicTokenCounter(BaseTokenCounter):
|
|||
original_response=result,
|
||||
)
|
||||
except AnthropicError as e:
|
||||
verbose_logger.warning(f"Anthropic CountTokens API error: status={e.status_code}, message={e.message}")
|
||||
verbose_logger.warning("Anthropic CountTokens API error: status=%s, message=%s", e.status_code, e.message)
|
||||
return TokenCountResponse(
|
||||
total_tokens=0,
|
||||
request_model=request_model,
|
||||
|
|
@ -92,7 +92,7 @@ class AnthropicTokenCounter(BaseTokenCounter):
|
|||
status_code=e.status_code,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.warning(f"Error calling Anthropic CountTokens API: {e}")
|
||||
verbose_logger.warning("Error calling Anthropic CountTokens API: %s", e)
|
||||
return TokenCountResponse(
|
||||
total_tokens=0,
|
||||
request_model=request_model,
|
||||
|
|
|
|||
|
|
@ -669,7 +669,7 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper):
|
|||
return {"type": "message_stop"}
|
||||
raise StopIteration
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"Anthropic Adapter - {e}\n{traceback.format_exc()}")
|
||||
verbose_logger.error("Anthropic Adapter - %s\n%s", e, traceback.format_exc())
|
||||
raise StopIteration
|
||||
|
||||
async def __anext__(self):
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue