This project adds OpenTelemetry instrumentation to .NET applications without having to modify their source code.
Warning
The following documentation refers to the in-development version of OpenTelemetry .NET Automatic Instrumentation. Docs for the latest version (1.16.0) can be found in opentelemetry.io or versioned README.
If you'd like to try the instrumentation on an existing application before learning more about the configuration options and the project, use the recommended installation method described at Using the OpenTelemetry.AutoInstrumentation NuGet packages or use the appropriate install script:
- On Linux and macOS, use the shell scripts.
- On Windows, use the PowerShell module.
Note
The NuGet packages are the recommended way to deploy automatic instrumentation, but they can't be used in all cases. See Limitations for details.
To see the telemetry from your application directly on the standard output, set
the following environment variables to console before launching your application:
OTEL_TRACES_EXPORTEROTEL_METRICS_EXPORTEROTEL_LOGS_EXPORTER
For a demo using docker compose, clone this repository and
follow the examples/demo/README.md.
OpenTelemetry .NET Automatic Instrumentation is built on top of OpenTelemetry .NET:
- Core components:
1.18.0 System.Diagnostics.DiagnosticSource:10.0.0referencingSystem.Runtime.CompilerServices.Unsafe:6.1.2
You can find all references here:
- OpenTelemetry.AutoInstrumentation.csproj
- OpenTelemetry.AutoInstrumentation.Assemblies/Directory.Packages.props
To automatically instrument applications, the OpenTelemetry .NET Automatic Instrumentation does the following:
- Injects and configures the OpenTelemetry .NET SDK into the application.
- Adds OpenTelemetry Instrumentation to key packages and APIs used by the application.
You can enable the OpenTelemetry .NET Automatic Instrumentation as a .NET Profiler to inject additional instrumentations of this project at runtime, using a technique known as monkey-patching. When enabled, the OpenTelemetry .NET Automatic Instrumentation generates traces for libraries that don't already generate traces using the OpenTelemetry .NET SDK.
See design.md for an architectural overview.
The versioning information and stability guarantees can be found in the versioning documentation.
OpenTelemetry .NET Automatic Instrumentation should work with all officially supported operating systems and versions of .NET.
The minimal supported version of
.NET Framework
is 4.6.2.
Supported processor architectures are:
- x86
- AMD64 (x86-64)
- ARM64 (Experimental)
CI tests run against the following operating systems:
- Alpine x64
- Alpine ARM64
- Debian x64
- Debian ARM64
- CentOS Stream 9 x64
- macOS Sonoma 14 ARM64
- Microsoft Windows Server 2022 x64
- Microsoft Windows Server 2025 x64
- Ubuntu 22.04 LTS x64
- Ubuntu 22.04 LTS ARM64
See config.md#instrumented-libraries-and-frameworks.
Instrumenting self-contained
applications is supported through NuGet packages.
Note that a self-contained application is
automatically generated in .NET 7+ whenever the dotnet publish or dotnet build
command is used with a Runtime Identifier (RID) parameter, for example when -r
or --runtime is used when running the command.
The NuGet packages are the recommended way to deploy automatic instrumentation, but they can't be used in all cases. To install using the NuGet packages, see Using the OpenTelemetry.AutoInstrumentation NuGet packages. See Limitations for incompatible scenarios.
To install the automatic instrumentation manually, download and extract the appropriate binaries from the latest release.
Note
The path where you put the binaries is referenced as $INSTALL_DIR.
When running your application, make sure to:
- Set the resources.
- Set the environment variables from the table below.
Note
Some settings can be omitted on .NET. For more information, see config.md.
| Environment variable | .NET version | Value |
|---|---|---|
COR_ENABLE_PROFILING |
.NET Framework | 1 |
COR_PROFILER |
.NET Framework | {918728DD-259F-4A6A-AC2B-B85E1B658318} |
COR_PROFILER_PATH_32 |
.NET Framework | $INSTALL_DIR/win-x86/OpenTelemetry.AutoInstrumentation.Native.dll |
COR_PROFILER_PATH_64 |
.NET Framework | $INSTALL_DIR/win-x64/OpenTelemetry.AutoInstrumentation.Native.dll |
CORECLR_ENABLE_PROFILING |
.NET | 1 |
CORECLR_PROFILER |
.NET | {918728DD-259F-4A6A-AC2B-B85E1B658318} |
CORECLR_PROFILER_PATH |
.NET on Linux glibc | $INSTALL_DIR/linux-x64/OpenTelemetry.AutoInstrumentation.Native.so |
CORECLR_PROFILER_PATH |
.NET on Linux musl | $INSTALL_DIR/linux-musl-x64/OpenTelemetry.AutoInstrumentation.Native.so |
CORECLR_PROFILER_PATH |
.NET on macOS | $INSTALL_DIR/osx-arm64/OpenTelemetry.AutoInstrumentation.Native.dylib |
CORECLR_PROFILER_PATH_32 |
.NET on Windows | $INSTALL_DIR/win-x86/OpenTelemetry.AutoInstrumentation.Native.dll |
CORECLR_PROFILER_PATH_64 |
.NET on Windows | $INSTALL_DIR/win-x64/OpenTelemetry.AutoInstrumentation.Native.dll |
DOTNET_STARTUP_HOOKS |
.NET | $INSTALL_DIR/net/OpenTelemetry.AutoInstrumentation.StartupHook.dll |
OTEL_DOTNET_AUTO_HOME |
All versions | $INSTALL_DIR |
Important
Starting in .NET 8, the environment variable DOTNET_EnableDiagnostics=0
disables all diagnostics, including the CLR Profiler facility which is needed
to launch the instrumentation, if not using .NET Startup hooks. Ensure that
DOTNET_EnableDiagnostics=1, or if you'd like to limit diagnostics only to
the CLR Profiler, you may set both DOTNET_EnableDiagnostics=1 and
DOTNET_EnableDiagnostics_Profiler=1 while setting other diagnostics features
to 0. See this issue
for more guidance.
You can install OpenTelemetry .NET Automatic Instrumentation and instrument your .NET application using the provided Shell scripts.
Note
On macOS coreutils is required.
The downloaded installer should be verified before it is executed because a
script cannot establish trust in its own code. By default, the installer also
requires the GitHub CLI and verifies both the
immutable release and artifact attestation for the downloaded ZIP archive. To
explicitly opt out of archive verification, set
SKIP_RELEASE_VERIFICATION=true. Skipping verification is not recommended.
Example usage:
# Download the installer into a private directory
version="v1.16.0"
repository="open-telemetry/opentelemetry-dotnet-instrumentation"
release_workflow="$repository/.github/workflows/release.yml"
download_dir="$(mktemp -d "${TMPDIR:-/tmp}/otel-dotnet-auto-installer.XXXXXX")"
installer="$download_dir/otel-dotnet-auto-install.sh"
trap 'rm -rf "$download_dir"' 0
curl -sSfL "https://github.com/$repository/releases/download/$version/otel-dotnet-auto-install.sh" -o "$installer"
# Verify the installer before executing it
gh release verify-asset "$version" "$installer" --repo "$repository"
gh attestation verify "$installer" \
--repo "$repository" \
--signer-workflow "$release_workflow" \
--source-ref "refs/tags/$version"
# Install core files; the installer verifies the downloaded ZIP archive
VERSION="$version" sh "$installer"
# Enable execution for the instrumentation script
chmod +x $HOME/.otel-dotnet-auto/instrument.sh
# Setup the instrumentation for the current shell session
. $HOME/.otel-dotnet-auto/instrument.sh
# Run your application with instrumentation
OTEL_SERVICE_NAME=myapp OTEL_RESOURCE_ATTRIBUTES=deployment.environment.name=staging,service.version=1.0.0 ./MyNetAppFor air-gapped environments, verify the archive before transferring it and explicitly skip the installer's online verification. You can provide either the archive directly with:
SKIP_RELEASE_VERIFICATION=true LOCAL_PATH=<PATH_TO_ARCHIVE> sh ./otel-dotnet-auto-install.shor the folder with the files, this has the added benefit that the install script will determine the correct file to choose.
SKIP_RELEASE_VERIFICATION=true DOWNLOAD_DIR=<PATH_TO_FOLDER_WITH_FILES> sh ./otel-dotnet-auto-install.shotel-dotnet-auto-install.sh script
uses environment variables as parameters:
| Parameter | Description | Required | Default value |
|---|---|---|---|
OTEL_DOTNET_AUTO_HOME |
Location where binaries are to be installed | No | $HOME/.otel-dotnet-auto |
OS_TYPE |
Possible values: linux-glibc, linux-musl, macos, windows |
No | Calculated |
ARCHITECTURE |
Possible values for Linux: x64, arm64 |
No | Calculated |
TMPDIR |
(deprecated) parent directory for temporary downloads; prefer DOWNLOAD_DIR |
No | Not set |
DOWNLOAD_DIR |
Folder to download the archive to. Will use local archive if it already exists | No | Calculated |
LOCAL_PATH |
Full path the archive to use for installation. (ideal for air-gapped scenarios) | No | Calculated |
SKIP_RELEASE_VERIFICATION |
Set to true to skip GitHub release and artifact attestation verification |
No | false |
VERSION |
Version to download | No | v1.16.0 |
The installer copies the archive into a unique otel-dotnet-auto.XXXXXX
directory under ${TMPDIR:-/tmp} before verification and extraction. When
DOWNLOAD_DIR is not set, this directory is also used for the download.
instrument.sh script uses environment variables as parameters:
| Parameter | Description | Required | Default value |
|---|---|---|---|
ENABLE_PROFILING |
Whether to set the .NET CLR Profiler, possible values: true, false |
No | true |
OTEL_DOTNET_AUTO_HOME |
Location where binaries are to be installed | No | $HOME/.otel-dotnet-auto |
OS_TYPE |
Possible values: linux-glibc, linux-musl, macos, windows |
No | Calculated |
ARCHITECTURE |
Possible values for Linux: x64, arm64 |
No | Calculated |
On Windows, you should install OpenTelemetry .NET Automatic Instrumentation and instrument your .NET application using the provided PowerShell module.
Warning
The PowerShell module works only on PowerShell 5.1 which is the one installed by default on Windows.
Example usage (run as administrator):
Note
The downloaded module should be verified before it is imported because a module
cannot establish trust in its own code. By default, installation requires the
GitHub CLI and verifies both the immutable release
and the artifact attestation. To explicitly opt out, set
$skip_release_verification to $true; this also passes
-SkipReleaseVerification to Install-OpenTelemetryCore for the Windows
archive.
# PowerShell 5.1 is required
#Requires -PSEdition Desktop
$version = "v1.16.0"
$repository = "open-telemetry/opentelemetry-dotnet-instrumentation"
$release_workflow = "$repository/.github/workflows/release.yml"
$skip_release_verification = $false
# Use a unique directory protected by the Program Files access controls.
$program_files = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::ProgramFiles)
$download_dir = Join-Path $program_files "OpenTelemetry .NET AutoInstrumentation Download $([System.Guid]::NewGuid().ToString("N"))"
$download_path = Join-Path $download_dir "OpenTelemetry.DotNet.Auto.psm1"
$module_url = "https://github.com/$repository/releases/download/$version/OpenTelemetry.DotNet.Auto.psm1"
New-Item -ItemType Directory -Path $download_dir -ErrorAction Stop | Out-Null
try {
Invoke-WebRequest -Uri $module_url -OutFile $download_path -UseBasicParsing
if ($skip_release_verification) {
Write-Warning "Release verification is skipped. Downloaded PowerShell code and binaries will not be verified."
}
else {
$github_cli = Get-Command gh.exe -CommandType Application -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $github_cli) {
throw "The GitHub CLI ('gh') is required. Install it from https://cli.github.com/ or explicitly set `$skip_release_verification to `$true."
}
& $github_cli.Source release verify-asset $version $download_path --repo $repository
if ($LASTEXITCODE -ne 0) {
throw "GitHub release verification failed for the PowerShell module."
}
& $github_cli.Source attestation verify $download_path `
--repo $repository `
--signer-workflow $release_workflow `
--source-ref "refs/tags/$version"
if ($LASTEXITCODE -ne 0) {
throw "GitHub artifact attestation verification failed for the PowerShell module."
}
}
# Import the module only after successful verification.
Import-Module $download_path
# To install from a previously downloaded Windows archive, add:
# -LocalPath "C:\Path\To\OpenTelemetry.zip"
Install-OpenTelemetryCore -SkipReleaseVerification:$skip_release_verification -ErrorAction Stop
# Cache the verified module for updates and uninstallation.
Copy-Item -LiteralPath $download_path -Destination (Get-OpenTelemetryInstallDirectory) -Force
}
finally {
if (Test-Path -LiteralPath $download_dir) {
Remove-Item -LiteralPath $download_dir -Force -Recurse
}
}
# Set up the instrumentation for the current PowerShell session
Register-OpenTelemetryForCurrentSession -OTelServiceName "MyServiceDisplayName"
# Run your application with instrumentation
.\MyNetApp.exeYou can get usage information by calling:
# List all available commands
Get-Command -Module OpenTelemetry.DotNet.Auto
# Get command's usage information
Get-Help Install-OpenTelemetryCore -DetailedUpdating OpenTelemetry installation:
Note
By default, Update-OpenTelemetryCore uses the
GitHub CLI to verify that the downloaded PowerShell
module and Windows archive belong to the selected immutable GitHub release and
have valid artifact attestations from this repository's release workflow. The
existing installation is not removed if verification fails. To update without
installing the GitHub CLI, use -SkipReleaseVerification. Skipping
verification is not recommended.
# Import the previously downloaded module. After an update the module is found in the default install directory.
# Note: It's best to use the same version of the module for installation and uninstallation to ensure proper removal.
Import-Module "C:\Program Files\OpenTelemetry .NET AutoInstrumentation\OpenTelemetry.DotNet.Auto.psm1"
# If IIS was previously registered, use RegisterIIS = $true.
Update-OpenTelemetryCore -RegisterIIS $true
# If Windows services were previously registered, these must be re-registered manually.
Unregister-OpenTelemetryForWindowsService -WindowsServiceName MyServiceName
Update-OpenTelemetryCore
Register-OpenTelemetryForWindowsService -WindowsServiceName MyServiceName -OTelServiceName MyOtelServiceNameUninstalling OpenTelemetry:
# PowerShell 5.1 is required
#Requires -PSEdition Desktop
# Import the previously downloaded module. After installation or an update the module is found in the default install directory.
# Note: It's best to use the same version of the module for installation and uninstallation to ensure proper removal.
Import-Module "C:\Program Files\OpenTelemetry .NET AutoInstrumentation\OpenTelemetry.DotNet.Auto.psm1"
# If IIS was previously registered, unregister it.
Unregister-OpenTelemetryForIIS
# If Windows services were previously registered, unregister them.
Unregister-OpenTelemetryForWindowsService -WindowsServiceName MyServiceName
# Finally, uninstall OpenTelemetry instrumentation
Uninstall-OpenTelemetryCoreBy default, Install-OpenTelemetryCore and Update-OpenTelemetryCore register
OpenTelemetry (and dependencies) assemblies in the Global Assembly Cache (GAC).
Some of these assemblies are tightly coupled to specific .NET Framework versions.
When upgrading from .NET Framework versions older than 4.7.2, these assemblies should be removed from the GAC. For such upgrade scenarios, it is recommended to uninstall and reinstall OpenTelemetry after the .NET Framework update is complete.
You can find our demonstrative example that uses Docker Compose.
You can also consider using the Kubernetes Operator for OpenTelemetry Collector.
See windows-service-instrumentation.md.
See config.md.
See manual-instrumentation.md.
See troubleshooting.md.
See CONTRIBUTING.md.
See CONTRIBUTING.md.
- Chris Ventura, New Relic
- Piotr Kiełkowicz, Splunk
- Rajkumar Rangaraj, Microsoft
- Robert Pająk, Splunk
- Zach Montoya, Datadog
For more information about the maintainer role, see the community repository.
- Igor Kiselev, Splunk
- Mateusz Łach, Splunk
- Rasmus Kuusmann, Splunk
For more information about the approver role, see the community repository.
- Colin Higgins
- Greg Paperin
- Kevin Gosse
- Lucas Pimentel-Ordyna
- Mike Goldsmith
- Paulo Janotti
- Tony Redondo
For more information about the emeritus role, see the community repository.
Starting with the 1.14.0 release the files included in the GitHub releases
are attested using GitHub Artifact attestations.
To verify the attestation of a file from a GitHub release use the GitHub CLI.
For example:
RELEASE_TAG="v1.14.0"
REPOSITORY="open-telemetry/opentelemetry-dotnet-instrumentation"
gh attestation verify ./otel-dotnet-auto-install.sh \
--repo "${REPOSITORY}" \
--signer-workflow "${REPOSITORY}/.github/workflows/release.yml" \
--source-ref "refs/tags/${RELEASE_TAG}"Note
A successful verification outputs Verification succeeded!.
This repository also uses GitHub Immutable Releases which can also be verified.
For example:
RELEASE_TAG="v1.14.0"
gh release verify "${RELEASE_TAG}" --repo open-telemetry/opentelemetry-dotnet-instrumentation
gh release verify-asset "${RELEASE_TAG}" ./otel-dotnet-auto-install.sh --repo open-telemetry/opentelemetry-dotnet-instrumentationNote
A successful verification outputs Release <tag> verified!.
For more verification options please refer to the documentation for
gh attestation verify,
gh release verify,
and gh release verify-asset.