Skip to content
Snippets Groups Projects
Commit c41c15e6 authored by Daniel Gerhardt's avatar Daniel Gerhardt
Browse files

Log unhandled exceptions

parent 7d72617c
Branches
Tags
No related merge requests found
package de.thm.arsnova.controller; 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 org.springframework.beans.factory.annotation.Value;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class AbstractControllerExceptionHandler { 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. */ /* Since exception messages might contain sensitive data, they are not exposed by default. */
@Value("${api.expose-error-messages:false}") private boolean exposeMessages; @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<>(); final Map<String, Object> result = new HashMap<>();
result.put("errorType", e.getClass().getSimpleName()); result.put("errorType", e.getClass().getSimpleName());
if (exposeMessages) { if (exposeMessages) {
...@@ -18,4 +26,24 @@ public class AbstractControllerExceptionHandler { ...@@ -18,4 +26,24 @@ public class AbstractControllerExceptionHandler {
return result; 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;
}
}
} }
...@@ -25,6 +25,7 @@ import de.thm.arsnova.exceptions.NotImplementedException; ...@@ -25,6 +25,7 @@ import de.thm.arsnova.exceptions.NotImplementedException;
import de.thm.arsnova.exceptions.PayloadTooLargeException; import de.thm.arsnova.exceptions.PayloadTooLargeException;
import de.thm.arsnova.exceptions.PreconditionFailedException; import de.thm.arsnova.exceptions.PreconditionFailedException;
import de.thm.arsnova.exceptions.UnauthorizedException; import de.thm.arsnova.exceptions.UnauthorizedException;
import org.slf4j.event.Level;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.AccessDeniedException;
...@@ -46,25 +47,32 @@ import java.util.Map; ...@@ -46,25 +47,32 @@ import java.util.Map;
*/ */
@ControllerAdvice @ControllerAdvice
public class ControllerExceptionHandler extends AbstractControllerExceptionHandler { 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) @ExceptionHandler(NotFoundException.class)
@ResponseBody @ResponseBody
@ResponseStatus(HttpStatus.NOT_FOUND) @ResponseStatus(HttpStatus.NOT_FOUND)
public Map<String, Object> handleNotFoundException(final Exception e, final HttpServletRequest request) { public Map<String, Object> handleNotFoundException(final Exception e, final HttpServletRequest request) {
return handleException(e); return handleException(e, Level.TRACE);
} }
@ExceptionHandler(UnauthorizedException.class) @ExceptionHandler(UnauthorizedException.class)
@ResponseBody @ResponseBody
@ResponseStatus(HttpStatus.UNAUTHORIZED) @ResponseStatus(HttpStatus.UNAUTHORIZED)
public Map<String, Object> handleUnauthorizedException(final Exception e, final HttpServletRequest request) { public Map<String, Object> handleUnauthorizedException(final Exception e, final HttpServletRequest request) {
return handleException(e); return handleException(e, Level.TRACE);
} }
@ExceptionHandler(AuthenticationCredentialsNotFoundException.class) @ExceptionHandler(AuthenticationCredentialsNotFoundException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED) @ResponseStatus(HttpStatus.UNAUTHORIZED)
@ResponseBody @ResponseBody
public Map<String, Object> handleAuthenticationCredentialsNotFoundException(final Exception e, final HttpServletRequest request) { public Map<String, Object> handleAuthenticationCredentialsNotFoundException(final Exception e, final HttpServletRequest request) {
return handleException(e); return handleException(e, Level.DEBUG);
} }
@ExceptionHandler(AccessDeniedException.class) @ExceptionHandler(AccessDeniedException.class)
...@@ -83,55 +91,48 @@ public class ControllerExceptionHandler extends AbstractControllerExceptionHandl ...@@ -83,55 +91,48 @@ public class ControllerExceptionHandler extends AbstractControllerExceptionHandl
response.setStatus(HttpStatus.FORBIDDEN.value()); response.setStatus(HttpStatus.FORBIDDEN.value());
} }
return handleException(e); return handleException(e, Level.DEBUG);
} }
@ExceptionHandler(ForbiddenException.class) @ExceptionHandler(ForbiddenException.class)
@ResponseBody @ResponseBody
@ResponseStatus(HttpStatus.FORBIDDEN) @ResponseStatus(HttpStatus.FORBIDDEN)
public Map<String, Object> handleForbiddenException(final Exception e, final HttpServletRequest request) { public Map<String, Object> handleForbiddenException(final Exception e, final HttpServletRequest request) {
return handleException(e); return handleException(e, Level.DEBUG);
}
@ExceptionHandler(NoContentException.class)
@ResponseBody
@ResponseStatus(HttpStatus.NO_CONTENT)
public Map<String, Object> handleNoContentException(final Exception e, final HttpServletRequest request) {
return handleException(e);
} }
@ExceptionHandler(BadRequestException.class) @ExceptionHandler(BadRequestException.class)
@ResponseBody @ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, Object> handleBadRequestException(final Exception e, final HttpServletRequest request) { public Map<String, Object> handleBadRequestException(final Exception e, final HttpServletRequest request) {
return handleException(e); return handleException(e, Level.DEBUG);
} }
@ExceptionHandler(PreconditionFailedException.class) @ExceptionHandler(PreconditionFailedException.class)
@ResponseBody @ResponseBody
@ResponseStatus(HttpStatus.PRECONDITION_FAILED) @ResponseStatus(HttpStatus.PRECONDITION_FAILED)
public Map<String, Object> handlePreconditionFailedException(final Exception e, final HttpServletRequest request) { public Map<String, Object> handlePreconditionFailedException(final Exception e, final HttpServletRequest request) {
return handleException(e); return handleException(e, Level.DEBUG);
} }
@ExceptionHandler(NotImplementedException.class) @ExceptionHandler(NotImplementedException.class)
@ResponseBody @ResponseBody
@ResponseStatus(HttpStatus.NOT_IMPLEMENTED) @ResponseStatus(HttpStatus.NOT_IMPLEMENTED)
public Map<String, Object> handleNotImplementedException(final Exception e, final HttpServletRequest request) { public Map<String, Object> handleNotImplementedException(final Exception e, final HttpServletRequest request) {
return handleException(e); return handleException(e, Level.DEBUG);
} }
@ExceptionHandler(PayloadTooLargeException.class) @ExceptionHandler(PayloadTooLargeException.class)
@ResponseBody @ResponseBody
@ResponseStatus(HttpStatus.PAYLOAD_TOO_LARGE) @ResponseStatus(HttpStatus.PAYLOAD_TOO_LARGE)
public Map<String, Object> handlePayloadTooLargeException(final Exception e, final HttpServletRequest request) { public Map<String, Object> handlePayloadTooLargeException(final Exception e, final HttpServletRequest request) {
return handleException(e); return handleException(e, Level.DEBUG);
} }
@ExceptionHandler(HttpMessageNotReadableException.class) @ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseBody @ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, Object> handleHttpMessageNotReadableException(final Exception e, final HttpServletRequest request) { public Map<String, Object> handleHttpMessageNotReadableException(final Exception e, final HttpServletRequest request) {
return handleException(e); return handleException(e, Level.DEBUG);
} }
} }
package de.thm.arsnova.controller; package de.thm.arsnova.controller;
import org.slf4j.event.Level;
import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ControllerAdvice;
...@@ -26,6 +27,6 @@ public class DefaultControllerExceptionHandler extends AbstractControllerExcepti ...@@ -26,6 +27,6 @@ public class DefaultControllerExceptionHandler extends AbstractControllerExcepti
throw e; throw e;
} }
return handleException(e); return handleException(e, Level.ERROR);
} }
} }
log4j.rootCategory=INFO, stdout log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout=org.apache.log4j.EnhancedPatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n%throwable
log4j.category.de.thm.arsnova=DEBUG log4j.category.de.thm.arsnova=DEBUG
log4j.category.com.corundumstudio.socketio=INFO log4j.category.com.corundumstudio.socketio=INFO
......
log4j.rootCategory=INFO, stdout log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout=org.apache.log4j.EnhancedPatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n%throwable{2}
log4j.category.de.thm.arsnova=INFO log4j.category.de.thm.arsnova=INFO
log4j.category.com.corundumstudio.socketio=INFO log4j.category.com.corundumstudio.socketio=INFO
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment