3 minute read

Whenever you are collecting a date with Application Insights, it might be handy to have the ability to filter the telemetry based on currently signed in user. The documentation is quite confusing about it, so I decided to write an article and clear it up.

So after setting up Application Insights in your application as per the Getting Started documentation, telemetry will start to get collected and will show up in the portal - however, when the user signs in, for example with Azure AD, you won't get any such information in the telemetry. This can be a sort of pain point, when you get report from one user that something is not working and you need to inspect the telemetry for that user.

JavaScript

If you want to add current user to the telemetry from JavaScript, the process is well document and explained.

ASP.NET Core

In ASP.NET (on the server-side) there isn't much guidance for how to do this correctly. You could modify the telemetry data yourself by for example setting custom properties for each telemetry request, or you could , but there is a much more cleaner way to do this - we will create our own implementation of ITelemetryInitializer, so whenever telemetry is supposed to be sent, the request will have the information populated automatically.

With classic ASP.NET, you would implement the ITelemetryInitializer and then add it to the TelemetryInitializers list (described here for example). This works for ASP.NET, however you usually want to pull the current user information from request's claims (HttpContext.User), which is possible from within ASP.NET, but with ASP.NET Core, there is no HttpContext.Current accessor. So we have to take another approach - using Dependency Injection, which does the job for us!

It took me a while to figure out, that the AI for ASP.NET Core is internally depending on the Dependency Injection container, which makes a lot of things simple and straightforward. You can look at the source of AI for ASP.NET Core package for reference.

So we implement an ITelemetryInitializer like usual, except that in the constructor, we are going to require IHttpContextAccessor which then allows us to access the correct HttpContext (more about it can be found here). You can see an example implementation below. The rest is then just about setting the property values to whatever you need them to be.

public class AppInsightsInitializer : ITelemetryInitializer
{
    private IHttpContextAccessor _httpContextAccessor;
    public AppInsightsInitializer(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException("httpContextAccessor");
    }
    public void Initialize(ITelemetry telemetry)
    {
        var httpContext = _httpContextAccessor.HttpContext;
        if (httpContext != null && httpContext.User.Identity.IsAuthenticated == true && httpContext.User.Identity.Name != null)
        {
            telemetry.Context.User.AuthenticatedUserId = httpContext.User.Identity.Name;
            telemetry.Context.User.AccountId = httpContext.User.FindFirst(AppClaimTypes.TenantId).Value;
        }
    }
}

A lot of great samples of ITelemetryInitializer implementation can be found in the official repo which contains some of the default ones.

After that, you just add this class to the DI container like so:

services.AddSingleton<ITelemetryInitializer, AppInsightsInitializer>();

Now you can see the user data in the telemetry as well. You could use the same if there is CloudFlare in front of you web server and you need to show the real user's IP address in the telemetry (passed as CF-Connecting-IP header in the request).

Comments

Sam

Hi, I tried to follow your sample but can’t find custom AccountId in any of my traces logs. I’m using “Microsoft.Extensions.Logging.ApplicationInsights” Version=”2.14.0” in my AspNet Core 3.1 project and not the SDK nuget package Microsoft.ApplicationInsights.AspNetCore. Any clues, what am I missing here? Thanks

To submit comments, go to GitHub Discussions.