mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-14 04:09:09 +00:00
fix(logging): surface persistent SLP rebuild failure
Per review: if the empty-response retry also returns None, log a second explicit error so the double failure is observable instead of masked by the first message, and stop promising success in the first log line.
This commit is contained in:
parent
327d4e20e1
commit
4d2713e8b0
2 changed files with 47 additions and 1 deletions
|
|
@ -3356,7 +3356,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
# fallback. See #32019.
|
||||
verbose_logger.error(
|
||||
"standard_logging_object build failed for streaming call_id=%s call_type=%s; "
|
||||
"rebuilding a degraded payload so success loggers still fire",
|
||||
"retrying with an empty response object",
|
||||
self.litellm_call_id,
|
||||
self.call_type,
|
||||
)
|
||||
|
|
@ -3364,6 +3364,13 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
self.model_call_details["standard_logging_object"] = self._build_standard_logging_payload(
|
||||
{}, start_time, end_time
|
||||
)
|
||||
if self.model_call_details["standard_logging_object"] is None:
|
||||
verbose_logger.error(
|
||||
"standard_logging_object rebuild failed for streaming call_id=%s call_type=%s; "
|
||||
"loggers gated on standard_logging_object will skip this request",
|
||||
self.litellm_call_id,
|
||||
self.call_type,
|
||||
)
|
||||
except Exception: # noqa: BLE001 # same rule as above: never block later callbacks
|
||||
verbose_logger.exception(
|
||||
"LiteLLM.LoggingError: [Non-Blocking] Exception rebuilding the degraded standard "
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ exception and returns ``None``, spend tracking still succeeds via the
|
|||
``response_cost`` fallback, and no error surfaces to the caller.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
import pytest
|
||||
|
|
@ -92,3 +93,41 @@ async def test_streaming_slo_build_success_does_not_rebuild(monkeypatch):
|
|||
|
||||
assert logging_obj.model_call_details["standard_logging_object"] == healthy_payload
|
||||
assert len(build_calls) == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_streaming_slo_double_build_failure_is_logged(monkeypatch, caplog):
|
||||
"""If the empty-response rebuild also fails, the persistent failure must be
|
||||
surfaced with a second error log instead of silently leaving the payload None."""
|
||||
logging_obj = Logging(
|
||||
model="claude-3-5-sonnet-20240620",
|
||||
messages=[{"role": "user", "content": "hi"}],
|
||||
stream=True,
|
||||
call_type="anthropic_messages",
|
||||
start_time=datetime.now(),
|
||||
litellm_call_id="test-32019-double",
|
||||
function_id="test-32019-double",
|
||||
)
|
||||
build_calls = []
|
||||
|
||||
def fake_build(self, init_response_obj, start_time, end_time):
|
||||
build_calls.append(init_response_obj)
|
||||
return None # both the primary build and the empty-response retry fail
|
||||
|
||||
monkeypatch.setattr(Logging, "_build_standard_logging_payload", fake_build)
|
||||
monkeypatch.setattr(litellm, "_async_success_callback", [])
|
||||
monkeypatch.setattr(litellm, "success_callback", [])
|
||||
|
||||
result = ModelResponse(model="claude-3-5-sonnet-20240620")
|
||||
|
||||
with caplog.at_level(logging.ERROR, logger="LiteLLM"):
|
||||
await logging_obj.async_success_handler(
|
||||
result,
|
||||
start_time=datetime.now(),
|
||||
end_time=datetime.now(),
|
||||
cache_hit=False,
|
||||
)
|
||||
|
||||
assert logging_obj.model_call_details["standard_logging_object"] is None
|
||||
assert build_calls == [result, {}]
|
||||
assert "rebuild failed" in caplog.text
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue