04 - Logging & Monitoring (Dedicated)¶
This tutorial enables monitoring for a Dedicated Function App with Application Insights and Log Analytics queries. Dedicated plans are always running, so telemetry volume and baseline cost are predictable and continuous.
Prerequisites¶
- Completed 03 - Configuration
- Azure CLI logged in and variables set:
export RG="rg-func-dedicated-dev"
export APP_NAME="func-dedi-<unique-suffix>"
export PLAN_NAME="asp-dedi-b1-dev"
export STORAGE_NAME="stdedidev<unique>"
export LOCATION="koreacentral"
export APPINSIGHTS_NAME="appi-dedi-<unique-suffix>"
export LOG_ANALYTICS_NAME="log-dedi-<unique-suffix>"
What You'll Build¶
You will connect the Dedicated Function App to workspace-based Application Insights, run request queries, and configure a baseline alert for HTTP failures.
Infrastructure Context
Plan: Dedicated (B1) | Network: Public internet | VNet: ❌ (requires Standard+ tier)
Basic B1 has no VNet integration or private endpoints. The app runs on a fixed App Service Plan (always on, no scale-to-zero). VNet support requires upgrading to Standard (S1) or Premium (P1v3) tier.
flowchart TD
INET[Internet] -->|HTTPS| FA[Function App\nDedicated B1-P3v3\nLinux Python 3.11]
subgraph VNET["VNet 10.0.0.0/16"]
subgraph INT_SUB["Integration Subnet 10.0.1.0/24\nDelegation: Microsoft.Web/serverFarms"]
FA
end
subgraph PE_SUB["Private Endpoint Subnet 10.0.2.0/24"]
PE_BLOB[PE: blob]
PE_QUEUE[PE: queue]
PE_TABLE[PE: table]
PE_FILE[PE: file]
end
end
PE_BLOB --> ST["Storage Account"]
PE_QUEUE --> ST
PE_TABLE --> ST
PE_FILE --> ST
subgraph DNS[Private DNS Zones]
DNS_BLOB[privatelink.blob.core.windows.net]
DNS_QUEUE[privatelink.queue.core.windows.net]
DNS_TABLE[privatelink.table.core.windows.net]
DNS_FILE[privatelink.file.core.windows.net]
end
PE_BLOB -.-> DNS_BLOB
PE_QUEUE -.-> DNS_QUEUE
PE_TABLE -.-> DNS_TABLE
PE_FILE -.-> DNS_FILE
FA -.->|System-Assigned MI| ENTRA[Microsoft Entra ID]
FA --> AI[Application Insights]
RFP["📦 WEBSITE_RUN_FROM_PACKAGE=1\nNo content share required"] -.- FA
ALWAYS_ON["⚙️ Always On: true\nFixed capacity"] -.- FA
style FA fill:#5c2d91,color:#fff
style VNET fill:#E8F5E9,stroke:#4CAF50
style ST fill:#FFF3E0
style DNS fill:#E3F2FD flowchart LR
A[Function App telemetry] --> B[Application Insights]
B --> C[Log Analytics queries]
B --> D[Metric alert rule] Steps¶
Step 1 - Create Log Analytics workspace¶
az monitor log-analytics workspace create \
--resource-group $RG \
--workspace-name $LOG_ANALYTICS_NAME \
--location $LOCATION
Step 2 - Create Application Insights (workspace-based)¶
WORKSPACE_ID=$(az monitor log-analytics workspace show \
--resource-group $RG \
--workspace-name $LOG_ANALYTICS_NAME \
--query id \
--output tsv)
az monitor app-insights component create \
--app $APPINSIGHTS_NAME \
--location $LOCATION \
--resource-group $RG \
--workspace $WORKSPACE_ID \
--application-type web
Step 3 - Connect Function App to Application Insights¶
APPINSIGHTS_CONNECTION_STRING=$(az monitor app-insights component show \
--app $APPINSIGHTS_NAME \
--resource-group $RG \
--query connectionString \
--output tsv)
az functionapp config appsettings set \
--name $APP_NAME \
--resource-group $RG \
--settings \
APPLICATIONINSIGHTS_CONNECTION_STRING="$APPINSIGHTS_CONNECTION_STRING"
Step 4 - Stream platform logs¶
az webapp log config \
--name $APP_NAME \
--resource-group $RG \
--application-logging filesystem \
--level information
az webapp log tail \
--name $APP_NAME \
--resource-group $RG
Kudu/SCM is available on Dedicated, so you can also inspect diagnostics through https://$APP_NAME.scm.azurewebsites.net.
Step 5 - Run a basic query for requests¶
APPINSIGHTS_APP_ID=$(az monitor app-insights component show \
--app $APPINSIGHTS_NAME \
--resource-group $RG \
--query appId \
--output tsv)
az monitor app-insights query \
--app $APPINSIGHTS_APP_ID \
--analytics-query "requests | take 5" \
--output json
Use --output json for App Insights queries
The --output table format for az monitor app-insights query may return empty results even when data exists. Use --output json to reliably retrieve query results.
Step 6 - Add an alert rule for failures¶
APP_ID=$(az functionapp show \
--name $APP_NAME \
--resource-group $RG \
--query id \
--output tsv)
ACTION_GROUP_ID=$(az monitor action-group create \
--name "ag-dedi-alerts" \
--resource-group $RG \
--short-name "dediag" \
--action webhook alertHook "https://example.com/webhook" \
--query id \
--output tsv)
az monitor metrics alert create \
--name "alert-func-http5xx" \
--resource-group $RG \
--scopes $APP_ID \
--condition "total Http5xx > 5" \
--window-size 5m \
--evaluation-frequency 1m \
--action $ACTION_GROUP_ID
Verification¶
az monitor app-insights component create ...:
{
"appId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"applicationType": "web",
"connectionString": "InstrumentationKey=<masked>;IngestionEndpoint=https://<region>.in.applicationinsights.azure.com/;LiveEndpoint=https://<region>.livediagnostics.monitor.azure.com/",
"id": "/subscriptions/<subscription-id>/resourceGroups/rg-func-dedicated-dev/providers/microsoft.insights/components/appi-dedi-<unique-suffix>",
"name": "appi-dedi-<unique-suffix>"
}
az monitor app-insights query --analytics-query "requests | take 5" --output json:
TimeGenerated name resultCode duration
---------------------------- ------- ------------ --------
2026-04-03T10:22:41.132000Z GET /api/health 200 00:00:00.018
2026-04-03T10:22:35.917000Z GET /api/info 200 00:00:00.025
az monitor metrics alert create ...:
{
"id": "/subscriptions/<subscription-id>/resourceGroups/rg-func-dedicated-dev/providers/microsoft.insights/metricAlerts/alert-func-http5xx",
"name": "alert-func-http5xx",
"enabled": true,
"severity": 3
}
Next Steps¶
Monitoring is now in place with logs, queries, and alerts. Next you will codify Dedicated infrastructure using Bicep.
See Also¶
- Tutorial Overview & Plan Chooser
- Python Language Guide
- Platform: Hosting Plans
- Operations: Deployment
- Recipes Index