Kubesense

.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_path

Install 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-OpenTelemetryCore

Installing 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-OpenTelemetryForIIS

This 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:

iisreset

Step 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.msi

Create 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.yaml

Check the installation folder name on your server. For production, run the collector as a Windows service that uses this configuration file.

Step 5: Verify

  1. Browse the application to generate traffic.
  2. Check that the IIS worker process is running: tasklist | findstr w3wp.
  3. Check the instrumentation logs in C:\ProgramData\OpenTelemetry .NET AutoInstrumentation\logs.
  4. 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

SymptomCheck
No log files in the instrumentation log folderThe profiler is not loading. Run Register-OpenTelemetryForIIS again, then iisreset
Logs show export errorsCheck 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 nameSet OTEL_SERVICE_NAME in each application's web.config
Traces appear under the wrong clusterCheck 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-OpenTelemetryCore

Remove the OTEL_* entries from web.config, then run iisreset.