# .NET Framework instrumentation configuration

LLMS index: [llms.txt](/llms.txt)

---

OpenTelemetry supports both
[.NET](https://dotnet.microsoft.com/en-us/learn/dotnet/what-is-dotnet) and
[.NET Framework](https://dotnet.microsoft.com/en-us/learn/dotnet/what-is-dotnet-framework)
(an older Windows-based .NET implementation).

If you're already using the modern, cross-platform implementation of .NET, you
can skip this article.

## ASP.NET Initialization

Initialization for ASP.NET is a little different than for ASP.NET Core.

First, install the following NuGet packages:

- [OpenTelemetry.Instrumentation.AspNet](https://www.nuget.org/packages/OpenTelemetry.Instrumentation.AspNet)
- [OpenTelemetry.Exporter.Console](https://www.nuget.org/packages/OpenTelemetry.Exporter.Console)

Next, modify your `Web.Config` file to add a required HttpModule:

```xml
<system.webServer>
    <modules>
        <add
            name="TelemetryHttpModule"
            type="OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule,
                OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule"
            preCondition="integratedMode,managedHandler" />
    </modules>
</system.webServer>
```

Finally, initialize ASP.NET instrumentation in your `Global.asax.cs` file along
with other OpenTelemetry initialization:

```csharp
using OpenTelemetry;
using OpenTelemetry.Trace;

public class WebApiApplication : HttpApplication
{
    private TracerProvider _tracerProvider;

    protected void Application_Start()
    {
        _tracerProvider = Sdk.CreateTracerProviderBuilder()
            .AddAspNetInstrumentation()

            // Other configuration, like adding an exporter and setting resources
            .AddConsoleExporter()
            .AddSource("my-service-name")
            .SetResourceBuilder(
                ResourceBuilder.CreateDefault()
                    .AddService(serviceName: "my-service-name", serviceVersion: "1.0.0"))

            .Build();
    }

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

## Advanced ASP.NET configuration

ASP.NET instrumentation can be configured to change the default behavior.

### Filter

ASP.NET instrumentation collects all incoming HTTP requests by default. However,
you can filter incoming requests by using the `Filter` method in
`AspNetInstrumentationOptions`. This works similar to a LINQ `Where` clause,
where only requests that match a condition will be collected.

The following code snippet shows how to use `Filter` to only allow GET requests.

```csharp
this.tracerProvider = Sdk.CreateTracerProviderBuilder()
    .AddAspNetInstrumentation(
        (options) => options.Filter =
            (httpContext) =>
            {
                // only collect telemetry about HTTP GET requests
                return httpContext.Request.HttpMethod.Equals("GET");
            })
    .Build();
```

Filtering happens at an early stage, and is different from
[Sampling](/docs/specs/otel/trace/sdk/#sampling), which occurs after data has
been collected. Filtering will limit what gets collected in the first place.

### Enrich

If you have data that you'd like to have added to every `Activity` that's
generated by OpenTelemetry, you can use the `Enrich` method.

The `Enrich` action is called only when `activity.IsAllDataRequested` is `true`.
It contains the `Activity` created, the name of the event, and the raw object

The following code snippet shows how to add additional tags using `Enrich`.

```csharp
this.tracerProvider = Sdk.CreateTracerProviderBuilder()
    .AddAspNetInstrumentation((options) => options.Enrich
        = (activity, eventName, rawObject) =>
    {
        if (eventName.Equals("OnStartActivity"))
        {
            if (rawObject is HttpRequest httpRequest)
            {
                activity?.SetTag("physicalPath", httpRequest.PhysicalPath);
            }
        }
        else if (eventName.Equals("OnStopActivity"))
        {
            if (rawObject is HttpResponse httpResponse)
            {
                activity?.SetTag("responseType", httpResponse.ContentType);
            }
        }
    })
    .Build();
```

See [Add tags to an Activity](../instrumentation/#activity-tags) for annotating
trace data more generally.

### RecordException

ASP.NET instrumentation automatically sets a given `Activity`'s status to
`Error` if an unhandled exception is thrown.

You can also set the `RecordException` property to `true`, which will store an
exception on the `Activity` itself as an `ActivityEvent`.

## Next steps

After you have observability generated automatically with instrumentation
libraries, you may want to add
[manual instrumentation](/docs/languages/dotnet/instrumentation) to collect
custom telemetry data.

You'll also want to configure an appropriate exporter to
[export your telemetry data](/docs/languages/dotnet/exporters) to one or more
telemetry backends.

You can also check the
[automatic instrumentation for .NET](/docs/zero-code/dotnet), which is currently
in beta.
