Skip to content

Commit daf11c4

Browse files
artembilanspring-builds
authored andcommitted
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 # Conflicts: # spring-kafka/src/main/java/org/springframework/kafka/core/KafkaTemplate.java (cherry picked from commit fffd5ef)
1 parent 6587123 commit daf11c4

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
@@ -827,6 +827,7 @@ private ProducerRecord<K, V> interceptorProducerRecord(ProducerRecord<K, V> prod
827827
return producerRecord;
828828
}
829829

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

@@ -839,10 +840,9 @@ private Callback buildCallback(final ProducerRecord<K, V> producerRecord, final
839840
catch (Exception e) {
840841
KafkaTemplate.this.logger.warn(e, () -> "Error executing interceptor onAcknowledgement callback");
841842
}
842-
try {
843+
try (Observation.Scope ignored = observation.openScope()) {
843844
if (exception == null) {
844845
successTimer(sample, producerRecord);
845-
observation.stop();
846846
future.complete(new SendResult<>(producerRecord, metadata));
847847
if (KafkaTemplate.this.producerListener != null) {
848848
KafkaTemplate.this.producerListener.onSuccess(producerRecord, metadata);
@@ -853,7 +853,6 @@ private Callback buildCallback(final ProducerRecord<K, V> producerRecord, final
853853
else {
854854
failureTimer(sample, exception, producerRecord);
855855
observation.error(exception);
856-
observation.stop();
857856
future.completeExceptionally(
858857
new KafkaProducerException(producerRecord, "Failed to send", exception));
859858
if (KafkaTemplate.this.producerListener != null) {
@@ -864,6 +863,7 @@ private Callback buildCallback(final ProducerRecord<K, V> producerRecord, final
864863
}
865864
}
866865
finally {
866+
observation.stop();
867867
if (!KafkaTemplate.this.transactional) {
868868
closeProducer(producer, false);
869869
}

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;
@@ -104,7 +105,14 @@ void endToEnd(@Autowired Listener listener, @Autowired KafkaTemplate<Integer, St
104105
@Autowired KafkaTemplate<Integer, String> customTemplate, @Autowired Config config)
105106
throws InterruptedException, ExecutionException, TimeoutException {
106107

107-
template.send("observation.testT1", "test").get(10, TimeUnit.SECONDS);
108+
AtomicReference<SimpleSpan> spanFromCallback = new AtomicReference<>();
109+
110+
template.send("observation.testT1", "test")
111+
.thenAccept((sendResult) -> spanFromCallback.set(tracer.currentSpan()))
112+
.get(10, TimeUnit.SECONDS);
113+
114+
assertThat(spanFromCallback.get()).isNotNull();
115+
108116
assertThat(listener.latch1.await(10, TimeUnit.SECONDS)).isTrue();
109117
assertThat(listener.record).isNotNull();
110118
Headers headers = listener.record.headers();

0 commit comments

Comments
 (0)