Skip to content

Commit a9e439c

Browse files
quaffmp911de
authored andcommitted
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. Fixes #2591 Original pull request: #2592
1 parent f237016 commit a9e439c

File tree

3 files changed

+27
-12
lines changed

3 files changed

+27
-12
lines changed

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

Lines changed: 13 additions & 12 deletions
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();

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

Lines changed: 4 additions & 0 deletions
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

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

Lines changed: 10 additions & 0 deletions
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)