Skip to content

fix: carry invocation-local X-Ray headers in InvocationInfo - #765

Open
zhongkechen wants to merge 35 commits into
mainfrom
fix/otel-lmi-header-762
Open

zhongkechen wants to merge 35 commits into
mainfrom
fix/otel-lmi-header-762

Conversation

@zhongkechen

@zhongkechen zhongkechen commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Issue Link, if available

Fixes #762. Shared plugin-instance concurrency remains the separate #782 factory migration.

Description

Lambda Managed Instances supplies its X-Ray header through the invocation Context. Capture Context.getXrayTraceId() on the runtime thread before worker dispatch, then carry that immutable snapshot in InvocationInfo.xRayTraceId. Plugin startup stays onInvocationStart(info) and context extraction uses extract(info). Both OTel views preserve the incoming trace, parent and explicit sampling decision.

A missing runtime accessor or inherited neutral Lambda Context default leaves the field null and retains ordinary system-property/environment fallback. An actual runtime override returning null/empty produces an empty field, which is authoritative absence; malformed captured headers likewise cannot borrow another invocation’s process-wide carrier. No global carrier is written. Capture is skipped when no plugins are registered. Non-fatal failures from a present runtime accessor, including assertion and linkage errors, are captured as authoritative absence rather than borrowing a stale process-wide trace or sampling decision. Only a genuinely missing visible API keeps legacy fallback. Direct and recognized transport-wrapped VirtualMachineError/ThreadDeath retain their identity and propagate. Public execution tests cover both sampled and unsampled stale carriers.

The old 4-, 5-, 6- and 7-argument InvocationInfo constructors remain, defaulting the optional field to null. Existing hook overrides and no-argument ContextExtractor lambdas/custom implementations retain their dispatch. The built-in X-Ray extractor preserves old subclass overrides through an extraction-only temporary scope. New plugin layers narrowly handle an older core that lacks the optional accessor, retaining existing tracing without raising provider/dependency floors.

Record compatibility boundary: InvocationInfo now has eight record components. Existing constructor source, compiled constructors/accessors and previously compiled seven-component record patterns remain compatible. Recompiling seven-component record patterns requires an eighth binding. Reflection observes eight components, and record equality/hash calculation includes the new header. This is not complete record-shape/source compatibility. Checkpoint formats and operation identities are unchanged.

The continuation follow-up prevents READY resumption failures from being lost in unobserved futures. Owned SDK continuation failures select retryable manager control before lease release; callers retain the original cause and persisted operation state remains available for retry. Direct JVM fatals also settle observation before escaping the coordinator. Rejected worker admission rolls back its activity registration, assuming rejection before task acceptance. Normal closing preserves unrelated operations and ordinary unowned helper behavior is unchanged. This repair retains this branch's existing invocation-hook threading, header/sampling behavior and workflow references.

Demo/Screenshots

Not applicable (SDK tracing behavior).

Checklist

  • All PR template sections completed
  • Local validation completed; record-source compatibility boundary documented

Testing

Full Corretto17 mvn -o -B clean verify passes 2,331 tests with zero failures/errors and 33 existing conditional skips. The combined READY/sampler controls pass301 focused tests on Java25, and the required released/current artifact matrix passes16/16. Spotless and diff checks pass. Existing header/record compatibility controls remain enabled; deployed LMI validation remains separate.

Unit Tests

Header authority and fallback; sampled/unsampled propagation; capture before worker dispatch; ordinary one-argument hook delivery; custom no-argument extractor and subclass dispatch; cleanup; source and binary constructor compatibility. Java 21+ compiler checks verify the new eight-component pattern, identify the old pattern’s source incompatibility, and run its previously compiled bytecode against the new record.

Integration Tests

Both OTel views exercise overlapping distinct headers, authoritative absence and durable suspension/resume. The released-package matrix covers old/old, old/new, new/old and new/new core/plugin combinations through a separate layer classloader. Existing runtime-interface controls cover old visible APIs, inherited neutral defaults and actual runtime overrides. These checks do not claim a newly deployed LMI validation.

