Microsoft Azure — Log Analytics & KQL
Log Analytics workspaces, Kusto Query Language (KQL), table schemas, and log analytics dashboards..
20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.
- ✓Azure subscription with a Log Analytics workspace ingesting logs, basic understanding of Azure Monitor, familiarity with SQL-like query syntax, access to Log Analytics query editor in Azure Portal.
Azure is Microsoft's cloud computing platform offering over 200 services. This article covers log analytics & kql with production-ready configurations, best practices, and hands-on examples.
Why Log Analytics and KQL Matter in Production
In production Azure environments, logs are the single source of truth for diagnosing failures, understanding performance, and auditing security. Log Analytics workspaces aggregate logs from Azure resources, VMs, containers, and custom sources. Kusto Query Language (KQL) is the query language used to extract insights from these logs. Without KQL, you're flying blind. This article assumes you have a Log Analytics workspace and some logs flowing in. We'll cover the essential KQL patterns that every DevOps engineer needs to know, from basic filtering to advanced time-series analysis.
Essential KQL Operators: Where, Project, Extend
The three most common operators are where (filter rows), project (select columns), and extend (create computed columns). In production, you'll use them constantly. Where filters based on conditions; project reduces the result set to relevant columns, improving performance; extend adds new columns derived from existing ones. Always project early to minimize data transfer. Avoid using project-away unless you're sure the excluded columns are not needed downstream.
Aggregating Logs with Summarize
Summarize is KQL's GROUP BY equivalent. It aggregates data over groups using functions like count(), sum(), avg(), percentile(), and make_list(). In production, you'll use it to compute error rates, average response times, or top error messages. Always include a time bin (bin()) to avoid unbounded aggregation. The bin() function rounds timestamps to a given interval — use it to create time series.
bin() in summarize by time will group by exact timestamp, producing millions of groups and a useless result.bin() for time-based aggregations; it's the only way to get meaningful time series.Joining Tables for Cross-Resource Analysis
Production incidents often span multiple resources. Joins let you correlate logs from different tables (e.g., AzureDiagnostics and AzureActivity). KQL supports lookup, join, and union. Use join with kind=leftouter or kind=inner. For performance, ensure the left table is the smaller one and that both sides have indexed columns (like TimeGenerated and CorrelationId). Avoid cross-joins at all costs.
Time Series Analysis with Series Functions
KQL has built-in functions for time series analysis: series_decompose(), series_fit_line(), and series_periods_detect(). These are invaluable for anomaly detection and trend analysis. For example, series_decompose() splits a time series into trend, seasonal, and residual components. In production, use it to detect sudden spikes in error rates or drops in throughput. The function expects a dynamic array — use make_list() with summarize to create it.
materialize() when creating a series to avoid re-evaluating the same query multiple times.Creating Alerts with KQL Query Results
Log Analytics alerts run KQL queries on a schedule and fire when results meet a threshold. The query must return a numeric metric (e.g., count of errors). Use the alert rule to set frequency, threshold, and action groups. In production, always include a time filter relative to now (ago()) to avoid stale data. Test your query in the Log Analytics UI before creating the alert. Use dimensions to split alerts by resource.
ago().Performance Tuning KQL Queries
Slow queries waste time and money. Key tuning techniques: filter early (where on indexed columns like TimeGenerated), project early, avoid excessive string operations, use materialize() for reused subqueries, and prefer summarize over join when possible. Use the query statistics pane to identify bottlenecks. In production, set a query timeout (default 10 minutes) and use take/limit to sample during development.
Advanced: Cross-Workspace Queries
In large organizations, logs are spread across multiple Log Analytics workspaces. Use the workspace() function to query across workspaces in a single query. This is essential for global views or when consolidating logs from different environments. The syntax: workspace('workspace-id'). You can also use union with workspace() to combine results. Be aware of cross-region latency and cost.
workspace() to query multiple workspaces, but watch for cross-region costs.Using KQL with Azure Workbooks
Azure Workbooks provide interactive reports powered by KQL. They combine queries, visualizations, and text into a single dashboard. In production, workbooks are used for post-mortems, capacity planning, and real-time monitoring. You can parameterize queries (e.g., time range, resource name) to make them reusable. Use the workbook's built-in charts (time chart, bar chart, grid) to visualize results.
Common Pitfalls and How to Avoid Them
Even experienced engineers make mistakes. Top pitfalls: forgetting time filters, using contains instead of has_cs, not using materialize() for reused subqueries, joining on non-indexed columns, and ignoring query limits (500,000 rows default). Always test with a small time range first. Use the query editor's 'Analyze' button to see execution stats. In production, set up a log query audit to catch expensive queries.
Production Monitoring with KQL Dashboards
Dashboards in Azure Monitor are built from KQL queries pinned from Log Analytics or Workbooks. They provide at-a-glance status of your production environment. Best practices: limit each tile to a single metric, use relative time ranges (e.g., last 24 hours), and set auto-refresh (5 minutes). Use conditional formatting to highlight anomalies. In production, dashboards should be the first thing an on-call engineer checks.
Next Steps: Automating KQL with APIs
KQL queries can be executed programmatically via the Azure Monitor Log Analytics API. This enables automation: run queries from CI/CD pipelines, generate reports, or trigger remediation. Use the REST API with a service principal for authentication. The response is JSON. In production, we use this to automatically create Jira tickets when certain error patterns appear. Be mindful of API rate limits (300 requests per minute per workspace).
| File | Command / Code | Purpose |
|---|---|---|
| basic-filter.kql | AzureDiagnostics | Why Log Analytics and KQL Matter in Production |
| operators.kql | AzureDiagnostics | Essential KQL Operators |
| summarize.kql | AzureDiagnostics | Aggregating Logs with Summarize |
| join.kql | let errors = AzureDiagnostics | Joining Tables for Cross-Resource Analysis |
| timeseries.kql | let errors = AzureDiagnostics | Time Series Analysis with Series Functions |
| alert-query.kql | AzureDiagnostics | Creating Alerts with KQL Query Results |
| tuning.kql | AzureDiagnostics | Performance Tuning KQL Queries |
| cross-workspace.kql | union | Advanced |
| workbook-query.kql | let timeRange = {TimeRange:timespan}; | Using KQL with Azure Workbooks |
| pitfalls.kql | AzureDiagnostics | Common Pitfalls and How to Avoid Them |
| dashboard-tile.kql | AzureDiagnostics | Production Monitoring with KQL Dashboards |
| run_kql.py | workspace_id = 'your-workspace-id' | Next Steps |
Key takeaways
bin()bin() for time-based aggregations; it's essential for time series and alerting.materialize() for reused subqueries to avoid redundant scans.Frequently Asked Questions
20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.
That's Azure. Mark it forged?
3 min read · try the examples if you haven't