Application Insights将用户名添加到遥测

时间:2019-12-13 10:24:18

标签: c# asp.net azure-application-insights

我正在尝试在用户执行请求时在应用程序见解中记录用户名。

我一直试图这样操作:

 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;
        }
    }

Startup.cs中注入并注册电报机之后:

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

但这会导致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)

然后我尝试了以下代码:

 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;
            }
        }
    }

这在本地计算机上运行良好。但是,当我在开发环境中尝试时,它只会记录服务器名称而不是用户名称。

所以我在想我的第一个解决方案是正确的方法。但是,我无法避免它因Safe handle has been closed异常而崩溃。

是否有帮助克服这个困难?

1 个答案:

答案 0 :(得分:1)

四处逛逛似乎可以解决您的问题

    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;
        }
    }

这实际上是您的两个示例的组合。 我相信,区别在于使用Initialize方法而不是重写的OnInitializeTelemetry方法。 您的httpContextAccessor可能仍然在Initialize方法中仍然有效,而已被放置在被覆盖的方法中。 不知道从ClientIpHeaderTelemetryInitializer继承的动机是什么,以及它是否相关。

代码是从here复制的。