Application Insights Auto-Instrumentation Gap: Python Linux App Service¶
Status: Published
Experiment completed with real data on 2026-05-04.
1. Question¶
When ApplicationInsightsAgent_EXTENSION_VERSION=~3 is set on a Python Linux App Service (the setting that enables automatic Application Insights instrumentation for .NET and Node.js apps), does the platform agent auto-instrument the Python process? What environment variables are injected, and what is the actual instrumentation status?
2. Why this matters¶
The Application Insights agent (ApplicationInsightsAgent_EXTENSION_VERSION=~3) is the recommended zero-code instrumentation approach for .NET, Java, and Node.js App Service applications. Python teams often apply the same setting expecting the same outcome — zero-code telemetry without SDK changes. In practice, this setting is silently disabled for Python Linux apps. The platform injects diagnostic environment variables but does not activate any Python-specific instrumentation agent. Applications that rely on this setting for telemetry emit nothing to Application Insights without an explicit SDK install.
3. Customer symptom¶
"I enabled Application Insights from the portal but see no telemetry from my Python app" or "The ApplicationInsightsAgent_EXTENSION_VERSION=~3 setting works on our Node.js app but not Python" or "Application Insights shows no dependency data or request traces despite being configured."
4. Hypothesis¶
- H1: Setting
ApplicationInsightsAgent_EXTENSION_VERSION=~3on a Python Linux App Service results in the environment variableApplicationInsightsAgent_EXTENSION_VERSION=disabledinside the running process — the platform overrides the setting todisabledfor unsupported runtimes. - H2: The platform injects
APPINSIGHTS_ENABLED=falseandAPPLICATIONINSIGHTS_DIAGNOSTICS_OUTPUT_DIRECTORYinto the process environment even when the agent is disabled, indicating the agent infrastructure is present but inactive. - H3: Setting
APPLICATIONINSIGHTS_CONNECTION_STRINGalone (without the SDK) does not enable telemetry — the connection string is visible in the APPSETTING_ namespace but is not consumed by any agent. - H4: Python apps require explicit SDK installation (
pip install azure-monitor-opentelemetry) and code-level configuration to send telemetry to Application Insights.
5. Environment¶
| Parameter | Value |
|---|---|
| Service | Azure App Service |
| SKU / Plan | B1 |
| Region | Korea Central |
| Runtime | Python 3.11 / gunicorn |
| OS | Linux |
| App name | app-batch-1777849901 |
| AI resource | ai-lab-batch (Korea Central) |
| Date tested | 2026-05-04 |
6. Variables¶
Experiment type: Observability / Platform behavior
Controlled:
ApplicationInsightsAgent_EXTENSION_VERSION=~3app settingAPPLICATIONINSIGHTS_CONNECTION_STRINGapp setting (valid connection string)- Flask app with
/envendpoint exposingos.environ
Observed:
ApplicationInsightsAgent_EXTENSION_VERSIONat runtime (inside process)APPINSIGHTS_ENABLEDvalueAPPLICATIONINSIGHTS_DIAGNOSTICS_OUTPUT_DIRECTORYPYTHONPATHchanges indicating agent injection- Presence of
APPLICATIONINSIGHTS_CONNECTION_STRINGin process environment
7. Instrumentation¶
az webapp config appsettings set --settings "ApplicationInsightsAgent_EXTENSION_VERSION=~3"— enable agent settingaz webapp config appsettings set --settings "APPLICATIONINSIGHTS_CONNECTION_STRING=<cs>"— set connection string- Flask
/envendpoint returningos.environas JSON — observe injected vars inside process az webapp config appsettings list— verify what is configured vs what the process sees
8. Procedure¶
- Set
ApplicationInsightsAgent_EXTENSION_VERSION=~3andAPPLICATIONINSIGHTS_CONNECTION_STRINGapp settings. - Restart app; check
/envendpoint for agent-related environment variables. - Compare the configured app setting value (
~3) vs the runtime value (expected:disabled). - Document all
APPINSIGHTS_*andAPPLICATIONINSIGHTS_*variables injected at runtime.
9. Expected signal¶
ApplicationInsightsAgent_EXTENSION_VERSION=disabledat runtime (overridden by platform for Python).APPINSIGHTS_ENABLED=falseinjected.APPLICATIONINSIGHTS_DIAGNOSTICS_OUTPUT_DIRECTORYinjected (agent infrastructure present).- No telemetry flow without SDK.
10. Results¶
App settings configured¶
```text ApplicationInsightsAgent_EXTENSION_VERSION = ~3 APPLICATIONINSIGHTS_CONNECTION_STRING = InstrumentationKey=11a2593f-...
```text
Runtime environment variables (inside gunicorn process via /env)¶
```text APPINSIGHTS_ENABLED=false APPLICATIONINSIGHTS_DIAGNOSTICS_OUTPUT_DIRECTORY=/var/log/applicationinsights/ APPSETTING_ApplicationInsightsAgent_EXTENSION_VERSION=~3 ApplicationInsightsAgent_EXTENSION_VERSION=disabled ORYX_AI_CONNECTION_STRING=InstrumentationKey=4aadba6b-... ← Oryx internal key ORYX_SDK_STORAGE_BASE_URL=https://oryx-cdn.microsoft.io PYTHONPATH=/opt/startup/app_logs
```text
Key finding
The configured value ~3 is overridden to disabled inside the running process. The platform explicitly sets ApplicationInsightsAgent_EXTENSION_VERSION=disabled for Python Linux apps, indicating the agent extension does not support Python on Linux.
APPLICATIONINSIGHTS_CONNECTION_STRING in process env¶
```text
Configured in app settings:¶
APPLICATIONINSIGHTS_CONNECTION_STRING = InstrumentationKey=11a2593f-...
Inside the process (/env endpoint):¶
APPLICATIONINSIGHTS_CONNECTION_STRING → NOT present in os.environ
(The connection string is present as APPSETTING_APPLICATIONINSIGHTS_CONNECTION_STRING¶
and available via Azure app settings injection, but not directly in os.environ¶
when the agent is disabled)¶
```text
ORYX_AI_CONNECTION_STRING vs APPLICATIONINSIGHTS_CONNECTION_STRING¶
Two different connection strings are present:
- ORYX_AI_CONNECTION_STRING — Oryx build system's internal AppInsights key (not the user's resource)
- APPLICATIONINSIGHTS_CONNECTION_STRING (from app settings) — user's AppInsights resource, not consumed without SDK
11. Interpretation¶
- Measured: H1 is confirmed. The platform overrides
ApplicationInsightsAgent_EXTENSION_VERSIONfrom~3todisabledfor Python Linux apps. Measured. - Measured: H2 is confirmed.
APPINSIGHTS_ENABLED=falseandAPPLICATIONINSIGHTS_DIAGNOSTICS_OUTPUT_DIRECTORY=/var/log/applicationinsights/are both injected — the agent infrastructure exists but is inactive. Measured. - Observed: H3 is consistent — the connection string is not consumed by any platform agent.
PYTHONPATH=/opt/startup/app_logssuggests the platform does inject a startup hook path, but without the Python SDK installed, nothing reads the connection string. Observed. - Inferred: H4 is correct by implication. Python apps must install
azure-monitor-opentelemetry(or the olderopencensus-ext-azure) and configure it in code. The platform agent path (/opt/startup/app_logs) is injected but contains no Python-specific agent.
12. What this proves¶
ApplicationInsightsAgent_EXTENSION_VERSION=~3is silently overridden todisabledfor Python Linux App Service. Measured.- The platform injects agent infrastructure env vars (
APPINSIGHTS_ENABLED=false,APPLICATIONINSIGHTS_DIAGNOSTICS_OUTPUT_DIRECTORY) even when the agent is disabled. Measured. ORYX_AI_CONNECTION_STRINGis always present (Oryx build telemetry) — it is NOT the user's Application Insights resource and should not be used for application telemetry. Observed.
13. What this does NOT prove¶
- Whether
azure-monitor-opentelemetrySDK installation enables telemetry was not tested (SDK not installed in this environment). - Whether the
PYTHONPATH=/opt/startup/app_logshook path contains any actual Python module was not verified (Kudu access disabled). - Whether Java or .NET runtimes correctly activate
~3was not tested in this experiment. - Whether Windows-based Python App Service behaves differently was not tested.
14. Support takeaway¶
When a customer's Python App Service does not send telemetry to Application Insights despite the portal showing "Application Insights enabled":
- Check the runtime value:
ApplicationInsightsAgent_EXTENSION_VERSIONinside the process will bedisabledfor Python Linux — the portal setting~3does not apply. - Python apps require explicit SDK installation. Add
azure-monitor-opentelemetrytorequirements.txt. -
Configure the SDK in code:
python from azure.monitor.opentelemetry import configure_azure_monitor configure_azure_monitor(connection_string=os.environ["APPLICATIONINSIGHTS_CONNECTION_STRING"]) -
The
ORYX_AI_CONNECTION_STRINGenv var is Oryx's own instrumentation key — do not use it for application telemetry. APPINSIGHTS_ENABLED=falsein the process env confirms the agent is inactive. After SDK installation and configuration, this var is irrelevant — the SDK readsAPPLICATIONINSIGHTS_CONNECTION_STRINGdirectly.
15. Reproduction notes¶
```bash
APP="
Configure agent setting + connection string¶
az webapp config appsettings set -n $APP -g $RG --settings \ "ApplicationInsightsAgent_EXTENSION_VERSION=~3" \ "APPLICATIONINSIGHTS_CONNECTION_STRING=$AI_CS"
az webapp restart -n $APP -g $RG sleep 30
Check runtime values (requires /env endpoint in app)¶
Expected: ApplicationInsightsAgent_EXTENSION_VERSION=disabled¶
Expected: APPINSIGHTS_ENABLED=false¶
curl https://
```text
16. Related guide / official docs¶
- Enable Azure Monitor OpenTelemetry for Python
- Application Insights agent — supported runtimes
- Migrate from OpenCensus Python SDK to Azure Monitor OpenTelemetry
1. Question¶
When migrating a Python App Service workload from the OpenCensus-based Application Insights SDK to the Azure Monitor OpenTelemetry Distro, are there observable differences in dependency capture coverage, telemetry table routing, and distributed trace correlation — and which gaps require explicit instrumentation to close?
2. Why this matters¶
Python teams migrating from the OpenCensus SDK (opencensus-ext-azure) to the Azure Monitor OpenTelemetry Distro (azure-monitor-opentelemetry) may encounter silent gaps: outbound HTTP dependency rows disappear from Application Insights, custom events appear in different Log Analytics tables, or traces fail to correlate across service boundaries. Support engineers diagnosing "App Insights shows no dependency data after migration" or "traces don't link across services after SDK upgrade" need to know which SDK behavior changed and what explicit configuration closes each gap.
3. Customer symptom¶
"After switching to the OpenTelemetry SDK, my dependency calls disappeared from Application Insights" or "Custom events are missing after the migration — they don't show up in customEvents table anymore" or "Distributed traces stopped correlating between my App Service and downstream services."
4. Hypothesis¶
- H1: The OpenCensus SDK auto-instruments the
requestslibrary for outbound HTTP dependency tracking out of the box. The Azure Monitor OTel Distro requires theopentelemetry-instrumentation-requestslibrary to be explicitly installed and configured; without it, outbound HTTP calls do not appear in thedependenciestable. - H2: Custom telemetry emitted via
TelemetryClient.track_event()in OpenCensus appears in thecustomEventstable. The equivalent in the OTel Distro (tracer.start_span()orlogger.info()with OTel) maps to thetracesorrequeststable, notcustomEvents— KQL queries targetingcustomEventswill silently miss OTel-sourced telemetry. - H3: Distributed trace correlation (W3C
traceparentpropagation) works correctly with both SDKs independently. A mixed deployment (one service on OpenCensus, another on OTel Distro) can maintain correlation if both sides propagate W3C headers; correlation breaks only when one side uses a legacy proprietary header format. - H4: Sampling configured in the Application Insights resource (adaptive sampling) applies downstream of both SDKs. SDK-level sampling in the OTel Distro (via
TraceIdRatioBased) is applied before data reaches the exporter and is additive with resource-level sampling.
5. Environment¶
| Parameter | Value |
|---|---|
| Service | Azure App Service |
| SKU / Plan | P1v3 |
| Region | Korea Central |
| Runtime | Python 3.11 |
| OS | Linux |
| Date tested | — |
6. Variables¶
Experiment type: Observability / Configuration
Controlled:
- Same Python app deployed with three instrumentation configurations
- Same outbound HTTP calls (to a stable internal test endpoint)
- Same Application Insights resource (connection string)
- Same request volume (100 requests per run, no sampling)
Observed:
- Row count in
dependenciestable per run - Row count in
customEventsvstracestable per run operation_Idlinkage betweenrequestsanddependenciesrowstraceparentheader propagation across service boundaries
Configurations:
- C1:
opencensus-ext-azurewithrequestsintegration enabled (baseline) - C2:
azure-monitor-opentelemetryDistro with default config (no explicit instrumentation libraries added) - C3:
azure-monitor-opentelemetryDistro withopentelemetry-instrumentation-requestsadded explicitly
Independent run definition: One 100-request burst per configuration with fixed outbound call set.
Planned runs per configuration: 3
Warm-up exclusion rule: Allow Application Insights ingestion to settle (5 minutes) before querying.
7. Instrumentation¶
- Log Analytics KQL:
dependencies | where timestamp > ago(15m) | summarize count() by sdkVersion— dependency row count per SDK - Log Analytics KQL:
customEvents | where timestamp > ago(15m)vstraces | where timestamp > ago(15m)— custom event table routing - Log Analytics KQL:
requests | join kind=inner dependencies on operation_Id | summarize count()— trace linkage - HTTP response header inspection:
traceparentvalue captured by load test client — propagation verification - App Service log stream: SDK initialization warnings or missing-library errors
8. Procedure¶
To be defined during execution.
Sketch¶
- Deploy C1 (OpenCensus); send 100 requests, each triggering one outbound HTTP call and one
track_event; wait 5 minutes; query Log Analytics. - Record:
dependenciescount,customEventscount,tracescount,operation_Idlinkage rate. - Redeploy with C2 (OTel Distro, default config); repeat same burst; compare counts.
- Redeploy with C3 (OTel Distro + explicit requests instrumentation); repeat; compare.
- For mixed-SDK test (H3): deploy one service on C1 and a downstream service on C3; send requests; check
operation_Idcorrelation across both services. - Document any telemetry that appears in C1 but not in C2, and whether C3 closes the gap.
9. Expected signal¶
- C1:
dependenciestable has ~100 rows (one per outbound call);customEventshas ~100 rows; trace linkage rate near 100%. - C2:
dependenciestable is empty or near-zero (no explicitrequestsinstrumentation);customEventsempty; OTel events appear intraces. - C3:
dependenciestable has ~100 rows; trace linkage rate near 100%; custom telemetry intraces, notcustomEvents. - Mixed (C1 + C3):
operation_Idlinks correctly across services if both propagate W3Ctraceparent.
10. Results¶
Awaiting execution.
11. Interpretation¶
Awaiting execution.
12. What this proves¶
Awaiting execution.
13. What this does NOT prove¶
Awaiting execution.
14. Support takeaway¶
Awaiting execution.
15. Reproduction notes¶
- Disable Application Insights adaptive sampling during the experiment to avoid confounding the row count comparison; set
APPLICATIONINSIGHTS_SAMPLING_PERCENTAGE=100in app settings. - Allow 3–5 minutes after each test burst before querying Log Analytics to allow ingestion to settle.
- The
azure-monitor-opentelemetryDistro auto-installs some instrumentation libraries but not all; check the distro's changelog for the current auto-included library list. customEventsvstracestable routing may change across distro versions; pin the distro version and document it in the experiment.