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
Step 3 of PR-C.3.
Renames ``_handle_started`` → ``_open_started_span`` and bakes
idempotency into it: a short-circuit at the top returns early if
a span already exists for the event's ``_StackKey``. That covers
the common case where ``prepare_sync`` opened the span
synchronously in the engine task and the async ``__call__`` later
re-fires for the same event — the second call becomes a true
no-op rather than opening a duplicate span. Observer-attached-late
and test paths that bypass ``prepare_sync`` still get the span
opened via ``__call__``'s fall-through.
Adds the public ``prepare_sync(event)`` method. Routing-gated
(only ``"started"``-phase non-LLM events qualify), it calls
``_open_started_span`` and then publishes the just-opened span via
``_set_active_observer_span``. The engine's ``innermost`` reads
the ContextVar in step 4 to attach the span into the OTel context
so logs emitted from inside the node body — even on the first
line, before any ``await`` — pick up the right trace_id/span_id
via the OTel ``LoggingHandler``.
The Token returned by ``_set_active_observer_span`` is discarded
on purpose: last-writer-wins is the documented contract — the
next ``prepare_sync`` call overwrites, and the task-local context
dies with the invocation task.
0 commit comments