简体   繁体   English

在Application Insight .Net Core 2.1中使用自定义属性记录用户名和IP

[英]Log UserName and IP with Custom Properties in Application Insight .Net Core 2.1

We are running an intranet Application on .Net Core 2.0. 我们正在.Net Core 2.0上运行Intranet应用程序。 Application insight is very helpfull to catch exceptions. 应用程序洞察对于捕获异常非常有帮助。 So when the User comes up to us for support we would like to find his request that caused problems in application insight. 因此,当用户向我们寻求支持时,我们希望找到他的请求,这会导致应用程序洞察力出现问题。 I added an ClientIpHeaderTelemetryInitializer like this: 我添加了一个ClientIpHeaderTelemetryInitializer,如下所示:

public class CustomTelemetry : ClientIpHeaderTelemetryInitializer
    {
        private readonly IHttpContextAccessor _httpContextAccessor ;

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

        /// <summary>
        /// Implements initialization logic.
        /// </summary>
        /// <param name="platformContext">Http context.</param>
        /// <param name="requestTelemetry">Request telemetry object associated with the current request.</param>
        /// <param name="telemetry">Telemetry item to initialize.</param>
        protected override void OnInitializeTelemetry(HttpContext platformContext, RequestTelemetry requestTelemetry, ITelemetry telemetry)
        {

            requestTelemetry.Properties.Add("UserName", _httpContextAccessor.HttpContext.User.Identity.Name);
            if (string.IsNullOrEmpty(telemetry.Context.Location.Ip))
            {
                LocationContext location = requestTelemetry.Context.Location;
                telemetry.Context.Location.Ip = location.Ip;
                requestTelemetry.Properties.Add("InternalIP", location.Ip);
            }
        }
    }

The Initalizer is registered at startup like this: Initalizer在启动时注册如下:

services.AddSingleton<ITelemetryInitializer, CustomTelemetry>();  

When I look at the requests Custom Data still turns up empty. 当我查看请求时,Custom Data仍然显示为空。 Application Insight自定义数据
Did I register it wrong? 我注册错了吗? I found the exact same line to add the service in the Integration Tests of Application Insights (although commented out...) 我在Application Insights的集成测试中找到了完全相同的行来添加服务(虽然注释掉了......)
Has anyone an Idea whats wrong? 有没有人的想法有什么不对?

First, you need to add application insights to your asp.net core project via menu option in visual studio: 首先,您需要通过visual studio中的menu选项向asp.net核心项目添加应用程序洞察: 在此输入图像描述

Second, in your CustomTelemetry class, you'd better set a breakpoint to make sure it can be hit when code is running. 其次,在CustomTelemetry类中,最好设置一个断点,以确保在代码运行时可以CustomTelemetry它。

Third, in your CustomTelemetry class, please do some logic when UserName and InternalIP is null or empty. 第三,在CustomTelemetry类中,当UserNameInternalIP为null或为空时,请执行一些逻辑。 If these values are null or empty, they will not be added. 如果这些值为null或为空,则不会添加它们。

My test code as below: 我的测试代码如下:

CustomTelemetry class: CustomTelemetry类:

public class CustomTelemetry: ITelemetryInitializer
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public CustomTelemetry(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public void Initialize(ITelemetry telemetry)
    {
        var requestTelemetry = telemetry as RequestTelemetry;
        if (requestTelemetry == null) return;

        if (!requestTelemetry.Context.Properties.ContainsKey("UserName"))
        {
            //if UserName is null or empty, add a default value for it
            if (string.IsNullOrEmpty(_httpContextAccessor.HttpContext.User.Identity.Name))
            {
                requestTelemetry.Context.Properties.Add("UserName", "NA");
            }
            else
            {
                requestTelemetry.Context.Properties.Add("UserName", _httpContextAccessor.HttpContext.User.Identity.Name);
            }

        }
        if (!requestTelemetry.Context.Properties.ContainsKey("InternalIP"))
        {
            //update
            if (!string.IsNullOrEmpty(requestTelemetry.Context.Location.Ip))
            {
                requestTelemetry.Context.Properties.Add("InternalIP", requestTelemetry.Context.Location.Ip);                   
            }
        }
    }
}

Then register in Startup class: 然后在Startup类中注册:

public void ConfigureServices(IServiceCollection services)
{
   services.AddMvc();
   services.AddSingleton<ITelemetryInitializer, CustomTelemetry>();
   services.AddApplicationInsightsTelemetry();
}

Test result: 测试结果:

在此输入图像描述

Since I don't have your ClientIpHeaderTelemetryInitializer class, just write the above test code. 由于我没有ClientIpHeaderTelemetryInitializer类,只需编写上面的测试代码即可。 If you need more help, please share that class. 如果您需要更多帮助,请分享该课程。

I finally got it working for my purposes. 我终于让它符合我的目的。

public class CustomTelemetry : ClientIpHeaderTelemetryInitializer
    {
        private readonly IHttpContextAccessor _httpContextAccessor ;

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

        /// <summary>
        /// Implements initialization logic.
        /// </summary>
        /// <param name="platformContext">Http context.</param>
        /// <param name="requestTelemetry">Request telemetry object associated with the current request.</param>
        /// <param name="telemetry">Telemetry item to initialize.</param>
        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 (ip != null) telemetry.Context.GlobalProperties.TryAdd("InternalIP", ip);
            if(userName != null) requestTelemetry.Properties.Add("UserName", userName);
        }
     }

(Note: ClientIpHeaderTelemetryInitializer is part of AppInsights) (注意:ClientIpHeaderTelemetryInitializer是AppInsights的一部分)

Important here is to get everything from the HttpContext , checking if it is null and adding custom properties. 这里重要的是从HttpContext获取所有内容,检查它是否为null并添加自定义属性。 The built in properties for IP can get overwritten otherwise. 否则,IP的内置属性可能会被覆盖。 Migrosoft GDPR Blogpost Migrosoft GDPR Blogpost

In the Startup add this to ConfigureService Startup中将此添加到ConfigureService

services.AddSingleton<ITelemetryInitializer, CustomTelemetry>();

Make sure to add the ContextAccessor beforehand so it can be injected: 确保事先添加ContextAccessor,以便可以注入:

services.AddHttpContextAccessor();

In Configure add this at the beginning: 在Configure中,在开头添加:

app.UseForwardedHeaders(new ForwardedHeadersOptions{ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto});

This is very important to optain the IP Adress when using reverse proxy like IIS . 在使用IIS反向代理时,这对于获取IP地址非常重要。 Otherwise you will always receive localhost. 否则,您将始终收到localhost。 UseForwardedHeaders() without options just does nothing! 没有选项的UseForwardedHeaders()什么都不做! (Also you will need a test setup with a remote server) (您还需要使用远程服务器进行测试设置)

Getting the Username just seems to work when the Request fails (tested with 500 Internal Server Error). 当请求失败时,获取用户名似乎正常工作(使用500内部服务器错误进行测试)。 Otherwise the HttpContextAccessor doesn't populate the User object. 否则,HttpContextAccessor不会填充User对象。 Could be a 2.1 thing, quite annoying maybe someone finds a way to get it for every request. 可能是一个2.1的事情,非常讨厌,也许有人找到一种方法来获得每个请求。

In the end your information should arrive at ApplicationInsights and look like this: 最后,您的信息应该到达ApplicationInsights,如下所示:
在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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