C# 将请求头添加到Application Insights telemetry for Nancy应用程序

C# 将请求头添加到Application Insights telemetry for Nancy应用程序,c#,asp.net-core,nancy,azure-application-insights,telemetry,C#,Asp.net Core,Nancy,Azure Application Insights,Telemetry,我想在ApplicationInsights中的请求事件中包含标题,并找到了以下文章,其中包含了一个针对具有HttpContext的应用程序的解决方案。我正在使用一个Nancy应用程序,其中请求头存储在NancyContext中。问题是Nancy并没有提供像HttpContext.Current这样的静态访问器,所以我想知道如何解决这个问题 我做了两次尝试都没有成功。第一个是构建一个ITelemetryInitializer,如下面的链接所述,但是我无法访问NancyContext 我的第二次

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

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

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


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

您的第二种方法应该可以工作,如果有,您可以使用现有的扩展方法来获取当前的请求遥测

方法是方法:
httpcontextension.GetRequestTelemetry
()

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

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

从Nancy模块内部?

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

方法是方法:
httpcontextension.GetRequestTelemetry
()

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

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

从你的Nancy模块内部?

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

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

public class RequestVariables
{
    public static AsyncLocal<RequestTelemetry> RequestTelemetry = new AsyncLocal<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();
});

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

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

public class RequestVariables
{
    public static AsyncLocal<RequestTelemetry> RequestTelemetry = new AsyncLocal<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();
});

实际上,.NET Framework有一个例子:

在.NET Core中,您只需使用IHttpContextAccessor而不是HttpContext来访问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>();
公共类遥测标头初始化器:ITelemetryInitializer
{
专用只读IHttpContextAccessor\u httpContextAccessor;
公共列表请求头{get;set;}
公共列表响应头{get;set;}
公共遥测磁头初始化器(IHttpContextAccessor httpContextAccessor)
{
RequestHeaders=新列表{“Referer”};//您需要什么
ResponseHeaders=新列表{…};
_httpContextAccessor=httpContextAccessor;
}
公共无效初始化(ITelemetry遥测)
{
var requestTelemetry=作为requestTelemetry的遥测;
//这是TrackRequest()吗?
if(requestTelemetry==null)返回;
var context=\u httpContextAccessor.HttpContext;
if(context==null)返回;
foreach(RequestHeaders中的var headerName)
{
var headers=context.Request.headers[headerName];
if(headers.Any())
{
remotery.Context.Properties.Add($“Request-{headerName}”,string.Join(Environment.NewLine,headers));
}             
}
foreach(负责人中的var headerName)
{
var headers=context.Response.headers[headerName];
if(headers.Any())
{
remotery.Context.Properties.Add($“Response-{headerName}”,string.Join(Environment.NewLine,headers));
}
}
}
}
//服务中心:
services.AddSingleton();
同时检查:

实际上,.NET Framework有一个例子:

在.NET Core中,您只需使用IHttpContextAccessor而不是HttpContext来访问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>();
公共类遥测标头初始化器:ITelemetryInitializer
{
专用只读IHttpContextAccessor\u httpContextAccessor;
公共列表请求头{get;set;}
公共列表响应头{get;set;}
公共遥测磁头初始化器(IHttpContextAccessor httpContextAccessor)
{
RequestHeaders=新列表{“Referer”};//您需要什么
ResponseHeaders=新列表{…};
_httpContextAccessor=httpContextAccessor;
}
公共无效初始化(ITelemetry遥测)
{
var requestTelemetry=作为requestTelemetry的遥测;
//这是TrackRequest()吗?
if(requestTelemetry==null)返回;
var context=\u httpContextAccessor.HttpContext;
if(context==null)返回;
foreach(RequestHeaders中的var headerName)
{
var headers=context.Request.headers[headerName];
if(headers.Any())
{
remotery.Context.Properties.Add($“Request-{headerName}”,string.Join(Environment.NewLine,headers));
}             
}
foreach(负责人中的var headerName)
{
var headers=context.Response.headers[headerName];
if(headers.Any())
{
remotery.Context.Properties.Add($“Response-{headerName}”,string.Join(Environment.NewLine,headers));
}
}
}
}
//服务中心:
services.AddSingleton();
同时检查:

未能通过这种方式获得请求遥测。可能是因为我的项目是AspNetCore,它使用的是
Microsoft.AspNe