This guide shows you how to instrument your .NET application with OpenTelemetry and send traces to SigNoz using zero-code automatic instrumentation. This approach requires no code changes to your application.
Prerequisites
- .NET SDK 8.0+ or .NET Framework 4.6.2+. See supported versions.
- A SigNoz Cloud account or self-hosted SigNoz instance
Send traces to SigNoz
Step 1. Install the instrumentation
Download and run the OpenTelemetry .NET automatic instrumentation installer:
curl -sSfL https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/latest/download/otel-dotnet-auto-install.sh -O
sh ./otel-dotnet-auto-install.sh
chmod +x $HOME/.otel-dotnet-auto/instrument.sh
On macOS, install coreutils first: brew install coreutils
Step 2. Run your application with zero-code instrumentation
. $HOME/.otel-dotnet-auto/instrument.sh
OTEL_SERVICE_NAME=<service-name> \
OTEL_TRACES_EXPORTER=otlp \
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \
OTEL_EXPORTER_OTLP_ENDPOINT=https://ingest.<region>.signoz.cloud:443 \
OTEL_EXPORTER_OTLP_HEADERS=signoz-ingestion-key=<your-ingestion-key> \
OTEL_RESOURCE_ATTRIBUTES=deployment.environment=production,service.version=1.0.0 \
dotnet run
Replace:
<service-name>: Your service name (e.g.,payment-service)<region>: Your SigNoz Cloud region (us,eu, orin). See endpoints.<your-ingestion-key>: Your SigNoz ingestion key.
Step 1. Install the instrumentation
Add the OpenTelemetry instrumentation to your Dockerfile:
RUN apt-get update && apt-get install -y curl unzip \
&& curl -sSfL https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/latest/download/otel-dotnet-auto-install.sh -o otel-dotnet-auto-install.sh \
&& sh ./otel-dotnet-auto-install.sh \
&& chmod +x $HOME/.otel-dotnet-auto/instrument.sh \
&& rm otel-dotnet-auto-install.sh \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
Step 2. Set environment variables in your deployment
Add these environment variables to your deployment manifest:
env:
- name: OTEL_SERVICE_NAME
value: '<service-name>'
- name: OTEL_TRACES_EXPORTER
value: 'otlp'
- name: OTEL_EXPORTER_OTLP_PROTOCOL
value: 'http/protobuf'
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: 'https://ingest.<region>.signoz.cloud:443'
- name: OTEL_EXPORTER_OTLP_HEADERS
value: 'signoz-ingestion-key=<your-ingestion-key>'
- name: OTEL_RESOURCE_ATTRIBUTES
value: 'deployment.environment=production,service.version=1.0.0'
Replace:
<service-name>: Your service name (e.g.,payment-service)<region>: Your SigNoz Cloud region (us,eu, orin). See endpoints.<your-ingestion-key>: Your SigNoz ingestion key.
Step 3. Update your Dockerfile entrypoint
CMD . $HOME/.otel-dotnet-auto/instrument.sh && dotnet MyApp.dll
The OpenTelemetry Operator auto-injects instrumentation into your .NET pods without modifying your application image.
Step 1. Set up the OpenTelemetry Operator
Install the Operator and Collector following the K8s OTel Operator installation guide.
Step 2. Create the Instrumentation resource
Create instrumentation.yaml to configure .NET auto-instrumentation:
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: dotnet-instrumentation
spec:
exporter:
endpoint: http://otel-collector-collector:4318
propagators:
- tracecontext
- baggage
dotnet:
image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-dotnet:latest
Deploy this resource to your cluster.
Step 3. Add annotations to your deployment
Add these annotations to your pod template's metadata.annotations:
instrumentation.opentelemetry.io/inject-dotnet: "true"
Step 1. Update your Dockerfile
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app/publish
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
RUN apt-get update && apt-get install -y curl unzip \
&& curl -sSfL https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/latest/download/otel-dotnet-auto-install.sh -o otel-dotnet-auto-install.sh \
&& sh ./otel-dotnet-auto-install.sh \
&& chmod +x $HOME/.otel-dotnet-auto/instrument.sh \
&& rm otel-dotnet-auto-install.sh \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
COPY /app/publish .
ENV OTEL_SERVICE_NAME="<service-name>"
ENV OTEL_TRACES_EXPORTER="otlp"
ENV OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
ENV OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.<region>.signoz.cloud:443"
ENV OTEL_EXPORTER_OTLP_HEADERS="signoz-ingestion-key=<your-ingestion-key>"
ENV OTEL_RESOURCE_ATTRIBUTES="deployment.environment=production,service.version=1.0.0"
CMD . $HOME/.otel-dotnet-auto/instrument.sh && dotnet MyApp.dll
Replace <service-name>, <region>, and <your-ingestion-key> with your values.
Step 2. Build and run
docker build -t my-dotnet-app .
docker run -d -p 8080:8080 my-dotnet-app
Step 1. Download the instrumentation module
$module_url = "https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/latest/download/OpenTelemetry.DotNet.Auto.psm1"
$download_path = Join-Path $env:temp "OpenTelemetry.DotNet.Auto.psm1"
Invoke-WebRequest -Uri $module_url -OutFile $download_path -UseBasicParsing
Step 2. Install the instrumentation
Import-Module $download_path
Install-OpenTelemetryCore
Step 3. Run your application
$env:OTEL_SERVICE_NAME = "<service-name>"
$env:OTEL_TRACES_EXPORTER = "otlp"
$env:OTEL_EXPORTER_OTLP_PROTOCOL = "http/protobuf"
$env:OTEL_EXPORTER_OTLP_ENDPOINT = "https://ingest.<region>.signoz.cloud:443"
$env:OTEL_EXPORTER_OTLP_HEADERS = "signoz-ingestion-key=<your-ingestion-key>"
$env:OTEL_RESOURCE_ATTRIBUTES = "deployment.environment=production,service.version=1.0.0"
Register-OpenTelemetryForCurrentSession -OTelServiceName "<service-name>"
dotnet run
Replace:
<service-name>: Your service name (e.g.,payment-service)<region>: Your SigNoz Cloud region (us,eu, orin). See endpoints.<your-ingestion-key>: Your SigNoz ingestion key.
Validate
- Generate traffic by making requests to your application.
- Open SigNoz and go to Services.
- Look for your service name in the list.
- Click on your service to view traces, latency, and error rates.
Troubleshooting
How do I verify traces are being generated?
Enable the console exporter to see traces in your terminal:
# Linux/macOS
OTEL_DOTNET_AUTO_TRACES_CONSOLE_EXPORTER_ENABLED=true dotnet run
# Windows PowerShell
$env:OTEL_DOTNET_AUTO_TRACES_CONSOLE_EXPORTER_ENABLED = "true"
dotnet run
You should see output like:
Activity.TraceId: e1c2b70e9f39c6cc15d5d94b75412b70
Activity.SpanId: 17da84c0833e0075
Activity.DisplayName: /
Activity.Kind: Server
Traces not appearing in SigNoz?
- Verify endpoint format:
https://ingest.<region>.signoz.cloud:443 - Check ingestion key format:
signoz-ingestion-key=<key>with no extra spaces - Ensure outbound HTTPS on port 443 is allowed
Connection refused errors?
- Cloud: Check internet connection and region
- Self-hosted: Verify collector is running on port 4317 (gRPC) or 4318 (HTTP)
- Kubernetes: Ensure collector service name matches instrumentation endpoint
Setup OpenTelemetry Collector (Optional)
What is the OpenTelemetry Collector?
Think of the OTel Collector as a middleman between your app and SigNoz. Instead of your application sending data directly to SigNoz, it sends everything to the Collector first, which then forwards it along.
Why use it?
- Cleaning up data: Filter out noisy traces you don't care about, or remove sensitive info before it leaves your servers.
- Keeping your app lightweight: Let the Collector handle batching, retries, and compression instead of your application code.
- Adding context automatically: The Collector can tag your data with useful info like which Kubernetes pod or cloud region it came from.
- Future flexibility: Want to send data to multiple backends later? The Collector makes that easy without changing your app.
See Switch from direct export to Collector for step-by-step instructions to convert your setup.
For more details, see Why use the OpenTelemetry Collector? and the Collector configuration guide.
Next steps
- NuGet based instrumentation to add OpenTelemetry via NuGet packages and configure in Program.cs
- Manual Instrumentation to create custom spans for business operations
- Setup alerts for your traces to get notified on errors and latency
Sample application: