CoursesAzure Administrator AssociateAzure Monitor & Log Analytics

Azure Monitor & Log Analytics

Metrics, logs, diagnostics, alerts, App Insights.

Intermediate30 min · lesson 13 of 15

A hospital ward at night runs on two kinds of information. The bedside monitor streams numbers, heart rate and blood pressure, second by second, and an alarm sounds the moment one crosses a line. The chart at the foot of the bed holds the story: which drug was given, at what time, by which nurse. That is what a doctor reads the next morning to work out *why* the night went wrong. Azure Monitor is the nurses' station for your Azure estate. Metrics are the bedside numbers. Logs are the chart. Alerts are the alarms. Here is the catch that surprises most new administrators. Unlike a hospital, most Azure resources arrive with the chart unplugged. Until you wire telemetry (the data a system reports about itself) into one central store, you are working blind, and you can never investigate something that was never written down.

Metrics and logs: two different kinds of evidence

Azure Monitor collects two kinds of telemetry, and AZ-104 (the Azure Administrator Associate exam) expects you to know which one answers which question. Metrics are plain numbers over time: processor percentage, disk IOPS (input/output operations per second, meaning reads and writes per second), HTTP request count. They get sampled about once a minute, live in a purpose-built time-series database for 93 days, and nearly every resource emits them automatically at no charge. They arrive close to real time, they are cheap to alert on, and they answer exactly one question well: is this thing healthy right now? Logs are event records with the detail attached. Who deleted that NSG (network security group, the packet filter wrapped around a subnet or a network card). Which secret was read. What the app wrote on its way down. Those land in a Log Analytics workspace, you question them with KQL (Kusto Query Language, a read-only language built for searching log data), and you pay per gigabyte ingested. The rule of thumb is short. Metrics tell you *that* something is wrong. Logs tell you *why*. Pull one platform metric from the CLI (command-line interface) to see the shape of the data.

query VM platform metrics
# Host-level platform metrics exist for every VM automatically — no agent needed
VM_ID=$(az vm show -g rg-prod -n vm-web-01 --query id -o tsv)
az monitor metrics list \
--resource $VM_ID \
--metric "Percentage CPU" \
--interval PT5M \
--output table
# Timestamp Name Average
# ------------------- -------------- --------
# 2026-07-13 09:00:00 Percentage CPU 4.31
# 2026-07-13 09:05:00 Percentage CPU 5.02
# 2026-07-13 09:10:00 Percentage CPU 91.87 <- something is chewing CPU

The Log Analytics workspace: one place to ask your questions

A Log Analytics workspace is the database where log telemetry lands. It lives in one region, works out the shape of each record as it arrives, and files everything into tables (AzureActivity, Heartbeat, AppRequests, and dozens more) with every row stamped TimeGenerated. Underneath sits the same Azure Data Explorer engine that runs Microsoft Sentinel, which is why Sentinel amounts to a workspace with security content layered on top. The design guidance in 2026 is refreshingly boring: use as few workspaces as you can get away with, often one per environment or one per region. Correlating across resources, table-level RBAC (role-based access control, deciding who is allowed to read what), and commitment-tier pricing all behave best when the data sits together in one big store. Cost follows ingestion. Pay-as-you-go analytics data runs roughly $2 to $3 per gigabyte, with the first 31 days of retention included. You can stretch interactive retention to 730 days, buy a commitment tier (starting at 100 GB per day) to cut the per-gigabyte rate, and move chatty low-value data onto the cheaper Basic or Auxiliary table plans, which give up query features in exchange for price.

create the central workspace
az group create -n rg-monitor -l westeurope -o none
az monitor log-analytics workspace create \
--resource-group rg-monitor \
--workspace-name log-prod-weu \
--location westeurope \
--retention-time 90
# {
# "customerId": "8d2ba9c1-4f6e-4c3a-9e2f-1b7d3c5a8e21", <- the GUID you query with
# "name": "log-prod-weu",
# "provisioningState": "Succeeded",
# "retentionInDays": 90,
# "sku": { "name": "PerGB2018" }
# }

