[英]Spring Sleuth - broken tracing on JMS ErrorHandler
我有一個簡單的例子https://github.com/gtiwari333/sleuth-jms-broken-tracing/tree/master使用 Spring Sleuth 和 JMS。
在這里,對/jms
端點的調用將消息排隊,並且在onMessage
方法收到消息后,我們正在對/test
進行 GET 調用並拋出MyException
。 我們希望跟蹤 id 傳遞給ErrorHandler
,以便我們在/jms
、 onMessage()
、 handleError()
和/test
端點之間的日志中看到相同的 traceId。
我現在得到什么/如何得到錯誤:
我運行了應用程序並點擊了localhost:8080/jms
端點。 在下面的日志中,TraceId 未在JmsListenerErrorHandler
class 中傳播,並且為對/test
的 GET 調用創建了新的 TraceId
2020-08-04 17:55:24.212 INFO [,225c47fb814f6584,225c47fb814f6584,true] 16956 --- [nio-8080-exec-1] sleuth.SleuthApplication : Queuing message ...
2020-08-04 17:55:24.282 INFO [,225c47fb814f6584,eac851f1650ae8a6,true] 16956 --- [enerContainer-1] sleuth.SleuthApplication : JMS message received SOME MESSAGE !!!
2020-08-04 17:55:24.321 INFO [,225c47fb814f6584,612a7956f6b29a01,true] 16956 --- [nio-8080-exec-3] sleuth.SleuthApplication : test1 called
<<<<<<<<< FINE UPTO HERE
2020-08-04 17:55:24.332 INFO [,,,] 16956 --- [enerContainer-1] sleuth.SleuthApplication : handling error by calling another endpoint ..
<<<<<<<<< new thread started and lost tracing
2020-08-04 17:55:24.336 INFO [,4c163d0997076729,4c163d0997076729,true] 16956 --- [nio-8080-exec-2] sleuth.SleuthApplication : test1 called
<<<<<<<<< new trace id received
它看起來 JMS 在新線程中處理新消息的接收/處理。 Sleuth 具有必要的“工具”邏輯來攔截 Trace/Span id 並將其傳播到@JmsListener
代碼,但它不會傳播到org.springframework.util.ErrorHandler
。
編碼:
@RestController 和 @JmsListener:
@RestController
static class Ctrl {
@Autowired RestTemplate restTemplate;
@Autowired JmsTemplate jmsTemplate;
@GetMapping("/test")
void test() {
log.info("test1 called");
}
@GetMapping("/jms")
void jms() {
log.info("Queuing message ...");
jmsTemplate.convertAndSend("test-queue", "SOME MESSAGE !!!");
}
@JmsListener(destination = "test-queue", concurrency = "5")
void onMessage(TextMessage message) throws JMSException {
log.info("JMS message received {}", message.getText());
restTemplate.getForEntity("http://localhost:8080/test", Void.class); //-->it works
throw new MyException("Some Error"); //-->it doesn't
}
static class MyException extends RuntimeException {
public MyException(String msg) { super(msg); }
}
}
錯誤處理程序:
@Component
static class JmsListenerErrorHandler implements ErrorHandler {
@Autowired RestTemplate restTemplate;
@Override
public void handleError(Throwable t) {
log.info("handling error by calling another endpoint .."); //1....tracing is lost here
restTemplate.getForEntity("http://localhost:8080/test", Void.class);
}
}
JMS 配置:
@Configuration
@EnableJms
static class ActiveMqConfig implements JmsListenerConfigurer {
@Autowired ErrorHandler jmsListenerErrorHandler;
@Autowired ConnectionFactory connectionFactory;
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
registrar.setContainerFactory(containerFactory());
}
@Bean
JmsListenerContainerFactory<?> containerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setErrorHandler(jmsListenerErrorHandler);
return factory;
}
}
我嘗試了什么:(使它成為一個完整的問題)
它在 PR: https://github.com/gtiwari333/sleuth-jms-broken-tracing/pull/1/files在這里,我嘗試使用創建一個由LazyTraceThreadPoolTaskExecutor
Executor 包裝的自定義 Executor bean 並嘗試將其傳遞給JmsListenerContainerFactory
它適用於正常的線程執行,但不適用於 JMS 的東西。
executor.execute(() -> log.info("Im inside thread 2")); //it works
有人已經想出如何攔截 ErrorHandler 來傳遞 TraceId 了嗎?
關於@JmsListener
的檢測存在一個未解決的問題。 所以我猜目前不支持。
一種可能的解決方案是在異常中傳遞Span
:
@RestController
static class Ctrl {
@Autowired
private Tracer tracer;
// ...
@JmsListener(destination = "test-queue", concurrency = "5")
void onMessage(TextMessage message) throws JMSException{
//..
throw new MyException("Some Error",tracer.currentSpan()); // <-- pass current span
}
}
所以你可以在JmsListenerErrorHandler
中得到它:
@Override
public void handleError(Throwable t) {
if(t.getCause() instanceof MyException){
MyException mEx = (MyException) t.getCause();
log.info("Failing span: {}",mEx.getSpan());
}
//...
}
我的MyException
:
class MyException extends RuntimeException {
private final Span span;
public MyException(String msg, Span span) {
super(msg);
this.span=span;
}
// Getter for the Span
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.