open-telemetry / opentelemetry-java-instrumentation

OpenTelemetry auto-instrumentation and instrumentation libraries for Java
https://opentelemetry.io
Apache License 2.0
1.95k stars 855 forks source link

Opentelemetry javaagent with rabbit mq + stomp gets error when disconnect #12498

Open ingyeoking13 opened 1 week ago

ingyeoking13 commented 1 week ago

Describe the bug

Opentelemetry Javaagent + rabbit mq stomps get error with following message

java.lang.IllegalStateException: No header accessor (not using the SimpMessagingTemplate?):

It's error from StompBrokerRelayMessageHandlerclass handleMessageInternal method. image

When Client Application disconnect from websocket that is connected, server got extra message with Headers (none MutableMessageHeaders). message should type of MutableMessageHeaders and accessor should be StompHeaderAccessor.

//message-instance-value maybe

GenericMessage [payload=byte[0], headers={simpMessageType=DISCONNECT, stompCommand=DISCONNECT, simpSessionAttributes={}, traceparent=00-a6f9f07152865fa16ea6076a9dd077c8-8605dc783c10878e-01, id=cef0afc3-9b43-4ae4-0d6e-e09ba0f564e4, simpUser=UsernamePasswordAuthenticationToken [Principal=0076bff3a7bf4082acfb3e524ee15923, Credentials=[PROTECTED], Authenticated=false, Details=null, Granted Authorities=[]], simpSessionId=gb4o2q3f, timestamp=1729606705285}]

Steps to reproduce

When Client Application disconnect from websocket that is connected.

Expected behavior

disconnect websocket gracefully.

Actual behavior

g.springframework.messaging.MessageDeliveryException: Failed to handle GenericMessage [payload=byte[0], headers={simpMessageType=DISCONNECT, stompCommand=DISCONNECT, simpSessionAttributes={org.springframework.messaging.simp.SimpAttributes.COMPLETED=true}, traceparent=00-9b8d341269731c0a8c68a9f1f1e1ff7a-0cf3999f0c7f635a-01, id=74640079-6032-4eb9-cf12-f91d1b511b8d, simpUser=UsernamePasswordAuthenticationToken [Principal=0076bff3a7bf4082acfb3e524ee15923, Credentials=[PROTECTED], Authenticated=false, Details=null, Granted Authorities=[]], simpSessionId=0m4tk0fn, timestamp=1729610042917}] to org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask@28733565 in StompBrokerRelay[ReactorNettyTcpClient[reactor.netty.tcp.TcpClientConnect@6c9a31c1]]
    at org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:161)
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
    at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
    at io.opentelemetry.exporter.sender.okhttp.internal.RetryInterceptor.intercept(RetryInterceptor.java:91)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
    at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.IllegalStateException: No header accessor (not using the SimpMessagingTemplate?): GenericMessage [payload=byte[0], headers={simpMessageType=DISCONNECT, stompCommand=DISCONNECT, simpSessionAttributes={org.springframework.messaging.simp.SimpAttributes.COMPLETED=true}, traceparent=00-9b8d341269731c0a8c68a9f1f1e1ff7a-0cf3999f0c7f635a-01, id=74640079-6032-4eb9-cf12-f91d1b511b8d, simpUser=UsernamePasswordAuthenticationToken [Principal=0076bff3a7bf4082acfb3e524ee15923, Credentials=[PROTECTED], Authenticated=false, Details=null, Granted Authorities=[]], simpSessionId=0m4tk0fn, timestamp=1729610042917}]
    at org.springframework.messaging.simp.stomp.StompBrokerRelayMessageHandler.handleMessageInternal(StompBrokerRelayMessageHandler.java:542)
Caused by: java.lang.IllegalStateException: No header accessor (not using the SimpMessagingTemplate?): GenericMessage [payload=byte[0], headers={simpMessageType=DISCONNECT, stompCommand=DISCONNECT, simpSessionAttributes={org.springframework.messaging.simp.SimpAttributes.COMPLETED=true}, traceparent=00-9b8d341269731c0a8c68a9f1f1e1ff7a-0cf3999f0c7f635a-01, id=74640079-6032-4eb9-cf12-f91d1b511b8d, simpUser=UsernamePasswordAuthenticationToken [Principal=0076bff3a7bf4082acfb3e524ee15923, Credentials=[PROTECTED], Authenticated=false, Details=null, Granted Authorities=[]], simpSessionId=0m4tk0fn, timestamp=1729610042917}]

    at org.springframework.messaging.simp.broker.AbstractBrokerMessageHandler.handleMessage(AbstractBrokerMessageHandler.java:297)
    at org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:152)
    ... 7 common frames omitted

Javaagent or library instrumentation version

2.9.0

Environment

JDK: 17 OS: mac os(intel), linux ubuntu

Additional context

No response

ingyeoking13 commented 1 week ago

I've modified my WebSocketConfig, but I'm unsure why non-STOMP messages are being received. The code works as expected, though. Apologies if I've raised an incorrect issue.

public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    ...
    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(new ChannelInterceptor() {
            @Override
            public Message<?> preSend(Message<?> message, MessageChannel channel) {
                StompHeaderAccessor accessor =
                        MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
                if (accessor == null) {
                    // If the accessor is null, wrap the message with a new StompHeaderAccessor
                    // to ensure that the headers are mutable for further processing.
                    StompHeaderAccessor newAccessor = StompHeaderAccessor.wrap(message);
                    newAccessor.setLeaveMutable(true);
                    return MessageBuilder.createMessage(message.getPayload(), newAccessor.getMessageHeaders());
                }
                // Additional logic here if accessor is not null
            }
        });
    }
}
laurit commented 1 week ago

Based on the provided information it is not possible to tell why this happens. Please provide a minimal application that reproduces the issue along with any necessary instructions if you wish someone to take a look at this.

ingyeoking13 commented 1 week ago

I'm trying to reproduce error with new project but I found that this is not only problem with stomp + rabbitmq + socket disconnect. I'm still adding adhoc to mimic my origin product to new project to reproduce error