fix(cache): redact Redis exceptions in traceback output

Signed-off-by: LeizhenZhang <zhangleizhen645@gmail.com>
This commit is contained in:
LeizhenZhang 2026-11-02 18:32:19 -06:00
parent eb780bd1ad
commit 26631bca72
2 changed files with 32 additions and 3 deletions

View file

@ -555,7 +555,7 @@ def log_redis_failure(
if isinstance(exc, RedisCircuitBreakerOpenError):
logger.debug("%s: %s", message, reason, stacklevel=2)
return
exc_info: Final = exc if with_traceback else None
exc_info: Final = (type(exc), Exception(reason), exc.__traceback__) if with_traceback else None
if not is_redis_timeout_failure(exc):
logger.log(level, "%s: %s", message, reason, exc_info=exc_info, stacklevel=2)
return

View file

@ -1034,8 +1034,9 @@ def test_prometheus_services_logger_starts_from_the_breakers_already_built(monke
monkeypatch.setattr(litellm, "service_callback", ["prometheus_system"])
gc.collect()
ServiceLogging()
assert REGISTRY.get_sample_value("litellm_redis_circuit_breaker_state", {"state": "closed"}) == (
redis_breaker_state_counts()["closed"]
assert (
REGISTRY.get_sample_value("litellm_redis_circuit_breaker_state", {"state": "closed"})
== (redis_breaker_state_counts()["closed"])
)
@ -1758,6 +1759,34 @@ def test_log_redis_failure_redacts_the_line_it_writes(caplog):
assert "WRONGTYPE" in caplog.text
@pytest.mark.parametrize("chained", [False, True])
def test_log_redis_failure_redacts_traceback_and_exception_chain(
caplog: pytest.LogCaptureFixture, chained: bool
) -> None:
import logging
from redis.exceptions import ResponseError
from litellm.caching.redis_cache import log_redis_failure
with caplog.at_level(logging.ERROR, logger="LiteLLM"):
try:
raise _annotated_pipeline_error()
except ResponseError as pipeline_error:
if chained:
try:
raise RuntimeError("Redis operation failed") from pipeline_error
except RuntimeError as wrapper:
log_redis_failure(verbose_logger, logging.ERROR, "Redis failed", wrapper, with_traceback=True)
else:
log_redis_failure(verbose_logger, logging.ERROR, "Redis failed", pipeline_error, with_traceback=True)
assert SENSITIVE_CACHE_KEY not in caplog.text
assert "private customer message" not in caplog.text
assert "Traceback (most recent call last)" in caplog.text
assert "Redis failed" in caplog.text
@pytest.mark.asyncio
async def test_service_failure_hook_redacts_before_telemetry():
"""Datadog/OTel must not receive the annotated command either."""