Skip to content
Learni
View all tutorials
Azure

How to Set Up Azure Monitor for Monitoring in 2026

Lire en français

Introduction

Azure Monitor is Microsoft Azure's unified solution for collecting, analyzing, and acting on monitoring data from your cloud resources. In 2026, with the rise of hybrid workloads and AI, it combines Logs (KQL), Metrics, Alerts, and Workbooks for full observability. This intermediate tutorial walks you through deploying a Log Analytics workspace, querying logs, setting up metric alerts, and creating actionable dashboards.

Why it matters: Poor monitoring costs a fortune—30% of cloud incidents stem from inadequate observability (Gartner 2025). You'll monitor a Windows VM with diagnostics, run advanced KQL queries, and automate responses via alerts. At the end, you'll have a production-ready, scalable, and secure setup—bookmark it for your Azure DevOps toolkit.

Prerequisites

  • Active Azure account with a subscription (free credits work for testing)
  • Azure CLI 2.65+ installed (download)
  • Azure PowerShell 13.0+ (install)
  • Basic knowledge of Azure Resource Manager (ARM) and Kusto Query Language (KQL)
  • Visual Studio Code with the Azure Monitor extension (optional but recommended)

Create the resource group and Log Analytics workspace

setup-workspace.sh
#!/bin/bash

# Variables (adapt to your environment)
SUBSCRIPTION_ID="votre-subscription-id"
RESOURCE_GROUP="rg-monitor-demo"
LOCATION="francecentral"
WORKSPACE_NAME="log-analytics-monitor-2026"

# Login and select subscription
az login
az account set --subscription $SUBSCRIPTION_ID

# Create the resource group
az group create --name $RESOURCE_GROUP --location $LOCATION --tags "project=monitor-demo" "env=dev"

# Create the Log Analytics Workspace
az monitor log-analytics workspace create \
  --resource-group $RESOURCE_GROUP \
  --workspace-name $WORKSPACE_NAME \
  --location $LOCATION \
  --sku PerGB2018 \
  --retention-time 30 \
  --immediate-purge-data-on-deletion true

# Retrieve the workspace ID for later steps
echo "Workspace ID: $(az monitor log-analytics workspace show --resource-group $RESOURCE_GROUP --workspace-name $WORKSPACE_NAME --query id -o tsv)"

This complete Bash script sets up a resource group and Log Analytics workspace with 30-day retention and immediate purge for GDPR compliance. Use PerGB2018 to optimize costs (pay-as-you-go). Pitfall: Don't forget az login or adapt the variables, or you'll hit a 400 error.

Deploy a test VM to generate logs

To test Azure Monitor, let's deploy a simple Windows VM using an ARM template. This generates Heartbeat and Performance Counter logs. Download the template below and tweak the parameters.

Deploy Windows VM with diagnostics extension

vm-template.json
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "vmName": {
      "type": "string",
      "defaultValue": "vm-monitor-test"
    },
    "adminUsername": {
      "type": "string",
      "defaultValue": "azureuser"
    },
    "adminPassword": {
      "type": "securestring"
    },
    "workspaceId": {
      "type": "string"
    }
  },
  "variables": {},
  "resources": [
    {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2023-03-01",
      "name": "[parameters('vmName')]",
      "location": "francecentral",
      "properties": {
        "hardwareProfile": {
          "vmSize": "Standard_B2s"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "MicrosoftWindowsServer",
            "offer": "WindowsServer",
            "sku": "2022-Datacenter",
            "version": "latest"
          }
        },
        "osProfile": {
          "computerName": "[parameters('vmName')]",
          "adminUsername": "[parameters('adminUsername')]",
          "adminPassword": "[parameters('adminPassword')]",
          "windowsConfiguration": {
            "enableAutomaticUpdates": true
          }
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/publicIPAddresses', concat(parameters('vmName'), '-pip'))]"
            }
          ]
        }
      }
    },
    {
      "type": "Microsoft.Compute/virtualMachines/extensions",
      "apiVersion": "2022-03-01",
      "name": "[concat(parameters('vmName'), '/MicrosoftMonitoringAgent')]",
      "properties": {
        "publisher": "Microsoft.Azure.Monitor",
        "type": "AzureMonitorWindowsAgent",
        "typeHandlerVersion": "1.0",
        "autoUpgradeMinorVersion": true,
        "settings": {
          "workspaceId": "[parameters('workspaceId')]"
        }
      }
    },
    {
      "type": "Microsoft.Network/publicIPAddresses",
      "apiVersion": "2023-04-01",
      "name": "[concat(parameters('vmName'), '-pip')]",
      "sku": {
        "name": "Basic"
      },
      "properties": {
        "publicIPAllocationMethod": "Dynamic",
        "dnsSettings": {
          "domainNameLabel": "[concat(parameters('vmName'), '-', uniqueString(resourceGroup().id))]"
        }
      }
    },
    {
      "type": "Microsoft.Network/networkInterfaces",
      "apiVersion": "2023-04-01",
      "name": "[concat(parameters('vmName'), '-nic')]",
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses', concat(parameters('vmName'), '-pip'))]"
              },
              "subnet": {
                "id": "/subscriptions/{subscription-id}/resourceGroups/rg-monitor-demo/providers/Microsoft.Network/virtualNetworks/vnet-demo/subnets/default"
              }
            }
          }
        ]
      }
    }
  ]
}

This complete ARM template deploys a B2s Windows Server 2022 VM with the Azure Monitor Agent extension pointing to your workspace. Replace {subscription-id} and pass workspaceId as a parameter. Pitfall: Create a VNet/subnet first or add it to the template; deploy with az deployment group create --template-file vm-template.json.