Diagnostic settings: nothing flows until you connect the pipe

Here is the part the portal hides and the exam loves. Resource logs go nowhere by default. A Key Vault knows about every secret that was read. A storage account knows about every blob operation, every file read or written. Both throw that knowledge away unless a diagnostic setting on the resource routes it somewhere: a Log Analytics workspace (queryable), a storage account (cheap archive), or an Event Hub (a live stream you can feed into an outside SIEM, a security information and event management platform). Each resource carries at most five diagnostic settings. Each one offers its own log *categories* (AuditEvent for Key Vault, StorageRead for blobs) plus the allLogs category group as a catch-all. One exception comes free. The activity log is the subscription-wide record of every control-plane operation that went through ARM (Azure Resource Manager, the layer that creates, changes and deletes resources). It answers 'who deleted that VM (virtual machine)' and it is kept for 90 days with zero configuration. You add a diagnostic setting on it only when you want it kept longer, or want to query it in KQL next to your resource logs.

route Key Vault logs to the workspace
KV_ID=$(az keyvault show -n kv-prod-secrets --query id -o tsv)
LAW_ID=$(az monitor log-analytics workspace show \
-g rg-monitor -n log-prod-weu --query id -o tsv)
az monitor diagnostic-settings create \
--name to-central-law \
--resource $KV_ID \
--workspace $LAW_ID \
--logs '[{"categoryGroup":"allLogs","enabled":true}]' \
--metrics '[{"category":"AllMetrics","enabled":true}]'
# Not sure what a resource can emit? List its categories first:
az monitor diagnostic-settings categories list --resource $KV_ID \
--query "value[].name" -o tsv
# AuditEvent
# AzurePolicyEvaluationDetails
# AllMetrics
No diagnostic setting means no evidence
Most teams find this gap in the middle of an incident. The Key Vault that leaked a secret, or the storage account somebody scraped, kept no trail at all, because nobody ever created a diagnostic setting on it. There is no backfill. That history is gone for good. Enforce coverage across the whole estate with a DeployIfNotExists Azure Policy assignment, so every new resource starts shipping telemetry to the central workspace the moment it exists, and audit compliance the same way you audit tags.

KQL: asking your logs a question

KQL reads like a Unix pipeline. Start with a table, then push the rows through operators separated by a pipe character (|). where filters rows out, summarize adds things up, project picks the columns you want, and each stage feeds the next one. This is the skill in the lesson that pays back fastest, because the same language drives workspace queries, log alert rules, Sentinel threat hunting, and Azure Resource Graph. One CLI quirk to keep in mind: az monitor log-analytics query wants the workspace customerId GUID (globally unique identifier, the long random-looking id), not its name and not its resource ID.

hunt deletions with KQL
WS=$(az monitor log-analytics workspace show \
-g rg-monitor -n log-prod-weu --query customerId -o tsv)
# Who deleted anything in the last 24 hours?
az monitor log-analytics query --workspace $WS --analytics-query '
AzureActivity
| where TimeGenerated > ago(24h)
| where OperationNameValue endswith "DELETE"
| project TimeGenerated, Caller, OperationNameValue, ResourceGroup
| order by TimeGenerated desc' -o table
# TimeGenerated Caller OperationNameValue ResourceGroup
# ------------------------ ------------------------------------ ---------------------------------------------- -------------
# 2026-07-13T07:42:11.301Z [email protected] MICROSOFT.NETWORK/NETWORKSECURITYGROUPS/DELETE rg-dev
# 2026-07-13T06:15:48.774Z f3b7a9d2-1c4e-4f6a-8b0d-5e2c7a9f1d38 MICROSOFT.COMPUTE/VIRTUALMACHINES/DELETE rg-ephemeral
# ^- service principals show up as their appId GUID, not a friendly name

Alerts and action groups: from data to somebody's phone

