简体   繁体   中英

Application Insights add username to telemetry

I'm trying to log the usernames for users in application insights when they are doing requests.

I've been trying to do it this way as:

 public class AppInsightsInitializer : ClientIpHeaderTelemetryInitializer
    {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public AppInsightsInitializer(IHttpContextAccessor httpContextAccessor) : base(httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        protected override void OnInitializeTelemetry(HttpContext platformContext, RequestTelemetry requestTelemetry, ITelemetry telemetry)
        {
            var userName = _httpContextAccessor.HttpContext?.User?.Identity?.Name; // Only set when request failed...
            var ip = _httpContextAccessor.HttpContext?.Connection?.RemoteIpAddress?.ToString();
            if (userName != null) requestTelemetry.Context.User.AuthenticatedUserId= userName;
        }
    }

After injecting and registering the telemtry in Startup.cs :

 services.AddApplicationInsightsTelemetry(instrumentKey);
 services.AddSingleton<ITelemetryInitializer, AppInsights.AppInsightsInitializer>();

But this one results in a System.ObjectDisposedException: 'Safe handle has been closed

System.ObjectDisposedException
  HResult=0x80131622
  Message=Safe handle has been closed
  Source=mscorlib
  StackTrace:
   at System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success)
   at System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle, Boolean& success)
   at Microsoft.Win32.Win32Native.GetTokenInformation(SafeAccessTokenHandle TokenHandle, UInt32 TokenInformationClass, SafeLocalAllocHandle TokenInformation, UInt32 TokenInformationLength, UInt32& ReturnLength)
   at System.Security.Principal.WindowsIdentity.GetTokenInformation(SafeAccessTokenHandle tokenHandle, TokenInformationClass tokenInformationClass)
   at System.Security.Principal.WindowsIdentity.get_User()
   at System.Security.Principal.WindowsIdentity.GetName()
   at System.Security.Principal.WindowsIdentity.get_Name()
   at Webeco.Web.AppInsights.AppInsightsInitializer.OnInitializeTelemetry(HttpContext platformContext, RequestTelemetry requestTelemetry, ITelemetry telemetry) in C:\Users\SESEGU\Documents\Projects\AppInsights\AppInsightsInitializer.cs:line 24
   at Microsoft.ApplicationInsights.AspNetCore.TelemetryInitializers.TelemetryInitializerBase.Initialize(ITelemetry telemetry)
   at Microsoft.ApplicationInsights.TelemetryClient.Initialize(ITelemetry telemetry)

Then I tried the below code:

 public class AppInsightsInitializer : ITelemetryInitializer
    {
        public void Initialize(ITelemetry telemetry)
        {
            var identity = WindowsIdentity.GetCurrent();
            if (identity != null)
            {
                var name = new WindowsPrincipal(identity);
                telemetry.Context.User.AuthenticatedUserId = name.Identity.Name;
            }
        }
    }

This works well on a localmachine. But when I try it in dev environment it only logs the server name instead of the user name.

So I'm thinking that my first solution is the correct way to go. However I can't get past it crashing with the Safe handle has been closed exception.

Any help in getting past this?

After looking around a bit it looks like this might solve your problem

    public class AuthenticatedUserIdTelemetryInitializer : ITelemetryInitializer
    {
        IHttpContextAccessor httpContextAccessor;

        public AuthenticatedUserIdTelemetryInitializer(IHttpContextAccessor httpContextAccessor)
        {
            this.httpContextAccessor = httpContextAccessor;
        }

        public void Initialize(ITelemetry telemetry)
        {
            if (this.httpContextAccessor?.HttpContext?.User?.Identity?.IsAuthenticated == true)
                telemetry.Context.User.AuthenticatedUserId = this.httpContextAccessor.HttpContext.User.Identity.Name;
        }
    }

It is really a combination of your two examples. I believe that the difference is in using Initialize method instead of the overridden OnInitializeTelemetry method. It might be that your httpContextAccessor is still alive in the Initialize method, while it is already disposed in the overridden one. Not sure what is the motivation to inherit from ClientIpHeaderTelemetryInitializer and if it is relevant.

Code is copied from here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM