Skip to content

Commit fffd5ef

Browse files
committed
GH-3146: Propagate KT observation callback
Fixes: #3146 Propagate `KafkaTemplate` observation callback. There is a requirement to see logs correlated in the `CompletableFuture` result after `KafkaTemplate.send()` operation. * Add `observation.openScope()` into the `buildCallback()` logic **Auto-cherry-pick to `3.0.x`** # Conflicts: # spring-kafka/src/main/java/org/springframework/kafka/core/KafkaTemplate.java
1 parent c34078c commit fffd5ef

File tree

2 files changed

+12
-4
lines changed

2 files changed

+12
-4
lines changed

spring-kafka/src/main/java/org/springframework/kafka/core/KafkaTemplate.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,7 @@ private ProducerRecord<K, V> interceptorProducerRecord(ProducerRecord<K, V> prod
829829
return producerRecord;
830830
}
831831

832+
@SuppressWarnings("try")
832833
private Callback buildCallback(final ProducerRecord<K, V> producerRecord, final Producer<K, V> producer,
833834
final CompletableFuture<SendResult<K, V>> future, @Nullable Object sample, Observation observation) {
834835

@@ -841,10 +842,9 @@ private Callback buildCallback(final ProducerRecord<K, V> producerRecord, final
841842
catch (Exception e) {
842843
KafkaTemplate.this.logger.warn(e, () -> "Error executing interceptor onAcknowledgement callback");
843844
}
844-
try {
845+
try (Observation.Scope ignored = observation.openScope()) {
845846
if (exception == null) {
846847
successTimer(sample, producerRecord);
847-
observation.stop();
848848
future.complete(new SendResult<>(producerRecord, metadata));
849849
if (KafkaTemplate.this.producerListener != null) {
850850
KafkaTemplate.this.producerListener.onSuccess(producerRecord, metadata);
@@ -855,7 +855,6 @@ private Callback buildCallback(final ProducerRecord<K, V> producerRecord, final
855855
else {
856856
failureTimer(sample, exception, producerRecord);
857857
observation.error(exception);
858-
observation.stop();
859858
future.completeExceptionally(
860859
new KafkaProducerException(producerRecord, "Failed to send", exception));
861860
if (KafkaTemplate.this.producerListener != null) {
@@ -866,6 +865,7 @@ private Callback buildCallback(final ProducerRecord<K, V> producerRecord, final
866865
}
867866
}
868867
finally {
868+
observation.stop();
869869
if (!KafkaTemplate.this.transactional) {
870870
closeProducer(producer, false);
871871
}

spring-kafka/src/test/java/org/springframework/kafka/support/micrometer/ObservationTests.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.concurrent.ExecutionException;
3030
import java.util.concurrent.TimeUnit;
3131
import java.util.concurrent.TimeoutException;
32+
import java.util.concurrent.atomic.AtomicReference;
3233

3334
import org.apache.kafka.clients.admin.AdminClientConfig;
3435
import org.apache.kafka.clients.consumer.ConsumerConfig;
@@ -108,7 +109,14 @@ void endToEnd(@Autowired Listener listener, @Autowired KafkaTemplate<Integer, St
108109
@Autowired Config config)
109110
throws InterruptedException, ExecutionException, TimeoutException {
110111

111-
template.send("observation.testT1", "test").get(10, TimeUnit.SECONDS);
112+
AtomicReference<SimpleSpan> spanFromCallback = new AtomicReference<>();
113+
114+
template.send("observation.testT1", "test")
115+
.thenAccept((sendResult) -> spanFromCallback.set(tracer.currentSpan()))
116+
.get(10, TimeUnit.SECONDS);
117+
118+
assertThat(spanFromCallback.get()).isNotNull();
119+
112120
assertThat(listener.latch1.await(10, TimeUnit.SECONDS)).isTrue();
113121
assertThat(listener.record).isNotNull();
114122
Headers headers = listener.record.headers();

0 commit comments

Comments
 (0)