Добавление заголовков запросов в телеметрию Application Insights для приложения Nancy

Я хочу включить заголовки в события запроса в Application Insights и нашел следующее сообщение, в котором есть решение для приложения с HttpContext. Я работаю с приложением Nancy, где заголовки запросов хранятся в NancyContext. Проблема в том, что Нэнси не предоставляет статический аксессор, такой как HttpContext.Current, поэтому мне интересно, как я могу это решить.

Я сделал две попытки, но безуспешно. Первым было создание ITelemetryInitializer, как описано в приведенной ниже ссылке, но затем я не смог получить доступ к NancyContext.

https://blogs.msdn.microsoft.com/stuartleeks/2016/11/03/including-headers-for-request-events-with-application-insights/

Моя вторая попытка состояла в том, чтобы передать NancyModule статической функции, которая добавляла заголовки запроса в ITelemetryContext, но вместо этого я не мог получить текущий ITelemetryContext.

Кто-нибудь еще сталкивался и решал эту проблему?


person OriginalUtter    schedule 06.03.2018    source источник


Ответы (3)


Собственно, для .NET Framework есть пример: https://blogs.msdn.microsoft.com/stuartleeks/2016/11/03/including-headers-for-request-events-with-application-insights/

В .NET Core вы просто получаете доступ к HttpContext с помощью IHttpContextAccessor вместо HttpContext.Current:

public class TelemetryHeadersInitializer : ITelemetryInitializer
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public List<string> RequestHeaders { get; set; }
    public List<string> ResponseHeaders { get; set; }

    public TelemetryHeadersInitializer(IHttpContextAccessor httpContextAccessor)
    {
        RequestHeaders = new List<string> { "Referer" }; //whatever you need
        ResponseHeaders = new List<string> { ... };
        _httpContextAccessor = httpContextAccessor;
    }

    public void Initialize(ITelemetry telemetry)
    {
        var requestTelemetry = telemetry as RequestTelemetry;
        // Is this a TrackRequest() ?
        if (requestTelemetry == null) return;

        var context = _httpContextAccessor.HttpContext;
        if (context == null) return;

        foreach (var headerName in RequestHeaders)
        {
            var headers = context.Request.Headers[headerName];
            if (headers.Any())
            {
                telemetry.Context.Properties.Add($"Request-{headerName}", string.Join(Environment.NewLine, headers));
            }             
        }
        foreach (var headerName in ResponseHeaders)
        {
            var headers = context.Response.Headers[headerName];
            if (headers.Any())
            {
                telemetry.Context.Properties.Add($"Response-{headerName}", string.Join(Environment.NewLine, headers));
            }
        }
    }
}

//Services.cs:
services.AddSingleton<ITelemetryInitializer, TelemetryHeadersInitializer>();

Также проверьте: https://github.com/Microsoft/ApplicationInsights-aspnetcore/wiki/Custom-Configuration

person Liero    schedule 17.07.2018


Я нашел решение, может быть, не самое красивое, но, по крайней мере, оно работает.

Я создал статически доступный экземпляр AsyncLocal для хранения объекта RequestTelemetry для каждого потока.

public class RequestVariables
{
    public static AsyncLocal<RequestTelemetry> RequestTelemetry = new AsyncLocal<RequestTelemetry>();
}

Я установил значение RequestVariables.RequestTelemetry в ITelemetryInitializer

public class RequestTelemetryInitializer : ITelemetryInitializer
{
    public void Initialize(ITelemetry telemetry)
    {
        if (telemetry is RequestTelemetry requestTelemetry)
            RequestVariables.RequestTelemetry.Value = requestTelemetry;
    }
}

Затем я зарегистрировал небольшое промежуточное ПО в методе Startup.Configure(...), которое извлекает экземпляр RequestTelemetry, установленный ITelemetryInitializer, и добавляет к нему заголовки запроса.

app.Use((context, next) =>
{
    var requestTelemetry = RequestVariables.RequestTelemetry.Value;
    if (requestTelemetry?.Context == null) return next();

    foreach (var header in context.Request.Headers)
    {
        if (!requestTelemetry.Context.Properties.ContainsKey(header.Key))
            requestTelemetry.Context.Properties.Add(header.Key, header.Value.First());
    }

    return next();
});
person OriginalUtter    schedule 14.03.2018