Skip to main content

Querying Logs with Kusto Query Language (KQL)

Learn the basic KQL syntax needed to search, filter, and summarize logs in a Log Analytics Workspace to actually find an incident's root cause.

Overview and What You Will Learn

In this lab, you will send VM logs into a Log Analytics Workspace, then write a series of KQL queries - starting simple and adding filtering and summarization - to go from "here is a huge pile of raw log data" to "here is exactly which error happened, how often, and when."

Why This Matters in Production

An engineer at a growing e-commerce platform is told "checkout is slow sometimes," with no more specific information than that. Without the ability to actually query logs - filtering by time range, error type, and frequency - finding the actual root cause becomes a matter of scrolling through raw text files by hand. KQL turns that into a precise, repeatable question asked directly against the data.

Core Principles

KQL queries are built as a pipeline - each step, separated by a pipe character, narrows or reshapes the data before passing it to the next step.

◈ DIAGRAM
+------------------------------------------+
| Start with a table (e.g. Heartbeat, |
| Syslog, AppExceptions) |
+------------------------------------------+
|
v
+------------------------------------------+
| Filter rows (where clause) |
+------------------------------------------+
|
v
+------------------------------------------+
| Reshape or summarize (project, summarize) |
+------------------------------------------+
|
v
+------------------------------------------+
| Sort and limit results |
+------------------------------------------+

Reading a KQL query top to bottom tells you exactly what's happening to the data at each stage - this pipeline structure is what makes even a complex query readable once you know to look for it.

Detailed Step-by-Step Practical Lab

  1. Create a Resource Group and a Log Analytics Workspace:
Bash
az group create --name rg-kql-lab-mumbai --location centralindia
az monitor log-analytics workspace create \
--resource-group rg-kql-lab-mumbai \
--workspace-name law-kql-lab
  1. Create a VM and connect it to send logs into this workspace:
Bash
az vm create \
--resource-group rg-kql-lab-mumbai \
--name vm-kql-lab \
--image Ubuntu2204 \
--size Standard_B1s \
--admin-username azureadmin \
--generate-ssh-keys
# on this VM and configured to send logs to the workspace created above
  1. Once logs are flowing, start with the simplest possible query - just look at recent entries from a table:
TEXT
Heartbeat
| take 10
  1. Narrow the query to a specific time range and computer name using where:
TEXT
Heartbeat
| where TimeGenerated > ago(1h)
| where Computer == "vm-kql-lab"
  1. Reshape the results to show only the specific columns that matter, using project:
TEXT
Heartbeat
| where TimeGenerated > ago(1h)
| project TimeGenerated, Computer, OSType
  1. Summarize how many heartbeats were received per hour, to spot any gaps in reporting:
TEXT
Heartbeat
| where TimeGenerated > ago(24h)
| summarize count() by bin(TimeGenerated, 1h)
| order by TimeGenerated asc
Note

bin(TimeGenerated, 1h) groups timestamps into 1-hour buckets before counting - this is the standard KQL pattern for building a time-series view of any metric, like errors per hour or requests per minute.

  1. Search across the Syslog table for any lines containing the word "error," a common first step when investigating an unspecified problem:
TEXT
Syslog
| where TimeGenerated > ago(6h)
| where SyslogMessage contains "error"
| project TimeGenerated, Computer, SyslogMessage
| order by TimeGenerated desc
  1. Clean up:
Bash
az group delete --name rg-kql-lab-mumbai --yes --no-wait

Production Best Practices & Common Pitfalls

Common Mistake

Writing a query with no time filter at all against a workspace collecting months of data. This can be slow and expensive to run, and usually returns far more results than are actually useful - always start with a where TimeGenerated > ago(...) filter before adding anything else.

Tip

Build a query incrementally - start with take 10 to see what the raw data looks like, then add where filters one at a time, checking results after each addition, rather than trying to write the complete, complex query in one attempt.

  • summarize is the tool for turning raw log rows into an actual answer - "how many," "average of what," "grouped by which field" are all summarize-shaped questions, distinct from filtering, which only narrows which raw rows you see.
  • Save frequently used queries rather than rewriting them from scratch during every incident. A saved query for "show me all errors in the last hour for this specific service" turns a repeatable investigation into a single click.

Quick Reference & Troubleshooting Commands

KQL Operator Description
where Filter rows based on a condition
project Select and reshape specific columns
summarize Aggregate rows (count, average, etc.)
order by Sort results
take N Return only the first N rows, useful for quick previews
ago(1h) A relative time reference, here meaning "1 hour ago"

Explore More in Azure Monitoring, Identity, and Production Readiness

All 6 Topics

Frequently Asked Questions

Is Querying Logs with Kusto Query Language (KQL) free to learn on DevOps Network?

Yes - this topic, like everything on DevOps Network, is 100% free with no paywall or sign-up gate.

What does the Querying Logs with Kusto Query Language (KQL) topic cover?

Learn the basic KQL syntax needed to search, filter, and summarize logs in a Log Analytics Workspace to actually find an incident's root cause.