Mapped Diagnostic Context (MDC)
Mapped Diagnostic Context (MDC) will help us add more context on every log output. For more information, refer to this web page: https://logback.qos.ch/manual/mdc.html. It is a kind of Map attached to the Thread context and maintained by the logging framework where you can put values and use them in your log layout.
As it is attached to a Thread, we can put values at the beginning of a request and print them in all the logs related to this request. That can give you a lot of information about the context of the request, without having to add them to all logs manually.
Implement MDC
A good sketch is better than a long speech. In the next section, we will use MDC to add the card number and the POS ID to all the logs related to a request.
π Go to the easypay-service/src/main/java/com/worldline/easypay/payment/boundary/PaymentResource
class and modify
the method processPayment()
to instantiate the MDC:
public ResponseEntity<PaymentResponse> processPayment(PaymentRequest paymentRequest) {
// Add cardNumber to SLF4J MDC
MDC.put("cardNumber",paymentRequest.cardNumber());
// Add Point Of Sale identifier to SLF4J MDC
MDC.put("pos",paymentRequest.posId());
try { // Add a try-finally construct and wrap the initial code here
//...
return httpResponse;
catch (Exception e) {
// Catch any exception to log it with MDC value
LOG.error(e.getMessage());
throw e;
} finally {
// Clear MDC at the end
MDC.clear();
}
}
Caution
Donβt forget to clear the MDC at the end of the method to avoid any data leak.
Now, we want to print these values when a log line is printed in the console.
π Modify to the spring configuration file (easypay-service/src/main/resources/application.yaml
) and add the
logging.level.pattern
property to add both the cardNumber
& pos
fields to all logs:
logging:
pattern:
level: "%5p [%mdc]"
Tip
%mdc
prints the full content of the MDC Map attached to the current thread.
If you want to print a single value, you can use %X{key}
where key
is the key of the value you want to print.
# Alternative to print specific fields instead
logging:
pattern:
level: "%5p [%X{cardNumber} - %X{pos}]"
Info
Using the Spring Boot logging.pattern.level
property is just a way to configure the logback pattern. You can also
use a logback configuration file to do the same thing.
You can also use the logging.pattern.correlation
property (used by tracing) or a logback configuration file to do
the same thing.
π οΈ Rebuild and redeploy the easypay-service
:
$ docker compose up -d --build easypay-service
Adding more content in our logs
π οΈ To have more logs, we will run several HTTP requests using K6. Run the following command:
$ k6 run -u 5 -d 5s k6/01-payment-only.js
π Check then the logs to pinpoint some exceptions.
Logs Correlation
Tip
You are probably wondering how to smartly debug in production when you have plenty of logs for several users and by the way different transactions?
One approach would be to correlate all of your logs using a correlation Id. If an incoming request has no correlation id header, the API creates it. If there is one, it uses it instead.
βΉοΈ This is a topic we will address in the tracing section.