在 ASP.NET Core 的 Application Insights 中填充用户 ID 字段

pba*_*nis 3 azure-application-insights asp.net-core asp.net-core-2.2 scrutor

我希望能够使用我的真实用户名数据填充 Application Insights 中的用户 ID 字段。这是一个内部应用程序,因此对简单用户名字段的隐私问题没有实际意义。

据我所知,所有在线可用的解决方案都严格适用于 .NET Framework,而不是 .NET Core。

您可以在几个地方找到此解决方案,包括 GitHub 上的一些旧 AI 文档。但是,当我运行它时,我在启动时收到一个错误,表明单例不能接受对作用域对象 IHttpContextAccessor 的依赖,这当然是合乎逻辑的。除非 .NET Core 的 DI 的先前版本允许(我使用的是 2.2),否则我看不出这是如何工作的。

GitHub 上的这个 issue有点说明了问题,但在 AI 团队指出你必须使用单例后,它被关闭了。我尝试了 OP 中的内容和第一个响应的变体,当代码运行时,AI 上的用户 ID 字段继续充满乱码数据。

有没有办法让 AI 中的 User Id 字段填充一些对来自 ASP.NET Core 应用程序的服务器请求有用的东西?

编辑

在看到下面的答案后,我的代码应该可以正常工作,我回过头来意识到异常消息没有特别提到 IHttpContextAccessor:

System.InvalidOperationException: '不能从单例'Microsoft.Extensions.Options.IConfigureOptions`1[Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration]'使用范围服务'Microsoft.ApplicationInsights.Extensibility.ITelemetryInitializer'。'

现在,我的代码看起来与下面@PeterBons 的答案几乎相同,因此从表面上看,此异常毫无意义。 TelemetryConfiguration没有事件出现在我的代码中。但后来我想起我正在使用 Scrutor 在 Startup 中懒惰地进行 DI 注册:

    services.Scan(scan => scan
        .FromAssembliesOf(typeof(Startup), typeof(MyDbContext))
        .AddClasses()
        .AsSelfWithInterfaces().WithScopedLifetime());
Run Code Online (Sandbox Code Playgroud)

我认为问题是我需要将我的 ITelemetryInitializer 注册为 Singleton,而这段代码无意中将其取消或重新注册为作用域。所以我把最后两行改为:

        .AddClasses(f => f.Where(t => t != typeof(RealUserAIProvider)))
        .AsSelfWithInterfaces().WithScopedLifetime());
Run Code Online (Sandbox Code Playgroud)

它奏效了。与其在上面编辑我的错误,不如留下它。@PeterBons 下面的回答仍然对其他人有帮助,也许我对 Scrutor 的困惑也会对某人有所帮助。

Pet*_*ons 6

您不必将 注册HttpContextAccessor为作用域依赖项。只需使用单例。

我们使用这个在生产中工作:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
Run Code Online (Sandbox Code Playgroud)

结合这个初始化器:

public class SessionDetailsTelemetryEnrichment : TelemetryInitializerBase
{
    public SessionDetailsTelemetryEnrichment(IHttpContextAccessor httpContextAccessor) : base(httpContextAccessor)
    {

    }

    protected override void OnInitializeTelemetry(HttpContext platformContext, RequestTelemetry requestTelemetry, ITelemetry telemetry)
    {
        telemetry.Context.User.AuthenticatedUserId =
            platformContext.User?.Claims.FirstOrDefault(c => c.Type == "Username")?.Value ?? string.Empty;

    }
}
Run Code Online (Sandbox Code Playgroud)