Application Insights is a monitoring service Microsoft provides which is now grouped under Azure Monitor. We use it monitor our applications and extremely useful in production environments. I spent most of the time in Transaction search when I have to look into deployed applications and it allows to see all the requests made apart from the trace and dependencies. Its extensible, so apart from providing most of the features we need out of the box, we can customize it and modify the default way of things.
In this blog, I just want to share a recent use case, where we had to add custom HTTP headers into application insights so that we can trace the id across multiple services. The standard way of doing it is explained in one of the Microsoft blogs that I have linked below. Its done in dot net framework style, so if you want it in the dot net core method, just have IHttpContextAccessor in the constructor to dependency inject and use HttpContext from that in place of sections where the blog uses HttpContext.Current. Also the way its registered in startup is obsolete, so just have the classes added to the container like :
services.AddSingleton<ITelemetryInitializer, HeaderTelemetryInitializer>();
Bottom line is to have a class inherit from ITelemetryInitializer and register it in the services and we are good to go.
Including Headers for Request Events with Application Insights | Microsoft Docs
But I was using the Microsoft provided NuGet package for header propagation. When I have a header “YourId” in the incoming request, I should use it. If it’s absent, my application would generate a new GUID and I need to transfer this value as “YourId” in the header for the next request made by the service.
Initially I created the TelemetryInitializer class and had the GUID logic in it. It worked when the incoming request already had the header. But when my service had to create a new GUID for the header, the right id wasn’t being populated into the application insights. This is because the GUID was generated in Telemetry class which doesn’t work well with the header propagation rules of the NuGet package.
As it turned out, all I wanted was the ability to add the id to the Telemetry as soon as it was created. I didn’t know how to get hold of the telemetry object in the Startup class. All I needed was the below line of code.
var requestTelemetry = context.HttpContext.Features.Get<RequestTelemetry>();
The above line gives you access to RequestTelemetry object which then gives you access to its properties. You can see the complete code below.
services.AddHeaderPropagation(options =>
{
var correlationId = "YourId";
options.Headers.Add(correlationId, context => {
var requestTelemetry = context.HttpContext.Features.Get<RequestTelemetry>();
if (context.HttpContext.Request.Headers.TryGetValue(correlationId, out var value))
{
requestTelemetry.Properties[correlationId] = value.ToString();
return value.ToString();
}
else
{
var guidId = Guid.NewGuid().ToString();
requestTelemetry.Properties[correlationId] = guidId;
return new StringValues(guidId);
}
});
});
So this allows you to delegate the job of header propagation to the Microsoft NuGet package, but also add the ids to application insights based on the condition. If you want to checkout basic header propagation, check my earlier post linked below.
HTTP Header Propogation in ASP.Net Core – Bobby’s Blog! (bobbythetechie.com)
I guess not many people face these kinds of issues or there might be better ways to do this. I posted the question in stackoverflow and I had to answer it myself. 🙂