Reputation: 1009
When a request comes into the server I would like to interrogate the headers and see if there is a specific header, if so I want to grab that headers value and add it to the SLF4Js MDC, if it doesn't exist I will generate my own (see code below).
I'm using Micronaut (v2.5.5) for the first time, been using Spring Boot for a while. With Spring Boot I was able to add a Filter method which would add a request ID to SLF4Js MDC context, so that when elements where logged it would include that in the log message.
example
2021-07-01 19:12:57.104 LogLevel=INFO rid=3568b2d7-d8f1-4d7d-9e8d-49f2be727255, 1 --- [nio-8080-exec-8] .....
This is failing in Micronaut, I presume because requests can be handed off between threads and the MDC is thread specific.
example
2021/01/07 18:50:05.021 INFO [qtp1561347421-43] c.c.dex.css.controllers.MyEndpoint rid= - .....
Is there any mechanism in Micronaut to support this functionality without having to switch to Jaeger etc...? If so what is it?
Here is the code that I tried, which doesn't work
@Slf4j
@Filter("/v1.0/**")
public class RequestId extends OncePerRequestHttpServerFilter {
public static final String X_REQUEST_ID = "X-REQUEST-ID";
public static final String RID = "rid";
@Override
protected Publisher<MutableHttpResponse<?>> doFilterOnce(HttpRequest<?> request, ServerFilterChain chain) {
// Was a request ID passed in, if so grab it
String requestID = request.getHeaders().get(X_REQUEST_ID);
if (null == requestID) {
// no create it
requestID = UUID.randomUUID().toString();
}
log.info("Storing RID in MDC and request: " + requestID);
MDC.put(RID, requestID);
}
I did try to put the rid in the request object (passed into doFilter), and then use that in my controller, e.g.
@Controller(value = "v1.0/")
public class XmlEndpoint {
@Post(uri = "request")
public MyResponse request(@NonNull @Body(value = "MyRequest") MyRequest request) {
Optional<HttpRequest<Object>> optionalReq = ServerRequestContext.currentRequest();
if (optionalReq.isPresent()) {
HttpRequest<Object> curRequest = optionalReq.get();
// Get the request ID from the request
MDC.put(RequestId.RID, (String) curRequest.getAttribute(X_REQUEST_ID).orElse(UNKNOWN_RID));
}
....
}
}
In this case the log messages contain the RID, but that seems a bit convoluted.
I did a search and saw, what I thought where, several related issues, however; the answers didn't make a lot of sense (Micronaut newbie, sorry) or didn't seem to have a solution that showed what needed to be done.
Thanks in advance
Upvotes: 4
Views: 2454
Reputation: 493
I finally got something similar to work by including the following dependency in build.gradle. Child threads running in the context of methods annotated with @Async now inherit the MDC properties of the parent thread and are visible by loggers.
implementation "io.micronaut:micronaut-tracing"
Upvotes: 0