从 ASP.NET Core 填写 Application Insights 中的用户 ID 字段

Filling User Id Field in Application Insights from ASP.NET Core

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

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

您可以在一些地方找到 this solution,包括一些关于 GitHub 的旧 AI 文档。但是,当我 运行 它时,我在启动时收到一个错误,指示对作用域对象 IHttpContextAccessor 的依赖对于单例来说是不可接受的,这当然是合乎逻辑的。除非 .NET Core 的 DI 的先前版本允许它(我在 2.2 上),否则我看不出这是怎么回事。

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

有什么方法可以使 AI 中的用户 ID 字段填充对来自 ASP.NET 核心应用的服务器请求有用的内容吗?

编辑

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

System.InvalidOperationException: 'Cannot consume scoped service 'Microsoft.ApplicationInsights.Extensibility.ITelemetryInitializer' from singleton 'Microsoft.Extensions.Options.IConfigureOptions`1[Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration]'.'

现在,我的代码看起来与下面@PeterBons 的回答几乎相同,所以从表面上看,这个异常没有任何意义。 TelemetryConfiguration 事件没有出现在我的代码中。但是后来我想起来我在 Startup 中使用 Scrutor 懒惰地进行 DI 注册:

    services.Scan(scan => scan
        .FromAssembliesOf(typeof(Startup), typeof(MyDbContext))
        .AddClasses()
        .AsSelfWithInterfaces().WithScopedLifetime());

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

        .AddClasses(f => f.Where(t => t != typeof(RealUserAIProvider)))
        .AsSelfWithInterfaces().WithScopedLifetime());

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

您不必将 HttpContextAccessor 注册为作用域依赖项。就用单例吧。

我们在生产中使用这个:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

结合这个初始值设定项:

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;

    }
}