Telemetry nobody acts on is an expensive diary. Azure Monitor keeps *detection* and *response* in separate boxes. An alert rule watches one signal: a metric crossing a threshold, a KQL query returning rows, an activity-log event. When the condition holds, it fires an action group, a reusable bundle of who to tell (email, SMS text message, mobile push, voice call) and what to run (webhook, Azure Function, Logic App, or a ticket in your ITSM tool, the IT service management system your service desk lives in). A few details matter on the exam and again at 3am. Metric alerts are stateful by default, so they fire once when the condition becomes true and close themselves when it clears, rather than shouting again every minute. Log search alerts are stateless by default and billed on how often the query runs, so a log alert set to evaluate every minute costs real money. Severity runs 0 (critical) to 4 (verbose). The action group's short name, 12 characters maximum, is what a half-awake human reads in the SMS. Alert on symptoms your users actually feel, things like error rates, latency and failed backups, rather than every wiggle in processor usage. Otherwise alert fatigue buries the one page that mattered.

wire an alert to on-call
az monitor action-group create \
--resource-group rg-monitor \
--name ag-ops-oncall \
--short-name opsoncall \
--action email oncall [email protected]
az monitor metrics alert create \
--name alert-vm-cpu-high \
--resource-group rg-monitor \
--scopes $VM_ID \
--condition "avg Percentage CPU > 80" \
--window-size 5m \
--evaluation-frequency 1m \
--severity 2 \
--action ag-ops-oncall \
--description "vm-web-01 CPU > 80% avg over 5 min"
# "enabled": true,
# "evaluationFrequency": "PT1M",
# "windowSize": "PT5M",
# "severity": 2 <- fires once, auto-resolves when CPU drops back
The Azure Monitor pipeline
1Resource emits
platform metrics + resource logs
2Diagnostic setting / DCR
routes telemetry
3Log Analytics workspace
central store, KQL
4Alert rule
evaluates the signal
5Action group
notify + automate
One workspace, many resources. Centralise first, then query and alert across the whole estate instead of resource by resource.

Agents, collection rules, and Application Insights

Two pieces finish the picture. Platform metrics give you the *host's* view of a virtual machine: processor, disk and network as the hypervisor (the host software running your VM) sees them from outside. Anything inside the guest operating system, such as memory per process, application log files, Linux Syslog or Windows event logs, needs the AMA (Azure Monitor Agent, a small program running on the machine itself) paired with a DCR (Data Collection Rule). That rule is its own Azure resource. It declares what to collect and which workspace receives it, and you can attach one rule to hundreds of machines at once. The old Log Analytics agent, MMA (Microsoft Monitoring Agent), retired in August 2024, so AMA plus a DCR is the only supported answer now, on the exam and in production. For what happens inside your code, Application Insights (the workspace-based flavour; the classic standalone one also retired in 2024) adds APM (application performance monitoring) on top of the same store: request rates, how long each downstream dependency took, exception stack traces, and traces that follow one user request across several services. So when the checkout page crawls, you can point at the exact SQL (database query) call behind it instead of stopping at 'the VM looked busy'.

Keep the pipeline straight for the exam. Platform metrics are free, automatic, and kept 93 days. Resource logs need a diagnostic setting or they never existed. The activity log hands you 90 days of control-plane history at no cost. An alert with no action group reaches nobody. In production, add two habits: watch ingested gigabytes as closely as you watch compute spend, and let Azure Policy guarantee coverage so nothing depends on somebody remembering. Monitoring tells you *when* something breaks. The next lesson covers what you do about the ugly breakages, with Azure Backup, disaster recovery and fleet patching through Update Manager, where the alerts you built here become the starting gun on the recovery clock.

The naming trips people up, so pin it down now. Azure Monitor is the umbrella over all of it. Log Analytics is the store underneath. Application Insights is the flavour aimed at application code. Diagnostic settings are the plumbing between a resource and that store, and every resource you care about needs one, or you will open the portal mid-incident and stare at an empty table. The activity log is the control-plane audit trail for the whole subscription: who created, changed or deleted a resource. Resource logs are what each individual service records about its own day-to-day work, the data plane.

