GH-9198: Fix MessageChannel observation for ErrorMessage
Fixes: #9198 When observation is enabled on the `MessageChannel`, the message to send is converted to a `MutableMessage`. In case of `ErrorMessage` this causes a loss of `originalMessage` and may lead to `ClassCastException` in the target error handler. * Check for `ErrorMessage` in the `AbstractMessageChannel.sendWithObservation()` and create a new one as a copy of original request, but including observation headers before performing `sendInternal()` * Modify `IntegrationObservabilityZipkinTests` to verify an observation with an `ErrorMessage` and its handler. **Auto-cherry-pick to `6.3.x` & `6.2.x`**
This commit is contained in:
@@ -30,6 +30,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
@@ -59,6 +60,7 @@ import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageDeliveryException;
|
||||
import org.springframework.messaging.converter.MessageConverter;
|
||||
import org.springframework.messaging.support.ChannelInterceptor;
|
||||
import org.springframework.messaging.support.ErrorMessage;
|
||||
import org.springframework.messaging.support.InterceptableChannel;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -335,12 +337,22 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
|
||||
|
||||
private boolean sendWithObservation(Message<?> message, long timeout) {
|
||||
MutableMessage<?> messageToSend = MutableMessage.of(message);
|
||||
return IntegrationObservation.PRODUCER.observation(
|
||||
this.observationConvention,
|
||||
DefaultMessageSenderObservationConvention.INSTANCE,
|
||||
() -> new MessageSenderContext(messageToSend, getComponentName()),
|
||||
this.observationRegistry)
|
||||
.observe(() -> sendInternal(messageToSend, timeout)); // NOSONAR - never null
|
||||
Observation observation = IntegrationObservation.PRODUCER.observation(
|
||||
this.observationConvention,
|
||||
DefaultMessageSenderObservationConvention.INSTANCE,
|
||||
() -> new MessageSenderContext(messageToSend, getComponentName()),
|
||||
this.observationRegistry);
|
||||
Boolean observe = observation.observe(() -> {
|
||||
Message<?> messageToSendInternal = messageToSend;
|
||||
if (message instanceof ErrorMessage errorMessage) {
|
||||
messageToSendInternal =
|
||||
new ErrorMessage(errorMessage.getPayload(),
|
||||
messageToSend.getHeaders(),
|
||||
errorMessage.getOriginalMessage());
|
||||
}
|
||||
return sendInternal(messageToSendInternal, timeout);
|
||||
});
|
||||
return Boolean.TRUE.equals(observe);
|
||||
}
|
||||
|
||||
private boolean sendWithMetrics(Message<?> message, long timeout) {
|
||||
|
||||
Reference in New Issue
Block a user