I want to add logging to my project ,I use webFilter
to add log .
I want to log request headers (except authentication header) ,request methods and response code I add this code to my project:
@Component
@Slf4j
public class LogFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange,
WebFilterChain webFilterChain) {
log.info("log :: requestId: {}, ip: {}, method: {},path :{}, headers: {}, response :{}",
serverWebExchange.getRequest().getId(), serverWebExchange.getRequest().getRemoteAddress(),
serverWebExchange.getRequest().getMethod(), serverWebExchange.getRequest().getPath(),
serverWebExchange.getRequest().getHeaders().entrySet()
.stream().filter(stringListEntry -> !stringListEntry.getKey().equals("Authorization")).toList(),
serverWebExchange.getResponse().getStatusCode);
return webFilterChain.filter(serverWebExchange);
}
I have All headers and needed information to log but response code is Always 200 OK
but some time response is 400 in result.
Your solution is incorrect because you used the logger before the filter and the filter will be triggered if anyone subscribed to it, so Mono/Flux flow chain will run later rather than the other code. Your controller hasn't run yet, so you're reading the response code prematurely. Please in the future use debug mode and check which call will be run first.
In my solution (this isn't the best, just one example), I am waiting for the end of communication. It can be complete or error. So, I watch those signals and will log if one of them.
One solution:
@Component
public class LogFilter implements WebFilter {
Logger log = LoggerFactory.getLogger(LogFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(exchange)
.doOnEach(signal -> {
if (signal.isOnComplete() || signal.isOnError()) {
log.info(
"log :: requestId: {}, ip: {}, method: {},path :{}, headers: {}, response :{}",
exchange.getRequest().getId(), exchange.getRequest().getRemoteAddress(),
exchange.getRequest().getMethod(), exchange.getRequest().getPath(),
exchange.getRequest().getHeaders().entrySet()
.stream().filter(stringListEntry -> !stringListEntry.getKey().equals("Authorization")).toList(),
exchange.getResponse().getStatusCode()
);
}
});
}
}
Update: If you use data in MDC, consider the follow:
What Is a Good Pattern for Contextual Logging? (MDC)
Or you can use my library which is has wrapped this pattern: GitHub