[Bug]: export stable fallback synthetic roots, including before suspension
Los mantenedores suelen responder en 1 día
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
- Área
- observability
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
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:
- Resolver creates the synthetic context.
- Execution plugin exports Workflow under the wrapped ancestor.
- Invocation plugin exports Workflow under the same ancestor.
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.
- Install a real OpenTelemetry SDK provider with an in-memory exporter and an always-on sampler.
- 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=0suppressing the spans under test. - Drive one execution through invocation start and terminal success with
ExecutionOtelPlugin; flush and inspect the exported spans. - Derive the expected synthetic execution-root span ID from the execution ARN. Inspect the
Workflowparent ID and search the exporter output for a span with that ID. - The source predicts that
Workflowreferences the synthetic parent, but no corresponding root span was exported. Repeat independently withInvocationOtelPlugin, then with terminal failure. - 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 onWorkflow. 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 asfaas.instancemay 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 aWorkflowwithout 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.
Workflowretains execution duration and terminal outcome;PENDINGand retry statuses remain non-terminal and do not prematurely export a completedWorkflow. - 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_SAMPLEDdecisions 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
- Equivalent JS defect and executed reproducer: https://github.com/aws/aws-durable-execution-sdk-js/issues/934
- JS implementation proposal (currently open): https://github.com/aws/aws-durable-execution-sdk-js/pull/935
- Synthetic-root lifecycle requirements: https://github.com/aws/aws-durable-execution-sdk-js/issues/938
- Lifecycle design discussion (timestamps, re-exports, resources, sampling): https://github.com/aws/aws-durable-execution-sdk-js/issues/938#issuecomment-5960529508
- Companion Python issue: https://github.com/aws/aws-durable-execution-sdk-python/issues/748
- Existing shared topology contract: https://github.com/aws/aws-durable-execution-conformance-tests/issues/99
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
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de aws/aws-durable-execution-sdk-java
-
documentation pkg:sdk
Dificultad 1/5 1-3 horas Aptitud para principiantes 88/100
aws/aws-durable-execution-sdk-java#645 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
aws/aws-durable-execution-sdk-java#300 ·
Los mantenedores suelen responder en 1 día
-
enhancement needs-triage
Dificultad 5/5 Más de una semana Aptitud para principiantes 35/100
aws/aws-durable-execution-sdk-java#779 ·
Los mantenedores suelen responder en 1 día
-
[Bug]: root handler instrumentation misses the canonical OTel execution contextPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abiertoneeds-triage
Dificultad 5/5 Más de una semana Aptitud para principiantes 40/100
aws/aws-durable-execution-sdk-java#770 ·
Los mantenedores suelen responder en 1 día
-
[Feature]: Propagate per-operation trace context for chained invokesPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abiertoenhancement needs-triage
Dificultad 5/5 Más de una semana Aptitud para principiantes 38/100
aws/aws-durable-execution-sdk-java#764 ·
Los mantenedores suelen responder en 1 día
Todos los issues de aws/aws-durable-execution-sdk-java
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 86/100
-
Make branch and label autocomplete matching locale-independentPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 83/100
jenkinsci/gitlab-plugin#1950 ·
-
It's not necessary to copy the memory block in the readWrite() of org.h2.store.fs.mem.FileMemDataAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
h2database/h2database#4435 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
micronaut-projects/micronaut-core#13717 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
ADORSYS-GIS/token-status-link#145 ·
Los mantenedores suelen responder en 3 días