1

我想在 Application Insights 中的请求事件中包含标头,并找到以下帖子,其中包含具有 HttpContext 的应用程序的解决方案。我正在使用 Nancy 应用程序,其中请求标头存储在 NancyContext 中。问题是 Nancy 没有提供像 HttpContext.Current 这样的静态访问器,所以我想知道如何解决它。

我做了两次尝试都没有成功。第一个是构建一个 ITelemetryInitializer,如下面的链接中所述,但后来我无法访问 NancyContext。

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

我的第二次尝试是将 NancyModule 传递给将请求标头添加到 ITelemetryContext 的静态函数,但随后我无法获得当前的 ITelemetryContext。

有没有其他人遇到并解决了这个问题?

4

3 回答 3

7

实际上,.NET Framework 有一个示例:https ://blogs.msdn.microsoft.com/stuartleeks/2016/11/03/includes-headers-for-request-events-with-application-insights/

在 .NET Core 中,您只需使用 IHttpContextAccessor 而不是 HttpContext.Current 访问 HttpContext:

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

于 2018-07-17T18:51:13.230 回答
1

我找到了一个解决方案,可能不是最漂亮的,但至少它似乎有效。

我创建了一个静态可访问的AsyncLocal实例来保存每个线程的 RequestTelemetry 对象。

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

我将值设置RequestVariables.RequestTelemetryITelemetryInitializer

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();
});
于 2018-03-14T18:31:57.167 回答
1

您的第二种方法应该有效,并且您可以使用现有的扩展方法来获取当前的请求遥测(如果有的话)。

方法是方法HttpContextExtension.GetRequestTelemetry:(https://github.com/Microsoft/ApplicationInsights-dotnet-server/blob/2a681f5399a6aaee554fa2d93a1d6447a8402fe1/Src/Web/Web.Shared.Net/HttpContextExtension.cs#L16

这将为您返回给定 HttpContext 的当前请求遥测数据,因此您应该能够:

 var requestTelemetry = HttpContext.Current?.GetRequestTelemetry();
 // add whatever you need to the request telemetry?

从你的南希模块内部?

于 2018-03-09T00:30:53.500 回答