Stage 5 · Platform
Azure Monitor & Observability
Log Analytics & KQL
Write KQL queries to analyze container logs, audit logs, and metrics.
KQL Overview
Kusto Query Language (KQL) is a read-only query language for Azure Data Explorer, Log Analytics, and Application Insights. It uses a pipe-based syntax where data flows through a series of operators.
// Every KQL query starts with a table name and pipes through operators
StormEvents
| where StartTime >= datetime(2024-01-01)
| where State == "TEXAS"
| summarize EventCount = count() by EventType
| order by EventCount descThe pipe operator (|) passes results to the next operator. Query results are limited to 500,000 rows by default in Log Analytics.
Basic Queries
// Select specific columns
AzureActivity
| project TimeGenerated, ResourceGroup, Resource, OperationName
// Take first 100 rows
AzureActivity
| take 100
// Sort by time
AzureActivity
| order by TimeGenerated desc
| take 50
// Count events by operation
AzureActivity
| summarize count() by OperationName
| order by count_ descThe take operator returns an arbitrary sample of rows. Use top instead of take when you need the highest/lowest values.
Filtering and Searching
// Exact match
AzureDiagnostics
| where Category == "kube-audit"
// Contains (case-insensitive)
AzureDiagnostics
| where Message contains "error"
// Startswith
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.CONTAINERSERVICE"
// Regex match
AzureDiagnostics
| where Resource matches regex "aks-.*-prod"
// Multiple conditions
AzureDiagnostics
| where Level == "Error" or Level == "Warning"
| where TimeGenerated > ago(24h)
// Free-text search across all columns
AzureDiagnostics
| search "connection refused"contains is case-insensitive and slower than has. Use has for exact word matching and contains for partial matches.
has checks for exact word boundaries and uses indexes, making it 10-100x faster than contains. Use contains only when you need partial matching.
Aggregation and Summarization
// Count by category
AzureDiagnostics
| summarize count() by Category
// Average, min, max
Perf
| where ObjectName == "Processor"
| summarize avg(CounterValue), min(CounterValue), max(CounterValue) by Computer
// Percentiles
Perf
| where ObjectName == "Processor"
| summarize percentile(CounterValue, 95) by Computer
// Distinct count
AzureActivity
| summarize dcount(Resource) by ResourceGroup
// Time series (make-series)
Perf
| where ObjectName == "Processor"
| make-series avg(CounterValue) default=0 on TimeGenerated from ago(24h) to now() step 5m by Computermake-series creates time-bucketed arrays for visualization. It is the foundation for time-series charts in workbooks and dashboards.
Joins and Correlation
// Inner join — only matching rows from both tables
requests
| where success == true
| join kind=inner (
dependencies
| where success == false
) on operation_Id
// Left outer join — all rows from left, matching from right
requests
| join kind=leftouter (
exceptions
| summarize ExceptionCount = count() by operation_Id
) on operation_Id
// Union — combine rows from multiple tables
union AppTraces, AppLogs
| where TimeGenerated > ago(1h)
| where SeverityLevel >= 3join correlates data from different tables using a common field. operation_Id links all telemetry for a single request in Application Insights.
Container Log Analysis
// Container stdout/stderr logs
ContainerLogV2
| where TimeGenerated > ago(1h)
| where ContainerName == "payments"
| project TimeGenerated, LogEntry, Level
// Container resource usage
Perf
| where ObjectName == "K8SContainer"
| summarize avg(CounterValue) by Computer, InstanceName
| order by avg_CounterValue desc
// Pod restart count
ContainerInsights
| where TimeGenerated > ago(24h)
| where PodRestartCount > 0
| summarize max(PodRestartCount) by PodName, Namespace
| order by max_PodRestartCount desc
// Failed pod scheduling events
KubeEvents
| where TimeGenerated > ago(1h)
| where Reason == "FailedScheduling"
| project TimeGenerated, ObjectName, MessageContainerLogV2 provides structured container logs with automatic parsing. ContainerInsights provides pod-level metrics when Container Insights is enabled.
Log Analytics charges per GB of data ingested. Use filtering and sampling to reduce volume. Retention beyond 30 days incurs additional storage costs.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.