fix: JSON logging for asyncio exceptions outputs plain text tracebacks #5
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Relevant issues
Fixes asyncio exceptions being logged as plain text tracebacks instead of JSON when
JSON_LOGS=true.Problem
When
JSON_LOGS=true, asyncio "Task exception was never retrieved" errors are logged as multi-line plain text instead of JSON. This breaks log aggregation in Datadog and other log management systems.Example from Datadog (
service:litellm-database):How to Reproduce
The asyncio "Task exception was never retrieved" error occurs when fire-and-forget tasks fail. These are internal background tasks (like
_check_db_connection) that are created withasyncio.create_task()but never awaited.Unit Test Reproduction
The tests verify:
test_async_json_exception_handler_logs_json_with_stacktrace- Handler produces JSON with stacktracetest_setup_asyncio_json_exception_handler_sets_handler_on_running_loop- Handler is set on the running event loopManual Reproduction (Python)
Without fix: Multi-line plain text traceback
With fix: Single-line JSON with
stacktracefieldRoot Cause
Two issues in
litellm/_logging.py:Wrong event loop: The asyncio exception handler was set at module import time using
asyncio.get_event_loop(). When uvicorn starts, it creates its own event loop, so the handler was set on the wrong loop. Asyncio exceptions fall back to the default handler which outputs plain text.Missing traceback: The original handler had
exc_info=None, so even if it was on the correct loop, the JSON output would be missing thestacktracefield.Fix
_setup_asyncio_json_exception_handler()that sets the handler on the running event loopproxy_startup_eventafter uvicorn's event loop is createdexception.__traceback__and include it in JSON output viaexc_infoPre-Submission checklist
tests/litellm/directory