Skip to content

KQL Cheatsheet - Azure Container Apps Logs

All queries target ContainerAppConsoleLogs_CL or ContainerAppSystemLogs_CL via the Azure Monitor datasource in Grafana Explore. Select Azure Log Analytics query type and point to the Log Analytics workspace resource for the target region.

Workspaces

Region Workspace Apps
Italy North law-stacksync-prod-italynorth backend-stacksync-prod, connectors-prod, connectors-prod-opt-conc, connectors-prod-16gb, connectors-prod-32gb, event-forward-prod, workflow-execution-engine-prod, workflows-events-receiver-prod
North Central US law-stacksync-prod-northcentralus backend-stacksync-prod, connectors-prod, connectors-prod-opt-conc, connectors-prod-16gb, connectors-prod-32gb, event-forward-prod, workflow-execution-engine-prod, workflows-events-receiver-prod

Replace backend-stacksync-prod with any container app name in the queries below.


Access Logs (gunicorn)

All requests with latency

Open in Grafana

ContainerAppConsoleLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where Log_s startswith 'access_log:'
| extend DurationMs = todouble(extract(@'dur=(\d+)', 1, Log_s)) / 1000.0
| extend StatusCode = toint(extract(@'status=(\d+)', 1, Log_s))
| extend Method = extract(@'method=(\w+)', 1, Log_s)
| extend Path = extract(@'path=(\S+)', 1, Log_s)
| project TimeGenerated, Method, Path, StatusCode, DurationMs
| order by TimeGenerated desc

Slow requests (> 1s)

Open in Grafana

ContainerAppConsoleLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where Log_s startswith 'access_log:'
| extend DurationMs = todouble(extract(@'dur=(\d+)', 1, Log_s)) / 1000.0
| extend StatusCode = toint(extract(@'status=(\d+)', 1, Log_s))
| extend Path = extract(@'path=(\S+)', 1, Log_s)
| where DurationMs > 1000
| project TimeGenerated, Path, StatusCode, DurationMs
| order by DurationMs desc

5xx errors

Open in Grafana

ContainerAppConsoleLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where Log_s startswith 'access_log:'
| extend StatusCode = toint(extract(@'status=(\d+)', 1, Log_s))
| extend Path = extract(@'path=(\S+)', 1, Log_s)
| where StatusCode >= 500
| project TimeGenerated, Path, StatusCode, Log_s
| order by TimeGenerated desc

P50/P95/P99 latency (5-min bins)

Open in Grafana

ContainerAppConsoleLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where Log_s startswith 'access_log:'
| extend DurationMs = todouble(extract(@'dur=(\d+)', 1, Log_s)) / 1000.0
| where isnotnull(DurationMs)
| summarize
    p50 = percentile(DurationMs, 50),
    p95 = percentile(DurationMs, 95),
    p99 = percentile(DurationMs, 99)
    by bin(TimeGenerated, 5m)
| order by TimeGenerated desc

Error rate per 5 min

Open in Grafana

ContainerAppConsoleLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where Log_s startswith 'access_log:'
| extend StatusCode = toint(extract(@'status=(\d+)', 1, Log_s))
| summarize
    Total = count(),
    Errors5xx = countif(StatusCode >= 500),
    ErrorRate = round(100.0 * countif(StatusCode >= 500) / count(), 2)
    by bin(TimeGenerated, 5m)
| order by TimeGenerated desc

Top endpoints by volume

Open in Grafana

ContainerAppConsoleLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where Log_s startswith 'access_log:'
| extend Path = extract(@'path=(\S+)', 1, Log_s)
| extend NormPath = replace_regex(Path, @'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|\b\d{4,}\b', '{id}')
| summarize Count = count() by NormPath
| order by Count desc
| take 20

Latency percentiles by endpoint

Open in Grafana

ContainerAppConsoleLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where Log_s startswith 'access_log:'
| extend DurationMs = todouble(extract(@'dur=(\d+)', 1, Log_s)) / 1000.0
| extend Method = extract(@'method=(\w+)', 1, Log_s)
| extend Path = extract(@'path=(\S+)', 1, Log_s)
| extend NormPath = replace_regex(Path, @'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|\b\d{4,}\b', '{id}')
| where isnotnull(DurationMs)
| summarize
    p50 = percentile(DurationMs, 50),
    p95 = percentile(DurationMs, 95),
    p99 = percentile(DurationMs, 99),
    Count = count()
    by Method, NormPath
| order by Count desc
| take 30

Application Logs

Python exceptions / tracebacks

Open in Grafana

ContainerAppConsoleLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where Log_s startswith 'Traceback' or Log_s startswith 'TypeError' or Log_s startswith 'Error'
| project TimeGenerated, Log_s
| order by TimeGenerated desc

App logs only (filter out noise)

Filters out urllib3 outgoing request logs and access logs to show only application-level logs.

Open in Grafana

ContainerAppConsoleLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where Log_s !startswith 'access_log:'
| where Log_s !startswith 'https://'
| where Log_s !startswith 'Starting new HTTPS'
| project TimeGenerated, Stream_s, Log_s
| order by TimeGenerated desc
| take 200

JSON structured app logs

Open in Grafana

ContainerAppConsoleLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where Log_s startswith '{'
| extend parsed = parse_json(Log_s)
| extend LogType = tostring(parsed.type), Msg = tostring(parsed.msg)
| where isnotempty(LogType)
| project TimeGenerated, LogType, Msg
| order by TimeGenerated desc
| take 100

System Logs

Scaling events

Open in Grafana

ContainerAppSystemLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where EventSource_s == 'Scaling'
| project TimeGenerated, Log_s, RevisionName_s
| order by TimeGenerated desc

KEDA scaler events

Open in Grafana

ContainerAppSystemLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where EventSource_s == 'KEDA'
| project TimeGenerated, Reason_s, Log_s
| order by TimeGenerated desc

Container restarts / crashes

Open in Grafana

ContainerAppSystemLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where Reason_s in ('BackOff', 'CrashLoopBackOff', 'Killing', 'Unhealthy', 'Failed')
| project TimeGenerated, Reason_s, Log_s, ReplicaName_s
| order by TimeGenerated desc

Health probe failures

Open in Grafana

ContainerAppSystemLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where Reason_s == 'ProbeFailed'
| project TimeGenerated, Log_s, ReplicaName_s
| order by TimeGenerated desc

Container terminations

Open in Grafana

ContainerAppSystemLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where Reason_s in ('ContainerTerminated', 'ProcessExited', 'StoppingContainer')
| project TimeGenerated, Reason_s, Log_s, ReplicaName_s
| order by TimeGenerated desc

Replica failures

Open in Grafana

ContainerAppSystemLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where Reason_s in ('AssigningReplicaFailed', 'ReplicaUnhealthy', 'ContainerBackOff', 'Error', 'ContainerAppFailure')
| project TimeGenerated, Reason_s, Log_s, ReplicaName_s
| order by TimeGenerated desc

Deployment / revision events

Open in Grafana

ContainerAppSystemLogs_CL
| where ContainerAppName_s == 'backend-stacksync-prod'
| where Reason_s in ('RevisionCreation', 'RevisionReady', 'RollingRevisionCompleted', 'RevisionUpdate')
| project TimeGenerated, Reason_s, RevisionName_s, Log_s
| order by TimeGenerated desc

Cross-App Queries

All apps - 5xx count last 1h

Open in Grafana

ContainerAppConsoleLogs_CL
| where Log_s startswith 'access_log:'
| extend StatusCode = toint(extract(@'status=(\d+)', 1, Log_s))
| where StatusCode >= 500
| summarize Count = count() by ContainerAppName_s
| order by Count desc

All apps - slowest requests last 1h

Open in Grafana

ContainerAppConsoleLogs_CL
| where Log_s startswith 'access_log:'
| extend DurationMs = todouble(extract(@'dur=(\d+)', 1, Log_s)) / 1000.0
| extend Path = extract(@'path=(\S+)', 1, Log_s)
| where DurationMs > 5000
| project TimeGenerated, ContainerAppName_s, Path, DurationMs
| order by DurationMs desc
| take 50

All apps - request volume

Open in Grafana

ContainerAppConsoleLogs_CL
| where Log_s startswith 'access_log:'
| summarize RequestCount = count() by ContainerAppName_s
| order by RequestCount desc

Notes

  • dur in access logs is in microseconds (divide by 1000 for ms)
  • Access logs are emitted via GUNICORN_CMD_ARGS env var set on all prod container apps
  • Log format: access_log:dur=<us>,status=<code>,method=<METHOD>,path=<path>
  • Path normalization: replace_regex(Path, @'[0-9a-f]{8}-...-[0-9a-f]{12}|\b\d{4,}\b', '{id}') collapses UUIDs and numeric IDs into {id}
  • Adjust TimeGenerated filters or Grafana time picker to control the time range
  • Each region has its own workspace — run cross-region comparisons by querying both workspaces separately