A Guide to OpenTelemetry for .NET Engineers

By: HitSubscribe
  |  April 18, 2023
A Guide to OpenTelemetry for .NET Engineers

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!

computer code on a screen

Understanding OpenTelemetry in the .NET Ecosystem

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:

  1. Easy integration: With its library, OpenTelemetry for .NET, it’s simple to incorporate tracing and metrics collection into your existing .NET applications.
  2. Broad compatibility: OpenTelemetry supports .NET Core 2.1+, .NET Framework 4.6.1+, and .NET 5, making it compatible with most .NET projects.
  3. Vendor-agnostic: It allows you to send data to various backends, like Jaeger, Zipkin, or Prometheus, without changing your code.

However, OpenTelemetry also has its weaknesses:

  1. Early stages: Since OpenTelemetry is still a relatively young project, some features may not be as mature or stable as other established tracing and monitoring tools.
  2. Limited auto-instrumentation: While auto-instrumentation is available for some libraries, it’s less extensive than other platforms, like Java.
  3. Learning curve: Learning how to use OpenTelemetry effectively might take time, especially if you’re new to observability.

Setting Up OpenTelemetry for .NET

Now that we’ve discussed the pros and cons, let’s walk through the setup process.

Step 1: Install the Required NuGet Packages

You’ll need to install the OpenTelemetry .NET packages from NuGet to get started. For basic tracing, install these packages:

  • OpenTelemetry
  • OpenTelemetry.Extensions.Hosting
  • OpenTelemetry.Exporter.Zipkin (or your preferred exporter)

For auto-instrumentation, you’ll also need the following:

  • OpenTelemetry.Instrumentation.AspNetCore
  • OpenTelemetry.Instrumentation.HTTP
  • OpenTelemetry.Instrumentation.SqlClient (if using SQL Server)

And for metrics collection, add:

  • OpenTelemetry.Metrics

Step 2: Configure OpenTelemetry

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.

Step 3: Use the Tracer

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.

OpenTelemetry Best Practices for .NET Engineers

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.

Additional Topics

Let’s briefly touch on some additional topics related to OpenTelemetry for .NET.

Auto-Instrumentation

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.

How Auto-Instrumentation Works

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:

  • OpenTelemetry.Instrumentation.AspNetCore: For instrumenting ASP.NET Core applications.
  • OpenTelemetry.Instrumentation.Http: For instrumenting outgoing HTTP requests made using HttpClient.
  • OpenTelemetry.Instrumentation.SqlClient: For instrumenting SQL Server database calls made with System.Data.SqlClient or Microsoft.Data.SqlClient.

Enabling Auto-Instrumentation

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

Configuring Auto-Instrumentation

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.

Limitations and Custom Instrumentation

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

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.

Supported Metric Types

OpenTelemetry Metrics supports several metric types that help you measure different aspects of your application:

  1. Counter: A cumulative metric representing a single numerical value that only increases or resets to zero on restart.
  2. UpDownCounter: Similar to a counter, it can also decrease, allowing you to track values that may go up or down.
  3. ValueRecorder: Used to record individual values and calculate statistics, like min, max, sum, and average.
  4. Gauge: This represents a single numerical value that can arbitrarily go up or down, often used to describe the current state of a system.

Setting Up Metrics Collection

To set up metrics collection in your .NET application, you’ll need to follow these steps:

  1. Install the OpenTelemetry.Metrics NuGet package.
  2. Create a meter and define the metrics you want to collect.
  3. Configure the metrics export pipeline with your preferred exporter.

Creating a Meter and Defining Metrics

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

Recording Metrics

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

Configuring the Metrics Export Pipeline

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.

Moving On

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.

Improve Your Code with Retrace APM

Stackify's APM tools are used by thousands of .NET, Java, PHP, Node.js, Python, & Ruby developers all over the world.
Explore Retrace's product features to learn more.

Learn More

Want to contribute to the Stackify blog?

If you would like to be a guest contributor to the Stackify blog please reach out to [email protected]