You can instrument your .NET application to report traces to Managed Service for OpenTelemetry using Zipkin. After the traces are reported, Managed Service for OpenTelemetry starts to monitor your application. You can then view monitoring data, such as application topology, call traces, abnormal transactions, slow transactions, and SQL analysis. This topic describes how to use the ASP.NET Core or Owin component for automatic instrumentation and how to perform manual instrumentation.
We recommend that you connect your application to Managed Service for OpenTelemetry by using OpenTelemetry Protocol (OTLP). In this case, you are provided with more features, more advanced tracing capabilities, and the best user experience.
Alibaba Cloud provides detailed instructions on how to integrate OpenTelemetry with an application and the best practices of using OpenTelemetry to help you quickly get started with Managed Service for OpenTelemetry. For more information, see Preparations.
Prerequisites
Background information
Zipkin is an open-source, distributed, real-time data tracking system developed by Twitter. It aggregates real-time monitoring data from various heterogeneous systems.
Automatic instrumentation using the ASP.NET Core component
Follow these steps to perform instrumentation using the ASP.NET Core component.
You can download the demo source code and run the program by following the instructions in the Readme file.
Install the NuGet package.
// Add the following components. // zipkin4net.middleware.aspnetcore (ASP.NET Core middleware) // zipkin4net (tracker) dotnet add package zipkin4net.middleware.aspnetcore dotnet add package zipkin4netRegister and start Zipkin.
lifetime.ApplicationStarted.Register(() => { TraceManager.SamplingRate = 1.0f; var logger = new TracingLogger(loggerFactory, "zipkin4net"); // Obtain the Zipkin endpoint from the Managed Service for OpenTelemetry console. The endpoint does not contain "/api/v2/spans". var httpSender = new HttpZipkinSender("http://tracing-analysis-dc-hz.aliyuncs.com/adapt_your_token", "application/json"); var tracer = new ZipkinTracer(httpSender, new JSONSpanSerializer()); TraceManager.RegisterTracer(tracer); TraceManager.Start(logger); }); lifetime.ApplicationStopped.Register(() => TraceManager.Stop()); app.UseTracing(applicationName);Add a tracing handler to the HttpClient that sends GET or POST requests.
public override void ConfigureServices(IServiceCollection services) { services.AddHttpClient("Tracer").AddHttpMessageHandler(provider => TracingHandler.WithoutInnerHandler(provider.GetService<IConfiguration>()["applicationName"])); }
Automatic instrumentation using the Owin component
Follow these steps to perform instrumentation using the Owin component.
You can download the demo source code and run the program by following the instructions in the Readme file.
Install the NuGet package.
// Add the following components. // zipkin4net.middleware.aspnetcore (ASP.NET Core middleware) // zipkin4net (tracker) dotnet add package zipkin4net.middleware.aspnetcore dotnet add package zipkin4netRegister and start Zipkin.
// Set up tracing. TraceManager.SamplingRate = 1.0f; var logger = new ConsoleLogger(); // Obtain the Zipkin endpoint from the Managed Service for OpenTelemetry console. The endpoint does not contain "/api/v2/spans". var httpSender = new HttpZipkinSender("http://tracing-analysis-dc-hz.aliyuncs.com/adapt_your_token", "application/json"); var tracer = new ZipkinTracer(httpSender, new JSONSpanSerializer()); TraceManager.RegisterTracer(tracer); TraceManager.Start(logger); //Stop TraceManager on app dispose var properties = new AppProperties(appBuilder.Properties); var token = properties.OnAppDisposing; if (token != CancellationToken.None) { token.Register(() => { TraceManager.Stop(); }); } // Setup Owin Middleware appBuilder.UseZipkinTracer(System.Configuration.ConfigurationManager.AppSettings["applicationName"]);Add a tracing handler to the HttpClient that sends GET or POST requests.
using (var httpClient = new HttpClient(new TracingHandler(applicationName))) { var response = await httpClient.GetAsync(callServiceUrl); var content = await response.Content.ReadAsStringAsync(); await context.Response.WriteAsync(content); }
Manual instrumentation
To report .NET application data to the Managed Service for OpenTelemetry console using Zipkin, you can use existing plugins or perform manual instrumentation.
You can download the demo source code and run the program by following the instructions in the Readme file.
Install the NuGet package.
// Add zipkin4net (tracker). dotnet add package zipkin4netRegister and start Zipkin.
TraceManager.SamplingRate = 1.0f; var logger = new ConsoleLogger(); // Obtain the Zipkin endpoint from the Managed Service for OpenTelemetry console. The endpoint does not contain "/api/v2/spans". var httpSender = new HttpZipkinSender("http://tracing-analysis-dc-hz.aliyuncs.com/adapt_your_token", "application/json"); var tracer = new ZipkinTracer(httpSender, new JSONSpanSerializer()); TraceManager.RegisterTracer(tracer); TraceManager.Start(logger);Record request data.
var trace = Trace.Create(); Trace.Current = trace; trace.Record(Annotations.ClientSend()); trace.Record(Annotations.Rpc("client")); trace.Record(Annotations.Tag("mytag", "spanFrist")); trace.Record(Annotations.ServiceName("dotnetManual")); // ...do something testCall(); trace.Record(Annotations.ClientRecv());NoteThe preceding code records the root operation of a request. To record child operations, call the `ChildOf` method. Example:
var trace = Trace.Current.Child(); Trace.Current = trace; trace.Record(Annotations.ServerRecv()); trace.Record(Annotations.Rpc("server")); trace.Record(Annotations.Tag("mytag", "spanSecond")); trace.Record(Annotations.ServiceName("dotnetManual")); // ...do something trace.Record(Annotations.ServerSend());Optional: To quickly troubleshoot issues, add custom tags to a record. For example, you can record whether an error occurred or the return value of a request.
tracer.activeSpan().setTag("http.status_code", "200");When you send an RPC request in a distributed system, you must propagate the trace context. The trace context includes data such as TraceId, ParentSpanId, SpanId, and Sampled. Use the `Extract` and `Inject` methods to propagate the trace context through HTTP request headers. The process is as follows:
Client Span Server Span ┌──────────────────┐ ┌──────────────────┐ │ │ │ │ │ TraceContext │ Http Request Headers │ TraceContext │ │ ┌──────────────┐ │ ┌───────────────────┐ │ ┌──────────────┐ │ │ │ TraceId │ │ │ X-B3-TraceId │ │ │ TraceId │ │ │ │ │ │ │ │ │ │ │ │ │ │ ParentSpanId │ │ Inject │ X-B3-ParentSpanId │Extract │ │ ParentSpanId │ │ │ │ ├─┼─────────>│ ├────────┼>│ │ │ │ │ SpanId │ │ │ X-B3-SpanId │ │ │ SpanId │ │ │ │ │ │ │ │ │ │ │ │ │ │ Sampled │ │ │ X-B3-Sampled │ │ │ Sampled │ │ │ └──────────────┘ │ └───────────────────┘ │ └──────────────┘ │ │ │ │ │ └──────────────────┘ └──────────────────┘On the client, call the `Inject` method to inject the trace context.
_injector.Inject(clientTrace.Trace.CurrentSpan, request.Headers);On the server-side, call the `Extract` method to extract the trace context.
Ivar traceContext = traceExtractor.Extract(context.Request.Headers); var trace = traceContext == null ? Trace.Create() : Trace.CreateFromId(traceContext);
FAQ
Q: The demo program runs successfully, but no data is reported to the console. Why?
A: Verify that the endpoint in `senderConfiguration` is correct.
// Obtain the Zipkin endpoint from the Managed Service for OpenTelemetry console. The endpoint does not contain "/api/v2/spans".
var httpSender = new HttpZipkinSender("http://tracing-analysis-dc-hz.aliyuncs.com/adapt_your_token", "application/json");