Examples

README documents the InvocationInfo field, carrier precedence, custom extractor compatibility and the record-pattern migration. The existing failure-only E2E diagnostic step remains unchanged; it gathers bounded logs without weakening test gates.

Readiness and sampling maintenance

READY polling registers before rechecking backend state, retaining executable work and normalized retry state. Attempts yield through the configured executor with an activity reservation through next-worker registration. Cancellation of observation cannot release queued/running work; normal close drains owned continuations before checkpoint shutdown. Three public READY cases failed before this repair while the true-PENDING control passed; the fixed branch also validates direct/submit-and-wait resumption, bounded-pool fairness, close/admission races and stored replay. This independently confirmed defect matches the earlier cloud error class, without claiming a unique cause for that historical execution.

Each SDK-span sampling intent is consumed before synchronous processors can reuse it. Same-copy samplers retain the full context carrier; foreign samplers resolve complete attributes and TraceState in their own loader. Deferred cache keys include execution ARN and canonical trace ID, retaining the existing256-entry LRU bound; eviction can cause reevaluation. Visible replacement samplers receive no unconsumable thread bridge. Actual per-branch public probes reproduced eight failures before these sampling fixes; local/foreign/opaque controls now pass.

The native-parent clock repair and the exact20-case test reference remain. The reusable workflow's published1768 interface preserves all gates and adds bounded retries for actual read-only GetLayer throttles. Runtime-header capture, its explicit record compatibility boundary, factory APIs and invocation lifecycle are preserved by these maintenance changes.

Current continuation validation

Full Java17 clean verify: 2,357 tests, zero failures/errors, 33 conditional skips. The owned continuation repair passes 66 focused Java25 controls and all 16 artifact compatibility cases. Eight public controls failed on this branch before the repair (six hidden-failure assertions and two bounded rejection timeouts); they now verify caller/cause identity, End status, worker fatal escape, activity cleanup and subsequent successful resumption. The two record-pattern cases skipped on Java17 were exercised successfully on Java25. Existing lifecycle and telemetry source outside the continuation/admission repair remains unchanged. Fresh CI, including pending core conformance workflows, is tracked separately.

Legacy outcome observer wakeup

A legacy End callback can execute synchronously inside continuation-failure publication. It now wakes waiters for the already-selected control before End can wait for handler cleanup, retaining the existing callback thread. An identity registry tracks active published controls, so a losing CompletableFuture publisher that drains the winner callback still wakes the winner cause. Exact entries are removed in finally; normal outcome diagnostics and threading remain unchanged. No scheduler handoff or timeout fallback is added.

Full Java17 verification passed 2,376 tests (zero failures/errors, 33 conditional skips), 85 focused Java25 controls and all 16 artifact compatibility cases. Fifteen public controls cover asynchronous, inline-root and submit-and-wait root dispatch with asynchronous children; ordinary/fatal/rejected continuations, cooperative End/finally ordering, replay, and unchanged normal End threads. Four of those controls fail on the published baseline. Two deterministic winner/loser cases fail with a thread-keyed candidate and pass with selected-control identity; cleanup/reentry controls also pass. Current-head cloud CI is tracked separately.

@zhongkechen
zhongkechen requested a review from a team October 2, 2026 20:38
@zhongkechen
zhongkechen deployed to ai-pr-review-runtime October 2, 2026 20:38 — with GitHub Actions Active
@zhongkechen
zhongkechen deployed to ai-pr-review-runtime October 2, 2026 20:39 — with GitHub Actions Active
@github-actions

This comment has been minimized.

@zhongkechen
zhongkechen deployed to ai-pr-review-runtime October 2, 2026 20:51 — with GitHub Actions Active
@github-actions

This comment has been minimized.

