Azure Monitor & Log Analytics
Metrics, logs, diagnostics, alerts, App Insights.
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.
# Host-level platform metrics exist for every VM automatically — no agent neededVM_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.
az group create -n rg-monitor -l westeurope -o noneaz 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.
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
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.
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.
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
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.
RG=rg-lab-monaz group create -n $RG -l eastusaz monitor log-analytics workspace create -g $RG -n law-lab -l eastusLAW=$(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 tableecho "Workspace customerId: $LAW"
$ az monitor activity-log list --offset 1h --query "[0:3].{op:operationName.localizedValue,status:status.value}" -o tableOp Status------------------------- ------Create Virtual Machine SucceededList 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.