1

I am doing some prototyping of Jaeger Tracing for an ASP.NET Core Web API and I am able to get it working using the All in One instance of Jaeger described in the Getting Started documentation and the following code in my Startup.ConfigureServices() method:

services.AddOpenTracing();

services.AddSingleton<ITracer>(serviceProvider =>
{
    string serviceName = serviceProvider.GetRequiredService<IWebHostEnvironment>().ApplicationName;

    ILoggerFactory loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();

    // Using the UDP sender
    Jaeger.Senders.Thrift.UdpSender udpSender = new Jaeger.Senders.Thrift.UdpSender();

    var reporter = new RemoteReporter.Builder().WithLoggerFactory(loggerFactory).WithSender(udpSender).Build();
    var sampler = new ConstSampler(true); //new GuaranteedThroughputSampler(samplingRate, lowerBound);
    
    ITracer tracer = new Tracer.Builder(serviceName).WithLoggerFactory(loggerFactory).WithReporter(reporter).WithSampler(sampler).Build();

    // Allows code that can't use DI to also access the tracer.
    GlobalTracer.Register(tracer);

    return tracer;
});

services.Configure<HttpHandlerDiagnosticOptions>(options =>
{
    //options.IgnorePatterns.Add(x => false);
    options.IgnorePatterns.Add(x => x.RequestUri.IsLoopback);
    
    options.OnRequest = (span, request) => 
    {
        span.SetTag("MyCustomTag", request.RequestUri.AbsoluteUri);
    };

    options.OperationNameResolver = (request) => 
    {
        return "X-" + request.RequestUri.AbsoluteUri;
    };
});

To use all this, you need to add a few packages to your project:

  1. dotnet add package OpenTracing.Contrib.NetCore --version 0.6.2
  2. dotnet add package Jaeger --version 0.4.1

So this works OK and I get Traces with their Spans showing up in my Jaeger Search UI (http://localhost:16686/search) but it just shows the Trace with my service name (in this case "MySuperCoolWebAPI") followed by "HTTP GET":

jaeger ui screenshot

This is not terribly useful to see "HTTP GET" there. Instead, I want to see the Web API action name or something else that lets me know what kind of request this really is.

As you can see from my sample code above, I have tried setting the HttpHandlerDiagnosticOptions.OperationNameResolver but this only affects HttpClient calls I make from within my web service. It does not seem to affect how the Trace/Span associated with the request I received is named.

I also tried setting the Span OperationName in my Web API Controller method using the GlobalTracer like this but this affects an inner span and NOT the main Trace/Span that shows up on the main Jaeger UI search results page:

OpenTracing.Util.GlobalTracer.Instance.ActiveSpan.SetOperationName("My Web API Action Name");

Here you can see the first child Span has its name set to what I forced it to but the main level Span (the parent of the one I changed) is not affected:

jaeger ui screenshot with child span

Is there a way I can set the operation name of the main Span with the Jaeger C# Client?

Also, I am using .NET Core 3.1 in case that is relevant.

BearsEars
  • 849
  • 1
  • 13
  • 21
  • Hi BearsEars i was looking for a setup .NET how Web API Controller send trace to jaeger because i have followed the same as yours but still seeing one service jaeger-query in jaeger UI – Umesh Shende Aug 10 '22 at 09:45
  • @UmeshShende I think most of this is probably irrelevant now because the Jaeger C# Client is deprecated in favor of using OpenTelemetry. Are you using OpenTelemetry or OpenTracing in your project? You should be now using OpenTelemetry. – BearsEars Aug 18 '22 at 14:39
  • Yes, Using Open Telemetry now Its working with open telemetry. Any idea how jaeger will work in production? because its fine in localhost but how jaeger deployed to azure production? – Umesh Shende Aug 22 '22 at 05:36
  • @UmeshShende afaik there is no Jaeger-as-a-service on Azure so you'd be responsible for deploying it to K8s yourself. So in other words, you can't just click a button to add it as a resource like you could for some of the built-in Azure resources. – BearsEars Nov 02 '22 at 15:41
  • Ok only the K8 way to deploy it. – Umesh Shende Nov 03 '22 at 13:32

1 Answers1

2

After digging around in the OpenTracing C# .NET Core source (https://github.com/opentracing-contrib/csharp-netcore) I figured out how to override the top level Span.OperationName.

I had to update my Startup.ConfigureServices() call to services.AddOpenTracing() to the following:

services.AddOpenTracingCoreServices(otBuilder =>
{
    otBuilder.AddAspNetCore()
        .ConfigureAspNetCore(options =>
        {
            options.Hosting.OperationNameResolver = (httpContext) =>
            {
                return $"MySuperCoolOperationName ({httpContext.Request.Path.Value})";
            };
        })
        .AddCoreFx()
        .AddEntityFrameworkCore()
        .AddLoggerProvider();
});
BearsEars
  • 849
  • 1
  • 13
  • 21