Skip to content

[otel] Scope deterministic trace IDs without replacing provider-wide generation #625

Description

@zhongkechen

Summary

The Java OTel plugin installs DeterministicIdGenerator as the ID generator for an entire SdkTracerProvider.

This includes:

  • Plugin-owned OTLP providers.
  • Providers built from caller-supplied SdkTracerProviderBuilder instances.
  • The Java agent/global provider through OtelPluginAutoConfigurationCustomizerProvider.

The generator stores the current durable execution trace ID in shared mutable state and JVM system properties. Once an invocation sets that state, every unrelated root span created through the same provider can receive the durable execution trace ID.

Evidence

  • otel-plugin/src/main/java/software/amazon/lambda/durable/otel/OtelPluginAutoConfigurationCustomizerProvider.java installs one static DeterministicIdGenerator on the auto-configured provider.
  • otel-plugin/src/main/java/software/amazon/lambda/durable/otel/OtelPluginSupport.java::buildAutoOtlpProvider calls setIdGenerator(idGenerator) on the provider builder.
  • The explicit-provider constructors in ExecutionOtelPlugin and InvocationOtelPlugin also call setIdGenerator(idGenerator).
  • DeterministicIdGenerator.generateTraceId() returns the cached extracted or ARN-derived durable trace ID for every root span request.
  • The trace ID is also shared through JVM system properties.
  • Invocation cleanup does not clear the durable execution ARN or restore provider ID generation.

OpenTelemetry requirements

The Trace API defines a trace as having a single root span. Creating a span without a parent starts a new trace and requires generation of a new trace ID:

https://opentelemetry.io/docs/specs/otel/trace/api/#span-creation

The SDK permits custom ID generators, but they are provider-level configuration and generated trace IDs must preserve the required uniqueness characteristics:

https://opentelemetry.io/docs/specs/otel/trace/sdk/#id-generators

Impact

  • Unrelated root spans can be merged into the current durable execution trace.
  • One trace can contain multiple unrelated roots.
  • Installing the Java agent extension changes ID generation for every instrumentation library using the global provider.
  • Concurrent invocations or plugin instances can overwrite shared trace-ID state.
  • Sampling and trace visualization can become misleading.

Acceptance criteria

  • Durable deterministic ID selection is scoped to spans created for the durable execution.
  • The plugin does not change trace-ID generation for unrelated instrumentation scopes.
  • An unrelated root span receives a fresh trace ID before, during, and after a durable invocation.
  • Concurrent plugin instances and executions cannot overwrite one another's trace-ID state.
  • Java agent/global, explicit-provider, and auto-provider modes are covered by tests.
  • Stable cross-invocation workflow and operation correlation is preserved.

Related cross-SDK issue: aws/aws-durable-execution-sdk-python#644

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

Status
In progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions