Skip to content

feat(otel): add no-arg InvocationOtelPlugin constructor with ADOT Java agent SPI - #540

Merged
ayushiahjolia merged 1 commit into
mainfrom
codex/otel-plugin-default-constructor
Jul 30, 2026
Merged

feat(otel): add no-arg InvocationOtelPlugin constructor with ADOT Java agent SPI#540
ayushiahjolia merged 1 commit into
mainfrom
codex/otel-plugin-default-constructor

Conversation

@zhongkechen

@zhongkechen zhongkechen commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

#541

Summary

  • Add new InvocationOtelPlugin() for ADOT Java agent usage without handler-side GlobalOpenTelemetry initialization.
  • Register OtelPluginAutoConfigurationCustomizerProvider through the OpenTelemetry Java agent autoconfigure SPI so the agent-created SdkTracerProviderBuilder gets the durable deterministic IdGenerator before the provider is built.
  • Make InvocationOtelPlugin() validate that the SPI ran, then use GlobalOpenTelemetry.getTracerProvider() directly instead of creating, copying, mutating, or reflecting into a provider.
  • Add MDC enrichment with trace_id/span_id on the executor thread for log-trace correlation with CloudWatch Application Signals.
  • Switch examples log format from EcsLayout to Log4j2 JsonLayout for proper X-Ray log correlation via requestId.
  • Move the deployed X-Ray Step/Wait examples off the old ADOT collector assumption and onto the same Java-agent extension setup as the default-constructor example.
  • Package the OTel plugin jar into the examples artifact under lib/ and generate SAM config that points OTEL_JAVAAGENT_EXTENSIONS / otel.javaagent.extensions at that jar for examples that use new InvocationOtelPlugin().
  • Update otel-plugin README with ADOT Java agent setup instructions and known X-Ray limitations.

How It Works Now

  • The ADOT Lambda layer starts the Java process through /opt/otel-instrument.
  • The generated template configures the extension path as /var/task/lib/aws-durable-execution-sdk-java-plugin-otel-.jar for no-arg OTel examples.
  • The Java agent loads the plugin jar as an extension and discovers META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider.
  • OtelPluginAutoConfigurationCustomizerProvider installs a shared DeterministicIdGenerator on the agent SDK builder and marks installation through a system property.
  • InvocationOtelPlugin() checks that marker, uses the existing global tracer provider, and keeps a separate DeterministicIdGenerator instance only to publish durable execution state through system properties. The agent-installed generator reads that state when spans are started, which works across the app and agent classloader split.

Logs correlation

  • The plugin injects trace_id into MDC at invocation start (on the executor thread) so all handler-level and step-level logs include it.
  • The core SDK's DurableLogger already injects requestId and executionArn into MDC.
  • Log4j2 JsonLayout with properties="true" outputs all MDC fields as top-level JSON keys.
  • CloudWatch parses the JSON and X-Ray correlates logs via requestId.

Why Not Reflection

  • ADOT exposes Java agent wrapper providers such as ApplicationTracerProvider14, not a stable public SdkTracerProviderBuilder surface.
  • Reflection paths were brittle across OpenTelemetry versions: some wrappers do not expose unobfuscate(), and internal fields such as agentTracerProvider are not consistently visible or typed from the application classloader.
  • Even when an SDK provider can be reached, replacing the ID generator after the provider is already built is not a supported contract and depends on private SDK internals.
  • The SPI runs at the right lifecycle point, before the agent builds the SDK provider, and is the documented OpenTelemetry Java agent extension mechanism.

Known limitations

  • X-Ray ungrouped view: Plugin spans don't nest as subsegments of the Lambda platform segment (OTLP-to-X-Ray conversion limitation). Use "Group by nodes" view.
  • Workflow span: Appears as a separate root segment (expected - setNoParent() with deterministic ID for cross-invocation correlation).

Testing

  • mvn clean install
  • Verified on Lambda with ADOT layer: traces, spans, and log correlation all working
  • Verified non-otel examples still produce correct log output with JsonLayout

@zhongkechen
zhongkechen requested a review from a team July 14, 2026 00:21

@SilanHe SilanHe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We'll have to add an integration test example where we use the optimized ADOT layer so that we can ensure this is working

Comment thread otel-plugin/README.md Outdated
@ayushiahjolia
ayushiahjolia force-pushed the codex/otel-plugin-default-constructor branch from d77c980 to d439811 Compare July 30, 2026 19:46
@ayushiahjolia
ayushiahjolia had a problem deploying to ai-pr-review-runtime July 30, 2026 19:46 — with GitHub Actions Failure
@ayushiahjolia
ayushiahjolia had a problem deploying to ai-pr-review-runtime July 30, 2026 19:46 — with GitHub Actions Failure
@ayushiahjolia
ayushiahjolia force-pushed the codex/otel-plugin-default-constructor branch 2 times, most recently from 33401b8 to 34cfd1c Compare July 30, 2026 20:04
@ayushiahjolia
ayushiahjolia self-requested a review July 30, 2026 20:09
@ayushiahjolia ayushiahjolia changed the title Add default constructor support for OTel plugin feat(otel): add no-arg InvocationOtelPlugin constructor with ADOT Java agent SPI Jul 30, 2026
@ayushiahjolia
ayushiahjolia had a problem deploying to ai-pr-review-runtime July 30, 2026 20:20 — with GitHub Actions Failure
@ayushiahjolia
ayushiahjolia had a problem deploying to ai-pr-review-runtime July 30, 2026 20:20 — with GitHub Actions Failure
@ayushiahjolia
ayushiahjolia force-pushed the codex/otel-plugin-default-constructor branch from 34cfd1c to 59b9945 Compare July 30, 2026 20:35
@ayushiahjolia
ayushiahjolia had a problem deploying to ai-pr-review-runtime July 30, 2026 20:42 — with GitHub Actions Failure
@ayushiahjolia
ayushiahjolia had a problem deploying to ai-pr-review-runtime July 30, 2026 20:42 — with GitHub Actions Failure

@SilanHe SilanHe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As follow up, can we add a constructor where we also create a tracerProvider and idGenerator? this would be the case where we're using the ocmmunity collector layer + the plugin. It allows for less code to write for customers in that case.

@ayushiahjolia
ayushiahjolia merged commit 570a195 into main Jul 30, 2026
49 of 57 checks passed
@ayushiahjolia
ayushiahjolia deleted the codex/otel-plugin-default-constructor branch July 30, 2026 23:26
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.

3 participants