---
title: "Instrument a .NET application | OpenTelemetry documentation"
description: "Instrument a .NET application with OpenTelemetry for Application Observability."
---

# Instrument a .NET application

The [Grafana OpenTelemetry distribution for .NET](https://github.com/grafana/grafana-opentelemetry-dotnet) provides a pre-configured and pre-packaged bundle of OpenTelemetry .NET components, optimized for Grafana Cloud Application Observability.

## Recommended setup for Grafana Cloud

Grafana Labs recommends that you set up OpenTelemetry components, including instrumentation and an OpenTelemetry Collector distribution, using one of the [Grafana Cloud setup guides](/docs/opentelemetry/grafana-cloud/).

These opinionated guides make it easy to get started. They include all the binaries, configuration, and connection parameters you need to set up OpenTelemetry for [Grafana Cloud](/products/cloud/).

## Before you begin

Ensure you have a .NET development environment and an application using **.NET 6+** or **.NET Framework version 4.6.2 or higher**.

## Install the SDK

Use either the command line or Visual Studio to install the package.

**Command line:**

Run the following command in your project folder:

sh ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```sh
dotnet add package Grafana.OpenTelemetry
```

Additionally, install the console exporter for local testing:

sh ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```sh
dotnet add package OpenTelemetry.Exporter.Console
```

**Visual Studio:**

Open your project in Visual Studio, search for, and install the `Grafana.OpenTelemetry` package.

Also install the `OpenTelemetry.Exporter.Console` package for local testing.

## Instrument your application

Choose the code tab below that matches your environment and modify it for your application.

> Warning
> 
> The `AddConsoleExporter` calls in the sample are only for local testing. Remove these calls for production applications.

netconsole aspnetcore netfx

![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

netconsole ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```netconsole
// .NET 6+ console
using OpenTelemetry;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
using Grafana.OpenTelemetry;

using var tracerProvider = Sdk.CreateTracerProviderBuilder()
    .UseGrafana()
    .AddConsoleExporter()
    .Build();
using var meterProvider = Sdk.CreateMeterProviderBuilder()
    .UseGrafana()
    .AddConsoleExporter()
    .Build();
using var loggerFactory = LoggerFactory.Create(builder =>
{
    builder.AddOpenTelemetry(logging =>
    {
        logging.UseGrafana()
            .AddConsoleExporter();
    });
});
```

aspnetcore ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```aspnetcore
// .NET 6+ ASP.NET Core
using Grafana.OpenTelemetry;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenTelemetry()
    .WithTracing(configure =>
    {
        configure.UseGrafana()
            .AddConsoleExporter();
    })
    .WithMetrics(configure =>
    {
        configure.UseGrafana()
            .AddConsoleExporter();
    });
builder.Logging.AddOpenTelemetry(options =>
{
    options.UseGrafana()
        .AddConsoleExporter();
});
```

netfx ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```netfx
// .NET Framework
using Grafana.OpenTelemetry;
using OpenTelemetry;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;

namespace DemoApplication
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        private TracerProvider tracerProvider;
        private MeterProvider meterProvider;

        protected void Application_Start()
        {
            // MVC, Web API, etc. configuration

            tracerProvider = Sdk.CreateTracerProviderBuilder()
                .UseGrafana()
                .Build();
            meterProvider = Sdk.CreateMeterProviderBuilder()
                .UseGrafana()
                .Build();
        }

        protected void Application_End()
        {
            tracerProvider?.Dispose();
            meterProvider?.Dispose();
        }
    }
}
```

## Run your application

Run your application with the following command:

sh ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```sh
OTEL_RESOURCE_ATTRIBUTES="service.name=<name>,service.namespace=<namespace>,deployment.environment=<environment>" \
OTEL_EXPORTER_OTLP_ENDPOINT=<endpoint> \
OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf" \
dotnet run
```

Replace variables in `<...>` with values specific to your application and backend. For more details, see the [OpenTelemetry service attributes](https://opentelemetry.io/docs/specs/semconv/attributes-registry/service/#service-attributes) documentation.

- `<name>`: your service name, for example, `shoppingcart`
- `<namespace>`: a string to group related services, such as `ecommerce` for a team that manages several services
- `<environment>`: the deployment environment, for example, the `production` deployment tier

Some backends, such as Grafana Cloud, also require you to set authentication headers in the `OTEL_EXPORTER_OTLP_HEADERS` environment variable.

## Test your instrumentation

To verify successful instrumentation, run your application, generate some traffic, and check that metrics and logs appear in the console.

Example metrics output:

log ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```log
Metric Name: process.cpu.count, The number of processors (CPU cores) available to the current process., Unit: {processors}, Meter: OpenTelemetry.Instrumentation.Process/0.5.0.3
(2024-06-05T02:14:47.6851243Z, 2024-06-05T02:14:57.7092810Z] LongSumNonMonotonic
Value: 12
```

Example logs output:

log ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```log
LogRecord.Timestamp:               2024-06-05T02:14:47.9338272Z
LogRecord.CategoryName:            Microsoft.Hosting.Lifetime
LogRecord.Severity:                Info
LogRecord.SeverityText:            Information
LogRecord.Body:                    Now listening on: {address}
LogRecord.Attributes (Key:Value):
    address: http://localhost:5117
    OriginalFormat (a.k.a Body): Now listening on: {address}
LogRecord.EventId:                 14
LogRecord.EventName:               ListeningOnAddress
```

## Example application

See the [Rolldice service](https://github.com/grafana/docker-otel-lgtm/?tab=readme-ov-file#run-example-apps-in-different-languages) for a complete example setup.

## Resources

1. [Grafana OpenTelemetry distribution for .NET on GitHub](https://github.com/grafana/grafana-opentelemetry-dotnet)
2. [Grafana.OpenTelemetry NuGet package](https://www.nuget.org/packages/Grafana.OpenTelemetry)
