gpt4 book ai didi

java - 避免在 Spring Boot 应用程序中向 Sentry 报告 Broken Pipe 错误

转载 作者:IT老高 更新时间:2023-10-28 13:57:46 30 4
gpt4 key购买 nike

我有一个使用 Sentry 进行异常跟踪的 Spring Boot 应用程序,我收到一些如下所示的错误:

ClientAbortExceptionorg.apache.catalina.connector.OutputBuffer in realWriteBytes
errorjava.io.IOException: Broken pipe

我的理解是这只是一个网络错误,因此我通常应该忽略它们。我想要做的是报告所有其他 IOExceptions 并将损坏的管道记录到 Librato,这样我就可以密切关注我得到了多少(峰值可能意味着客户端存在问题,即也是我用 Java 开发的):

我想出了这个:

@ControllerAdvice
@Priority(1)
@Order(1)
public class RestExceptionHandler {
@ExceptionHandler(ClientAbortException.class)
@ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
public ResponseEntity<?> handleClientAbortException(ClientAbortException ex, HttpServletRequest request) {
Throwable rootCause = ex;
while (ex.getCause() != null) {
rootCause = ex.getCause();
}
if (rootCause.getMessage().contains("Broken pipe")) {
logger.info("count#broken_pipe=1");
} else {
Sentry.getStoredClient().sendException(ex);
}
return null;
}
}

这是处理这个问题的可接受方式吗?

我以这种方式按照文档配置了 Sentry:

@Configuration
public class FactoryBeanAppConfig {
@Bean
public HandlerExceptionResolver sentryExceptionResolver() {
return new SentryExceptionResolver();
}

@Bean
public ServletContextInitializer sentryServletContextInitializer() {
return new SentryServletContextInitializer();
}
}

最佳答案

如果你查看类 SentryExceptionResolver

public class SentryExceptionResolver implements HandlerExceptionResolver, Ordered {
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {

Sentry.capture(ex);

// null = run other HandlerExceptionResolvers to actually handle the exception
return null;
}

@Override
public int getOrder() {
// ensure this resolver runs first so that all exceptions are reported
return Integer.MIN_VALUE;
}
}

通过在 getOrder 中返回 Integer.MIN_VALUE 确保它首先被调用。即使您将 Priority 设置为 1,它也不起作用。所以你想改变你的

@Configuration
public class FactoryBeanAppConfig {
@Bean
public HandlerExceptionResolver sentryExceptionResolver() {
return new SentryExceptionResolver();
}

@Bean
public ServletContextInitializer sentryServletContextInitializer() {
return new SentryServletContextInitializer();
}
}

@Configuration
public class FactoryBeanAppConfig {
@Bean
public HandlerExceptionResolver sentryExceptionResolver() {
return new SentryExceptionResolver() {
@Override
public int getOrder() {
// ensure we can get some resolver earlier than this
return 10;
}
};
}

@Bean
public ServletContextInitializer sentryServletContextInitializer() {
return new SentryServletContextInitializer();
}
}

这将确保您可以更早地运行您的处理程序。在您的代码中,获取 rootCause 的循环不正确

while (ex.getCause() != null) {
rootCause = ex.getCause();
}

这是一个无限循环,因为您使用的是 ex 而不是 rootCause。即使你改正它,它仍然可以成为一个无限循环。当异常原因返回时,它将被卡住。我还没有彻底测试它,但我相信它应该像下面这样

while (rootCause.getCause() != null && rootCause.getCause() != rootCause) {
rootCause = rootCause.getCause();
}

这是解决问题的一种方法。但是您需要自己将异常发送给 Sentry。所以还有另一种方法来处理您的要求

方式 2

在这种情况下,您可以在配置中执行整个逻辑并将其更改为下面

@Configuration
public class FactoryBeanAppConfig {
@Bean
public HandlerExceptionResolver sentryExceptionResolver() {
return new SentryExceptionResolver() {
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
Throwable rootCause = ex;

while (rootCause .getCause() != null && rootCause.getCause() != rootCause) {
rootCause = rootCause.getCause();
}

if (!rootCause.getMessage().contains("Broken pipe")) {
super.resolveException(request, response, handler, ex);
}
return null;
}

};
}

@Bean
public ServletContextInitializer sentryServletContextInitializer() {
return new SentryServletContextInitializer();
}
}

关于java - 避免在 Spring Boot 应用程序中向 Sentry 报告 Broken Pipe 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48914391/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com