Reputation: 11
My GlobalFilter only logs successful requests (200). For example, code 500 does not pass through the ServerHttpRequestDecorator and ServerHttpResponseDecorator.
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequestDecorator requestMutated = new ServerHttpRequestDecorator(exchange.getRequest()) {
@Override
public Flux<DataBuffer> getBody() {
Logger requestLogger = new Logger(getDelegate());
if (LOGGABLE_CONTENT_TYPES.contains(String.valueOf(getHeaders().getContentType()).toLowerCase())) {
return super.getBody().map(ds -> {
requestLogger.appendBody(ds.asByteBuffer());
return ds;
}).doFinally(s -> requestLogger.log());
} else {
requestLogger.log();
return super.getBody();
}
}
};
ServerHttpResponseDecorator responseMutated = new ServerHttpResponseDecorator(exchange.getResponse()) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
Logger responseLogger = new Logger(getDelegate());
if (LOGGABLE_CONTENT_TYPES.contains(String.valueOf(getHeaders().getContentType()).toLowerCase())) {
return join(body).flatMap(db -> {
responseLogger.appendBody(db.asByteBuffer());
responseLogger.log();
return getDelegate().writeWith(Mono.just(db));
});
} else {
responseLogger.log();
return getDelegate().writeWith(body);
}
}
};
return chain.filter(exchange.mutate().request(requestMutated).response(responseMutated).build());
}
ServerResponse.status(HttpStatus.valueOf(statusCode)) .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue(errorPropertiesMap))
=> not log request and response;
What am I doing wrong? thanks for the help.
Upvotes: 1
Views: 7725
Reputation: 1386
This will help
@Component
public class GlobalExceptionHandler implements ErrorWebExceptionHandler {
@Autowired
private DataBufferWriter bufferWriter;
Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@Override
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
HashMap<String, String> errorMap = new HashMap<String, String>();
byte[] body = null;
if (ex instanceof JwtException || ex instanceof UsernameNotFoundException) {
exchange.getResponse().setRawStatusCode(HttpServletResponse.SC_UNAUTHORIZED);
exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
status = HttpStatus.UNAUTHORIZED;
errorMap.put("timestamp", LocalDateTime.now().toString());
errorMap.put("message", ex.getLocalizedMessage());
errorMap.put("error",ex.getClass().getName());
errorMap.put("status", "401");
log.error("Error in url :{} with error ", exchange.getRequest().getURI(), ex.getMessage(), ex);
} else if (ex instanceof Throwable || ex instanceof IOException) {
log.error("Exception occured in url :{} while getting response. for trackingId= {} with exception : {}",
exchange.getRequest().getURI(), exchange.getRequest().getHeaders().getFirst("trackingId"),
ex.getLocalizedMessage(), ex);
errorMap.put("timestamp", LocalDateTime.now().toString());
errorMap.put("message", ex.getLocalizedMessage());
errorMap.put("error",ex.getClass().getName());
errorMap.put("status", "500");
}
if (exchange.getResponse().isCommitted()) {
return Mono.error(ex);
}
exchange.getResponse().setStatusCode(status);
return bufferWriter.write(exchange.getResponse(), errorMap);
}
}
@Component
public class DataBufferWriter {
Logger log = LoggerFactory.getLogger(DataBufferWriter.class);
public <T> Mono<Void> write(ServerHttpResponse httpResponse, HashMap<String, String> errorMap) {
ObjectMapper objectMapper = new ObjectMapper();
return httpResponse
.writeWith(Mono.fromSupplier(() -> {
DataBufferFactory bufferFactory = httpResponse.bufferFactory();
try {
return bufferFactory.wrap(objectMapper.writeValueAsBytes(errorMap));
} catch (Exception ex) {
log.warn("Error writing response", ex);
return bufferFactory.wrap(new byte[0]);
}
}));
}
}
Upvotes: 0
Reputation: 3576
Try enable these properties in application.yml:
logging:
level:
org.springframework.web.HttpLogging: TRACE
reactor.netty.http.server: DEBUG
reactor.netty.http.client: DEBUG
spring
cloud
gateway
httpserver
wiretap: true
Upvotes: 1