Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

[Bug]: export stable fallback synthetic roots, including before suspension

Abierto
#756 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

@zhongkechen ya está trabajando en esto.

Desde el 2/10/2026.

  • #767 de @zhongkechen — abierto

Evaluación

Dificultad
5/5
Tiempo estimado
Más de una semana
Aptitud para principiantes
35/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Activo
Stack tecnológico
java

Línea de trabajo

Start with ExecutionTraceContext.java and the terminal export paths in ExecutionOtelPlugin.java and InvocationOtelPlugin.java, then compare the equivalent JavaScript issue and shared topology contract. Build the described in-memory-exporter scenarios for fallback and propagated contexts, including sampling, retries, and shared trace IDs. Done means both plugin views preserve identity and sampling while producing connected exports without conflicting roots.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

bug pkg:otel
Scope

This issue covers both related JavaScript problems for the Java OTel plugins:

  • JS #934: the SDK-created fallback ancestor is never exported.
  • JS #938: exporting that ancestor only at terminal completion leaves executions stopped or timed out while suspended without an exported root.

Both the missing span and its export lifecycle are in scope.

Expected Behavior

A sampled execution using an SDK-created fallback ancestor should have a connected exported trace hierarchy. The SDK must export the ancestor it invents, including during the first invocation before it returns or suspends, so the ancestor remains available if the execution is later stopped or times out without a terminal invocation.

The synthetic root should be a stable anchor. Workflow continues to carry execution duration and terminal outcome. Preserve complete propagated-parent behavior, deterministic operation/workflow identity, and upstream sampling decisions. The lifecycle requirements below cover stable timestamps, missing timestamp metadata, repeated exports, and multiple executions sharing one trace ID.

Actual Behavior

When no complete remote parent can be constructed, ExecutionTraceContext.resolve creates a SpanContext with generateExecutionRootSpanId(arn). The plugins use this context as their execution ancestor, but neither creates a recording span with that synthetic root ID.

At terminal completion, both ExecutionOtelPlugin and InvocationOtelPlugin create Workflow with Span.wrap(executionAncestor) as its parent. Span.wrap supplies a non-recording parent context. In the no-ambient fallback case, Invocation also points to the synthetic ancestor. Exported descendants therefore reference a parent that has no producer and never reaches the exporter, even with sampling enabled and flushes completed.

Immutable source evidence, rechecked on October 1 at d3208f2e759d3c79e84b46f53c2eb11fb7fe4c09:

Steps to Reproduce

This is a source-inspection report. The following plugin-level validation recipe has not been executed for this SDK; the linked JavaScript issue includes an executed runtime reproducer of the equivalent defect.

  1. Install a real OpenTelemetry SDK provider with an in-memory exporter and an always-on sampler.
  2. Run with no ambient span and configure the context extractor to return no usable remote context, so the SDK takes its synthetic fallback path. This also avoids an explicit upstream Sampled=0 suppressing the spans under test.
  3. Drive one execution through invocation start and terminal success with ExecutionOtelPlugin; flush and inspect the exported spans.
  4. Derive the expected synthetic execution-root span ID from the execution ARN. Inspect the Workflow parent ID and search the exporter output for a span with that ID.
  5. The source predicts that Workflow references the synthetic parent, but no corresponding root span was exported. Repeat independently with InvocationOtelPlugin, then with terminal failure.
  6. Repeat with a valid extracted trace ID but no usable parent span ID to exercise fallback on an existing trace.

For the lifecycle case, supply a stable platform execution start timestamp, run the first invocation to suspension, and inspect the exporter before any terminal hook. Then omit further invocations to model a stop or execution timeout while suspended. A terminal-only fix cannot export the missing ancestor in this sequence. Repeat with a first-invocation retry, eventual terminal completion, and missing start timestamp metadata as specified below.

No Lambda account is required for these plugin-level checks. The lifecycle sequence is a validation recipe, not a claim of an executed Java or live Lambda reproduction.

SDK Version

Source inspected on main at d3208f2e759d3c79e84b46f53c2eb11fb7fe4c09. The same pattern was previously identified in Java 2.2.1 source by the cross-SDK investigation in aws/aws-durable-execution-sdk-js#934.

Java Version

Not applicable to the evidence collected: source inspection only; no Java runtime reproduction was executed for this report.

Is this a regression?

Unknown; no previously published working version has been established.

Last Working Version

None identified.

Synthetic Root Lifecycle Requirements

These requirements bring the lifecycle gap in JS #938 into this issue's scope; terminal-only materialization is not sufficient to close it.

  • Early export: Materialize, end, and export the SDK-owned anchor during the first invocation, before that invocation returns, including when it suspends. A stopped or timed-out suspended execution may never run a terminal plugin hook.
  • Stable identity and contents: Keep the root span ID scoped to the execution ARN using generateExecutionRootSpanId(arn). Use only stable execution identity/state for anchor span fields. A zero-duration anchor with both timestamps set to the platform-provided execution start time is the proposed shape; keep duration and terminal status on Workflow. Multiple executions may share a propagated trace ID, but must retain distinct synthetic-root span IDs, even with different start times and provider resources. Do not substitute one trace-scoped synthetic span ID for those execution-owned identities.
  • Missing execution start time: Define and test the fallback when the platform does not supply a stable execution start timestamp. Do not use a fresh wall-clock value and claim the resulting anchor is stable across retries or execution environments. Deferring anchor export to terminal completion is one option; document the remaining suspended-execution gap for that case.
  • Export cadence and retries: Choose and document first-invocation-only export or first-invocation export plus an identical terminal re-export. First-invocation-only export can lose the anchor if that invocation is killed before flushing; terminal re-export can recover it for executions that later complete. If an anchor is exported more than once, all span fields must match, including timestamps, attributes, status, events, and links. Do not also emit a terminal-duration root with the same (traceId, spanId). Document and test resource handling across execution environments: resource attributes such as faas.instance may differ even when span fields match.
  • Sampling across invocations: Explicit upstream sampling decisions remain authoritative. For undecided sampling, use the configured sampler and document the consistency requirement across invocations, such as a deterministic policy based on trace ID. Independently re-evaluating a non-deterministic sampler can export an anchor without a Workflow, or a Workflow without its anchor.
Acceptance Criteria

Use a real OpenTelemetry provider and in-memory exporter, and run the relevant cases independently for both ExecutionOtelPlugin and InvocationOtelPlugin:

  • Sampled fallback executions have a connected exported hierarchy after terminal success and failure. Cover absent/invalid extracted context and a valid trace ID without a usable parent span ID.
  • With a stable execution start timestamp, the first invocation exports the anchor before returning, for both immediate completion and suspension. For suspension, inspect exports before any terminal invocation.
  • After suspension, simulating stop or execution timeout by omitting subsequent invocations still leaves the already-exported anchor available. This must not require a terminal plugin hook.
  • Wait/resume and retries preserve canonical trace identity, deterministic operation/workflow span IDs, and links. Workflow retains execution duration and terminal outcome; PENDING and retry statuses remain non-terminal and do not prematurely export a completed Workflow.
  • Retrying the first invocation and reaching terminal completion follow the documented export cadence, without differing span fields for the same anchor identity. Cover loss of the first invocation's flush and re-export from a different execution environment according to the chosen policy, including its resource limitations.
  • A missing platform execution start timestamp follows the documented fallback and does not create conflicting copies based on per-invocation wall-clock values.
  • Two executions sharing one propagated trace ID, with different start times and provider resources, retain distinct ARN-scoped synthetic-root IDs; descendants attach to the correct execution's anchor.
  • Preserve explicit sampled/NOT_SAMPLED decisions and configured sampling for undecided context across invocations. Unsampled executions emit no stray synthetic root; document the stable-sampling requirement.
  • Complete propagated remote parents retain their existing behavior. Do not manufacture replacement spans for externally owned parents.
Additional Context

Coordinate the fallback behavior and language-neutral conformance coverage across SDKs through the existing shared topology issue. The chained-invoke parent propagation gap is a separate work item; this issue concerns a parent created by the SDK itself.

Lenguaje dominante
Java
Estrellas
28
Forks
13
Merge medio
2 d 3 h
PR fusionados (30 d)
44

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de aws/aws-durable-execution-sdk-java

Todos los issues de aws/aws-durable-execution-sdk-java

Issues similares

Más issues de Java

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.