Create custom metric alerts
Create custom metric alerts in Azure — hands-on guide with practical steps, troubleshooting, and what to learn next.
Focus: create custom metric alerts
You've built your Azure environment, deployed apps, and wired up networking — but when something breaks, how do you know before your users do? Watching dashboards manually is a losing game. In this lesson, you'll learn to create custom metric alerts that watch your key performance indicators and page you the moment they drift out of bounds — so you can fix problems while they're still quiet, not after the incident page explodes.
The problem this lesson solves
Without alerts, you're flying blind. Your app could be slowly leaking memory, your database could be approaching its connection limit, or your API could be returning 500s to a small but growing set of users. By the time anyone notices, the issue has often escalated into a full-blown incident.
Custom metric alerts give you a programmatic tripwire. You define a condition — say, CPU usage greater than 80% for five minutes — and Azure monitors it continuously, firing a notification when the condition is met. This isn't just about avoiding downtime; it's about operational maturity. Teams that respond to alerts before customers complain are happier, more productive, and less stressed.
Alerting also matters for cost control. A sudden spike in outbound data transfer might be a sign of an inefficient query or a runaway process. Alerting on those metrics helps you catch cost leaks early.
The core problem this lesson solves is simple: how to turn raw telemetry into actionable signals that trigger the right people at the right time.
Core concept / mental model
Think of Azure Monitor as the central nervous system of your Azure resources. Every service emits metrics — numerical values like CPU percentage, request count, or queue length. These metrics are stored for a rolling period (typically 30 days for most services).
A metric alert is a rule that watches one of these metrics and compares it to a threshold. Think of it like a thermostat: you set a desired range, and when the temperature (your metric) crosses the threshold, the furnace or AC (your alert action) kicks in.
Key terms you'll encounter: - Metric — a single measurable value emitted by a resource. - Metric alert rule — a definition that includes the metric, condition, window, and action group. - Condition — the logical operation, like "greater than" or "less than", applied to the metric value over a time window. - Action group — a set of actions (email, SMS, webhook, ITSM) that trigger when the alert fires. - Alert state — Fired, Resolved, or Acknowledged.
The anatomy of a metric alert
A metric alert works in three phases: 1. Collect — Azure Monitor ingests metrics from your resource. 2. Evaluate — At a frequency you set (e.g., every 1 minute), the alert engine checks if the condition is true. 3. Act — If the condition is true, the alert is fired and the action group is invoked.
This model is consistent across resource types, which is why once you master one alert, you can quickly build others.
How it works step by step
Creating a custom metric alert involves a series of logical steps. Let's break them down.
Step 1: Identify the metric you care about
First, decide which metric best represents the health of your resource. For an App Service, it might be CpuTime or Requests. For a Storage account, Ingress or Egress. For a Virtual Machine, Percentage CPU or Network In Total.
You can see available metrics in the Azure Portal by navigating to your resource → Monitoring → Metrics. Scroll through the list and note the name (and unit) of the metric you want.
Step 2: Define the threshold and window
Ask: What value would indicate a problem? This depends on your workload. A burst of CPU to 90% for one minute might be normal for a batch job; an average above 80% for 30 minutes is likely problematic.
You'll set a threshold (the value) and an evaluation window (how long the condition must hold before firing). For example:
- Greater than 80% CPU for 10 minutes
- Less than 2 requests per minute for 5 minutes
Step 3: Choose the aggregation
Metrics are raw samples. You can aggregate them over the window using Average, Minimum, Maximum, Total, or Count. For steady-state resources, Average is typical. For detecting latency spikes, Maximum is better.
Step 4: Set an evaluation frequency
How often should Azure check the condition? Every 1 minute is granular, but it costs a bit more. Every 5 minutes is often sufficient. Balance alert responsiveness with cost.
Step 5: Configure the action group
An alert that no one sees is worthless. Create an Action group with your preferred channels — email, SMS, webhook, ITSM. You can reuse the same action group across many alerts.
Step 6: Create the alert rule
Finally, assemble the rule via Portal, CLI, or ARM template. Each method is valid — choose the one that fits your workflow.
Hands-on walkthrough
Let's create a custom metric alert on an Azure Virtual Machine, watching Percentage CPU. We'll use the Azure CLI because it's scriptable and repeatable.
Prerequisites
- An Azure subscription
- An existing VM named
myVM(or any resource) - Azure CLI installed and logged in
Example 1: Create a metric alert via CLI
First, create an action group that sends email to ops@example.com:
az monitor action-group create \
--resource-group myResourceGroup \
--name myActionGroup \
--short-name myAlertGroup \
--action email ops-email ops@example.com
Then create the alert rule:
az monitor metrics alert create \
--name "High CPU" \
--resource-group myResourceGroup \
--scopes /subscriptions/<sub-id>/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/myVM \
--condition "Percentage CPU > 80 avg 5m" \
--action-groups /subscriptions/<sub-id>/resourceGroups/myResourceGroup/providers/microsoft.insights/actionGroups/myActionGroup \
--evaluation-frequency 1m \
--window-size 5m \
--auto-mitigate true
Expected output (condensed):
{
"name": "High CPU",
"condition": {
"metricName": "Percentage CPU",
"operator": "GreaterThan",
"threshold": 80,
"timeAggregation": "Average",
"windowSize": "PT5M"
},
"enabled": true
}
The rule is now active. If CPU averages above 80% over any 5-minute window, the action group will fire an email.
Example 2: Create an alert with a dynamic threshold
Dynamic thresholds use machine learning to detect anomalies instead of a fixed number. This is great for metrics with seasonal patterns.
az monitor metrics alert create \
--name "Dynamic CPU Anomaly" \
--resource-group myResourceGroup \
--scopes /subscriptions/<sub-id>/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/myVM \
--condition "Percentage CPU dynamic 5m" \
--action-groups /subscriptions/<sub-id>/resourceGroups/myResourceGroup/providers/microsoft.insights/actionGroups/myActionGroup
This rule has no fixed threshold; it learns the normal baseline and alerts on deviations.
Example 3: Deploy alert rules as infrastructure with Bicep
For production, define alerts in code so they're versioned and repeatable. Here's a Bicep snippet:
resource alertRule 'Microsoft.Insights/metricAlerts@2018-03-01' = {
name: 'High-CPU-Alert'
location: 'global'
properties: {
description: 'Alert when CPU is high'
severity: 3
enabled: true
scopes: [
vmId
]
evaluationFrequency: 'PT1M'
windowSize: 'PT5M'
criteria: {
'odata.type': 'Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria'
allOf: [
{
name: 'Metric1'
metricName: 'Percentage CPU'
operator: 'GreaterThan'
threshold: 80
timeAggregation: 'Average'
}
]
}
actions: [
{
actionGroupId: actionGroupId
}
]
}
}
Deploy with:
az deployment group create --resource-group myResourceGroup --template-file main.bicep
This IaC approach makes your alerts reviewable, auditable, and deployable to multiple environments.
Compare options / when to choose what
You have several ways to create metric alerts. Here's a quick comparison:
| Method | Pros | Cons | Best for |
|---|---|---|---|
| Azure Portal | Visual, easy to explore metrics | Manual, hard to reproduce | First-time setup, one-off exploration |
| Azure CLI | Scriptable, quick to automate | Requires CLI familiarity | Ad-hoc scripting, automation |
| ARM/Bicep | Infrastructure-as-code, versioned, reviewable | Steeper learning curve | Production environments, CI/CD |
| Azure Policy / Terraform | Governance, multi-subscription | More complex setup | Compliance, large-scale deployments |
Our recommendation: Start in the Portal to understand the concepts, then move to CLI for rapid iteration, and finally commit to Bicep for production. The investment in IaC pays off when you need to recreate alerts across environments or trace changes.
Variations on alert conditions
- Static threshold — fixed value; simplest and most predictable.
- Dynamic threshold — machine-learning based; adapts to seasonality but may require tuning.
- Multi-condition — combine several metrics (e.g., CPU > 80% AND memory > 90%); more complex but more precise.
Troubleshooting & edge cases
Alert not firing
- Check that the resource actually emits metrics. Some metrics appear only when activity occurs (e.g., a VM that's stopped has no CPU data).
- Verify the threshold is realistic. If you set CPU > 90% but your app runs at 30%, it will never fire.
- Confirm the action group is valid and has active channels. Email can land in spam.
Alert fires too often
- "Flapping" happens when your metric lingers right near the threshold. Increase the window size (e.g., from 5 to 15 minutes) or use dynamic thresholds.
- Check the aggregation — Average is smoother than Maximum. Using Maximum over a 1-minute window may catch transient spikes.
Legal/security issues
- For compliance, ensure alerts meet your retention and privacy policies. Alert emails may contain resource names — keep them non-sensitive.
Wrong metric
- The metric name is case-sensitive in API calls. In Portal, metrics often have friendly names like "CPU Utilization" but the underlying metric name is
Percentage CPU. Always verify with the CLI or metrics API.
Action group not triggering
- Test the action group independently — use Test action group in Portal to send a test email.
What you learned & what's next
You now know how to create custom metric alerts — the art of turning raw telemetry into actionable notifications. You've learned the mental model (metric adductors → alert rule → action group), the step-by-step process, and how to implement it with CLI, Portal, and Bicep. You can troubleshoot the most common traps and choose static vs dynamic thresholds.
This is a foundational skill for any Azure operator. In the next lesson, you'll build on this by diving into Azure Log Analytics queries — combining metric alerts with log-based alerts for even richer monitoring. You'll be able to alert not just on numbers but on log messages, giving you visibility into application errors and exceptions. Keep your alerting sharp and your on-call schedule quiet.
Key objectives met: - You can explain the core idea behind custom metric alerts. - You completed a practical exercise (CLI + Bicep). - You know how to connect this knowledge to the next step in your Azure learning path.
Practice recap
Now it's your turn: create a metric alert on a resource in your sandbox using the Azure CLI, trigger the condition (e.g., start a CPU-intensive script on a VM), and confirm you receive the email/SMS from your action group. Then try rewriting the same alert as a Bicep template and redeploy it. Finally, experiment with a dynamic threshold to see how it adjusts to your metric's baseline.
Common mistakes
- Forgetting that some resources emit metrics only when active — a VM that's stopped or an app with zero traffic will show no data, which can cause false 'alert not firing' assumptions.
- Using an overly narrow evaluation window (e.g., 1 minute) with a static threshold leads to flapping alerts on bursty workloads — increase the window or use a dynamic threshold.
- Mixing up the friendly metric name (e.g., 'CPU Utilization') with the actual API metric name ('Percentage CPU') — always verify with CLI or metrics explorer.
- Reusing a single action group for every alert without testing it — a typo in the email address or a disabled SMS channel can silently fail.
- Skipping auto-mitigation — the alert stays 'fired' forever if the condition normalizes, causing noise in your monitoring dashboard.
Variations
- Use dynamic thresholds to auto-learn baselines — great for seasonal traffic, but requires extra tuning and monitoring.
- Combine multiple metrics in a single alert rule (e.g., CPU > 80% AND memory > 90%) for more precise, albeit more complex, conditions.
- Deploy alert rules via Azure Policy to enforce standard alerting across all subscriptions, ensuring no resource is ever unmonitored.
Real-world use cases
- Page the on-call engineer when the CPU on a production VM exceeds 85% for more than 10 minutes, preventing a crash before customers notice.
- Monitor a Storage account's egress for unusual spikes that signal a data exfiltration attempt or a runaway export job, triggering a webhook to a SIEM.
- Slack/email a DevOps team when a web app's request error rate (based on a custom metric) crosses 5% over 5 minutes, enabling rapid response to deployment regressions.
Key takeaways
- A metric alert rule couples a metric, a condition, and an action group — change any of them and the alert behavior changes dramatically.
- Start in the Portal to visualize metrics, then move to CLI for automation, and adopt Bicep for Infrastructure-as-Code in production.
- Static thresholds are simple but blind to normal variation — dynamic thresholds adapt to your workload's natural rhythms.
- Always verify the exact metric name and aggregation method; a small typo or wrong operator is the #1 reason alerts don't fire as expected.
- Test your action groups independently to guarantee notifications are actually delivered before you depend on them.
- An alert that never fires is just dead code — pair your alert rule with a healthy dashboards review regular review of thresholds and incidents.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.