An Azure service that is used to collect, analyze, and act on telemetry data from Azure and on-premises environments.
Why is this Alert not working as expected
I have the following Alert set up in Azure Monitor. It's purpose is to alert us if an automated shutdown does not run correctly and therefore our Azure VM is running for longer than 3 hours, but for some reason it is not firing at all:
NOTE: I have redected the server name, so the dimension value would be the actual server name if this where not changed.
If I run the KQL manually I get the following result:
Azure Monitor
-
Siva shunmugam Nadessin • 10,905 Reputation points • Microsoft External Staff • Moderator
2025-10-16T15:07:56.5233333+00:00 Hello Mark Pearson,
Could you please let us know the details of Evaluation frequency & Lookback period in minutes for us to investigate further?
-
Mark Pearson • 320 Reputation points
2025-10-16T15:11:48.3766667+00:00 Hopefully this is what you are looking for:
-
Siva shunmugam Nadessin • 10,905 Reputation points • Microsoft External Staff • Moderator
2025-10-16T18:21:16.66+00:00 Hello Mark Pearson,
Your query returns one static value (1440), so there’s nothing to aggregate per time slice hence it is not firing for the selected Measure = UptimeMinutes, Aggregation type = Total, and Granularity = 15 minutes.
Azure Monitor expects time-series data for aggregation, but your query returns a single static row (no timestamp column for grouping). So the alert engine never evaluates the condition properly.
How to Fix
Change to following
Measurement : Table rows
Aggregation Type: Empty
Aggregation granularity: You can keep default to 15 minutes.
Operator: Greater than
Threshold: 0
Split by dimensions: Leave blank (or remove Computer split since query already filters).
The reason behind the logic is
The query already filters for UptimeMinutes > 180.
If any row exists, the alert fires.
No dependency on time-series aggregation or granularity.
Updated KQL query, it's the same query you have used, the only change is update in threshold variable.
let threshold = 180; // 3 hours in minutes Heartbeat | where Computer == "<your-server-name>" | summarize FirstSeen = min(TimeGenerated) by Computer | extend UptimeMinutes = datetime_diff('minute', now(), FirstSeen) | where UptimeMinutes > thresholdTry and let us know if any queries?
[Edited with screenshots]
Thanks.
-
Mark Pearson • 320 Reputation points
2025-10-20T09:22:45.72+00:00 Hi Siva,
Thanks for the quick response, I will try this now and let you know how I get on.
-
Mark Pearson • 320 Reputation points
2025-10-21T12:29:27.2366667+00:00 Hi Siva,
I have made the adjustments you have mentioned, but the alert is still not firing:
-
Siva shunmugam Nadessin • 10,905 Reputation points • Microsoft External Staff • Moderator
2025-10-21T16:40:46.0733333+00:00 Hello Mark Pearson,
Follow below steps and let us know if it works
- Validate Query in Logs Run the query in Log Analytics and confirm it returns rows for the target VM.
- Adjust Threshold or Logic Lower threshold or remove the uptime filter temporarily to test.
- Check Data Ingestion Verify that the VM is sending heartbeat data to the workspace.
- Expand Scope Remove where Computer == "<server-name>" for testing.
- Increase Evaluation Period Initially try with lower evaluation period and see if it works later consider a longer evaluation window (e.g., 30 minutes). Check and let us know if you have further questions?
-
Mark Pearson • 320 Reputation points
2025-10-22T14:10:54.8366667+00:00 - Validate Query in Logs Run the query in Log Analytics and confirm it returns rows for the target VM.
I am seeing results come back when ran against the logs.
- Adjust Threshold or Logic Lower threshold or remove the uptime filter temporarily to test.
I set both the Alert Logic frequency of evaluation and Aggregation Granularity to 5 mins, still alert not firing (even after changing "let threshold to = 15".
- Check Data Ingestion Verify that the VM is sending heartbeat data to the workspace.
Heartbeat data is coming back.
- Expand Scope Remove where Computer == "<server-name>" for testing.
Removed the scope, currently testing this now.
- Increase Evaluation Period Initially try with lower evaluation period and see if it works later consider a longer evaluation window (e.g., 30 minutes). Check and let us know if you have further questions?
Adjusted the Evaluation period to 15 mins, still no alert.
-
Siva shunmugam Nadessin • 10,905 Reputation points • Microsoft External Staff • Moderator
2025-10-23T13:17:22.94+00:00 Hello Mark Pearson,
Kindly try below options and let us know if it works?
Option 1 (Using Total Rows):
let thresholdMinutes = 180; let lookback = 1d; Heartbeat | where TimeGenerated > ago(lookback) | summarize FirstSeen = min(TimeGenerated) by Computer | extend UptimeMinutes = datetime_diff('minute', now(), FirstSeen) | where UptimeMinutes >= thresholdMinutes | project Computer, FirstSeen, UptimeMinutesAlert configuration (Condition tab):
- Signal type: Custom log search → Aggregated logs
- Measurement mode: Table Rows
- Alert logic: Operator Greater than or equal to, Threshold 1
- Frequency of evaluation: 15 minutes
- Split by dimensions: optional (if you want one alert per VM, split on Computer)
Option 2 (Metric Measurement):
let thresholdMinutes = 180; let lookback = 1d; // make sure this covers the possible uptime periods Heartbeat | where TimeGenerated > ago(lookback) | summarize FirstSeen = min(TimeGenerated) by Computer | extend UptimeMinutes = datetime_diff('minute', now(), FirstSeen) | project TimeGenerated = now(), Computer, UptimeMinutes // Create a time series so Metric measurement can aggregate over the evaluation window | summarize UptimeMinutes = max(UptimeMinutes) by Computer, bin(TimeGenerated, 15m)Alert configuration (Condition tab):
- Signal type: Custom log search → Aggregated logs
- Measure: UptimeMinutes
- Aggregation type: Max (or Average; Max is fine since we project one value)
- Aggregation granularity: 15 minutes (matches the bin in the query)
- Split by dimensions: Computer = your VM name (you can leave * to monitor all, but to replicate the single-VM case, set the exact name)
- Alert logic: Operator Greater than or equal to, Threshold 180
- Frequency of evaluation: 15 minutes
- Evaluation time range: 15 minutes–1 hour (any window that includes the bin will work; 15m keeps it tight)
-
Mark Pearson • 320 Reputation points
2025-10-24T09:59:48.57+00:00 Option 1 was the solution that worked for me here.
Thanks for all of your help on this, greatfully appreciated.
-
Siva shunmugam Nadessin • 10,905 Reputation points • Microsoft External Staff • Moderator
2025-10-24T10:43:44.2466667+00:00 Hello Mark Pearson,
Please do not forget to "Accept Answer" and upvote as this may help other community members to refer the info if facing a similar issue. Your contribution to the Microsoft Q&A community is highly appreciated.
-
Mark Pearson • 320 Reputation points
2025-10-24T10:46:12.2033333+00:00 Hi Siva,
It appears that this is still not resolved.
It looks like it's taking the firstseen value as the start time, then calculating that time until now as the total uptimeminutes value, as opposed to tracking it's actual total uptime....
So even if i set the lookback value to 6 hours, because it first turned on at 8am, it's firing the alert, even though it's total uptime is only around 1 hour (Accross various start-stops)
-
Siva shunmugam Nadessin • 10,905 Reputation points • Microsoft External Staff • Moderator
2025-10-30T14:16:38.1166667+00:00 Hello Mark Pearson,
Kindly check below answer and see if it helps.
- Signal type: Custom log search → Aggregated logs
- Measurement mode: Table Rows
- Alert logic: Operator Greater than or equal to, Threshold 1
- Frequency of evaluation: 15 minutes
Heartbeat | where TimeGenerated > ago(4h) // Look back 4 hours | where Computer == "<VMName>" // Replace with your VM name or use a dynamic parameter | summarize LastHeartbeat = max(TimeGenerated) by Computer | where LastHeartbeat < ago(3h) // No heartbeat for 3 hours -
Anonymous
2025-11-04T08:34:39.3433333+00:00 Hello Mark Pearson,
Kindly please let us know did the response provided by Siva addressed your issue do let me know if you have any questions on it.
-
Mark Pearson • 320 Reputation points
2025-11-05T11:29:13.85+00:00 Appologies, I have been away from work on holiday, and also from illness, will try these out soon and report back by early next week.
-
Mark Pearson • 320 Reputation points
2025-11-18T09:19:00.2166667+00:00 Hi @Anonymous ,
I'm still trying to get an answer on this issue, and now I can no longer see our Private Messages to repond there?
Sign in to comment