Quick Diagnosis Cards
One-page reference cards for rapid incident triage. Each card maps: Symptom → First Query → Platform Segment → Playbook.
Use these when you have 60 seconds to identify the failure category.
Card 1: App Returns 503 After Deployment
graph TD
A[503 after deploy] --> B[First Query]
B --> C[Platform Segment]
C --> D[Playbook]
| Step | Action |
| Symptom | All requests return 503 immediately after deployment or restart |
| First Query | AppServiceConsoleLogs \| where TimeGenerated > ago(15m) \| where ResultDescription has_any ("failed", "error", "exception", "listening") \| take 50 |
| What to Look For | [Observed] Listening at 127.0.0.1 supports a bind-path hypothesis; a matching traceback supports a crash hypothesis. No rows are INCONCLUSIVE: verify log configuration, collection delay, query window, selected instance, and stream health, then inspect process/listener state. |
| Platform Segment | Startup / Availability |
| Playbook | Deployment Succeeded but Startup Failed |
Quick CLI Check:
az webapp log tail --resource-group <resource-group> --name <app-name>
| Command | Purpose |
az webapp log tail --resource-group <resource-group> --name <app-name> | Streams live web app logs so you can watch startup, runtime, or dependency errors as they happen. |
--resource-group <resource-group> --name <app-name> | Looks up the web app in this resource group. |
--name <app-name> | Targets this web app. |
Card 2: Intermittent 5xx Under Load
| Step | Action |
| Symptom | 5xx errors appear during traffic spikes, recover when load drops |
| First Query | AppServiceHTTPLogs \| where TimeGenerated > ago(1h) \| summarize total=count(), err5xx=countif(ScStatus >= 500) by bin(TimeGenerated, 5m) \| order by TimeGenerated asc |
| What to Look For | 5xx spikes correlating with request volume. High TimeTaken on failed requests. |
| Platform Segment | Performance |
| Playbook | Intermittent 5xx Under Load |
Quick CLI Check:
az monitor metrics list --resource <app-resource-id> --metric "Http5xx,Requests,CpuPercentage" --interval PT1M
| Command | Purpose |
az monitor metrics list --resource <app-resource-id> --metric "Http5xx,Requests,CpuPercentage" --interval PT1M | Fetches 5xx, request volume, and CPU together to see whether burst traffic coincides with failures and saturation. |
--resource <app-resource-id> | Scopes the metric query to this specific Azure resource. |
--metric "Http5xx,Requests,CpuPercentage" | Requests exactly these metrics from Azure Monitor for this check. |
--interval PT1M | Samples the metrics at this time granularity. |
Card 3: Outbound Connection Timeouts
| Step | Action |
| Symptom | Requests to external APIs/databases time out intermittently |
| First Query | AppServiceConsoleLogs \| where TimeGenerated > ago(1h) \| where ResultDescription has_any ("connect timed out", "ReadTimeout", "ConnectTimeout", "ECONNRESET") \| summarize count() by bin(TimeGenerated, 5m) |
| What to Look For | [Observed] Connection errors and outbound volume in the same window. [Not Proven] HTTP 499/503 or repeated timeout boundaries do not establish SNAT. Compare client cancellation, worker queueing, one-dependency failures, and measured SNAT detector pressure. If detector or dependency telemetry is unavailable, record Unknown. |
| Platform Segment | Outbound / Network |
| Playbook | SNAT or Application Issue |
Quick CLI Check (Linux):
# Check for connection patterns in logs
az webapp log tail --resource-group <resource-group> --name <app-name> | grep -i "timeout\|reset\|refused"
| Command | Purpose |
az webapp log tail --resource-group <resource-group> --name <app-name> \| grep -i "timeout\\|reset\\|refused" | Streams live web app logs and filters them locally for timeout, reset, or refusal signatures. |
--resource-group <resource-group> | Looks up the web app in this resource group. |
--name <app-name> | Targets this web app. |
grep -i "timeout\\|reset\\|refused" | Filters the streamed log lines locally, case-insensitively, to show only timeout/reset/refused patterns. |
Card 4: DNS Resolution Failures (VNet)
| Step | Action |
| Symptom | App cannot resolve private endpoint FQDNs or custom DNS names |
| First Query | AppServiceConsoleLogs \| where TimeGenerated > ago(1h) \| where ResultDescription has_any ("Name or service not known", "getaddrinfo", "DNS", "NXDOMAIN") \| take 50 |
| What to Look For | Resolution failures for *.privatelink.* domains. Public IP returned instead of private. |
| Platform Segment | Outbound / Network |
| Playbook | DNS Resolution VNet-Integrated |
Quick SSH Check (Linux):
# SSH into container and test resolution
az webapp ssh --resource-group <resource-group> --name <app-name>
# Then run: nslookup <private-endpoint-fqdn>
| Command | Purpose |
az webapp ssh --resource-group <resource-group> --name <app-name> | Opens an SSH session into the running app container so you can test DNS, routes, and process state from app context. |
--resource-group <resource-group> --name <app-name> | Looks up the resource in this resource group. |
--name <app-name> | Targets this web app. |
Card 5: Slow First Request (Cold Start)
| Step | Action |
| Symptom | First request after deploy or idle period takes 10-60+ seconds |
| First Query | AppServiceHTTPLogs \| where TimeGenerated > ago(1h) \| where TimeTaken > 10000 \| project TimeGenerated, CsUriStem, TimeTaken, ScStatus \| order by TimeTaken desc |
| What to Look For | High TimeTaken on first requests only. Subsequent requests normal. |
| Platform Segment | Performance |
| Playbook | Slow Start / Cold Start |
Quick CLI Check (Linux):
# Stream logs to see startup sequence
az webapp log tail --resource-group <resource-group> --name <app-name>
| Command | Purpose |
az webapp log tail --resource-group <resource-group> --name <app-name> | Streams live web app logs so you can watch startup, runtime, or dependency errors as they happen. |
--resource-group <resource-group> --name <app-name> | Looks up the web app in this resource group. |
--name <app-name> | Targets this web app. |
Card 6: Memory Pressure / Worker Restarts
| Step | Action |
| Symptom | App becomes slow, then restarts. Pattern repeats. |
| First Query | AppServicePlatformLogs \| where TimeGenerated > ago(6h) \| where ResultDescription has_any ("OOM", "killed", "memory", "SIGKILL", "recycle") \| project TimeGenerated, ResultDescription |
| What to Look For | OOM kill messages. Restart timing correlating with memory growth. |
| Platform Segment | Performance |
| Playbook | Memory Pressure and Worker Degradation |
Quick CLI Check:
az monitor metrics list --resource <app-resource-id> --metric "MemoryWorkingSet" --interval PT5M
| Command | Purpose |
az monitor metrics list --resource <app-resource-id> --metric "MemoryWorkingSet" --interval PT5M | Fetches memory working set so you can see whether memory pressure is building during the incident. |
--resource <app-resource-id> | Scopes the metric query to this specific Azure resource. |
--metric "MemoryWorkingSet" | Requests exactly these metrics from Azure Monitor for this check. |
--interval PT5M | Samples the metrics at this time granularity. |
Card 7: Slot Swap Broke the App
| Step | Action |
| Symptom | App worked in staging slot, fails after swap to production |
| First Query | AppServicePlatformLogs \| where TimeGenerated > ago(6h) \| where ResultDescription has_any ("swap", "slot", "warm-up") \| project TimeGenerated, ResultDescription |
| What to Look For | Config values that should have stayed in production slot. Connection strings pointing to wrong environment. |
| Platform Segment | Startup / Availability |
| Playbook | Slot Swap Config Drift |
Quick CLI Check:
# Compare app settings between slots
az webapp config appsettings list --resource-group <resource-group> --name <app-name> --slot staging
az webapp config appsettings list --resource-group <resource-group> --name <app-name>
| Command | Purpose |
az webapp config appsettings list --resource-group <resource-group> --name <app-name> --slot staging | Lists the app settings currently applied to this web app so you can inspect runtime or deployment configuration. |
--resource-group <resource-group> --name <app-name> --slot staging | Looks up the resource in this resource group. |
--name <app-name> --slot staging | Targets this web app. |
--slot staging | Scopes the read or update to this deployment slot instead of the production slot. |
az webapp config appsettings list --resource-group <resource-group> --name <app-name> | Lists the app settings currently applied to this web app so you can inspect runtime or deployment configuration. |
--resource-group <resource-group> --name <app-name> | Looks up the resource in this resource group. |
--name <app-name> | Targets this web app. |
Card 8: Disk Full / No Space Left
| Step | Action |
| Symptom | Errors include "No space left on device" or ENOSPC |
| First Query | AppServiceConsoleLogs \| where TimeGenerated > ago(24h) \| where ResultDescription has_any ("No space left", "ENOSPC", "disk full") \| take 50 |
| What to Look For | Temp file accumulation. Log rotation not working. Large uploads filling /tmp. |
| Platform Segment | Performance |
| Playbook | No Space Left on Device |
Quick SSH Check (Linux):
# SSH into container
az webapp ssh --resource-group <resource-group> --name <app-name>
# Then run:
df -h
du -sh /tmp/* | sort -h | tail -20
| Command | Purpose |
az webapp ssh --resource-group <resource-group> --name <app-name> | Opens an SSH session into the running app container so you can test DNS, routes, and process state from app context. |
--resource-group <resource-group> --name <app-name> | Looks up the resource in this resource group. |
--name <app-name> | Targets this web app. |
du -sh /tmp/* \| sort -h \| tail -20 | Shows human-readable total sizes for each matching path so you can identify the biggest directories or files quickly. |
-sh | Summarizes each path once and formats sizes in human-readable units. |
Universal First 3 Queries
When you don't know where to start, run these three queries to establish baseline:
All three baseline queries below run in the same Logs editor. Before pasting each one, set the blade-level Time range to match that query's own ago(...) window, and keep the editor in KQL mode since all three assume raw Kusto. The Show: 1000 results cap matters on high-volume incidents, so raise it or refine the filter when a query is noisy, and export the queries that produced actionable evidence into the incident ticket.
Query 1: HTTP Error Trend
AppServiceHTTPLogs
| where TimeGenerated > ago(2h)
| summarize total=count(), err5xx=countif(ScStatus >= 500), p95=percentile(TimeTaken, 95) by bin(TimeGenerated, 5m)
| order by TimeGenerated asc
AppServicePlatformLogs
| where TimeGenerated > ago(24h)
| where ResultDescription has_any ("restart", "recycle", "health", "swap", "deploy", "container", "OOM", "killed")
| project TimeGenerated, OperationName, ResultDescription
| order by TimeGenerated desc
Query 3: Console Error Signatures
AppServiceConsoleLogs
| where TimeGenerated > ago(6h)
| where ResultDescription has_any ("timeout", "failed", "error", "exception", "could not", "DNS", "connect")
| project TimeGenerated, ResultDescription
| order by TimeGenerated desc
| take 100
Decision Matrix
| Observation | Next hypothesis or check | Confidence |
| 503 + no console output | Inconclusive. Before Card 1, verify logging is enabled, allow for collection delay, confirm the query window, scope, and instance, and check stream health. | None until telemetry coverage is established |
| 5xx spikes with traffic | Card 2 (Load) | High |
| Outbound timeout errors | Card 3 (Outbound/network hypothesis). Separate DNS, route, dependency, worker, and connection-pressure causes; raise SNAT confidence only when the SNAT detector reports pressure for the same instance and incident window. | Low without same-window SNAT pressure |
| DNS resolution errors | Card 4 (VNet DNS) | High |
| First request slow, rest fast | Card 5 (Cold Start) | High |
| Gradual slowdown → restart | Card 6 (Memory) | High |
| Broken after slot swap | Card 7 (Config Drift) | High |
| ENOSPC errors | Card 8 (Disk) | High |
See Also
Sources