Skip to content

How to diagnose codeless startup

Saar Shen edited this page Jul 16, 2026 · 2 revisions

How to diagnose codeless startup

When you enable the profiler codelessly (via the Windows App Service site extension or the Linux enable script), activation happens very early in the startup sequence — before your app's Main runs. That makes its diagnostics easy to miss in the normal log stream. This page shows how to capture and read a full startup trace.

First: restart and wait ~2 minutes

Before digging into logs, restart the app and give it a couple of minutes:

  1. Restart the app from the Azure Portal (App Service → Overview → Restart). Restart from the portal, not from Kudu — a full site restart is required, not just an SCM/Kudu restart. The injected environment variables only take effect on a fresh worker process, so a restart is required after installing, upgrading, or changing settings.
  2. Send some traffic to the app so a request pipeline actually starts.
  3. Wait ~2 minutes for the worker to recycle, the profiler to activate, and the first trace to be captured and uploaded.

Then check Application Insights (Investigate → Performance → Profiler) or the startup log below. Many "it's not working" reports resolve simply because the app wasn't restarted or wasn't given enough time.

Enable startup logging

Set the SP_STARTUP_LOG environment variable, then restart the app.

Value Behavior
unset / empty Off — standard output only (the default).
1 or true On — writes to the default log path (below).
any other value On — treated as an explicit log file path.

Windows App Service: add the app setting under App Service → Settings → Environment variables → App settings:

SP_STARTUP_LOG = 1

Linux App Service: the enable script sets this for you when you pass --debug (enable-linux-appservice.sh) or -DebugLog (Enable-LinuxAppService.ps1).

Where to find the log

With SP_STARTUP_LOG = 1, the log is written under the App Service persistent root:

  • Windows: D:\home\LogFiles\AzureMonitorProfiler\startup_<pid>.log
  • Linux: /home/LogFiles/AzureMonitorProfiler/startup_<pid>.log

Read it through Kudu (https://<your-app>.scm.azurewebsites.net) or via log streaming. Files are per-process (<pid>), so the app worker and the platform worker never overwrite each other.

Startup-file logging is fail-safe: if the file can't be written, it falls back to standard output and never affects app startup.

What a healthy startup looks like

Each line is formatted as UTC-timestamp [PID <pid>] <level> <component>: <message>. On a successful activation you'll see the stack detection followed by the matching profiler being enabled — for an OpenTelemetry app:

[Azure.Monitor.OpenTelemetry.Profiler.StartupHook] Detected telemetry stack: OpenTelemetry
[Azure.Monitor.OpenTelemetry.Profiler.StartupHook] Assembly resolver installed. Probe order: ...\payload\<version>\otel, ...\payload\<version>
[Azure.Monitor.OpenTelemetry.Profiler.HostingStartup] info: Detected a supported OpenTelemetry-based telemetry stack. Enabling the Azure Monitor OpenTelemetry profiler.

A classic Application Insights app shows the same pattern routed to the classic payload instead.

Common outcomes and what they mean

  • "Detected telemetry stack: None" / nothing activated. The app doesn't reference a supported telemetry stack (or has no *.deps.json to scan). Add OpenTelemetry (Azure.Monitor.OpenTelemetry.AspNetCore or Microsoft.ApplicationInsights.AspNetCore 3.x) or classic Application Insights SDK ≥ 2.23.0 and < 3.0.0, then redeploy.

  • Codeless backed off because a profiler NuGet is already referenced. If your app references Azure.Monitor.OpenTelemetry.Profiler or Microsoft.ApplicationInsights.Profiler.AspNetCore, codeless enablement intentionally does nothing to avoid enabling the profiler twice. The app is expected to activate the profiler in its own code.

  • A dependency is below the supported floor. The log names the assembly and the required minimum (for example, OpenTelemetry ≥ 1.8.1 or Azure.Core ≥ 1.46.1). The profiler skips activation and the app keeps running. Upgrade the named dependency and redeploy.

  • Invalid or missing connection string. With a missing or malformed APPLICATIONINSIGHTS_CONNECTION_STRING, the profiler disables itself (logged) but the app keeps running. Set a valid connection string for traces to capture and upload.

  • No profiler lines at all in the log. The injection likely never ran. Confirm the environment variables and the Kudu transform log (see Confirm the injection was applied) and that the app was restarted. On non-.NET stacks (Node.js, Python, Java, PHP) the enablement is a safe no-op and produces no profiler output.

Confirm the injection was applied (Windows)

If you see no startup logs at all, the codeless injection itself may not have been applied. On Windows App Service the site extension injects three environment variables into the worker via an applicationHost.xdt transform that Kudu applies on install:

Environment variable Points to
DOTNET_STARTUP_HOOKS …\payload\<version>\Azure.Monitor.OpenTelemetry.Profiler.StartupHook.dll
ASPNETCORE_HOSTINGSTARTUPASSEMBLIES Azure.Monitor.OpenTelemetry.Profiler.HostingStartup
SP_UPLOADER_PATH …\payload\<version>\Uploader\Microsoft.ApplicationInsights.Profiler.Uploader.dll

Check the variables on the running process. In Kudu (https://<your-app>.scm.azurewebsites.net) open Process explorer, select the app worker — the w3wp process whose APP_POOL_ID equals the site name, not the ~1-prefixed SCM/Kudu worker — and inspect its environment variables (or use the REST API: GET /api/processes then GET /api/processes/<pid>/environ). Confirm all three variables are present and point to the extension's payload folder.

Because these variables are set globally, they also appear on the SCM/Kudu worker. Always verify the app worker, not the ~1 SCM worker.

Check the transform log in Kudu. When the extension installs, Kudu applies the applicationHost.xdt transform and writes a log for it under C:\home\LogFiles\Transform (Kudu → Debug consoleLogFiles/Transform). Review the most recent transform log for errors. If the transform didn't apply, the variables above will be missing.

No injection means no logs. If the transform never applied (install error, or the variables aren't on the app worker), the StartupHook and HostingStartup never run — so there will be no SP_STARTUP_LOG output at all. In that case, don't look for startup logs: confirm the environment variables and the Kudu transform log first, then reinstall the extension and restart.

Related