Заполнение поля идентификатора пользователя в Application Insights из ASP.NET Core

Я хотел бы иметь возможность заполнять поле User Id в Application Insights данными моего настоящего имени пользователя. Это внутреннее приложение, поэтому вопросы конфиденциальности, связанные с простым полем имени пользователя, остаются спорными.

Насколько я могу судить, все доступные в Интернете решения для этого работают строго в .NET Framework, а не в .NET Core.

Вы можете найти это решение в нескольких местах, включая старую документацию по ИИ на GitHub. Однако, когда я запускаю его, я получаю сообщение об ошибке при запуске, указывающее на то, что зависимость от объекта с областью действия IHttpContextAccessor неприемлема для синглтона, что, конечно, логично. Я не понимаю, как это могло когда-либо работать, если бы это не было разрешено в предыдущей версии .NET Core DI (я использую 2.2).

Эта проблема на GitHub как бы описывает проблему, но она была закрыта после Команда AI указала, что вы должны использовать синглтон. Я пробовал варианты того, что находится в OP и первом ответе, и пока код работал, поле User Id в AI продолжало заполняться тарабарщиной данными.

Есть ли способ заполнить поле User Id в AI чем-то полезным для запросов к серверу, поступающих из приложения ASP.NET Core?

РЕДАКТИРОВАТЬ

Увидев ответ ниже, что мой код должен работать нормально, я вернулся и понял, что в сообщении об исключении конкретно не упоминается IHttpContextAccessor:

System.InvalidOperationException: 'Невозможно использовать службу с заданной областью' Microsoft.ApplicationInsights.Extensibility.ITelemetryInitializer 'из одиночного объекта' Microsoft.Extensions.Options.IConfigureOptions`1 [Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration] '.

Теперь мой код выглядит почти идентично ответу @PeterBons ниже, поэтому на первый взгляд это исключение не имело смысла. TelemetryConfiguration в моем коде не отображается событие. Но потом я вспомнил, что использую Scrutor для ленивой регистрации DI в Startup:

    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 кому-то тоже поможет.


person pbarranis    schedule 10.07.2019    source источник


Ответы (1)


Вам не нужно регистрировать 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;

    }
}
person Peter Bons    schedule 11.07.2019
comment
Спасибо. Увидев ваш комментарий, я вернулся и повторил то, что делал вчера, только чтобы понять, что полученное мной исключение не упоминает конкретно IHttpContextAccessor. Меня кусает Scrutor, выполняющий автоматическую регистрацию. Как только я найду исправление, я обновлю свой пост выше. Очень неловко, но, возможно, это поможет кому-то другому. Еще раз спасибо. - person pbarranis; 11.07.2019
comment
Привет, не могли бы вы обновить свой ответ, чтобы показать, как использовать SessionDetailsTelemetryEnrichment? Я пробовал services.AddSingleton<ITelemetryInitializer, SessionDetailsTelemetryEnrichment>();, но это не помогло. Пожалуйста, ответьте на мой вопрос на этом здесь - person Priyank Panchal; 17.02.2020