java 在 Spring Boot 应用程序中防止自定义异常的堆栈跟踪日志记录

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31250598/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 18:20:44  来源:igfitidea点击:

Prevent stack trace logging for custom exception in Spring Boot application

javaspringloggingexception-handlingspring-boot

提问by rhorvath

Is there a way in Spring Boot (mvc) to log a custom exception and throw it without its stack trace being visible in the logfile? But for any other exception still see the stack trace.

Spring Boot (mvc) 中有没有办法记录自定义异常并抛出它,而其堆栈跟踪在日志文件中不可见?但是对于任何其他异常,仍然可以看到堆栈跟踪。

Long explanation:

长解释:

I am using spring boot to create a simple rest service. I like that for a custom exceptions there is no stack trace in the logs by defaultand json response is created with the basic exception details (status, error, message).

我正在使用 spring boot 来创建一个简单的休息服务。我喜欢自定义异常,默认情况下日志中没有堆栈跟踪,并且使用基本异常详细信息(状态、错误、消息)创建 json 响应。

The problem is that it also creates no logentry at all, therefore I would have to do this manually:

问题是它也根本不创建日志条目,因此我必须手动执行此操作:

Custom Exception

自定义异常

@ResponseStatus(value = HttpStatus.CONFLICT)
public class DuplicateFoundException extends RuntimeException {
    public DuplicateFoundException(String message) {
        super(message);
    }
}

Exception throwing in service method (in @RestController)

服务方法中的异常抛出(在@RestController 中)

if (!voteDao.findByItemAndUser(item, voteDto.getUserId()).isEmpty()) {
    log.warn("... already voted ...");   //TODO: don't do this for every throw
    throw new DuplicateFoundException("... already voted ...");
}

Having more exceptions leads to placing log statement before each throw, which is a bad approach I think. I've tried removing all the log statements from the service method and created @ControlledAdvice where I would log all the custom exceptionsand just re-throw them so I still get the nice json as before:

有更多的异常会导致在每次抛出之前放置日志语句,我认为这是一种糟糕的方法。我已经尝试从服务方法中删除所有日志语句并创建了@ControlledAdvice,我将在其中记录所有自定义异常并重新抛出它们,所以我仍然像以前一样得到漂亮的 json:

@ControllerAdvice
public class RestExceptionHandler {
    private static final Logger log = Logger.getLogger(RestExceptionHandler.class);

    @ExceptionHandler
    public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) {
            log.warn(e.getMessage());
        } else {
            log.error("...");
        }
        throw e;
    }
}

Now the problem is that I see not just the log entry but also the stack trace for custom exceptionsand can't find a way how to prevent this. I think the problem is caused by throwing it again. A possible solution could be to create a custom class for exception which I will return instead, but I dislike the idea since exception marshalling seems to work fine.

现在的问题是,我不仅看到了日志条目,还看到了自定义异常的堆栈跟踪,但找不到如何防止这种情况发生的方法。我认为问题是再次抛出引起的。一个可能的解决方案是为异常创建一个自定义类,我将返回它,但我不喜欢这个想法,因为异常编组似乎工作正常。

Any hints? Thanks.

任何提示?谢谢。

采纳答案by rhorvath

Solution was to leave the exception handling to spring boot, so that custom exception is not logged and any other is logged by default. I removed the @ControllerAdvice and also the logging statements from the rest controller and added logging statement to custom exception constructor.

解决方案是将异常处理留给 spring boot,以便不记录自定义异常,默认情况下记录任何其他异常。我从其余控制器中删除了 @ControllerAdvice 和日志语句,并将日志语句添加到自定义异常构造函数中

public DuplicateFoundException(String message) {
    super(message);
    LOGGER.warn(message);
}

I am not sure if this is the best approach, but now I have custom exception logging only at one place and don't have to repeat the log statement for every exception or see its stack trace or any other error message in the logs.

我不确定这是否是最好的方法,但现在我只在一个地方有自定义异常日志记录,并且不必为每个异常重复日志语句或查看其堆栈跟踪或日志中的任何其他错误消息。

回答by Carlos Negron

I'm using Spring Boot 2+ just add this line to your application.properties:

我正在使用 Spring Boot 2+ 只需将此行添加到您的 application.properties:

server.error.include-stacktrace=never

server.error.include-stacktrace=从不

https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/web/ErrorProperties.IncludeStacktrace.html

https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/web/ErrorProperties.IncludeStacktrace.html

回答by Roland Weisleder

If you don't need the stack trace you can suppress the stack trace by overriding fillInStackTracein your exception class.

如果您不需要堆栈跟踪,您可以通过覆盖fillInStackTrace异常类来抑制堆栈跟踪。

public class DuplicateFoundException extends RuntimeException {
    @Override
    public synchronized Throwable fillInStackTrace() {
        return this;
    }
}

When you invoke e.printStackTrace()then no stack trace will be printed.

当您调用时,e.printStackTrace()不会打印堆栈跟踪。

See also this blog post.

另请参阅此博客文章

回答by muttonUp

Be wary of Spring Boot DevTools.

警惕 Spring Boot DevTools。

Despite NEVERbeing the default for server.error.include-stacktrace, if you include Spring Boot DevTools it overides to ALWAYS.

尽管NEVER是默认的server.error.include-stacktrace,如果包括它都不会到春季启动DevTools ALWAYS

If you're interested in more detail, see this commit, which became part of Spring Boot 2.1.0+

如果您对更多细节感兴趣,请参阅此提交,它成为 Spring Boot 2.1.0+ 的一部分