perf: build log messages lazily so filtered-out log records cost nothing (#35703)

This commit is contained in:
Classic298 2026-08-04 06:34:52 +02:00 • committed by GitHub
parent 2039981210
commit c9887a1f94
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
419 changed files with 3919 additions and 3140 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:
@ -1098,7 +1099,7 @@ def _store_cost_breakdown_in_logging_obj(
)
except Exception as breakdown_error:
verbose_logger.debug(f"Error storing cost breakdown: {breakdown_error}")
verbose_logger.debug("Error storing cost breakdown: %s", breakdown_error)
# Don't fail the main cost calculation if breakdown storage fails
@ -1225,7 +1226,7 @@ def completion_cost(
for idx, model in enumerate(potential_model_names):
try:
if verbose_logger.isEnabledFor(logging.DEBUG):
verbose_logger.debug(f"selected model name for cost calculation: {model}")
verbose_logger.debug("selected model name for cost calculation: %s", model)
if completion_response is not None and (
isinstance(completion_response, BaseModel) or isinstance(completion_response, dict)
@ -1321,7 +1322,8 @@ def completion_cost(
) # strip the llm provider from the model name -> for image gen cost calculation
except Exception as e:
verbose_logger.debug(
f"litellm.cost_calculator.py::completion_cost() - Error inferring custom_llm_provider - {e}"
"litellm.cost_calculator.py::completion_cost() - Error inferring custom_llm_provider - %s",
e,
)
if CostCalculatorUtils._call_type_has_image_response(call_type) and isinstance(
completion_response, ImageResponse
@ -1672,7 +1674,7 @@ def completion_cost(
return _final_cost
except Exception as e:
verbose_logger.debug(
f"litellm.cost_calculator.py::completion_cost() - Error calculating cost for model={model} - {e}"
"litellm.cost_calculator.py::completion_cost() - Error calculating cost for model=%s - %s", model, e
)
if idx == len(potential_model_names) - 1:
raise e
@ -1888,7 +1890,7 @@ def vector_store_search_cost(
)
if config is None:
verbose_logger.debug(f"Vector store search is not supported for {custom_llm_provider}")
verbose_logger.debug("Vector store search is not supported for %s", custom_llm_provider)
return 0.0, 0.0
return config.calculate_vector_store_cost(
@ -1976,7 +1978,7 @@ def default_image_cost_calculator(
# gpt-image-1 models use low, medium, high quality. If user did not specify quality, use medium fot gpt-image-1 model family
model_name_with_v2_quality = f"{ImageGenerationRequestQuality.HIGH.value}/{base_model_name}"
verbose_logger.debug(f"Looking up cost for models: {model_name_with_quality}, {base_model_name}")
verbose_logger.debug("Looking up cost for models: %s, %s", model_name_with_quality, base_model_name)
model_without_provider = f"{size_str}/{model.split('/')[-1]}"
model_with_quality_without_provider = f"{quality}/{model_without_provider}" if quality else model_without_provider
@ -2046,7 +2048,7 @@ def default_video_cost_calculator(
model_name_without_custom_llm_provider = model.replace(f"{custom_llm_provider}/", "")
base_model_name = f"{custom_llm_provider}/{model_name_without_custom_llm_provider}"
verbose_logger.debug(f"Looking up cost for video model: {base_model_name}")
verbose_logger.debug("Looking up cost for video model: %s", base_model_name)
model_without_provider = model.split("/")[-1]
@ -2082,7 +2084,8 @@ def default_video_cost_calculator(
# If no cost information found, return 0
verbose_logger.info(
f"No cost information found for video model {model}. Please add pricing to model_prices_and_context_window.json"
"No cost information found for video model %s. Please add pricing to model_prices_and_context_window.json",
model,
)
return 0.0

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

@ -163,9 +163,9 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
parsed_rate = float(rbrk_sampling_rate.strip())
self.sampling_rate = max(0.0, min(1.0, parsed_rate))
if parsed_rate != self.sampling_rate:
verbose_logger.warning(f"RUBRIK_SAMPLING_RATE={parsed_rate} clamped to {self.sampling_rate}")
verbose_logger.warning("RUBRIK_SAMPLING_RATE=%s clamped to %s", parsed_rate, self.sampling_rate)
except ValueError:
verbose_logger.warning(f"Invalid RUBRIK_SAMPLING_RATE: {rbrk_sampling_rate!r}, using 1.0")
verbose_logger.warning("Invalid RUBRIK_SAMPLING_RATE: %r, using 1.0", rbrk_sampling_rate)
def _parse_batch_size(self) -> None:
_batch_size = os.getenv("RUBRIK_BATCH_SIZE")
@ -173,11 +173,11 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
try:
parsed_size = int(_batch_size)
if parsed_size <= 0:
verbose_logger.warning(f"RUBRIK_BATCH_SIZE={_batch_size!r} must be > 0, using default")
verbose_logger.warning("RUBRIK_BATCH_SIZE=%r must be > 0, using default", _batch_size)
else:
self.batch_size = parsed_size
except ValueError:
verbose_logger.warning(f"Invalid RUBRIK_BATCH_SIZE: {_batch_size!r}, using default")
verbose_logger.warning("Invalid RUBRIK_BATCH_SIZE: %r, using default", _batch_size)
def _setup_clients(self, webhook_url: str) -> None:
self.response_moderation_endpoint = f"{webhook_url}{_WEBHOOK_PATH_RESPONSE_MODERATION}"
@ -279,7 +279,9 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
return inputs
except Exception as e:
verbose_logger.error(
f"{label} hook failed: {e}. Returning original inputs unchanged.",
"%s hook failed: %s. Returning original inputs unchanged.",
label,
e,
exc_info=True,
)
return inputs
@ -388,8 +390,9 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
if logging_obj is None:
verbose_logger.error(
"Rubrik: moderation block fired with logging_obj=None for "
f"litellm_call_id={request_data.get('litellm_call_id')}; "
"cannot suppress success event or attach failure payload."
"litellm_call_id=%s; "
"cannot suppress success event or attach failure payload.",
request_data.get("litellm_call_id"),
)
request_data["_rubrik_logging_obj"] = None
return
@ -650,14 +653,15 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
payload["messages"] = (system_scaffold, messages)
except Exception as e:
verbose_logger.warning(
f"Rubrik: failed to prepend system prompt: {e}",
"Rubrik: failed to prepend system prompt: %s",
e,
exc_info=True,
)
async def _prepare_log_payload(self, kwargs: Mapping[str, Any], event_type: str) -> StandardLoggingPayload | None:
"""Shared logic for success logging (sampled)."""
if random.random() > self.sampling_rate:
verbose_logger.debug(f"Skipping Rubrik {event_type} logging (sampling_rate={self.sampling_rate})")
verbose_logger.debug("Skipping Rubrik %s logging (sampling_rate=%s)", event_type, self.sampling_rate)
return None
# Deep-copy so mutations don't affect other callbacks sharing this object
@ -701,7 +705,9 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
await self._append_and_maybe_flush(payload)
except Exception as e:
verbose_logger.error(
f"Rubrik {event_type} logging hook failed: {e}. Skipping logging for this event.",
"Rubrik %s logging hook failed: %s. Skipping logging for this event.",
event_type,
e,
exc_info=True,
)
@ -710,7 +716,8 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
# skip here to avoid double-logging the pre-block response.
if kwargs.get("_rubrik_blocked"):
verbose_logger.debug(
f"Rubrik: skipping success event for blocked request litellm_call_id={kwargs.get('litellm_call_id')}"
"Rubrik: skipping success event for blocked request litellm_call_id=%s",
kwargs.get("litellm_call_id"),
)
return
await self._enqueue_log_event(kwargs, "success")
@ -755,11 +762,14 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
# way we cannot build the payload.
verbose_logger.warning(
"Rubrik: block exception without stashed logging_obj. "
f"litellm_call_id={request_data.get('litellm_call_id')}, "
f"model={request_data.get('model')}, "
f"user_id={user_api_key_dict.user_id}, "
f"raising_guardrail="
f"{getattr(original_exception, 'guardrail_name', None)}"
"litellm_call_id=%s, "
"model=%s, "
"user_id=%s, "
"raising_guardrail=%s",
request_data.get("litellm_call_id"),
request_data.get("model"),
user_api_key_dict.user_id,
getattr(original_exception, "guardrail_name", None),
)
return
@ -786,8 +796,9 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
payload = self._prepare_block_failure_payload(logging_obj, exception, user_api_key_dict)
except (AttributeError, ImportError, KeyError, TypeError) as e:
verbose_logger.error(
f"Rubrik: failed to build blocked-tool payload for "
f"litellm_call_id={call_id}: {e}. Event will NOT be logged.",
"Rubrik: failed to build blocked-tool payload for litellm_call_id=%s: %s. Event will NOT be logged.",
call_id,
e,
exc_info=True,
)
return
@ -796,7 +807,9 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
await self._append_and_maybe_flush(payload)
except Exception as e:
verbose_logger.error(
f"Rubrik: failed to enqueue blocked-tool event for litellm_call_id={call_id}: {e}.",
"Rubrik: failed to enqueue blocked-tool event for litellm_call_id=%s: %s.",
call_id,
e,
exc_info=True,
)
@ -853,8 +866,9 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
else:
verbose_logger.debug(
"Rubrik: standard_logging_object not yet on model_call_details "
f"for litellm_call_id={call_details.get('litellm_call_id')}; "
"using best-effort fallback payload."
"for litellm_call_id=%s; "
"using best-effort fallback payload.",
call_details.get("litellm_call_id"),
)
payload = self._build_fallback_payload(call_details, user_api_key_dict)
@ -932,7 +946,7 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
)
response.raise_for_status()
except httpx.HTTPStatusError as e:
verbose_logger.exception(f"Rubrik HTTP Error: {e.response.status_code} - {e.response.text}")
verbose_logger.exception("Rubrik HTTP Error: %s - %s", e.response.status_code, e.response.text)
raise
except Exception:
verbose_logger.exception("Rubrik Layer Error")
@ -989,7 +1003,7 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
Exception: If the service is unavailable or returns an error.
TypeError: If the response JSON is not a dict.
"""
verbose_logger.debug(f"Sending request to {service_name}: {endpoint}")
verbose_logger.debug("Sending request to %s: %s", service_name, endpoint)
http_response = await self.moderation_client.post(
endpoint,
json=payload,

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:
@ -1439,14 +1440,14 @@ class Logging(LiteLLMLoggingBaseClass):
error_str=str(e),
traceback_str=_get_traceback_str_for_error(str(e)),
)
verbose_logger.debug(f"response_cost_failure_debug_information: {debug_info}")
verbose_logger.debug("response_cost_failure_debug_information: %s", debug_info)
self.model_call_details["response_cost_failure_debug_information"] = debug_info
return None
try:
response_cost = litellm.response_cost_calculator(**response_cost_calculator_kwargs)
verbose_logger.debug(f"response_cost: {response_cost}")
verbose_logger.debug("response_cost: %s", response_cost)
additional_response_cost: object = self.model_call_details.get("additional_response_cost")
if isinstance(additional_response_cost, (int, float)) and additional_response_cost > 0:
return (response_cost or 0.0) + additional_response_cost
@ -1462,7 +1463,7 @@ class Logging(LiteLLMLoggingBaseClass):
call_type=response_cost_calculator_kwargs["call_type"],
custom_pricing=response_cost_calculator_kwargs["custom_pricing"],
)
verbose_logger.debug(f"response_cost_failure_debug_information: {debug_info}")
verbose_logger.debug("response_cost_failure_debug_information: %s", debug_info)
self.model_call_details["response_cost_failure_debug_information"] = debug_info
return None
@ -1497,7 +1498,7 @@ class Logging(LiteLLMLoggingBaseClass):
raw_response=httpx.Response(status_code=200, headers={}),
)
except Exception as e: # noqa: BLE001 - cost normalization must never break the response path
verbose_logger.debug(f"generate_content response cost normalization failed: {e}")
verbose_logger.debug("generate_content response cost normalization failed: %s", e)
return None
async def _response_cost_calculator_async(
@ -1666,7 +1667,7 @@ class Logging(LiteLLMLoggingBaseClass):
# proxy cost tracking cal backs should run
if not (isinstance(callback, CustomLogger) and "_PROXY_" in callback.__class__.__name__):
verbose_logger.debug(f"no-log request, skipping logging for {event_hook} event")
verbose_logger.debug("no-log request, skipping logging for %s event", event_hook)
return False
# Check for dynamically disabled callbacks via headers
@ -1676,7 +1677,7 @@ class Logging(LiteLLMLoggingBaseClass):
standard_callback_dynamic_params=self.standard_callback_dynamic_params,
):
verbose_logger.debug(
f"Callback {callback} disabled via x-litellm-disable-callbacks header for {event_hook} event"
"Callback %s disabled via x-litellm-disable-callbacks header for %s event", callback, event_hook
)
return False
@ -1989,7 +1990,7 @@ class Logging(LiteLLMLoggingBaseClass):
await self.async_success_handler(result=complete_streaming_response)
def success_handler(self, result=None, start_time=None, end_time=None, cache_hit=None, **kwargs):
verbose_logger.debug(f"Logging Details LiteLLM-Success Call: Cache_hit={cache_hit}")
verbose_logger.debug("Logging Details LiteLLM-Success Call: Cache_hit=%s", cache_hit)
if not self.should_run_logging(event_type="sync_success"): # prevent double logging
return
start_time, end_time, result = self._success_handler_helper_fn(
@ -2210,7 +2211,8 @@ class Logging(LiteLLMLoggingBaseClass):
# this only logs streaming once, complete_streaming_response exists i.e when stream ends
if self.stream:
verbose_logger.debug(
f"is complete_streaming_response in kwargs: {kwargs.get('complete_streaming_response', None)}"
"is complete_streaming_response in kwargs: %s",
kwargs.get("complete_streaming_response", None),
)
if complete_streaming_response is None:
continue
@ -2247,7 +2249,8 @@ class Logging(LiteLLMLoggingBaseClass):
# this only logs streaming once, complete_streaming_response exists i.e when stream ends
if self.stream:
verbose_logger.debug(
f"is complete_streaming_response in kwargs: {kwargs.get('complete_streaming_response', None)}"
"is complete_streaming_response in kwargs: %s",
kwargs.get("complete_streaming_response", None),
)
if complete_streaming_response is None:
continue
@ -2389,7 +2392,8 @@ class Logging(LiteLLMLoggingBaseClass):
pass
except Exception as e:
verbose_logger.exception(
f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while success logging {e}",
"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while success logging %s",
e,
)
async def async_success_handler(self, result=None, start_time=None, end_time=None, cache_hit=None, **kwargs):
@ -2483,10 +2487,10 @@ class Logging(LiteLLMLoggingBaseClass):
result=complete_streaming_response
)
verbose_logger.debug(f"Model={self.model}; cost={self.model_call_details['response_cost']}")
verbose_logger.debug("Model=%s; cost=%s", self.model, self.model_call_details["response_cost"])
except litellm.NotFoundError:
verbose_logger.warning(
f"Model={self.model} not found in completion cost map. Setting 'response_cost' to None"
"Model=%s not found in completion cost map. Setting 'response_cost' to None", self.model
)
self.model_call_details["response_cost"] = None
@ -2681,7 +2685,8 @@ class Logging(LiteLLMLoggingBaseClass):
)
except Exception:
verbose_logger.error(
f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while success logging {traceback.format_exc()}"
"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while success logging %s",
traceback.format_exc(),
)
self._handle_callback_failure(callback=callback)
@ -2705,7 +2710,7 @@ class Logging(LiteLLMLoggingBaseClass):
break # Only increment once
except Exception as e:
verbose_logger.debug(f"Error in _handle_callback_failure: {e}")
verbose_logger.debug("Error in _handle_callback_failure: %s", e)
def _failure_handler_helper_fn(self, exception, traceback_exception, start_time=None, end_time=None):
if start_time is None:
@ -2784,7 +2789,7 @@ class Logging(LiteLLMLoggingBaseClass):
) # type: ignore
def failure_handler(self, exception, traceback_exception, start_time=None, end_time=None):
verbose_logger.debug(f"Logging Details LiteLLM-Failure Call: {litellm.failure_callback}")
verbose_logger.debug("Logging Details LiteLLM-Failure Call: %s", litellm.failure_callback)
if not self.should_run_logging(event_type="sync_failure"): # prevent double logging
return
litellm_params = self.model_call_details.get("litellm_params", {})
@ -2949,7 +2954,7 @@ class Logging(LiteLLMLoggingBaseClass):
capture_exception(e)
except Exception as e:
verbose_logger.exception(
f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while failure logging {e}"
"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while failure logging %s", e
)
async def async_failure_handler(self, exception, traceback_exception, start_time=None, end_time=None):
@ -3005,8 +3010,9 @@ class Logging(LiteLLMLoggingBaseClass):
)
except Exception as e:
verbose_logger.exception(
f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while failure \
logging {e}\nCallback={callback}"
"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while failure logging %s\nCallback=%s",
e,
callback,
)
# Track callback logging failures in Prometheus
self._handle_callback_failure(callback=callback)
@ -3134,7 +3140,7 @@ class Logging(LiteLLMLoggingBaseClass):
"""
filtered = [cb for cb in callbacks if not self._is_internal_litellm_proxy_callback(cb)]
verbose_logger.debug(f"Filtered callbacks: {filtered}")
verbose_logger.debug("Filtered callbacks: %s", filtered)
return filtered
def _get_callback_name(self, cb) -> str:
@ -4149,7 +4155,7 @@ def _init_custom_logger_compatible_class(
return newrelic_logger # type: ignore
return None
except Exception as e:
verbose_logger.exception(f"[Non-Blocking Error] Error initializing custom logger: {e}")
verbose_logger.exception("[Non-Blocking Error] Error initializing custom logger: %s", e)
return None
return None
@ -4433,7 +4439,7 @@ def get_custom_logger_compatible_class(
return None
except Exception as e:
verbose_logger.exception(f"[Non-Blocking Error] Error getting custom logger: {e}")
verbose_logger.exception("[Non-Blocking Error] Error getting custom logger: %s", e)
return None
@ -4783,7 +4789,8 @@ class StandardLoggingPayloadSetup:
)
except Exception:
verbose_logger.debug( # keep in debug otherwise it will trigger on every call
f"Model={model_cost_name} is not mapped in model cost map. Defaulting to None model_cost_information for standard_logging_payload"
"Model=%s is not mapped in model cost map. Defaulting to None model_cost_information for standard_logging_payload",
model_cost_name,
)
model_cost_information = StandardLoggingModelInformation(
model_map_key=model_cost_name, model_map_value=None
@ -5437,7 +5444,7 @@ def get_standard_logging_object_payload(
return payload
except Exception as e:
verbose_logger.exception(f"Error creating standard logging object - {e}")
verbose_logger.exception("Error creating standard logging object - %s", e)
return None

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