Page people on symptoms they can do something about: availability dropping, error rates spiking, a backup that failed overnight. Action groups then fan that out to the right channel. Workbooks and dashboards are built for humans to read. Metric alerts and query-based alerts are built for machines to act on. As the administrator, your standing jobs are retention settings, who holds access to the workspace, and making sure every new resource inherits diagnostic settings through Azure Policy rather than through goodwill.

Try this

Create a Log Analytics workspace, turn on a diagnostic setting for a lab resource (or for the activity log), and run a small Kusto query that returns a handful of rows. Then put a metric alert on processor usage or availability and watch it evaluate.

terminal
RG=rg-lab-mon
az group create -n $RG -l eastus
az monitor log-analytics workspace create -g $RG -n law-lab -l eastus
LAW=$(az monitor log-analytics workspace show -g $RG -n law-lab --query customerId -o tsv)
az monitor activity-log list --offset 1h --query "[0:3].{op:operationName.localizedValue,status:status.value}" -o table
echo "Workspace customerId: $LAW"
output
$ az monitor activity-log list --offset 1h --query "[0:3].{op:operationName.localizedValue,status:status.value}" -o table
Op Status
------------------------- ------
Create Virtual Machine Succeeded
List Storage Account Keys Succeeded
# Sample output — without diagnostic settings, most resource logs never reach the workspace.

Takeaway

Metrics are numbers and they arrive fast. Logs carry the detail, and you question them with KQL inside Log Analytics. Alerts turn either one into an action group: an email, an SMS, a webhook, or a ticket on your service desk.

Your next move in a real subscription: send the activity log and your resource diagnostics into one central workspace, then put a lock on that resource group so nobody deletes it by accident. That workspace becomes the one place you trust when you are trying to work out what actually happened.

Quick check
01A production Key Vault leaks a secret. Your team goes looking for who read the vault's secrets in the days before the leak and finds nothing at all. What most likely happened, and can that history be recovered?
Correct — Resource logs go nowhere by default. Without a diagnostic setting the data is dropped as it is produced, and as the lesson stresses, there is no backfill, ever.
Incorrect — The activity log records control-plane actions such as 'who deleted the VM'. It never sees a secret being read, so it was never the source for this data.
Incorrect — Basic and Auxiliary plans do trade query features for a lower price, but here nothing was ingested at all, and no plan change conjures up data that was never captured.
Incorrect — Who read a secret is a log event, not a number on a chart. Metrics are automatic and free, but they record health signals like processor usage, not audit trails.
02The lesson calls Azure Monitor metric alerts stateful by default. What does stateful mean for that kind of alert?
Incorrect — 93 days is how long platform metrics themselves are kept. It says nothing about how an alert behaves.
Incorrect — That constant re-firing is the behaviour stateful alerts are built to avoid.
Correct — A stateful metric alert raises one alert and then closes it again as soon as the signal comes back to normal.
Incorrect — A Data Collection Rule governs guest-operating-system data collection through the Azure Monitor Agent. It has nothing to do with alert state.
03You need to keep 90 days of very high-volume, low-value firewall logs for the occasional compliance lookup. Nobody reads them day to day, they never need KQL joins or alerting, and you want the Azure Monitor bill as small as possible. Where should that data go?
Incorrect — Analytics is the priciest plan, and 730 days of retention piles on cost you have no use for when the data is barely read.
Incorrect — Firewall log entries are structured records, not numbers on a time series, so they cannot be pushed into the metrics store.
Incorrect — An Event Hub is for streaming out to an external SIEM. It adds cost here rather than removing it.
Correct — The lesson puts chatty, low-value data on the Basic or Auxiliary plans, which cut the per-gigabyte price in exchange for query features you were never going to use.

Related