Application Insights 请求遥测缺少基本路径

Application Insights Request Telemetry missing base path

我在反向代理(Azure 应用程序网关)后面的 Service Fabric 节点上有一个 ASP.NET Core 2.1 WebApi 运行。

网址如下:

Application Insights 照常添加。

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddApplicationInsightsTelemetry();
                new ServiceInstanceListener(serviceContext => new HttpSysCommunicationListener(serviceContext, "ServerServiceEndpoint",
                    (url, listener) =>
                    {
                        var endpointConfig = serviceContext.CodePackageActivationContext.GetEndpoint("ServerServiceEndpoint");

                        return new WebHostBuilder()
                            .UseHttpSys()
                            .ConfigureServices(services => services.AddSingleton(serviceContext))
                            .UseContentRoot(Directory.GetCurrentDirectory())
                            .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                            .UseStartup<Startup>()
                            .UseUrls($"{url}{endpointConfig.PathSuffix}") // "/product/api"
                            .Build();
                    }))

所以 endpointConfig.PathSuffix 没有被添加到请求遥测中。我该怎么做才能解决这个问题?我更愿意编写自定义遥测初始化器或处理器。

我尝试将此行添加到我的 WebHostBuilder,但行为没有任何变化:

                            .Configure(app => app.UsePathBase(endpointConfig.PathSuffix))

编辑:PathBase 被 ASP.NET 核心正确识别,但请求遥测中缺少它。如果我在没有 Service Fabric 的情况下设置独立项目,PathBase 会按预期添加到 Request Telemetry。

根据docs,你需要注册一个TelemetryInitializer,并调用UseApplicationInsights:

.UseKestrel()
    .ConfigureServices(
        services => services
            .AddSingleton<HttpClient>(new HttpClient())
            .AddSingleton<FabricClient>(new FabricClient())
            .AddSingleton<StatelessServiceContext>(serviceContext)
            .AddSingleton<ITelemetryInitializer>((serviceProvider) => FabricTelemetryInitializerExtension.CreateFabricTelemetryInitializer(serviceContext)))
    .UseContentRoot(Directory.GetCurrentDirectory())
    .UseStartup<Startup>()
    .UseApplicationInsights()
    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
    .UseUrls(url)
    .Build();
    ...

要解决此问题,您可以创建自定义遥测初始化程序,如下所示:

class RewriteUriInitializer : ITelemetryInitializer
{
    private const int SegmentsToSkip = 3;

    public void Initialize(ITelemetry telemetry)
    {
        var requestTelemetry = telemetry as RequestTelemetry;
        if (requestTelemetry != null)
        {
            //change requestTelemetry.Url and requestTelemetry.Name 
        }

(灵感来源于此issue。)

为了完整起见,这是我根据 LoekD 的信息实施的解决方法:

new ServiceInstanceListener(serviceContext => new HttpSysCommunicationListener(serviceContext, "ServerServiceEndpoint",
    (url, listener) =>
    {
        var endpointConfig = serviceContext.CodePackageActivationContext.GetEndpoint("ServerServiceEndpoint");

        return new WebHostBuilder()
            .UseHttpSys()
            .ConfigureServices(services => services
                .AddSingleton(serviceContext)
                .AddSingleton<ITelemetryInitializer>(c => new RewriteUriInitializer(endpointConfig.PathSuffix)))
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
            .UseStartup<Startup>()
            .UseUrls($"{url}{endpointConfig.PathSuffix}") // "/product/api"
            .Build();
    }))
class RewriteUriInitializer : ITelemetryInitializer
{
    private readonly string _EndpointConfigPathSuffix;

    public RewriteUriInitializer(string endpointConfigPathSuffix)
    {
        _EndpointConfigPathSuffix = endpointConfigPathSuffix;
    }

    public void Initialize(ITelemetry telemetry)
    {
        if (telemetry is RequestTelemetry requestTelemetry && requestTelemetry.Url != null)
        {
            // https://localhost:1234/controller/action => https://localhost:1234/product/api/controller/action
            requestTelemetry.Url = new Uri(
                new Uri(requestTelemetry.Url.AbsoluteUri.Substring(0,
                    requestTelemetry.Url.AbsoluteUri.IndexOf(requestTelemetry.Url.PathAndQuery, 
                       StringComparison.OrdinalIgnoreCase))),
                $"{_EndpointConfigPathSuffix}{requestTelemetry.Url.PathAndQuery}");
        }
    }
}