Hey .NET engineers! Today, we’ll explore the world of OpenTelemetry, focusing on how it can benefit your .NET applications. We’ll talk about the strengths and weaknesses of OpenTelemetry, walk you through the setup process, discuss the basics, and share some best practices. Plus, we’ll touch on topics like auto-instrumentation, metrics, and more. So, let’s dive in!
OpenTelemetry is an open-source observability framework for cloud-native software that provides a way to collect, analyze, and visualize traces and metrics from your applications. It’s a project under the Cloud Native Computing Foundation (CNCF) and is quickly becoming the standard for telemetry data collection.
When it comes to .NET, OpenTelemetry offers some great strengths, like:
However, OpenTelemetry also has its weaknesses:
Now that we’ve discussed the pros and cons, let’s walk through the setup process.
You’ll need to install the OpenTelemetry .NET packages from NuGet to get started. For basic tracing, install these packages:
For auto-instrumentation, you’ll also need the following:
And for metrics collection, add:
Once you install the packages, it’s time to configure OpenTelemetry. First, modify the Program.cs file in your .NET Core or .NET 5 application to set up the OpenTelemetry services:
using OpenTelemetry; using OpenTelemetry.Trace; public static void Main(string[] args) { using var tracerProvider = Sdk.CreateTracerProviderBuilder() .AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddSqlClientInstrumentation() .AddZipkinExporter(o => { o.Endpoint = new Uri("http://localhost:9411/api/v2/spans"); }) .Build(); CreateHostBuilder(args).Build().Run(); }
We use the Zipkin exporter in this example, but you can replace it with your preferred back end.
To start using the tracer in your application, inject it into your controllers or services:
public class MyController : ControllerBase { private readonly Tracer _tracer; public MyController(Tracer tracer) { _tracer = tracer; } public IActionResult Get() { using var scope = _tracer.StartActiveSpan("MyController.Get"); // Your logic here scope.Span.End(); return Ok(); } }
Now you’re all set to start using OpenTelemetry in your .NET application!
To get the most out of OpenTelemetry, follow these best practices:
1. Leverage auto-instrumentation: Use the OpenTelemetry auto-instrumentation packages to simplify collecting data from your application. This approach can save you time and reduce the risk of misconfiguration.
2. Use semantic conventions: Following the OpenTelemetry semantic conventions for span and attribute names helps ensure consistency across different services and makes it easier to analyze the data.
3. Avoid high cardinality attributes: High cardinality attributes, like user IDs or timestamps, can lead to many unique spans, making it difficult to analyze data and increasing storage and processing costs.
4. Implement custom instrumentation: For parts of your application not covered by auto-instrumentation, implement custom instrumentation using the OpenTelemetry API.
5. Monitor OpenTelemetry performance: Keep an eye on the performance of your OpenTelemetry implementation, as it can impact your application’s performance. In addition, use the OpenTelemetry metrics package to collect data on OpenTelemetry itself.
6. Leverage opentelemetry-dotnet-contrib: The opentelemetry-dotnet-contrib repository contains additional instrumentation packages and exporters for .NET. Check it out to see if it offers additional value for your project.
Let’s briefly touch on some additional topics related to OpenTelemetry for .NET.
As mentioned earlier, OpenTelemetry provides auto-instrumentation for some libraries.
Auto-instrumentation is a valuable feature of OpenTelemetry that enables the automatic collection of traces and metrics from your application without requiring manual code changes. It works by injecting code into your application at runtime to capture telemetry data from various libraries and frameworks. This means you don’t need to instrument your code to collect traces and metrics manually. This can save you time and reduce the possibility of errors introduced through manual instrumentation.
Auto-instrumentation in OpenTelemetry for .NET is achieved using DiagnosticSource and Activity APIs, which provide hooks into various parts of the .NET runtime and libraries. The OpenTelemetry .NET SDK listens to these hooks, collects data, and creates spans accordingly.
Auto-instrumentation packages are available for several popular libraries and frameworks, including:
To enable auto-instrumentation, you must install the relevant NuGet packages for the libraries you want to instrument. Once installed, you can enable auto-instrumentation by adding the corresponding extension methods to your tracer provider builder:
using var tracerProvider = Sdk.CreateTracerProviderBuilder() .AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddSqlClientInstrumentation() // ... .Build();
Auto-instrumentation can be configured to suit your needs. For example, you can filter out specific requests, add custom tags to spans, or modify span names. To do this, you can pass configuration options when adding the instrumentation:
using var tracerProvider = Sdk.CreateTracerProviderBuilder() .AddAspNetCoreInstrumentation(options => { options.Filter = (httpContext) => httpContext.Request.Path != "/health"; options.Enrich = (activity, eventName, obj) => { if (eventName == "OnStartActivity") { activity.SetTag("custom-tag", "custom-value"); } }; }) // ... .Build();
In this example, we filter out requests to the /health endpoint and add a custom tag to the spans.
While auto-instrumentation is convenient, it has some limitations. For example, it may only cover some libraries or frameworks you use and may not provide the granularity you need for some parts of your application. In such cases, you must implement custom instrumentation using the OpenTelemetry API.
Remember that combining auto-instrumentation and custom instrumentation can help you achieve the desired level of observability for your .NET applications.
Metrics are an essential aspect of observability, providing insights into your applications’ performance, health, and behavior. OpenTelemetry Metrics is a component of the OpenTelemetry framework designed to collect, process, and export metrics data from your applications.
OpenTelemetry Metrics supports several metric types that help you measure different aspects of your application:
To set up metrics collection in your .NET application, you’ll need to follow these steps:
A meter is a factory for creating metric instruments. Start by creating a meter in your application:
using OpenTelemetry.Metrics; var meter = new Meter("MyApp", "1.0.0");
Next, define the metrics you want to collect. For example, you can create a counter to track the number of requests:
var requestCounter = meter.CreateCounter<long>("requests_total", "Total number of requests");
Once you have defined your metrics, you can start recording data. In this example, we’ll increment the request counter every time a request is processed:
public class MyController : ControllerBase { private static readonly Counter<long> RequestCounter = GlobalMeterProvider .GetMeter("MyApp", "1.0.0") .CreateCounter<long>("requests_total", "Total number of requests"); public IActionResult Get() { RequestCounter.Add(1); // Your logic here return Ok(); } }
Finally, you must set up the metrics export pipeline to send your collected metrics to a backend system like Prometheus or InfluxDB. To do this, create a new MeterProvider and configure it with the appropriate exporter:
using OpenTelemetry.Exporter.Prometheus; using OpenTelemetry.Metrics; var metricsHost = "localhost"; var metricsPort = 9184; var prometheusExporter = new PrometheusExporterOptions { Url = $"http://{metricsHost}:{metricsPort}/metrics/", }; Sdk.CreateMeterProviderBuilder() .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MyApp")) .AddSource("MyApp") .AddPrometheusExporter(prometheusExporter) .Build();
In this example, we’re using the Prometheus exporter, but you can replace it with an exporter for your preferred back end.
For a complete .NET Core example that demonstrates how to set up and use OpenTelemetry for tracing and metrics, check out the official OpenTelemetry .NET GitHub repository. You’ll find several sample projects that showcase different use cases and integrations.
You can also explore Prefix’s OpenTelemetry feature, a great dynamic code analysis tool that minimizes code churn. It offers detailed code traces, logs per request, hidden exceptions, and SQL query monitoring. Plus, .Net is among its 12 supported languages. Check it out here!
OpenTelemetry offers a powerful and flexible way to collect and analyze telemetry data from your .NET applications. By understanding its strengths and weaknesses, following best practices, and leveraging available resources like auto-instrumentation and opentelemetry-dotnet-contrib, you can significantly improve the observability of your applications. So try it, and feel free to explore other tools if OpenTelemetry doesn’t cover all your needs. Happy coding!
This post was written by Juan Reyes. As an entrepreneur, skilled engineer, and mental health champion, Juan pursues sustainable self-growth, embodying leadership, wit, and passion. With over 15 years of experience in the tech industry, Juan has had the opportunity to work with some of the most prominent players in mobile development, web development, and e-commerce in Japan and the US.
If you would like to be a guest contributor to the Stackify blog please reach out to [email protected]