Monitoring & Governance
.mdVerified against Azure CLI 2.87.0, flags verified via `az <cmd> --help`, 2026-08-21 · official docs
Azure Monitor metrics and Log Analytics queries for observability, and Azure Policy for enforcing organization-wide governance rules.
Listing available metrics for a resource#
az monitor metrics list-definitions --resource <resource-id> az monitor metrics list --resource <resource-id> --metrics "Percentage CPU" --interval 5m
az monitor metrics list-definitions tells you which metric names, aggregation types, and dimensions a given resource actually supports before you query it — resource types expose different metrics, so guessing a metric name is a common source of an empty result.
Creating a metric-based alert#
az monitor metrics alert create \ --resource-group my-rg --name high-cpu-alert \ --scopes /subscriptions/<sub-id>/resourceGroups/my-rg/providers/Microsoft.Compute/virtualMachines/my-vm \ --condition "avg Percentage CPU > 80" \ --window-size 5m --evaluation-frequency 1m \ --action my-action-group
--condition uses a compact expression syntax ({avg,min,max,total,count} METRIC {operator} THRESHOLD) rather than a JSON body — az monitor metrics alert condition create can build more complex dynamic-threshold conditions if a static threshold isn't enough.
Querying a Log Analytics workspace#
az monitor log-analytics workspace create --resource-group my-rg --workspace-name my-workspace az monitor log-analytics query \ --workspace <workspace-customer-id> \ --analytics-query "AzureActivity | summarize count() by bin(TimeGenerated, 1h)" \ --timespan P1D
The --workspace value is the workspace's customer ID (a GUID), not its resource name — get it with az monitor log-analytics workspace show --resource-group my-rg --workspace-name my-workspace --query customerId -o tsv. --analytics-query takes a KQL (Kusto Query Language) query, the same language used in the Log Analytics portal blade.
Azure Policy: definitions and assignments#
az policy definition create \ --name require-tag-environment \ --rules @policy-rule.json --params @policy-params.json \ --mode Indexed --display-name "Require an environment tag" az policy definition list --query "[?policyType=='Custom']" --output table az policy assignment create \ --name enforce-env-tag --policy require-tag-environment \ --scope /subscriptions/<sub-id>/resourceGroups/my-rg
A policy definition is just a rule (what to check, and the effect — deny, audit, append, etc.); it does nothing until a policy assignment attaches it to a scope (subscription, resource group, or management group). The same definition can be assigned at multiple scopes with different parameters.
Checking policy compliance#
az policy state list --resource-group my-rg --filter "complianceState eq 'NonCompliant'" az policy state trigger-scan --resource-group my-rg --no-wait
Compliance state is evaluated on a periodic cycle (roughly every 24 hours) plus on resource create/update — az policy state trigger-scan forces an on-demand re-evaluation instead of waiting for the next cycle, useful right after creating or changing an assignment.