Azure Monitor Agent and data collection rules
-
Phase 0: Before you start
-
Phase 1: The foundation
-
Phase 2: Day-to-day operations
-
Phase 3: Enterprise architecture
-
Phase 4: Troubleshooting step by step
-
Phase 5: Final project and career
The Azure Monitor Agent (AMA) collects logs and performance counters from inside your VMs and sends them to a Log Analytics workspace. What it collects, and where it sends it, is set by data collection rules (DCRs), not by settings on the agent.
Platform metrics (Lesson 31) see a VM from the outside. AMA sees inside: syslog, Windows event logs, memory and disk counters. It replaced the old Log Analytics agent (MMA/OMS), which retired on 31 August 2024.
In the lab you build the course workspace, install AMA on both VMs, write a DCR, and fix the two reasons agents “run fine” but send nothing.
| Time | You need | Cost | By the end you can |
|---|---|---|---|
| About 60 minutes | web01, win01, vnet-saat, the CLI | About 10 US cents for a temporary NAT Gateway; the few MB of logs stay inside Log Analytics’ monthly allowance of 5 GB | Install AMA, write and associate DCRs, and troubleshoot missing data |
What it is, in one line
The Azure Monitor Agent collects data inside a VM, and data collection rules tell it what to collect and where to send it.
In Simple Words
The class monitor and the instruction card
Each class has a monitor who writes things down: who was late, what broke, how hot the room was. That’s the agent.
The head teacher gives monitors an instruction card: “note the temperature every hour and anything broken, and hand it to the office”. That’s a data collection rule. The office filing cabinet is the Log Analytics workspace.
A monitor with no card writes nothing, however hard-working. And a monitor whose door to the office is locked can’t hand in the notes. Those are today’s two breaks.
Engineer's View
AMA, DCRs and workspaces
- Azure Monitor Agent: a VM extension (AzureMonitorLinuxAgent, AzureMonitorWindowsAgent). It authenticates with the VM’s managed identity, system-assigned by default.
- Data collection rule: an Azure resource listing data sources (performance counters, syslog, Windows event logs with XPath, text logs), destinations (workspaces, Azure Monitor metrics) and data flows between them. One DCR can serve many VMs; one VM can have many DCRs.
- Association: a DCR does nothing until it’s associated with a VM. Azure Policy can associate DCRs at scale.
- Tables: Heartbeat (every minute), Perf, Syslog, Event, plus custom tables for text logs.
- Network: the agent needs HTTPS to
global.handler.control.monitor.azure.com,<region>.handler.control.monitor.azure.com,*.ods.opinsights.azure.comand*.ingest.monitor.azure.com, or Azure Monitor Private Link Scope. Private subnets need an explicit outbound path. - Costs: you pay for data ingested and retained in the workspace, after 5 GB a month at no charge per billing account. Analytics logs keep 31 days at no extra charge. A daily cap protects labs from surprises.
How it works, step by step
What happens after you associate a DCR with web01:
- AMA on web01 asks the handler endpoint which DCRs apply to it, using its managed identity.
- It downloads dcr-saat-basic: collect CPU and memory every 60 seconds, and syslog warnings and above.
- It reads the counters and syslog messages locally.
- It sends them, with a heartbeat every minute, to the workspace’s ingestion endpoint over HTTPS.
- The data lands in the Perf, Syslog and Heartbeat tables, ready for KQL (Lesson 33).
If any step fails, the agent still shows as Succeeded in the portal. “Extension healthy” only means the agent installed, not that data arrives.
That’s why the first check for missing data is always the Heartbeat table: no heartbeat means a config or network problem, not a data source problem.
Hands-on lab: Azure Monitor Agent on web01 and win01
Load the network IDs and start both VMs:
$v = Get-Content C:\azure-lab\vnet-saat.json | ConvertFrom-Json
az vm start --resource-group rg-saat-vms --name web01
az vm start --resource-group rg-saat-vms --name win011Create the course Log Analytics workspace
This workspace stays for the rest of the course. The daily cap of 0.1 GB protects you from a runaway bill:
az monitor log-analytics workspace create --resource-group rg-saat-core --name law-saat --location centralindia --retention-time 30 --quota 0.1 --tags course=saatvedha-azure lesson=32 keep=true -o none
$lawId = az monitor log-analytics workspace show --resource-group rg-saat-core --name law-saat --query id -o tsv
$ws = az monitor log-analytics workspace show --resource-group rg-saat-core --name law-saat --query customerId -o tsv
az monitor log-analytics workspace show --resource-group rg-saat-core --name law-saat --query "{name:name, sku:sku.name, retention:retentionInDays, dailyCapGb:workspaceCapping.dailyQuotaGb}" -o tableYou should see this:
Name Sku Retention DailyCapGb
-------- ----------- ----------- ------------
law-saat PerGB2018 30 0.12Give the VMs a way out
Same NAT Gateway as Lesson 30, for this lab only:
az network public-ip create --resource-group rg-saat-core --name pip-saat-natgw --sku Standard --location centralindia --tags course=saatvedha-azure lesson=32 -o none
az network nat gateway create --resource-group rg-saat-core --name natgw-saat --public-ip-addresses pip-saat-natgw --idle-timeout 4 --location centralindia --tags course=saatvedha-azure lesson=32 -o none
az network vnet subnet update --ids $v.'snet-web' --nat-gateway natgw-saat -o none
az network vnet subnet update --ids $v.'snet-mgmt' --nat-gateway natgw-saat -o none3Install the agent on both VMs
Turn on the system-assigned identity, then add the extension:
az vm identity assign --resource-group rg-saat-vms --name web01 -o none
az vm identity assign --resource-group rg-saat-vms --name win01 -o none
az vm extension set --resource-group rg-saat-vms --vm-name web01 --name AzureMonitorLinuxAgent --publisher Microsoft.Azure.Monitor --enable-auto-upgrade true -o none
az vm extension set --resource-group rg-saat-vms --vm-name win01 --name AzureMonitorWindowsAgent --publisher Microsoft.Azure.Monitor --enable-auto-upgrade true -o none
az vm extension list --resource-group rg-saat-vms --vm-name win01 --query "[?publisher=='Microsoft.Azure.Monitor'].{name:name, state:provisioningState}" -o tableYou should see this:
Name State
------------------------ ---------
AzureMonitorWindowsAgent Succeeded4Write a data collection rule
CPU and memory every 60 seconds, syslog warnings and above, and Windows System and Application errors and warnings:
$dcr = @{
location = 'centralindia'
properties = @{
dataSources = @{
performanceCounters = @(@{ name = 'perfBasic'; streams = @('Microsoft-Perf'); samplingFrequencyInSeconds = 60
counterSpecifiers = @('\Processor Information(_Total)\% Processor Time', '\Memory\Available Bytes',
'Processor(*)\% Processor Time', 'Memory(*)\Available MBytes Memory') })
syslog = @(@{ name = 'syslogBasic'; streams = @('Microsoft-Syslog'); facilityNames = @('auth', 'daemon', 'syslog', 'user')
logLevels = @('Warning', 'Error', 'Critical', 'Alert', 'Emergency') })
windowsEventLogs = @(@{ name = 'eventsBasic'; streams = @('Microsoft-Event')
xPathQueries = @('System!*[System[(Level=1 or Level=2 or Level=3)]]', 'Application!*[System[(Level=1 or Level=2 or Level=3)]]') })
}
destinations = @{ logAnalytics = @(@{ name = 'law'; workspaceResourceId = $lawId }) }
dataFlows = @(@{ streams = @('Microsoft-Perf', 'Microsoft-Syslog', 'Microsoft-Event'); destinations = @('law') })
}
}
$dcr | ConvertTo-Json -Depth 10 | Set-Content -Path C:\azure-lab\dcr-basic.json
$sub = az account show --query id -o tsv
$dcrId = "/subscriptions/$sub/resourceGroups/rg-saat-core/providers/Microsoft.Insights/dataCollectionRules/dcr-saat-basic"
az rest --method put --url "https://management.azure.com${dcrId}?api-version=2022-06-01" --body '@C:\azure-lab\dcr-basic.json' --query "properties.provisioningState" -o tsvYou should see this:
Succeeded5Associate it with web01 and check the data
Run this, then wait about 10 minutes:
Set-Content -Path C:\azure-lab\dcr-assoc.json -Value ('{"properties": {"dataCollectionRuleId": "' + $dcrId + '"}}')
$id = az vm show --resource-group rg-saat-vms --name web01 --query id -o tsv
az rest --method put --url "https://management.azure.com${id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/dcra-saat-basic?api-version=2022-06-01" --body '@C:\azure-lab\dcr-assoc.json' -o none
az vm run-command invoke --resource-group rg-saat-vms --name web01 --command-id RunShellScript --scripts 'logger -p user.err saatvedha test error' -o none
Start-Sleep -Seconds 600
az monitor log-analytics query --workspace $ws --analytics-query "Heartbeat | summarize LastSeen=max(TimeGenerated) by Computer, Category" -o table
az monitor log-analytics query --workspace $ws --analytics-query "Syslog | where SyslogMessage has 'saatvedha' | project TimeGenerated, Computer, SeverityLevel, SyslogMessage" -o tableYou should see something like this:
Category Computer LastSeen TableName
-------------------- ---------- ---------------------------- -------------
Azure Monitor Agent web01 2026-10-20T18:52:10.000Z PrimaryResult
Computer SeverityLevel SyslogMessage TableName TimeGenerated
---------- --------------- ----------------------- ------------- ----------------------------
web01 err saatvedha test error PrimaryResult 2026-10-20T18:44:31.000Z
✅ Checkpoint: law-saat exists with a 0.1 GB daily cap, AMA runs on both VMs, and web01 sends heartbeats and syslog through dcr-saat-basic.
Break It, Then Fix It
Keep both VMs running for these two.
1Break it: agent installed, no data
win01 has the agent and shows Succeeded. Write a test event on it and look for it:
az vm run-command invoke --resource-group rg-saat-vms --name win01 --command-id RunPowerShellScript --scripts 'eventcreate /T ERROR /ID 900 /L APPLICATION /SO SaatLab /D SaatvedhaTest' -o none
Start-Sleep -Seconds 300
az monitor log-analytics query --workspace $ws --analytics-query "Heartbeat | where Computer startswith 'win01' | count" -o tableYou should see this:
Count TableName
------- -------------
0 PrimaryResultNo heartbeat, no events. The agent is healthy but has no DCR, so it has nothing to do and nowhere to send it. This is the most common AMA ticket: the extension went on through a policy or a script, the DCR association didn’t.
Fix it: associate the DCR with win01, wait, and check again:
Set-Content -Path C:\azure-lab\dcr-assoc.json -Value ('{"properties": {"dataCollectionRuleId": "' + $dcrId + '"}}')
$id = az vm show --resource-group rg-saat-vms --name win01 --query id -o tsv
az rest --method put --url "https://management.azure.com${id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/dcra-saat-basic?api-version=2022-06-01" --body '@C:\azure-lab\dcr-assoc.json' -o none
Start-Sleep -Seconds 300
az vm run-command invoke --resource-group rg-saat-vms --name win01 --command-id RunPowerShellScript --scripts 'eventcreate /T ERROR /ID 901 /L APPLICATION /SO SaatLab /D SaatvedhaTest' -o none
Start-Sleep -Seconds 300
az monitor log-analytics query --workspace $ws --analytics-query "Event | where Source == 'SaatLab' | project TimeGenerated, Computer, EventLevelName, RenderedDescription" -o tableYou should see something like this:
Computer EventLevelName RenderedDescription TableName TimeGenerated
---------- ---------------- --------------------- ------------- ----------------------------
win01 Error SaatvedhaTest PrimaryResult 2026-10-20T19:03:12.000ZEvents are collected from the moment the agent receives the rule, so write a fresh test event after any DCR change.
2Break it: the heartbeat stops
Remove the NAT Gateway from snet-web, wait, and compare the two VMs:
az network vnet subnet update --ids $v.'snet-web' --remove natGateway -o none
Start-Sleep -Seconds 900
az monitor log-analytics query --workspace $ws --analytics-query "Heartbeat | summarize LastSeen=max(TimeGenerated) by Computer | extend MinutesAgo=datetime_diff('minute', now(), LastSeen)" -o tableYou should see something like this:
Computer LastSeen MinutesAgo TableName
---------- ---------------------------- ------------ -------------
web01 2026-10-20T19:05:10.000Z 14 PrimaryResult
win01 2026-10-20T19:19:40.000Z 0 PrimaryResultweb01 went quiet 14 minutes ago while win01 keeps reporting. The agent can’t reach the ingestion endpoints from a private subnet with no outbound path. Its local log on Linux, /var/opt/microsoft/azuremonitoragent/log/mdsd.err, shows connection errors.
In production this looks like “the server stopped logging” during the incident you most need logs for.
Fix it: restore an outbound path (NAT Gateway, firewall rules for the Azure Monitor endpoints, or Azure Monitor Private Link Scope), then check:
az network vnet subnet update --ids $v.'snet-web' --nat-gateway natgw-saat -o none
Start-Sleep -Seconds 300
az monitor log-analytics query --workspace $ws --analytics-query "Heartbeat | where Computer == 'web01' | summarize LastSeen=max(TimeGenerated)" -o tableYou should see a time from the last few minutes.
Clean up: keep the workspace, DCR and agents; remove the NAT Gateway and stop the VMs:
az network vnet subnet update --ids $v.'snet-web' --remove natGateway -o none
az network vnet subnet update --ids $v.'snet-mgmt' --remove natGateway -o none
az network nat gateway delete --resource-group rg-saat-core --name natgw-saat
az network public-ip delete --resource-group rg-saat-core --name pip-saat-natgw
az vm deallocate --resource-group rg-saat-vms --name web01
az vm deallocate --resource-group rg-saat-vms --name win01
✅ Checkpoint: Both VMs sent heartbeats once they had a DCR and an outbound path. law-saat and dcr-saat-basic stay for Lessons 33 and 34.
This happened at work
The audit logs that were never collected
A bank moved 400 Windows servers from the old Log Analytics agent to AMA before the August 2024 retirement. An Azure Policy installed the agent everywhere, and the migration dashboard showed 400 green ticks.
Six months later, an auditor asked for sign-in failure events from a group of payment servers. The Event table had nothing for 90 of them. The policy that installed AMA had run; the policy that associated the security DCR was scoped to the wrong management group.
What they changed: agent install and DCR association now live in one policy initiative assigned together. A daily KQL check compares the VM inventory from Resource Graph with computers seen in Heartbeat in the last hour, and opens a ticket for any gap.
Common mistakes and troubleshooting
| Mistake | What you see | What to do |
|---|---|---|
| Agent installed, no DCR associated | No Heartbeat, no data | Associate a DCR; check Heartbeat first. |
| No outbound path or blocked endpoints | Heartbeat stops; mdsd errors | NAT, firewall rules, or Azure Monitor Private Link. |
| No managed identity on the VM | Agent can’t authenticate | Enable system-assigned identity. |
| Collecting everything at debug level | Big ingestion bill | Collect warnings and above; filter with XPath. |
| No daily cap in dev workspaces | Surprise costs from a noisy VM | Set a cap; alert on ingestion. |
| Still planning on the old MMA agent | Unsupported since August 2024 | Migrate to AMA with DCRs. |
Interview questions
Click a question to open it. Each one is written the way an interviewer would ask it. Under it you will see why they ask it and one way you could answer, in your own words.
Fresher level
1. What is the Azure Monitor Agent?
Why they ask this: The basic concept.
How you might answer: A VM extension that collects logs and performance data from inside Windows and Linux machines and sends them to Log Analytics or Azure Monitor metrics. It replaced the Log Analytics agent (MMA).
2. What is a data collection rule?
Why they ask this: The key AMA idea.
How you might answer: An Azure resource that defines what data to collect, how to filter it, and where to send it. Agents get their work from the DCRs associated with their machine.
3. Which table shows that an agent is alive?
Why they ask this: A first-check question.
How you might answer: Heartbeat. AMA writes a record about every minute, so a missing heartbeat means the agent isn’t running, has no DCR, or can’t reach Azure.
2–5 years experience
4. AMA is installed but no data arrives. How do you troubleshoot?
Why they ask this: A very common ticket.
How you might answer: Check Heartbeat for the computer. If it’s missing, check the DCR association, the managed identity, and network access to the handler and ingestion endpoints. If heartbeats arrive but a table is empty, check the DCR’s data sources and filters.
5. How do you collect only important Windows events?
Why they ask this: They want XPath knowledge.
How you might answer: Use XPath queries in the DCR, for example System!*[System[(Level=1 or Level=2 or Level=3)]] for critical, errors and warnings. That keeps ingestion and cost down.
6. How would you control Log Analytics costs?
Why they ask this: They want practical levers.
How you might answer: Collect only what’s used, filter at the DCR, use Basic or Auxiliary logs for high-volume low-value tables, set retention per table, and set daily caps with alerts in non-production workspaces.
Senior level
7. How would you roll out AMA across thousands of servers, including Arc?
Why they ask this: They want scale and governance.
How you might answer: Azure Policy initiatives that install AMA, assign managed identity and associate standard DCRs by OS and role, with remediation tasks for existing machines. Arc brings on-premises servers in the same way, and a daily Heartbeat-versus-inventory check catches gaps.
8. How do you send VM logs from private networks without internet?
Why they ask this: They’re checking private connectivity.
How you might answer: Azure Monitor Private Link Scope with private endpoints for the monitor endpoints and private DNS, or an outbound path through Azure Firewall allowing only the Azure Monitor FQDNs and service tags.
9. Workspace design: one central workspace or many?
Why they ask this: They want trade-offs.
How you might answer: Start with as few as possible, often one per region or per security boundary, because cross-workspace queries add friction. Split only for data residency, separate billing, or strict access needs, and use resource-context access to limit what teams see.
Quick quiz
Q1. What tells the Azure Monitor Agent what to collect?
- The VM size
- A data collection rule
- An NSG
- The Activity log
Show answer
B — DCRs define sources, destinations and flows.
Q2. How does AMA authenticate by default?
- Account key
- System-assigned managed identity
- SAS token
- Password
Show answer
B — AMA uses the VM’s managed identity.
Q3. AMA shows Succeeded but no Heartbeat appears. First suspect?
- Disk size
- No DCR association or no outbound path
- Blob tier
- Region pair
Show answer
B — Healthy extension doesn’t mean data flows.
Q4. Which agent retired on 31 August 2024?
- Azure Monitor Agent
- Log Analytics agent (MMA)
- VM agent
- Dependency agent
Show answer
B — MMA is retired; use AMA.
Q5. What does a workspace daily cap do?
- Deletes old data
- Stops ingestion for the day once reached
- Speeds up queries
- Adds retention
Show answer
B — It limits daily ingestion to protect cost.
Quick recap
Your VMs now report from the inside, and you know what to check when they stop.
- AMA collects inside the VM; DCRs say what and where.
- No DCR association means no data, even with a healthy agent.
- The agent needs outbound HTTPS or Private Link.
- Heartbeat is the first check for missing data.
- Filter at the DCR and cap dev workspaces to control cost.
Next lesson
Lesson 33: Log Analytics workspaces and KQL basics → You write KQL queries to filter, summarize and chart the data your agents collect.
Further reading: Azure Monitor Agent
Want to go deeper into Azure Monitor Agent? See Microsoft’s Azure Monitor Agent overview and Data collection rules in Azure Monitor. You can also see the full plan for this course on the Azure Cloud Administration course page.
