Skip to content

[reactor-optional] Implement trace context propagation without hard dependency on Reactor - #3708

Merged
atakavci merged 9 commits into
redis:feature/reactor-optional-1from
atakavci:ali/reactor-optional-tracing
Apr 24, 2026
Merged

[reactor-optional] Implement trace context propagation without hard dependency on Reactor#3708
atakavci merged 9 commits into
redis:feature/reactor-optional-1from
atakavci:ali/reactor-optional-tracing

Conversation

@atakavci

@atakavci atakavci commented Mar 30, 2026

Copy link
Copy Markdown
Collaborator

Introduces a new getTraceContextAsync method on TraceContextProvider that accepts a plain Map<Object, Object> instead of relying on Reactor's Mono-based deferred resolution. This removes the hard dependency on Reactor from the TraceContextProvider interface while still supporting trace context propagation in reactive command flows. A lightweight ContextViewMapAdapter bridges Reactor's ContextView to the Map interface at the call site.

Changes

  • TraceContextProvider – Added getTraceContextAsync(Map<Object, Object>) default method that returns a Supplier<TraceContext>. Deprecated the existing getTraceContextLater() method.
  • BraveTracing – Implemented getTraceContextAsync to look up Span or TraceContext from the provided map, intentionally skipping ThreadLocal fallback in async contexts.
  • MicrometerTracing – Implemented getTraceContextAsync to look up Observation, TraceContext, or ObservationThreadLocalAccessor.KEY from the provided map, with the same ThreadLocal-skip policy.
  • AbstractRedisReactiveCommands – Added ContextViewMapAdapter (a read-only AbstractMap backed by Reactor's ContextView) and replaced withTraceContext() with an implementation that uses deferContextual + getTraceContextAsync for non-blocking trace context resolution.

Note

Medium Risk
Changes how reactive tracing context is resolved and propagated (new async context API and updated withTraceContext()), which can affect span parentage/trace continuity across reactive flows. Scope is contained to tracing integration, with new integration tests reducing regression risk.

Overview
Updates trace-context propagation to avoid a hard Reactor dependency by introducing TraceContextProvider#getTraceContextAsync(Map) (returning a Supplier<TraceContext>) and deprecating getTraceContextLater().

Reactive command tracing now resolves parent context via Reactor ContextView using a lightweight ContextViewMapAdapter, calling getTraceContextAsync during deferContextual in AbstractRedisReactiveCommands#withTraceContext().

Adds async-context implementations for Brave and Micrometer providers (explicitly not falling back to ThreadLocals when an async context map is present), plus new integration tests covering async (connection.async()) and reactive (contextWrite) tracing flows and verifying emitted spans/tags and parent/trace IDs.

Reviewed by Cursor Bugbot for commit 208dbb9. Bugbot is set up for automated code reviews on this repo. Configure here.

…thout hard dependency to reactor in tracexontextprovider

Copilot AI 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.

Pull request overview

This PR refactors reactive trace-context propagation to avoid relying on Reactor ContextView/Mono-based resolution at the TraceContextProvider call site by introducing a Map-based async context lookup and adapting Reactor context to that interface.

Changes:

  • Add TraceContextProvider.getTraceContextAsync(Map<Object, Object>) (returns Supplier<TraceContext>) and deprecate getTraceContextLater().
  • Implement getTraceContextAsync for Brave and Micrometer tracing providers to resolve trace context from the provided map (with deliberate no-ThreadLocal fallback when async context is present).
  • Update reactive command tracing (AbstractRedisReactiveCommands.withTraceContext) to resolve trace context via deferContextual + ContextViewMapAdapter.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 7 comments.

File Description
src/main/java/io/lettuce/core/tracing/TraceContextProvider.java Introduces Map-based async context lookup API and deprecates Reactor-Mono method.
src/main/java/io/lettuce/core/tracing/BraveTracing.java Adds getTraceContextAsync implementation for Brave context lookup.
src/main/java/io/lettuce/core/tracing/MicrometerTracing.java Adds getTraceContextAsync implementation for Micrometer context lookup.
src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java Adapts Reactor ContextView to Map and switches reactive trace context resolution to the new API.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/main/java/io/lettuce/core/tracing/MicrometerTracing.java
Comment thread src/main/java/io/lettuce/core/tracing/TraceContextProvider.java
Comment thread src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java
Comment thread src/main/java/io/lettuce/core/tracing/MicrometerTracing.java Outdated
Comment thread src/main/java/io/lettuce/core/tracing/BraveTracing.java Outdated
Comment thread src/main/java/io/lettuce/core/tracing/MicrometerTracing.java
Comment thread src/main/java/io/lettuce/core/tracing/BraveTracing.java

@tishun tishun left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

Comment thread src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java

@a-TODO-rov a-TODO-rov left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The approach LGTM - this is the way !
I think we should follow the same approach on all public APIs, directly exposing reactive - simple plain java foundation (async based) for the reactive implementation to adapt.
Minor comments to become production ready:

  • javadoc
  • tests

Comment thread src/main/java/io/lettuce/core/tracing/TraceContextProvider.java
Comment thread src/main/java/io/lettuce/core/tracing/TraceContextProvider.java
Comment thread src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java
Comment thread src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java

@a-TODO-rov a-TODO-rov left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@atakavci
atakavci changed the base branch from main to feature/reactor-optional-1 April 24, 2026 10:45
Comment thread src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 76aeb15. Configure here.

Comment thread src/main/java/io/lettuce/core/tracing/TraceContextProvider.java
atakavci and others added 2 commits April 24, 2026 14:30
Co-authored-by: Copilot <copilot@github.com>
@atakavci
atakavci merged commit 11ae917 into redis:feature/reactor-optional-1 Apr 24, 2026
18 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: feature A new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants