Skip to content

Azure Monitor Alerts

Overview

Azure Monitor Alerts proactively notify you when important conditions are found in your monitoring data. They allow you to identify and address issues before users notice them.

Alert Types

1. Metric Alerts

Monitor numeric values from Azure resources.

Features: - Near real-time evaluation (1-5 minutes) - Multiple conditions and dimensions - Dynamic thresholds - Stateful and stateless

2. Log Search Alerts

Query-based alerts using KQL.

Features: - Complex logic using KQL - Cross-resource queries - Custom time windows - Aggregation-based conditions

3. Activity Log Alerts

Monitor subscription-level events.

Features: - Resource creation/deletion - Configuration changes - Service health events - Administrative operations

4. Smart Detection Alerts

AI-powered anomaly detection (Application Insights).

Features: - Automatic baseline learning - Failure anomalies - Performance degradation - Memory leak detection

Create Metric Alert

Azure Portal

  1. Navigate to Azure Monitor
  2. Select "Alerts" > "Create" > "Alert rule"
  3. Select resource scope
  4. Add condition (metric)
  5. Configure action group
  6. Set alert details

Azure CLI

az monitor metrics alert create \
  --name myMetricAlert \
  --resource-group myResourceGroup \
  --scopes /subscriptions/{sub-id}/resourceGroups/{rg}/providers/Microsoft.Compute/virtualMachines/{vm} \
  --condition "avg Percentage CPU > 80" \
  --description "Alert when CPU exceeds 80%" \
  --evaluation-frequency 5m \
  --window-size 15m \
  --severity 2 \
  --action /subscriptions/{sub-id}/resourceGroups/{rg}/providers/microsoft.insights/actionGroups/{action-group}

ARM Template

{
  "type": "Microsoft.Insights/metricAlerts",
  "apiVersion": "2018-03-01",
  "name": "myMetricAlert",
  "location": "global",
  "properties": {
    "description": "Alert when CPU exceeds 80%",
    "severity": 2,
    "enabled": true,
    "scopes": [
      "/subscriptions/{sub-id}/resourceGroups/{rg}/providers/Microsoft.Compute/virtualMachines/{vm}"
    ],
    "evaluationFrequency": "PT5M",
    "windowSize": "PT15M",
    "criteria": {
      "allOf": [
        {
          "name": "HighCPU",
          "metricName": "Percentage CPU",
          "metricNamespace": "Microsoft.Compute/virtualMachines",
          "operator": "GreaterThan",
          "threshold": 80,
          "timeAggregation": "Average"
        }
      ],
      "odata.type": "Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria"
    },
    "actions": [
      {
        "actionGroupId": "/subscriptions/{sub-id}/resourceGroups/{rg}/providers/microsoft.insights/actionGroups/{action-group}"
      }
    ]
  }
}

Create Log Search Alert

Azure CLI

az monitor scheduled-query create \
  --name myLogAlert \
  --resource-group myResourceGroup \
  --scopes /subscriptions/{sub-id}/resourceGroups/{rg}/providers/Microsoft.OperationalInsights/workspaces/{workspace} \
  --condition "count 'Heartbeat | where TimeGenerated > ago(5m) | summarize AggregatedValue = count() by Computer | where AggregatedValue < 1' > 0" \
  --description "Alert when VM heartbeat is missing" \
  --evaluation-frequency 5m \
  --window-size 15m \
  --severity 1 \
  --action-groups /subscriptions/{sub-id}/resourceGroups/{rg}/providers/microsoft.insights/actionGroups/{action-group}

Query Examples

Failed Requests Alert:

requests
| where timestamp > ago(5m)
| where success == false
| summarize FailedRequests = count()
| where FailedRequests > 10

High Error Rate Alert:

requests
| where timestamp > ago(15m)
| summarize 
    TotalRequests = count(),
    FailedRequests = countif(success == false)
| extend ErrorRate = (FailedRequests * 100.0) / TotalRequests
| where ErrorRate > 5

Missing Heartbeat Alert:

Heartbeat
| where TimeGenerated > ago(10m)
| summarize LastHeartbeat = max(TimeGenerated) by Computer
| where LastHeartbeat < ago(5m)

Disk Space Alert:

Perf
| where ObjectName == "LogicalDisk" and CounterName == "% Free Space"
| where TimeGenerated > ago(5m)
| where InstanceName != "_Total"
| summarize FreeSpace = avg(CounterValue) by Computer, InstanceName
| where FreeSpace < 10

Dynamic Thresholds

Automatically learn metric patterns and adjust thresholds.

az monitor metrics alert create \
  --name myDynamicAlert \
  --resource-group myResourceGroup \
  --scopes /subscriptions/{sub-id}/resourceGroups/{rg}/providers/Microsoft.Compute/virtualMachines/{vm} \
  --condition "avg Percentage CPU > dynamic High 2 violations out of 4" \
  --description "Dynamic CPU alert" \
  --evaluation-frequency 5m \
  --window-size 15m \
  --severity 2

Sensitivity Levels: - High: More alerts, catches smaller deviations - Medium: Balanced sensitivity - Low: Fewer alerts, only major deviations

Multi-Resource Alerts

Monitor multiple resources with a single alert rule.

az monitor metrics alert create \
  --name myMultiResourceAlert \
  --resource-group myResourceGroup \
  --scopes \
    /subscriptions/{sub-id}/resourceGroups/{rg}/providers/Microsoft.Compute/virtualMachines/{vm1} \
    /subscriptions/{sub-id}/resourceGroups/{rg}/providers/Microsoft.Compute/virtualMachines/{vm2} \
  --condition "avg Percentage CPU > 80" \
  --description "Alert for multiple VMs" \
  --evaluation-frequency 5m \
  --window-size 15m

Action Groups

Define what happens when an alert fires.

Create Action Group

az monitor action-group create \
  --name myActionGroup \
  --resource-group myResourceGroup \
  --short-name myAG \
  --email-receiver name=admin email=admin@example.com \
  --sms-receiver name=oncall country-code=1 phone-number=5551234567 \
  --webhook-receiver name=webhook service-uri=https://example.com/webhook \
  --azure-function-receiver name=function function-app-resource-id={function-app-id} function-name=AlertHandler http-trigger-url={function-url}

Action Types

Email/SMS/Push/Voice:

--email-receiver name=admin email=admin@example.com
--sms-receiver name=oncall country-code=1 phone-number=5551234567
--voice-receiver name=voice country-code=1 phone-number=5551234567

Webhook:

--webhook-receiver name=webhook service-uri=https://example.com/webhook use-common-alert-schema=true

Azure Function:

--azure-function-receiver \
  name=function \
  function-app-resource-id=/subscriptions/{sub-id}/resourceGroups/{rg}/providers/Microsoft.Web/sites/{function-app} \
  function-name=AlertHandler \
  http-trigger-url=https://{function-app}.azurewebsites.net/api/AlertHandler

Logic App:

--logic-app-receiver \
  name=logicapp \
  resource-id=/subscriptions/{sub-id}/resourceGroups/{rg}/providers/Microsoft.Logic/workflows/{logic-app} \
  callback-url={callback-url}

Automation Runbook:

--automation-runbook-receiver \
  name=runbook \
  automation-account-id=/subscriptions/{sub-id}/resourceGroups/{rg}/providers/Microsoft.Automation/automationAccounts/{account} \
  runbook-name=RestartVM \
  webhook-resource-id={webhook-id} \
  is-global-runbook=false

ITSM:

--itsm-receiver \
  name=itsm \
  workspace-id={workspace-id} \
  connection-id={connection-id} \
  ticket-configuration='{"PayloadRevision":0,"WorkItemType":"Incident","UseTemplate":false}'

Alert Severity Levels

Severity Description Use Case
Sev 0 Critical Service down, data loss
Sev 1 Error Major functionality impaired
Sev 2 Warning Potential issues, degraded performance
Sev 3 Informational Non-urgent information
Sev 4 Verbose Detailed diagnostic information

Alert Processing Rules

Modify alert behavior without changing alert rules.

Suppress Alerts During Maintenance

az monitor alert-processing-rule create \
  --name maintenanceWindow \
  --resource-group myResourceGroup \
  --scopes /subscriptions/{sub-id}/resourceGroups/{rg} \
  --rule-type RemoveAllActionGroups \
  --schedule-start-datetime "2026-02-15T22:00:00" \
  --schedule-end-datetime "2026-02-16T02:00:00" \
  --schedule-recurrence-type Weekly \
  --schedule-recurrence-days Saturday

Add Action Group to Specific Alerts

az monitor alert-processing-rule create \
  --name addActionGroup \
  --resource-group myResourceGroup \
  --scopes /subscriptions/{sub-id}/resourceGroups/{rg} \
  --rule-type AddActionGroups \
  --action-groups /subscriptions/{sub-id}/resourceGroups/{rg}/providers/microsoft.insights/actionGroups/{action-group} \
  --filter-severity Equals Sev0 Sev1

Common Alert Scenarios

Application Alerts

High Response Time:

requests
| where timestamp > ago(5m)
| summarize AvgDuration = avg(duration)
| where AvgDuration > 5000

Exception Rate:

exceptions
| where timestamp > ago(5m)
| summarize ExceptionCount = count()
| where ExceptionCount > 10

Dependency Failures:

dependencies
| where timestamp > ago(5m)
| where success == false
| summarize FailureCount = count() by target
| where FailureCount > 5

Infrastructure Alerts

High CPU:

--condition "avg Percentage CPU > 80"

Low Memory:

Perf
| where ObjectName == "Memory" and CounterName == "Available MBytes"
| where TimeGenerated > ago(5m)
| summarize AvgMemory = avg(CounterValue) by Computer
| where AvgMemory < 500

Disk Space:

Perf
| where ObjectName == "LogicalDisk" and CounterName == "% Free Space"
| where TimeGenerated > ago(5m)
| summarize FreeSpace = avg(CounterValue) by Computer, InstanceName
| where FreeSpace < 10

Kubernetes Alerts

Pod Restarts:

KubePodInventory
| where TimeGenerated > ago(15m)
| where RestartCount > 0
| summarize TotalRestarts = sum(RestartCount) by Namespace, Name
| where TotalRestarts > 3

Failed Pods:

KubePodInventory
| where TimeGenerated > ago(5m)
| where PodStatus in ("Failed", "Pending", "Unknown")
| summarize count() by PodStatus, Namespace

Node Not Ready:

KubeNodeInventory
| where TimeGenerated > ago(5m)
| where Status != "Ready"
| summarize count() by Computer, Status

Security Alerts

Failed Login Attempts:

SecurityEvent
| where TimeGenerated > ago(15m)
| where EventID == 4625
| summarize FailedLogins = count() by Account, Computer
| where FailedLogins > 5

Firewall Blocks:

AzureDiagnostics
| where TimeGenerated > ago(5m)
| where Category == "AzureFirewallNetworkRule"
| where msg_s contains "Deny"
| summarize BlockCount = count()
| where BlockCount > 100

Alert Best Practices

1. Alert Design

  • Alert on symptoms, not causes
  • Set appropriate thresholds
  • Use dynamic thresholds for variable workloads
  • Avoid alert fatigue

2. Action Groups

  • Create role-based action groups
  • Use different actions for different severities
  • Test action groups regularly
  • Document escalation procedures

3. Alert Processing

  • Use suppression rules for maintenance windows
  • Group related alerts
  • Set up alert enrichment
  • Implement alert correlation

4. Monitoring

  • Track alert volume and trends
  • Monitor alert resolution time
  • Review and tune alert rules regularly
  • Document alert runbooks

5. Cost Optimization

  • Use appropriate evaluation frequencies
  • Consolidate similar alerts
  • Use multi-resource alerts
  • Monitor alert rule costs

Webhook Payload

Common alert schema payload:

{
  "schemaId": "azureMonitorCommonAlertSchema",
  "data": {
    "essentials": {
      "alertId": "/subscriptions/{sub-id}/providers/Microsoft.AlertsManagement/alerts/{alert-id}",
      "alertRule": "myAlert",
      "severity": "Sev2",
      "signalType": "Metric",
      "monitorCondition": "Fired",
      "monitoringService": "Platform",
      "alertTargetIDs": [
        "/subscriptions/{sub-id}/resourceGroups/{rg}/providers/Microsoft.Compute/virtualMachines/{vm}"
      ],
      "originAlertId": "{origin-id}",
      "firedDateTime": "2026-02-02T10:00:00.0000000Z",
      "description": "Alert when CPU exceeds 80%"
    },
    "alertContext": {
      "properties": null,
      "conditionType": "SingleResourceMultipleMetricCriteria",
      "condition": {
        "windowSize": "PT15M",
        "allOf": [
          {
            "metricName": "Percentage CPU",
            "metricNamespace": "Microsoft.Compute/virtualMachines",
            "operator": "GreaterThan",
            "threshold": "80",
            "timeAggregation": "Average",
            "dimensions": [],
            "metricValue": 85.5
          }
        ]
      }
    }
  }
}

Query Alert History

// Alert history
AlertsManagementResources
| where type == "microsoft.alertsmanagement/alerts"
| where properties.essentials.startDateTime > ago(7d)
| project 
    AlertName = properties.essentials.alertRule,
    Severity = properties.essentials.severity,
    Status = properties.essentials.monitorCondition,
    StartTime = properties.essentials.startDateTime,
    Resource = tostring(properties.essentials.targetResourceName)
| order by StartTime desc

// Alert frequency
AlertsManagementResources
| where type == "microsoft.alertsmanagement/alerts"
| where properties.essentials.startDateTime > ago(30d)
| summarize AlertCount = count() by AlertName = tostring(properties.essentials.alertRule)
| order by AlertCount desc

Resources