@zhongkechen
zhongkechen deployed to ai-pr-review-runtime October 2, 2026 21:21 — with GitHub Actions Active
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@zhongkechen zhongkechen changed the title fix(otel): preserve invocation-local X-Ray headers fix: use invocation-local Lambda X-Ray headers Oct 3, 2026
@zhongkechen
zhongkechen deployed to ai-pr-review-runtime October 3, 2026 06:15 — with GitHub Actions Active
@github-actions

This comment has been minimized.

@zhongkechen zhongkechen changed the title fix: use invocation-local Lambda X-Ray headers fix: carry invocation-local X-Ray headers in InvocationInfo Oct 5, 2026
@zhongkechen
zhongkechen had a problem deploying to ai-pr-review-runtime October 5, 2026 23:27 — with GitHub Actions Failure
@zhongkechen
zhongkechen deployed to ai-pr-review-runtime October 6, 2026 00:01 — with GitHub Actions Active
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@zhongkechen
zhongkechen deployed to ai-pr-review-runtime October 8, 2026 18:22 — with GitHub Actions Active
@Experimental Map<String, OperationChangeItemInfo> operations,
@Experimental Map<String, OperationChangeItemInfo> updatedOperations) {
@Experimental Map<String, OperationChangeItemInfo> updatedOperations,
String xRayTraceId) {

This comment was marked as outdated.

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.

That source/record-shape compatibility limit is real and is explicitly documented in this PR and the README. This change intentionally uses an eighth immutable record component while retaining the old 4/5/6/7-argument constructors and accessors; it does not claim that preserving constructors preserves record patterns, reflection, equality or hashing. A seven-component source pattern must be updated when recompiled.

InvocationInfoCompatibilityTest separately compiles the legacy API shape and callers, verifies retained constructor linkage and old compiled-pattern behavior, proves that recompiling the seven-component pattern against this shape fails, and checks the eight-component pattern/reflection on Java25. All three controls passed in the current validation. Checkpoint formats remain unchanged. The chosen documented record boundary is retained rather than adding another hook overload or a process-wide metadata carrier.

@github-actions

This comment has been minimized.

@zhongkechen
zhongkechen deployed to ai-pr-review-runtime October 8, 2026 21:29 — with GitHub Actions Active
@Experimental Map<String, OperationChangeItemInfo> operations,
@Experimental Map<String, OperationChangeItemInfo> updatedOperations) {
@Experimental Map<String, OperationChangeItemInfo> updatedOperations,
String xRayTraceId) {

This comment was marked as outdated.

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.

The seven-component source-pattern break and changed reflection/equality/hash semantics are acknowledged in the explicit record compatibility boundary in the README and PR description. This is not described as complete record-shape compatibility. Existing constructor/accessor callers remain supported; recompiling a record pattern requires the eighth binding.

The three InvocationInfoCompatibilityTest compiler/reflection controls passed on Java25, including the expected seven-pattern source rejection and retained old compiled-pattern execution. This change keeps the documented immutable header component and existing hook signature; it does not introduce a second hook or mutable metadata channel.

@github-actions

This comment has been minimized.

@zhongkechen
zhongkechen deployed to ai-pr-review-runtime October 8, 2026 22:47 — with GitHub Actions Active
@Experimental Map<String, OperationChangeItemInfo> operations,
@Experimental Map<String, OperationChangeItemInfo> updatedOperations) {
@Experimental Map<String, OperationChangeItemInfo> updatedOperations,
String xRayTraceId) {

This comment was marked as outdated.

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.

The compatibility impact is real and is the explicit record-shape boundary documented in InvocationInfo: the nullable runtime header is the eighth component, old constructors remain, and record patterns/reflection/value semantics observe the new field. Constructor/binary compatibility is not a claim that seven-component source patterns still compile unchanged. The retained Java25 source-shape and installed-artifact controls cover these distinct contracts. The detailed disposition and migration explanation is #765 (comment) . This PR intentionally retains that documented representation; a separate hook/metadata design would be a different API choice.

@github-actions

This comment has been minimized.

@zhongkechen zhongkechen mentioned this pull request Oct 8, 2026
3 of 7 tasks
@zhongkechen
zhongkechen deployed to ai-pr-review-runtime October 9, 2026 00:09 — with GitHub Actions Active
@Experimental Map<String, OperationChangeItemInfo> operations,
@Experimental Map<String, OperationChangeItemInfo> updatedOperations) {
@Experimental Map<String, OperationChangeItemInfo> updatedOperations,
String xRayTraceId) {

This comment was marked as outdated.

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.

The compatibility impact is real and is the explicit record-shape boundary documented in InvocationInfo: the nullable runtime header is the eighth component, old constructors remain, and record patterns/reflection/value semantics observe the new field. Constructor/binary compatibility is not a claim that seven-component source patterns still compile unchanged. The retained Java25 source-shape and installed-artifact controls cover these distinct contracts. The detailed disposition and migration explanation is #765 (comment) . This PR intentionally retains that documented representation; a separate hook/metadata design would be a different API choice.

@github-actions

This comment has been minimized.

@zhongkechen
zhongkechen deployed to ai-pr-review-runtime October 9, 2026 01:33 — with GitHub Actions Active
CompletableFuture<Void> completion) {
try {
try {
if (!isClosing()) continuation.run();

This comment was marked as outdated.

@Experimental Map<String, OperationChangeItemInfo> operations,
@Experimental Map<String, OperationChangeItemInfo> updatedOperations) {
@Experimental Map<String, OperationChangeItemInfo> updatedOperations,
String xRayTraceId) {

This comment was marked as outdated.

Comment on lines +770 to +774
activeThreads.wait();
} catch (InterruptedException interrupted) {
Thread.currentThread().interrupt();
throw new IllegalStateException(
"Interrupted while waiting for checkpoint continuations", interrupted);

This comment was marked as outdated.

@github-actions

This comment has been minimized.

@zhongkechen
zhongkechen deployed to ai-pr-review-runtime October 9, 2026 02:12 — with GitHub Actions Active
@Experimental Map<String, OperationChangeItemInfo> operations,
@Experimental Map<String, OperationChangeItemInfo> updatedOperations) {
@Experimental Map<String, OperationChangeItemInfo> updatedOperations,
String xRayTraceId) {

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.

Codex AI review · Finding arf_v1_gllxxbgubf2bn2fv2ypdxga6v2

[P2] Adding an eighth record component breaks recompilation of seven-component record patterns and changes reflection, equality, and hashing contracts. Retaining constructors does not preserve these public APIs. Keep the record at seven components and pass the header through separate immutable metadata, such as a new default plugin-hook overload delegating to the existing hook.

Comment on lines +771 to +774
} catch (InterruptedException interrupted) {
Thread.currentThread().interrupt();
throw new IllegalStateException(
"Interrupted while waiting for checkpoint continuations", interrupted);

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.

Codex AI review · Finding arf_v1_i4lbxzcmfbb7c3bcctwksulmfn

[P2] An interrupted close exits while continuation registrations remain and skips validateRunningThreads() and checkpointManager.shutdown(), allowing queued work and delayed backend requests to outlive invocation cleanup. Continue draining and shut down the checkpoint manager before restoring or propagating interruption, and add an interrupted-close regression test.

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Codex AI review

Two P2 findings remain in public API compatibility and continuation teardown.

Reviewed commit f9bba67b5ac08ace2bfcac2ee4e6a5c4ff39c85b. Workflow run

This branch was successfully deployed

1 active deployment
ai-pr-review-runtime — f9bba67b Deployed Oct 9, 2026 by zhongkechen via ai-pr-review / Codex review / Generate Codex review #2042
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.

[Bug]: OTel ignores the invocation-local X-Ray header on Lambda Managed Instances

1 participant