From c41c15e61a80c8e45e8336f16f002ff2a18a97a5 Mon Sep 17 00:00:00 2001 From: Daniel Gerhardt <code@dgerhardt.net> Date: Wed, 26 Apr 2017 13:53:44 +0200 Subject: [PATCH] Log unhandled exceptions --- .../AbstractControllerExceptionHandler.java | 30 +++++++++++++++- .../ControllerExceptionHandler.java | 35 ++++++++++--------- .../DefaultControllerExceptionHandler.java | 3 +- src/main/resources/log4j-dev.properties | 4 +-- src/main/resources/log4j.properties | 4 +-- 5 files changed, 53 insertions(+), 23 deletions(-) diff --git a/src/main/java/de/thm/arsnova/controller/AbstractControllerExceptionHandler.java b/src/main/java/de/thm/arsnova/controller/AbstractControllerExceptionHandler.java index a393dc248..58e3f907e 100644 --- a/src/main/java/de/thm/arsnova/controller/AbstractControllerExceptionHandler.java +++ b/src/main/java/de/thm/arsnova/controller/AbstractControllerExceptionHandler.java @@ -1,15 +1,23 @@ package de.thm.arsnova.controller; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.event.Level; import org.springframework.beans.factory.annotation.Value; import java.util.HashMap; import java.util.Map; public class AbstractControllerExceptionHandler { + private static final Logger logger = LoggerFactory.getLogger(AbstractControllerExceptionHandler.class); + /* Since exception messages might contain sensitive data, they are not exposed by default. */ @Value("${api.expose-error-messages:false}") private boolean exposeMessages; - protected Map<String, Object> handleException(Throwable e) { + protected Map<String, Object> handleException(@NonNull Throwable e, @NonNull Level level) { + final String message = e.getMessage() != null ? e.getMessage() : ""; + log(level, message, e); final Map<String, Object> result = new HashMap<>(); result.put("errorType", e.getClass().getSimpleName()); if (exposeMessages) { @@ -18,4 +26,24 @@ public class AbstractControllerExceptionHandler { return result; } + + private void log(Level level, String message, Throwable e) { + switch (level) { + case ERROR: + logger.error(message, e); + break; + case WARN: + logger.warn(message, e); + break; + case INFO: + logger.info(message, e); + break; + case DEBUG: + logger.debug(message, e); + break; + case TRACE: + logger.trace(message, e); + break; + } + } } diff --git a/src/main/java/de/thm/arsnova/controller/ControllerExceptionHandler.java b/src/main/java/de/thm/arsnova/controller/ControllerExceptionHandler.java index 433f259aa..9e91b10a1 100644 --- a/src/main/java/de/thm/arsnova/controller/ControllerExceptionHandler.java +++ b/src/main/java/de/thm/arsnova/controller/ControllerExceptionHandler.java @@ -25,6 +25,7 @@ import de.thm.arsnova.exceptions.NotImplementedException; import de.thm.arsnova.exceptions.PayloadTooLargeException; import de.thm.arsnova.exceptions.PreconditionFailedException; import de.thm.arsnova.exceptions.UnauthorizedException; +import org.slf4j.event.Level; import org.springframework.http.HttpStatus; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.security.access.AccessDeniedException; @@ -46,25 +47,32 @@ import java.util.Map; */ @ControllerAdvice public class ControllerExceptionHandler extends AbstractControllerExceptionHandler { + @ExceptionHandler(NoContentException.class) + @ResponseBody + @ResponseStatus(HttpStatus.NO_CONTENT) + public Map<String, Object> handleNoContentException(final Exception e, final HttpServletRequest request) { + return handleException(e, Level.TRACE); + } + @ExceptionHandler(NotFoundException.class) @ResponseBody @ResponseStatus(HttpStatus.NOT_FOUND) public Map<String, Object> handleNotFoundException(final Exception e, final HttpServletRequest request) { - return handleException(e); + return handleException(e, Level.TRACE); } @ExceptionHandler(UnauthorizedException.class) @ResponseBody @ResponseStatus(HttpStatus.UNAUTHORIZED) public Map<String, Object> handleUnauthorizedException(final Exception e, final HttpServletRequest request) { - return handleException(e); + return handleException(e, Level.TRACE); } @ExceptionHandler(AuthenticationCredentialsNotFoundException.class) @ResponseStatus(HttpStatus.UNAUTHORIZED) @ResponseBody public Map<String, Object> handleAuthenticationCredentialsNotFoundException(final Exception e, final HttpServletRequest request) { - return handleException(e); + return handleException(e, Level.DEBUG); } @ExceptionHandler(AccessDeniedException.class) @@ -83,55 +91,48 @@ public class ControllerExceptionHandler extends AbstractControllerExceptionHandl response.setStatus(HttpStatus.FORBIDDEN.value()); } - return handleException(e); + return handleException(e, Level.DEBUG); } @ExceptionHandler(ForbiddenException.class) @ResponseBody @ResponseStatus(HttpStatus.FORBIDDEN) public Map<String, Object> handleForbiddenException(final Exception e, final HttpServletRequest request) { - return handleException(e); - } - - @ExceptionHandler(NoContentException.class) - @ResponseBody - @ResponseStatus(HttpStatus.NO_CONTENT) - public Map<String, Object> handleNoContentException(final Exception e, final HttpServletRequest request) { - return handleException(e); + return handleException(e, Level.DEBUG); } @ExceptionHandler(BadRequestException.class) @ResponseBody @ResponseStatus(HttpStatus.BAD_REQUEST) public Map<String, Object> handleBadRequestException(final Exception e, final HttpServletRequest request) { - return handleException(e); + return handleException(e, Level.DEBUG); } @ExceptionHandler(PreconditionFailedException.class) @ResponseBody @ResponseStatus(HttpStatus.PRECONDITION_FAILED) public Map<String, Object> handlePreconditionFailedException(final Exception e, final HttpServletRequest request) { - return handleException(e); + return handleException(e, Level.DEBUG); } @ExceptionHandler(NotImplementedException.class) @ResponseBody @ResponseStatus(HttpStatus.NOT_IMPLEMENTED) public Map<String, Object> handleNotImplementedException(final Exception e, final HttpServletRequest request) { - return handleException(e); + return handleException(e, Level.DEBUG); } @ExceptionHandler(PayloadTooLargeException.class) @ResponseBody @ResponseStatus(HttpStatus.PAYLOAD_TOO_LARGE) public Map<String, Object> handlePayloadTooLargeException(final Exception e, final HttpServletRequest request) { - return handleException(e); + return handleException(e, Level.DEBUG); } @ExceptionHandler(HttpMessageNotReadableException.class) @ResponseBody @ResponseStatus(HttpStatus.BAD_REQUEST) public Map<String, Object> handleHttpMessageNotReadableException(final Exception e, final HttpServletRequest request) { - return handleException(e); + return handleException(e, Level.DEBUG); } } diff --git a/src/main/java/de/thm/arsnova/controller/DefaultControllerExceptionHandler.java b/src/main/java/de/thm/arsnova/controller/DefaultControllerExceptionHandler.java index fe8546c82..3d1249280 100644 --- a/src/main/java/de/thm/arsnova/controller/DefaultControllerExceptionHandler.java +++ b/src/main/java/de/thm/arsnova/controller/DefaultControllerExceptionHandler.java @@ -1,5 +1,6 @@ package de.thm.arsnova.controller; +import org.slf4j.event.Level; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ControllerAdvice; @@ -26,6 +27,6 @@ public class DefaultControllerExceptionHandler extends AbstractControllerExcepti throw e; } - return handleException(e); + return handleException(e, Level.ERROR); } } diff --git a/src/main/resources/log4j-dev.properties b/src/main/resources/log4j-dev.properties index bae1f9dff..021ba3029 100644 --- a/src/main/resources/log4j-dev.properties +++ b/src/main/resources/log4j-dev.properties @@ -1,8 +1,8 @@ log4j.rootCategory=INFO, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n +log4j.appender.stdout.layout=org.apache.log4j.EnhancedPatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n%throwable log4j.category.de.thm.arsnova=DEBUG log4j.category.com.corundumstudio.socketio=INFO diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties index fb38b279b..b0ce03ef6 100644 --- a/src/main/resources/log4j.properties +++ b/src/main/resources/log4j.properties @@ -1,8 +1,8 @@ log4j.rootCategory=INFO, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n +log4j.appender.stdout.layout=org.apache.log4j.EnhancedPatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n%throwable{2} log4j.category.de.thm.arsnova=INFO log4j.category.com.corundumstudio.socketio=INFO -- GitLab