You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
instrument treats an async method behind a sync decorator as sync #2933
If an async def sits under a plain functools.wraps decorator, @instrument wraps it as a sync function. The span ends as soon as the coroutine object is returned (about 0.1 ms), the record output is <coroutine object ...>, and instrumented calls made while it runs start their own records and lose their span type. OpenAI's AsyncCompletions.create is shaped like this.
Confirmed on main @ 5eaf76ba. With the functools.wraps passthrough decorator, instrument falls back to the sync wrapper: the run emits 2 record events instead of 1, the record output is <coroutine object _App.query ...>, and TruSession logs "Could not determine main output of query from coroutine value ...". The span also ends when the coroutine is returned rather than when the awaited work finishes.
The cause is that the async detection at src/core/trulens/core/otel/instrument.py:~703 does not unwrap __wrapped__ before deciding between async_wrapper and sync_wrapper. Unwrapping first (or using inspect.iscoroutinefunction on the unwrapped function, e.g. via functools.unwrap) fixes it for the plain-wraps shape.
Activity
feiiiiii5 commentedon Oct 8, 2026
Confirmed on
main@5eaf76ba. With thefunctools.wrapspassthrough decorator,instrumentfalls back to the sync wrapper: the run emits 2 record events instead of 1, the record output is<coroutine object _App.query ...>, and TruSession logs "Could not determine main output of query from coroutine value ...". The span also ends when the coroutine is returned rather than when the awaited work finishes.The cause is that the async detection at
src/core/trulens/core/otel/instrument.py:~703does not unwrap__wrapped__before deciding betweenasync_wrapperandsync_wrapper. Unwrapping first (or usinginspect.iscoroutinefunctionon the unwrapped function, e.g. viafunctools.unwrap) fixes it for the plain-wrapsshape.feiiiiii5 commentedon Oct 8, 2026
Follow-up: handled in open PR #2934.