In a previous article, I showed you how to log to Azure Application Insights from a Java Spring Boot Application.
When logging a lot of data for a popular application, it can be difficult to search for data related to a specific call to a method. One way to address this is to generate a unique key for each call and record that key with every entry logged by the method or by any method called by that method.
You could pass this key as a parameter to every method, and include it with each logging statement; but that is inefficient and there is a good chance you may sometimes forget to pass it. The Mapped Diagnostic Context (MDC) service provides a way for you to include one or more key-value pairs in every Application Insights logging entry made by the current method and by any methods called in-process by that method.
Imagine I have a controller class that calls a service class and I have instantiated a logger object at the top of each:
private Logger logger = LoggerFactory.getLogger(MathController.class);
and that I have a Controller method named "Add" that adds together two number and I do some logging in that method, as shown below
@GetMapping("add/{firstNumber}/{secondNumber}")
public ResponseEntity<Integer> Add(
@PathVariable("firstNumber") Integer firstNumber,
@PathVariable("secondNumber") Integer secondNumber) {
logger.info("MathController.Add() called with " + firstNumber + " and " + secondNumber);
Integer sum = mathService.AddNumbers(firstNumber, secondNumber);
return new ResponseEntity<Integer>(sum, HttpStatus.OK);
}
and that this method calls a service to do the work of adding together the numbers and that service also does some logging, like so:
@Override
public Integer AddNumbers(Integer firstNumber, Integer secondNumber) {
logger.info("MathServiceImpl.AddNumbers() called with " + firstNumber + " and " + secondNumber);
Integer sum = firstNumber + secondNumber;
return sum;
}
I can add the following two lines to the top of my Controller's Add() method:
String requestKey = UUID.randomUUID().toString();
MDC.put("Request-Key", requestKey);
This generates a new random key on each call to the controller and stores that key in the MDC object.
The modified method now looks like this:
@GetMapping("add/{firstNumber}/{secondNumber}")
public ResponseEntity<Integer> Add(
@PathVariable("firstNumber") Integer firstNumber,
@PathVariable("secondNumber") Integer secondNumber) {
String requestKey = UUID.randomUUID().toString();
MDC.put("Request-Key", requestKey);
logger.info("MathController.Add() called with " + firstNumber + " and " + secondNumber);
Integer sum = mathService.AddNumbers(firstNumber, secondNumber);
return new ResponseEntity<Integer>(sum, HttpStatus.OK);
}
Now, every time I log from this method or any in-process calls that this method makes, it will automatically add the Request-Key name-value pair to the log entry in Application Insights. I do not need to add the MDC.put() code to the service method. Because it is called in-process, it already knows to include the extra logging information.
When I run this code and call the controller method, Application Insights will include an extra custom property, as shown in Fig. 1.
Fig. 1
This is a simple, low-code way to add extra information to your logging, making it easier to track and troubleshoot your application.
You can find the code for this article here.