.NET on IIS (Windows Server)
Zero-code instrumentation for ASP.NET Core applications hosted on IIS.
This guide instruments ASP.NET Core applications hosted on IIS with OpenTelemetry .NET automatic instrumentation. You don't change application code.
Prerequisites
- Windows Server 2016 or later, with IIS installed
- An ASP.NET Core application (.NET 6 or later) hosted on IIS
- Administrator access (PowerShell Run as Administrator)
- The GitHub CLI (
gh), signed in. The installer uses it to verify the downloaded release (see Step 1) - Network access from the server to the KubeSense trace endpoint on port
33443, or to a local OpenTelemetry Collector. See Instrumentation.
Step 1: Install the automatic instrumentation
Open Windows PowerShell as Administrator.
Download and import the installation 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
Import-Module $download_pathInstall the instrumentation files. The installer verifies the downloaded release with the GitHub CLI, which must be signed in (gh auth login, or a token in the GH_TOKEN environment variable):
Install-OpenTelemetryCoreInstalling without verification: If you can't install or sign in to the GitHub CLI on the server, run Install-OpenTelemetryCore -SkipReleaseVerification. The installer then prints a warning and installs the release without verifying it.
By default, the files go to C:\Program Files\OpenTelemetry .NET AutoInstrumentation. Verify:
Get-ChildItem "$env:ProgramFiles\OpenTelemetry .NET AutoInstrumentation"Step 2: Enable instrumentation for IIS
Register-OpenTelemetryForIISThis sets the profiler environment variables (CORECLR_*, DOTNET_STARTUP_HOOKS and the others) for IIS only, and restarts IIS. Other .NET processes on the server are not affected.
Avoid machine-wide profiler variables: Don't set CORECLR_ENABLE_PROFILING and the other profiler variables at Machine level with [Environment]::SetEnvironmentVariable(..., "Machine"). That instruments every .NET process on the server, including unrelated tools and services. If you must set them by hand, point them at the actual installation directory (C:\Program Files\OpenTelemetry .NET AutoInstrumentation) and apply them to IIS only.
Step 3: Configure each application
Set the service name and exporter settings in each application's web.config, inside the <aspNetCore> element.
Option A: send directly to KubeSense (simplest)
<aspNetCore processPath="dotnet" arguments=".\SampleApi.dll" hostingModel="inprocess">
<environmentVariables>
<environmentVariable name="OTEL_SERVICE_NAME" value="sample-api" />
<environmentVariable name="OTEL_EXPORTER_OTLP_ENDPOINT" value="http://<KUBESENSE_INGEST_HOST>:33443" />
<environmentVariable name="OTEL_EXPORTER_OTLP_PROTOCOL" value="http/protobuf" />
<environmentVariable name="OTEL_TRACES_EXPORTER" value="otlp" />
<environmentVariable name="OTEL_METRICS_EXPORTER" value="none" />
<environmentVariable name="OTEL_LOGS_EXPORTER" value="none" />
<environmentVariable name="OTEL_RESOURCE_ATTRIBUTES" value="kubesense.cluster=<CLUSTER_NAME>,kubesense.env_type=legacy,deployment.environment.name=prod" />
</environmentVariables>
</aspNetCore>Option B: send to a local OpenTelemetry Collector. Use this if you also want .NET metrics, or retries and buffering during network interruptions. Set the endpoint to the collector and enable metrics:
<environmentVariable name="OTEL_EXPORTER_OTLP_ENDPOINT" value="http://localhost:4318" />
<environmentVariable name="OTEL_METRICS_EXPORTER" value="otlp" />Then configure the collector as described in Step 4.
Restart IIS to apply the changes:
iisresetStep 4 (Option B only): Install the OpenTelemetry Collector
Download the Windows installer for otelcol-contrib from the collector releases page (otelcol-contrib_<VERSION>_windows_x64.msi) and install it:
msiexec /i .\otelcol-contrib_<VERSION>_windows_x64.msiCreate C:\otel\collector.yaml:
receivers:
otlp:
protocols:
grpc:
endpoint: 127.0.0.1:4317
http:
endpoint: 127.0.0.1:4318
processors:
memory_limiter:
check_interval: 1s
limit_mib: 400
resource/kubesense:
attributes:
- key: kubesense.cluster
value: <CLUSTER_NAME>
action: upsert
- key: kubesense.env_type
value: legacy
action: upsert
resourcedetection:
detectors: [system]
override: true
batch:
timeout: 5s
exporters:
otlphttp/kubesense-traces:
endpoint: http://<KUBESENSE_INGEST_HOST>:33443
retry_on_failure:
enabled: true
sending_queue:
enabled: true
prometheusremotewrite/kubesense:
endpoint: http://<KUBESENSE_INGEST_HOST>:30060/api/v1/write
resource_to_telemetry_conversion:
enabled: true
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, resourcedetection, resource/kubesense, batch]
exporters: [otlphttp/kubesense-traces]
metrics:
receivers: [otlp]
processors: [memory_limiter, resourcedetection, resource/kubesense, batch]
exporters: [prometheusremotewrite/kubesense]Start the collector:
& "C:\Program Files\OpenTelemetry Collector Contrib\otelcol-contrib.exe" --config C:\otel\collector.yamlCheck the installation folder name on your server. For production, run the collector as a Windows service that uses this configuration file.
Step 5: Verify
- Browse the application to generate traffic.
- Check that the IIS worker process is running:
tasklist | findstr w3wp. - Check the instrumentation logs in
C:\ProgramData\OpenTelemetry .NET AutoInstrumentation\logs. - Open APM → Traces in KubeSense and filter by your service name.
For more detail while troubleshooting, add OTEL_LOG_LEVEL with the value debug to web.config temporarily. Remove it afterwards, because debug logging is verbose.
Troubleshooting
| Symptom | Check |
|---|---|
| No log files in the instrumentation log folder | The profiler is not loading. Run Register-OpenTelemetryForIIS again, then iisreset |
| Logs show export errors | Check that the server can reach <KUBESENSE_INGEST_HOST>:33443 (firewall, security group). Check that trace ingestion is enabled on KubeSense |
| All applications show the same service name | Set OTEL_SERVICE_NAME in each application's web.config |
| Traces appear under the wrong cluster | Check kubesense.cluster and kubesense.env_type in OTEL_RESOURCE_ATTRIBUTES, or in the collector's resource/kubesense processor |
Removing the instrumentation
Import-Module $download_path
Unregister-OpenTelemetryForIIS
Uninstall-OpenTelemetryCoreRemove the OTEL_* entries from web.config, then run iisreset.