diff --git a/litellm/utils.py b/litellm/utils.py index 3769b2cb25d..63fa848d453 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -1540,12 +1540,14 @@ def _schedule_async_success_logging( def _enqueue_async_logging() -> None: logging_obj.mark_async_success_log_enqueued() - _client_async_logging_helper( - logging_obj=logging_obj, - result=result, - start_time=start_time, - end_time=end_time, - is_completion_with_fallbacks=is_completion_with_fallbacks, + asyncio.create_task( + _client_async_logging_helper( + logging_obj=logging_obj, + result=result, + start_time=start_time, + end_time=end_time, + is_completion_with_fallbacks=is_completion_with_fallbacks, + ) ) if not logging_obj.defer_async_logging: @@ -1556,13 +1558,13 @@ def _schedule_async_success_logging( logging_obj.enqueue_deferred_logging = _enqueue_async_logging -def _client_async_logging_helper( +async def _client_async_logging_helper( logging_obj: LiteLLMLoggingObject, - result: object, - start_time: datetime.datetime, - end_time: datetime.datetime, + result, + start_time, + end_time, is_completion_with_fallbacks: bool, -) -> None: +): if ( is_completion_with_fallbacks is False ): # don't log the parent event litellm.completion_with_fallbacks as a 'log_success_event', this will lead to double logging the same call - https://github.com/BerriAI/litellm/issues/7477 diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index 665e37c7e1b..436c966e5d5 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -10884,45 +10884,6 @@ def test_get_optional_params_forwards_a_tool_config_cache_point_to_a_downstream_ assert optional_params["extra_body"] == {"kept": True, "cache_control_injection_points": [point]} -@pytest.mark.asyncio -@pytest.mark.parametrize("deferred", [False, True]) -async def test_success_logging_is_enqueued_before_the_worker_is_flushed(deferred: bool) -> None: - from litellm.litellm_core_utils.litellm_logging import Logging - from litellm.litellm_core_utils.logging_worker import GLOBAL_LOGGING_WORKER - from litellm.utils import _schedule_async_success_logging - - completed: Final[asyncio.Queue[object]] = asyncio.Queue() - - async def callback(kwargs: object, response: object, start: object, end: object) -> None: - completed.put_nowait(response) - - now: Final = datetime(2026, 1, 1, tzinfo=timezone.utc) - logging_obj: Final = Logging( - model="synthetic-model", - messages=[], - stream=False, - call_type="acompletion", - start_time=now.timestamp(), - litellm_call_id="logging-enqueue", - function_id="logging-enqueue", - dynamic_async_success_callbacks=[callback], - ) - logging_obj.defer_async_logging = deferred - result: Final = litellm.ModelResponse(id="accounted-response") - try: - _schedule_async_success_logging(logging_obj, result, now, now, False) - if deferred: - assert completed.empty() - assert logging_obj.enqueue_deferred_logging is not None - logging_obj.enqueue_deferred_logging() - await GLOBAL_LOGGING_WORKER.flush() - assert completed.get_nowait() is result - assert completed.empty() - finally: - await asyncio.sleep(0) - await GLOBAL_LOGGING_WORKER.flush() - await GLOBAL_LOGGING_WORKER.stop() - @pytest.mark.parametrize( ("provider", "expected_warnings"),