From 558f9a7cafd49d177cb428e4138f51f0907809ec Mon Sep 17 00:00:00 2001 From: yryzhan-vitech Date: Sun, 26 Jul 2026 13:48:36 +0200 Subject: [PATCH] refactor(logging): extract _redact_and_sanitize helper for print_verbose stdout Every print_verbose stdout path repeated _sanitize_log_message(redact_secrets( str(x))). Extract a single _redact_and_sanitize() helper in _logging.py and route all call-sites through it, so the redact->sanitize order is defined once. No behavior change. --- litellm/_logging.py | 8 +++++--- litellm/caching/caching.py | 6 ++---- litellm/litellm_core_utils/streaming_handler.py | 6 ++---- litellm/main.py | 6 ++---- litellm/proxy/guardrails/guardrail_hooks/presidio.py | 7 ++----- litellm/proxy/hooks/batch_redis_get.py | 7 ++----- litellm/proxy/hooks/parallel_request_limiter.py | 7 ++----- litellm/proxy/hooks/prompt_injection_detection.py | 7 ++----- litellm/proxy/utils.py | 4 ++-- litellm/utils.py | 7 ++----- tests/test_litellm/test_logging.py | 8 ++++++++ 11 files changed, 31 insertions(+), 42 deletions(-) diff --git a/litellm/_logging.py b/litellm/_logging.py index b251f2b13cf..3e9a8095230 100644 --- a/litellm/_logging.py +++ b/litellm/_logging.py @@ -424,12 +424,14 @@ def _sanitize_log_message(message: str) -> str: return re.sub(r"[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]", "?", message) +def _redact_and_sanitize(value) -> str: + return _sanitize_log_message(redact_secrets(str(value))) + + def print_verbose(print_statement): try: if set_verbose: - print( # noqa: T201 - _sanitize_log_message(redact_secrets(str(print_statement))) - ) + print(_redact_and_sanitize(print_statement)) # noqa: T201 except Exception: pass diff --git a/litellm/caching/caching.py b/litellm/caching/caching.py index 6a17e5423e7..50cd427f13f 100644 --- a/litellm/caching/caching.py +++ b/litellm/caching/caching.py @@ -18,7 +18,7 @@ from typing import Any, Dict, List, Optional, Tuple, Union from pydantic import BaseModel import litellm -from litellm._logging import _sanitize_log_message, redact_secrets, verbose_logger +from litellm._logging import _redact_and_sanitize, verbose_logger from litellm.constants import CACHED_STREAMING_CHUNK_DELAY from litellm.litellm_core_utils.model_param_helper import ModelParamHelper from litellm.types.caching import * @@ -41,9 +41,7 @@ def print_verbose(print_statement): try: verbose_logger.debug(print_statement) if litellm.set_verbose: - print( # noqa: T201 - _sanitize_log_message(redact_secrets(str(print_statement))) - ) + print(_redact_and_sanitize(print_statement)) # noqa: T201 except Exception: pass diff --git a/litellm/litellm_core_utils/streaming_handler.py b/litellm/litellm_core_utils/streaming_handler.py index 337c20e1327..5f23b133bd1 100644 --- a/litellm/litellm_core_utils/streaming_handler.py +++ b/litellm/litellm_core_utils/streaming_handler.py @@ -26,7 +26,7 @@ from pydantic import BaseModel import litellm from litellm import verbose_logger -from litellm._logging import _sanitize_log_message, redact_secrets +from litellm._logging import _redact_and_sanitize from litellm._uuid import uuid from litellm.litellm_core_utils.model_response_utils import ( is_model_response_stream_empty, @@ -94,9 +94,7 @@ def is_async_iterable(obj: Any) -> bool: def print_verbose(print_statement): try: if litellm.set_verbose: - print( # noqa: T201 - _sanitize_log_message(redact_secrets(str(print_statement))) - ) + print(_redact_and_sanitize(print_statement)) # noqa: T201 except Exception: pass diff --git a/litellm/main.py b/litellm/main.py index 667c1c42408..3df9c71f222 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -179,7 +179,7 @@ from litellm.utils import ( validate_openai_optional_params, ) -from ._logging import _sanitize_log_message, redact_secrets, verbose_logger +from ._logging import _redact_and_sanitize, verbose_logger from .caching.caching import disable_cache, enable_cache, update_cache from .litellm_core_utils.core_helpers import safe_deep_copy from .litellm_core_utils.fallback_utils import ( @@ -8381,9 +8381,7 @@ def print_verbose(print_statement): try: verbose_logger.debug(print_statement) if litellm.set_verbose: - print( # noqa: T201 - _sanitize_log_message(redact_secrets(str(print_statement))) - ) + print(_redact_and_sanitize(print_statement)) # noqa: T201 except Exception: pass diff --git a/litellm/proxy/guardrails/guardrail_hooks/presidio.py b/litellm/proxy/guardrails/guardrail_hooks/presidio.py index 943423638f3..4075bbd2e95 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/presidio.py +++ b/litellm/proxy/guardrails/guardrail_hooks/presidio.py @@ -31,8 +31,7 @@ import aiohttp import litellm from litellm import get_secret from litellm._logging import ( - _sanitize_log_message, - redact_secrets, + _redact_and_sanitize, verbose_proxy_logger, ) from litellm.types.utils import GenericGuardrailAPIInputs @@ -1324,9 +1323,7 @@ class _OPTIONAL_PresidioPIIMasking(CustomGuardrail): try: verbose_proxy_logger.debug(print_statement) if litellm.set_verbose: - print( # noqa: T201 - _sanitize_log_message(redact_secrets(str(print_statement))) - ) + print(_redact_and_sanitize(print_statement)) # noqa: T201 except Exception: pass diff --git a/litellm/proxy/hooks/batch_redis_get.py b/litellm/proxy/hooks/batch_redis_get.py index 95157de2ec1..e32aa939964 100644 --- a/litellm/proxy/hooks/batch_redis_get.py +++ b/litellm/proxy/hooks/batch_redis_get.py @@ -10,8 +10,7 @@ from fastapi import HTTPException import litellm from litellm._logging import ( - _sanitize_log_message, - redact_secrets, + _redact_and_sanitize, verbose_proxy_logger, ) from litellm.caching.caching import DualCache, InMemoryCache, RedisCache @@ -35,9 +34,7 @@ class _PROXY_BatchRedisRequests(CustomLogger): elif debug_level == "INFO": verbose_proxy_logger.debug(print_statement) if litellm.set_verbose is True: - print( # noqa: T201 - _sanitize_log_message(redact_secrets(str(print_statement))) - ) + print(_redact_and_sanitize(print_statement)) # noqa: T201 async def async_pre_call_hook( self, diff --git a/litellm/proxy/hooks/parallel_request_limiter.py b/litellm/proxy/hooks/parallel_request_limiter.py index ea085668638..c2263183db8 100644 --- a/litellm/proxy/hooks/parallel_request_limiter.py +++ b/litellm/proxy/hooks/parallel_request_limiter.py @@ -9,8 +9,7 @@ from typing_extensions import TypedDict import litellm from litellm import DualCache, EmbeddingResponse, ModelResponse, TextCompletionResponse from litellm._logging import ( - _sanitize_log_message, - redact_secrets, + _redact_and_sanitize, verbose_proxy_logger, ) from litellm.integrations.custom_logger import CustomLogger @@ -55,9 +54,7 @@ class _PROXY_MaxParallelRequestsHandler(CustomLogger): try: verbose_proxy_logger.debug(print_statement) if litellm.set_verbose: - print( # noqa: T201 - _sanitize_log_message(redact_secrets(str(print_statement))) - ) + print(_redact_and_sanitize(print_statement)) # noqa: T201 except Exception: pass diff --git a/litellm/proxy/hooks/prompt_injection_detection.py b/litellm/proxy/hooks/prompt_injection_detection.py index 8dcc8adf030..7a2abee3c92 100644 --- a/litellm/proxy/hooks/prompt_injection_detection.py +++ b/litellm/proxy/hooks/prompt_injection_detection.py @@ -14,8 +14,7 @@ from fastapi import HTTPException import litellm from litellm._logging import ( - _sanitize_log_message, - redact_secrets, + _redact_and_sanitize, verbose_proxy_logger, ) from litellm.caching.caching import DualCache @@ -76,9 +75,7 @@ class _OPTIONAL_PromptInjectionDetection(CustomLogger): verbose_proxy_logger.debug(print_statement) if litellm.set_verbose is True: - print( # noqa: T201 - _sanitize_log_message(redact_secrets(str(print_statement))) - ) + print(_redact_and_sanitize(print_statement)) # noqa: T201 def update_environment(self, router: Optional[Router] = None): self.llm_router = router diff --git a/litellm/proxy/utils.py b/litellm/proxy/utils.py index cb3849e901f..1686c1d128d 100644 --- a/litellm/proxy/utils.py +++ b/litellm/proxy/utils.py @@ -89,8 +89,8 @@ from litellm import ( Router, ) from litellm._logging import ( + _redact_and_sanitize, _redact_string, - _sanitize_log_message, verbose_proxy_logger, ) from litellm._service_logger import ServiceLogging, ServiceTypes @@ -201,7 +201,7 @@ def print_verbose(print_statement): verbose_proxy_logger.debug("{}\n{}".format(print_statement, traceback.format_exc())) if litellm.set_verbose: print( # noqa: T201 - f"LiteLLM Proxy: {_sanitize_log_message(_redact_string(str(print_statement)))}" + f"LiteLLM Proxy: {_redact_and_sanitize(print_statement)}" ) diff --git a/litellm/utils.py b/litellm/utils.py index 9e4ceb4a241..4c97dcee475 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -397,8 +397,7 @@ from litellm.llms.base_llm.skills.transformation import BaseSkillsAPIConfig from ._logging import ( _is_debugging_on, - _sanitize_log_message, - redact_secrets, + _redact_and_sanitize, verbose_logger, ) from .caching.caching import ( @@ -497,9 +496,7 @@ def print_verbose( elif log_level == "ERROR": verbose_logger.error(print_statement) if litellm.set_verbose is True and logger_only is False: - print( # noqa: T201 - _sanitize_log_message(redact_secrets(str(print_statement))) - ) + print(_redact_and_sanitize(print_statement)) # noqa: T201 except Exception: pass diff --git a/tests/test_litellm/test_logging.py b/tests/test_litellm/test_logging.py index 4c3a60be14c..2e21bd076d2 100644 --- a/tests/test_litellm/test_logging.py +++ b/tests/test_litellm/test_logging.py @@ -480,6 +480,14 @@ def test_proxy_hook_print_verbose_methods_redact_and_sanitize(capsys, monkeypatc assert "\\r\\n" in out and "\x9b" not in out, cls.__name__ +def test_redact_and_sanitize_helper_combines_both_stages(): + from litellm._logging import _redact_and_sanitize + + out = _redact_and_sanitize({"api_key": SECRET_VALUE, "note": "a\r\nb\x9b"}) + assert SECRET_VALUE not in out and "REDACTED" in out + assert "\\r\\n" in out and "\x9b" not in out + + def test_utils_print_verbose_skips_stdout_when_not_verbose(capsys, monkeypatch): from litellm.utils import print_verbose as utils_print_verbose