0
votes

I have an ASP.NET Core 2.1 WebApi running on a Service Fabric node behind a reverse proxy (Azure Application Gateway).

The Urls are something as follows:

Application Insights is added as usual.

        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();
                    }))

So endpointConfig.PathSuffix is not being added to the request telemetry. What can I do to fix this? I would prefer to to write a custom telemetry initializer or processor.

I tried adding this line to my WebHostBuilder, without any change in behavior:

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

Edit: The PathBase is identified correctly by ASP.NET Core, but it is missing from the Request Telemetry. If I set up a standalone project without Service Fabric, PathBase is added to Request Telemetry as expected.

2

2 Answers

1
votes

According to the docs, you need to register a TelemetryInitializer, and a call to 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();
    ...

To work around the issue, you can create a custom telemetry initializer, like this:

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 
        }

(Inspiration from this issue.)

0
votes

For the sake of completeness, this is what I implemented as a workaround based on LoekD's information:

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}");
        }
    }
}