Skip to content

Commit d29836b

Browse files
authored
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.1.x` & `3.0.x`**
1 parent d8e7299 commit d29836b

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
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 (this.producerListener != null) {
850850
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 (this.producerListener != null) {
@@ -865,6 +864,7 @@ private Callback buildCallback(final ProducerRecord<K, V> producerRecord, final
865864
}
866865
}
867866
finally {
867+
observation.stop();
868868
closeProducer(producer, this.transactional);
869869
}
870870
};

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)