perf: build log messages lazily so filtered-out log records cost nothing

litellm's loggers sit at INFO by default; the proxy sets that level explicitly and the SDK inherits root's WARNING, so every debug record is discarded. The message gets built anyway. 2877 logging calls interpolate their payload into an f-string before the call runs, so the work happens on every request and the result is thrown away. The expensive sites stringify a whole message list or kwargs dict, so the cost grows with conversation length

Passing the values as %-style arguments hands them to record.getMessage(), which only runs once a record has passed the level check. With the level turned up the emitted lines are byte-identical, including f"{x=}" sites, which map to %r. A 60-message chat completion runs 22% faster through litellm.completion and allocates 163 kB less; a 20-message one runs 11% faster

f-strings carrying a format spec are left as they are, since %-style has no faithful equivalent for something like {ratio:.1%}, and those sites interpolate scalars rather than payloads. The added test walks the package and fails on any new eager logging call
This commit is contained in:
Classic298 2026-08-03 22:53:00 +02:00 committed by Claude
parent c6a796a84b
commit b248f7b39d
No known key found for this signature in database
410 changed files with 3845 additions and 3119 deletions

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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),

View file

@ -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

View file

@ -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(

View file

@ -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)

View file

@ -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(

View file

@ -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)

View file

@ -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."""

View file

@ -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

View file

@ -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

View file

@ -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(

View file

@ -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:

View file

@ -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):
"""

View file

@ -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,

View file

@ -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,

View file

@ -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

View file

@ -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(

View file

@ -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}",

View file

@ -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

View file

@ -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):

View file

@ -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)
)

View file

@ -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:
@ -1092,7 +1093,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
@ -1219,7 +1220,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)
@ -1315,7 +1316,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
@ -1662,7 +1664,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
@ -1878,7 +1880,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(
@ -1966,7 +1968,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
@ -2036,7 +2038,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]
@ -2072,7 +2074,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

View file

@ -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:

View file

@ -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:

View file

@ -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)

View file

@ -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):
""" """

View file

@ -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 []

View file

@ -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:

View file

@ -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)

View file

@ -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

View file

@ -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]:

View file

@ -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()

View file

@ -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)

View file

@ -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]:

View file

@ -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:

View file

@ -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):

View file

@ -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):

View file

@ -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,

View file

@ -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

View file

@ -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:

View file

@ -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,

View file

@ -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
)

View file

@ -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

View file

@ -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:

View file

@ -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):

View file

@ -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:

View file

@ -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(

View file

@ -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()

View file

@ -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

View file

@ -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]:

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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")

View file

@ -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"""

View file

@ -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")

View file

@ -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())

View file

@ -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):
"""

View file

@ -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

View file

@ -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")

View file

@ -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(

View file

@ -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))

View file

@ -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

View file

@ -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,

View file

@ -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)

View file

@ -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:

View file

@ -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

View file

@ -161,9 +161,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")
@ -171,11 +171,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}"
@ -277,7 +277,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
@ -386,8 +388,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
@ -648,14 +651,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
@ -699,7 +703,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,
)
@ -708,7 +714,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")
@ -753,11 +760,11 @@ 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={getattr(user_api_key_dict, 'user_id', None)}, "
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"),
getattr(user_api_key_dict, "user_id", None),
getattr(original_exception, "guardrail_name", None),
)
return
@ -783,8 +790,9 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
payload = self._prepare_block_failure_payload(logging_obj, exception)
except (AttributeError, 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
@ -793,7 +801,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,
)
@ -845,8 +855,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)
@ -906,7 +917,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")
@ -963,7 +974,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,

View file

@ -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

View file

@ -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

View file

@ -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:
"""

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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 = {

View file

@ -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

View file

@ -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

View file

@ -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):

View file

@ -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()
)

View file

@ -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

View file

@ -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:
@ -1433,14 +1434,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
@ -1456,7 +1457,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
@ -1491,7 +1492,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(
@ -1660,7 +1661,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
@ -1670,7 +1671,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
@ -1983,7 +1984,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(
@ -2204,7 +2205,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
@ -2241,7 +2243,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
@ -2383,7 +2386,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):
@ -2477,10 +2481,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
@ -2675,7 +2679,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)
@ -2699,7 +2704,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:
@ -2778,7 +2783,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", {})
@ -2943,7 +2948,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):
@ -2999,8 +3004,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)
@ -3128,7 +3134,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:
@ -4143,7 +4149,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
@ -4427,7 +4433,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
@ -4777,7 +4783,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
@ -5431,7 +5438,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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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):

View file

@ -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:

View file

@ -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)

View file

@ -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())

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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):

View file

@ -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}",

View file

@ -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,

View file

@ -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