Skip to content

feat: add otel logger injection#427

Open
wangyb-A wants to merge 1 commit into
mainfrom
otel_logger
Open

feat: add otel logger injection#427
wangyb-A wants to merge 1 commit into
mainfrom
otel_logger

Conversation

@wangyb-A

@wangyb-A wangyb-A commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Issue #, if available: #

Description

  • Add a wrap_logger hook to DurableInstrumentationPlugin and chain it in PluginExecutor.wrap_logger.
  • Wire logger wrapping into DurableContext.set_logger, and trigger it once on the root context in durable_execution. Child contexts inherit the already-wrapped logger; wrapping is idempotent.
  • New OtelEnrichedLogger that injects the active span context into each log extra.
  • Plugin resolves the correct span via get_current_span_context: the active operation span inside a step/child context, the enclosing operation span between steps, and the invocation span (from the registry) at the top level.
  • on_user_function_end now restores the enclosing operation span (parent_id) rather than always the invocation span, so between-step logs inside a child context correlate to that child context.

Testing

  • Unit test
  • Example logging:
// Top level → invocation span
{
  "level": "INFO", "message": "Workflow started", "logger": "root",
  "otel.trace_id": "6a288a880695a2d879ef07517e60531b",
  "otel.span_id":  "bbe5fdb86682dac4",
  "otel.trace_sampled": true
}

// Inside top-level step "top-greet" → step span
{
  "level": "INFO", "message": "Greeting inside step", "logger": "root",
  "operationName": "top-greet", "attempt": 1, "greeting_name": "world",
  "otel.trace_id": "6a288a880695a2d879ef07517e60531b",
  "otel.span_id":  "796a9b22593b6959",
  "otel.trace_sampled": true
}

// Inside child context (between steps) → child-context span
{
  "level": "INFO", "message": "Entering child context", "logger": "root",
  "parentId": "c5faca15...3947e6",
  "otel.trace_id": "6a288a880695a2d879ef07517e60531b",
  "otel.span_id":  "be02ea8c17bd3715",
  "otel.trace_sampled": true
}

// Inside nested step "child-greet" → nested step span
{
  "level": "INFO", "message": "Greeting inside step", "logger": "root",
  "operationName": "child-greet", "attempt": 1, "greeting_name": "nested",
  "otel.trace_id": "6a288a880695a2d879ef07517e60531b",
  "otel.span_id":  "67fdcf54688f3644",
  "otel.trace_sampled": true
}

Comment on lines +157 to +160
2. The invocation span from the plugin registry. This is the path used
for top-level handler code: the invocation span is never attached to
the worker thread's context, so the registry is the only way to
resolve it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, on_invocation_start is running on main thread (instead of worker thread). So, even if we attach the span to the context, it's invisible for worker thread.

@wangyb-A wangyb-A marked this pull request as ready for review June 10, 2026 00:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant