Complete AI-200 KQL Cheatsheet — Azure Monitor Queries for the Exam
KQL appears in 3–5 questions on the AI-200 exam. You will not need to write queries from memory, but you must recognise what a given query does and choose the correct operator for a monitoring scenario.
KQL mental model
Every KQL query is a pipeline: each | operator takes the output of the previous step as input. Read left-to-right, top-to-bottom.
TableName // 1. Start with a table | where timestamp > ago(1h) // 2. Filter rows | summarize count() by name // 3. Aggregate | top 10 by count_ desc // 4. Return top results
Application Insights — Requests
Failed requests in last 1 hour
requests | where timestamp > ago(1h) | where success == false | count
Top 5 slowest endpoints
requests | summarize avg_duration = avg(duration) by name | top 5 by avg_duration desc
Request rate per minute
requests | summarize count() by bin(timestamp, 1m) | render timechart
P95 response time by endpoint
requests | summarize percentile(duration, 95) by name | order by percentile_duration_95 desc
Application Insights — Exceptions
Top exception types
exceptions | summarize count() by type | top 10 by count_
Exceptions in last 24h with stack trace
exceptions | where timestamp > ago(24h) | project timestamp, type, outerMessage, innermostMessage, operation_Id
Application Insights — Dependencies
Failed dependency calls
dependencies | where success == false | summarize count() by target, type | order by count_ desc
SQL query duration outliers
dependencies | where type == "SQL" | where duration > 1000 | project timestamp, name, duration, target
Log Analytics — AzureActivity
Who deleted a resource group
AzureActivity | where OperationNameValue endswith "delete" | where ActivityStatusValue == "Success" | project TimeGenerated, Caller, ResourceGroup, OperationNameValue
Role assignment changes
AzureActivity | where OperationNameValue == "Microsoft.Authorization/roleAssignments/write" | project TimeGenerated, Caller, Properties
Container Insights — AKS
Pod restarts in last hour
KubePodInventory | where TimeGenerated > ago(1h) | where ContainerStatusReason == "CrashLoopBackOff" | project TimeGenerated, Name, Namespace, ContainerStatusReason
Node CPU usage > 80%
Perf | where ObjectName == "K8SNode" | where CounterName == "cpuUsageNanoCores" | summarize avg_cpu = avg(CounterValue) by Computer | where avg_cpu > 80
Container memory usage by namespace
Perf | where ObjectName == "K8SContainer" | where CounterName == "memoryRssBytes" | summarize sum(CounterValue) by Namespace | render piechart
KQL Operators (exam essentials)
Filter rows
| where timestamp > ago(1h) and success == false
Aggregate and group
| summarize count(), avg(duration) by name
Time bucket
| bin(timestamp, 5m)
Return top N rows
| top 10 by count_ desc
Select columns
| project timestamp, name, duration, resultCode
Add computed column
| extend failed = (resultCode >= 500)
String contains
| where message contains "timeout"
Join two tables
TableA | join kind=inner TableB on $left.id == $right.id
Parse JSON field
| extend props = parse_json(customDimensions) | project props.orderId
Cross-workspace query
union workspace("workspace-A").requests, workspace("workspace-B").requests
| where success == falseExam tips for KQL questions
- • ago() is almost always the right time filter for recent data
- • summarize + by = GROUP BY equivalent
- • top N by col desc ≠ order by: top also limits rows
- • Failed requests:
success == falsein Application Insights,ResultType != "Success"in AAD logs - •
extendadds a computed column without aggregation;projectselects columns - • For time charts: always pipe to
| render timechart - • Container Insights table names:
KubePodInventory,KubeNodeInventory,ContainerLog,Perf