Deploy the VM via Azure CLI

deploy-vm.sh
#!/bin/bash

RESOURCE_GROUP="rg-monitor-demo"
TEMPLATE_FILE="vm-template.json"
WORKSPACE_ID="$(az monitor log-analytics workspace show --resource-group $RESOURCE_GROUP --workspace-name log-analytics-monitor-2026 --query id -o tsv)"

# Deploy (adapt password)
az deployment group create \
  --resource-group $RESOURCE_GROUP \
  --template-file $TEMPLATE_FILE \
  --parameters adminPassword='P@ssw0rd123!^' workspaceId=$WORKSPACE_ID

# Check deployment
echo "VM IP: $(az vm show -g $RESOURCE_GROUP -n vm-monitor-test --query publicIps -o tsv)"

This script deploys the ARM template with the right parameters, including the Monitor agent to stream logs/metrics to the workspace. Wait 5-10 minutes for the first logs. Pitfall: Password must meet Azure policy (uppercase, numbers, symbols) or validation fails.

Query logs with KQL

Once logs are ingested (check in Azure Portal > Log Analytics > Logs), run KQL queries to analyze them. KQL is as powerful as SQL but optimized for big data: joins, time-series, ML anomalies.

KQL query for Heartbeat and CPU usage

heartbeat-cpu.kql
Heartbeat
| where TimeGenerated > ago(1h)
| summarize HeartbeatCount = count() by Computer, bin(TimeGenerated, 5m)
| join kind=inner (
    Perf
    | where ObjectName == "Processor" and CounterName == "% Processor Time"
    | where TimeGenerated > ago(1h)
    | summarize AvgCPU = avg(CounterValue) by Computer, bin(TimeGenerated, 5m)
) on Computer, $left.TimeGenerated == $right.TimeGenerated
| project TimeGenerated, Computer, HeartbeatCount, AvgCPU
| render timechart

This KQL query joins Heartbeat (available) and Perf CPU over 1 hour, aggregates by 5 minutes, and renders a timechart. Copy-paste into the Logs blade. Pitfall: ago(1h) needs fresh data; if empty, check the agent with the InsightsMetrics table.

Enable diagnostic settings via PowerShell

enable-diagnostics.ps1
# Variables
$rgName = "rg-monitor-demo"
$vmName = "vm-monitor-test"
$workspaceId = (Get-AzOperationalInsightsWorkspace -ResourceGroupName $rgName -Name "log-analytics-monitor-2026").CustomerId.Guid

# Login
Connect-AzAccount
Set-AzContext -SubscriptionId "votre-subscription-id"

# Enable diagnostics for VM (logs + metrics to workspace)
$diagSettings = New-AzDiagnosticSetting -Name "diag-to-workspace" `
    -ResourceId (Get-AzVM -ResourceGroupName $rgName -Name $vmName).Id `
    -WorkspaceId $workspaceId `
    -Log '' `
    -Metric '' `
    -Category "VMInsights", "Perf", "Heartbeat", "WindowsEvent"

Write-Output "Diagnostics enabled: $($diagSettings.Id)"

This PowerShell script enables VM diagnostics to the workspace, capturing Perf/Heartbeat/WindowsEvent. Use '' for all logs/metrics. Pitfall: Connect-AzAccount is interactive; for CI/CD, use a service principal.

Create a CPU > 80% metric alert

create-alert.sh
#!/bin/bash

RESOURCE_GROUP="rg-monitor-demo"
ALERT_NAME="High-CPU-Alert"
SCOPE_ID="$(az vm show -g $RESOURCE_GROUP -n vm-monitor-test --query id -o tsv)"

az monitor metrics alert create \
  --name $ALERT_NAME \
  --resource-group $RESOURCE_GROUP \
  --scopes $SCOPE_ID \
  --condition "\"Microsoft.Compute/virtualMachines\" AnyOf \"\"Percentage CPU\" > 80 avg 5m" \
  --description "Alerte si CPU >80% sur 5min" \
  --action-group "/subscriptions/votre-subscription-id/resourceGroups/rg-monitor-demo/providers/microsoft.insights/actionGroups/actiongroup-demo" \
  --severity 2 \
  --window-size 5m \
  --evaluation-frequency 1m

# Note: Create an Action Group first via Portal or CLI

Creates a metric alert rule for CPU avg >80% (5min eval every 1min). Link to an Action Group (email/SMS). Pitfall: Replace subscription/actiongroup; test with CPU stress on the VM.

Best practices

  • Optimized retention: 30-90 days for dev logs, 365+ for prod; enable purge to cut costs.
  • Saved queries: Pin favorites in the Logs blade for quick reuse.
  • Strict RBAC: Assign 'Monitoring Reader' minimally; use managed identities for agents.
  • Costs: Track ingestion GB/month via Cost Management; filter useless logs.
  • Integrate AIOps: Enable Smart Detection for ML-powered anomaly detection.

Common errors to avoid

  • Agent not installed: Check AzureMonitorWindowsAgent extension; redeploy if missing.
  • Empty queries: 15min ingestion delay; run search * to validate.
  • Silent alerts: Test action group; no notifications for Sev0 without one.
  • Region mismatch: Match workspace/VM location for <1s latency.

Next steps

Master Application Insights for web apps or Grafana with Azure Data Explorer. Check out our Azure DevOps training and official KQL docs. Contribute to Learni's GitHub for advanced templates.