Using Context Managers (with
/async with
)
The langwatch.trace()
and langwatch.span()
functions can be used directly as asynchronous (async with
) or synchronous (with
) context managers. This is the recommended approach for manual instrumentation as it automatically handles ending the trace/span, even if errors occur.
Here’s how you can achieve the same instrumentation as the decorator examples, but using context managers:
- Use
with langwatch.trace(...)
orasync with langwatch.trace(...)
to start a trace. - Use
with langwatch.span(...)
orasync with langwatch.span(...)
inside a trace block to create nested spans. - The trace or span object is available in the
as trace:
oras span:
part of thewith
statement. - Use methods like
span.add_event()
, and primarilyspan.update(...)
/trace.update(...)
to add details. Theupdate()
method is flexible for adding structured data likeinput
,output
,metadata
, andcontexts
. - This approach gives explicit control over the start and end of each instrumented block, as the context manager handles ending the span automatically.
Direct Span Creation (span.end()
)
Alternatively, you can manage span and trace lifecycles completely manually. Call langwatch.span()
or langwatch.trace()
directly to start them, and then explicitly call the end()
method on the returned object (span.end()
or trace.end()
) when the operation finishes. This requires careful handling to ensure end()
is always called, even if errors occur (e.g., using try...finally
). Context managers are generally preferred as they handle this automatically.