Skip to content

Commit 7c7e4c2

Browse files
committed
Construct LettuceObservationContext with parent observation
After this commit, LettuceObservationContext.setParentObservation() is called right after Context rather than Observation created, then Context.getParentObservation() could be used in ObservationPredicate to determine whether Observation should be created. Fix spring-projectsGH-2591
1 parent aea748d commit 7c7e4c2

File tree

3 files changed

+27
-12
lines changed

3 files changed

+27
-12
lines changed

Diff for: src/main/java/org/springframework/data/redis/connection/lettuce/observability/MicrometerTracingAdapter.java

+13-12
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
* arguments will be captured in traces including these that may contain sensitive details.
4545
*
4646
* @author Mark Paluch
47+
* @author Yanming Zhou
4748
* @since 3.0
4849
*/
4950
public class MicrometerTracingAdapter implements Tracing {
@@ -121,29 +122,28 @@ public MicrometerTracer(ObservationRegistry observationRegistry) {
121122

122123
@Override
123124
public Tracer.Span nextSpan() {
124-
return this.postProcessSpan(createObservation());
125+
return this.postProcessSpan(createObservation(null));
125126
}
126127

127128
@Override
128129
public Tracer.Span nextSpan(TraceContext traceContext) {
129-
130-
if (traceContext instanceof MicrometerTraceContext micrometerTraceContext) {
131-
132-
return micrometerTraceContext.observation == null ? nextSpan()
133-
: postProcessSpan(createObservation().parentObservation(micrometerTraceContext.observation()));
134-
}
135-
136-
return nextSpan();
130+
return postProcessSpan(createObservation(traceContext));
137131
}
138132

139-
private Observation createObservation() {
133+
private Observation createObservation(@Nullable TraceContext traceContext) {
140134
return RedisObservation.REDIS_COMMAND_OBSERVATION.observation(observationRegistry,
141-
() -> new LettuceObservationContext(serviceName));
135+
() -> {
136+
LettuceObservationContext context = new LettuceObservationContext(serviceName);
137+
if (traceContext instanceof MicrometerTraceContext micrometerTraceContext) {
138+
context.setParentObservation(micrometerTraceContext.observation);
139+
}
140+
return context;
141+
});
142142
}
143143

144144
private Tracer.Span postProcessSpan(Observation observation) {
145145

146-
return observation != null && !observation.isNoop()
146+
return !observation.isNoop()
147147
? new MicrometerSpan(observation.observationConvention(observationConvention))
148148
: NoOpSpan.INSTANCE;
149149
}
@@ -292,6 +292,7 @@ public void finish() {
292292
record MicrometerTraceContextProvider(ObservationRegistry registry) implements TraceContextProvider {
293293

294294
@Override
295+
@Nullable
295296
public TraceContext getTraceContext() {
296297

297298
Observation observation = registry.getCurrentObservation();

Diff for: src/test/java/org/springframework/data/redis/connection/lettuce/observability/SynchronousIntegrationTests.java

+4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
* Collection of tests that log metrics and tracing using the synchronous API.
3636
*
3737
* @author Mark Paluch
38+
* @author Yanming Zhou
3839
*/
3940
@ExtendWith(SpringExtension.class)
4041
@ContextConfiguration(classes = TestConfig.class)
@@ -77,6 +78,9 @@ public SampleTestRunnerConsumer yourCode() {
7778
.containsEntry("net.sock.peer.port", "" + SettingsUtils.getPort());
7879
assertThat(finishedSpan.getTags()).containsKeys("db.operation");
7980
}
81+
82+
assertThat(TestConfig.PARENT_OBSERVATION_NAMES_COLLECTED_IN_PREDICATE).isNotEmpty();
83+
TestConfig.PARENT_OBSERVATION_NAMES_COLLECTED_IN_PREDICATE.clear();
8084
};
8185
}
8286

Diff for: src/test/java/org/springframework/data/redis/connection/lettuce/observability/TestConfig.java

+10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import io.micrometer.observation.ObservationRegistry;
2323

2424
import java.time.Duration;
25+
import java.util.ArrayList;
26+
import java.util.List;
2527
import java.util.concurrent.TimeUnit;
2628

2729
import org.springframework.context.annotation.Bean;
@@ -33,15 +35,23 @@
3335

3436
/**
3537
* @author Mark Paluch
38+
* @author Yanming Zhou
3639
*/
3740
@Configuration
3841
class TestConfig {
3942

4043
static final MeterRegistry METER_REGISTRY = new SimpleMeterRegistry();
4144
static final ObservationRegistry OBSERVATION_REGISTRY = ObservationRegistry.create();
45+
static final List<String> PARENT_OBSERVATION_NAMES_COLLECTED_IN_PREDICATE = new ArrayList<>();
4246

4347
static {
4448
OBSERVATION_REGISTRY.observationConfig().observationHandler(new DefaultMeterObservationHandler(METER_REGISTRY));
49+
OBSERVATION_REGISTRY.observationConfig().observationPredicate((name, context) -> {
50+
if (context.getParentObservation() != null) {
51+
PARENT_OBSERVATION_NAMES_COLLECTED_IN_PREDICATE.add(context.getParentObservation().getContextView().getName());
52+
}
53+
return true;
54+
});
4555
}
4656

4757
@Bean(destroyMethod = "timer")

0 commit comments

Comments
 (0)