Take advantage of the built-in correlation IDs in Web API to track HTTP requests that flow through multiple back-end services Credit: Thinkstock When working with microservices that communicate over the HTTP protocol, you will want to use correlation IDs to track individual requests. Because requests might flow through many services that are spread across multiple systems, tracking them with correlation IDs will be your only hope of detecting and diagnosing errors that might creep into the middleware systems. This article discusses what correlation IDs are, why they are useful, and how they can be used in ASP.Net Web API. What are correlation IDs? Let’s assume you have implemented a microservices architecture. In an application comprised of microservices, different aspects of incoming requests will be handled by different microservices, all working asynchronously on their specific tasks and ultimately coming together to generate the response. Now, if something goes wrong, how would you determine by looking at the logs exactly where the request failed? Your logs might contain millions upon millions of log messages. It would be a daunting task to find the relevant log entries among so many messages. The basic idea is that you may want to track every request. Because the request may be executed by different service components, you need a way to tie all of these service components to the request. Here’s exactly where a correlation ID comes to the rescue. A correlation ID is a unique identifier that provides a way to correlate all of the different micro tasks to the same macro operation. By ensuring that all of the responses contain the same unique identifier, you allow for the tracking and debugging of each request. Using correlation IDs in Web API ASP.Net Web API is a lightweight framework for building RESTful services that can run over HTTP. It has been the framework of choice for building RESTful services in ASP.Net for quite some time now. In this example, we will implement a message handler to store a correlation ID in the response header, so that we can send that ID back to the client. Message handlers are used to process, edit, or even decline an incoming request before it reaches the HttpControllerDispatcher in Web API. Incidentally, HttpControllerDispatcher is a built-in message handler that dispatches the request to the HTTP controller. We can take advantage of our own message handler to add a response header much earlier in the request processing pipeline. Note that you should also include the correlation ID in every log message so that you can track individual HTTP requests. Create a simple Web API project in Visual Studio and create a class named CorrelationIdHandler that extends the DelegatingHandler class. Our custom message handler will have this basic form: public class CorrelationIdHandler : DelegatingHandler { } The following code snippet can be used to add a correlation ID to the response header. response.Headers.Add(CorrelationIdHeaderName, request.GetCorrelationId().ToString()); The GetCorrelationId() extension method first checks to see if the correlation ID is present in the request. If the correlation ID is present, the method retrieves the correlation ID from the request object and adds it to the response header. If the correlation ID is not present, it generates one and adds it to the response header. Here’s the complete source code of the message handler for your reference: public class CorrelationIdHandler : DelegatingHandler { private const string key ="X-Correlation-ID"; protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var response = await base.SendAsync(request, cancellationToken); response.Headers.Add(key, request.GetCorrelationId().ToString()); return response; } } You should add the custom message handler to the MessageHandlers collection of the HttpConfiguration object. Here’s how you can do this in the Register method of the WebApiConfig class. public static void Register(HttpConfiguration config) { // Usual code here config.MessageHandlers.Add(new CorrelationIdHandler()); } The following unit test method can be used to retrieve the correlation ID from the HTTP response. [TestMethod] public void CorrelationIdTest() { HttpClient client = new HttpClient(); client.BaseAddress = new Uri(“http://localhost:10564/“); string key ="X-Correlation-ID"; IEnumerable<string> correlationIds = null; var response = client.GetAsync(“api/values/“).Result; if (response.Headers.Contains(key)) { response.Headers.TryGetValues(key, out correlationIds); } string correlationId = correlationIds.First(); Assert.IsNotNull(correlationId); } The next step is including the correlation ID in the logs. To do this, you should capture the correlation ID from the response header and add it to your log context so that all writes to the log include the correlation ID. Finally, note that the approach to implementing correlation IDs in ASP.Net MVC Core is a bit different. To accomplish the same as above using ASP.Net MVC Core, you would have to write some middleware, because ASP.Net MVC Core does not have message handlers. I will demonstrate how to do this together with logging in a future article. Related content feature 14 great preprocessors for developers who love to code Sometimes it seems like the rules of programming are designed to make coding a chore. Here are 14 ways preprocessors can help make software development fun again. By Peter Wayner Nov 18, 2024 10 mins Development Tools Software Development feature Designing the APIs that accidentally power businesses Well-designed APIs, even those often-neglected internal APIs, make developers more productive and businesses more agile. By Jean Yang Nov 18, 2024 6 mins APIs Software Development news Spin 3.0 supports polyglot development using Wasm components Fermyon’s open source framework for building server-side WebAssembly apps allows developers to compose apps from components created with different languages. By Paul Krill Nov 18, 2024 2 mins Microservices Serverless Computing Development Libraries and Frameworks news Go language evolving for future hardware, AI workloads The Go team is working to adapt Go to large multicore systems, the latest hardware instructions, and the needs of developers of large-scale AI systems. By Paul Krill Nov 15, 2024 3 mins Google Go Generative AI Programming Languages Resources Videos