Create Azure Monitor Scheduled Query Rules

The azure-native:monitor:ScheduledQueryRule resource, part of the Pulumi Azure Native provider, defines scheduled query rules that evaluate log data on a schedule and trigger actions when conditions are met. This guide focuses on three capabilities: static and dynamic threshold evaluation, dimension filtering and resource type scoping, and simple log alerts without aggregation.

Scheduled query rules reference action groups for notifications and scope to VMs, resource groups, or subscriptions. The examples are intentionally small. Combine them with your own action groups, monitoring targets, and Log Analytics workspaces.

Monitor VM performance with dimension filtering

Most performance monitoring starts by tracking metrics like CPU usage while filtering out maintenance hosts or focusing on specific OS types.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const scheduledQueryRule = new azure_native.monitor.ScheduledQueryRule("scheduledQueryRule", {
    actions: {
        actionGroups: ["/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup"],
        actionProperties: {
            "Icm.Title": "Custom title in ICM",
            "Icm.TsgId": "https://tsg.url",
        },
        customProperties: {
            key11: "value11",
            key12: "value12",
        },
    },
    checkWorkspaceAlertsStorageConfigured: true,
    criteria: {
        allOf: [{
            dimensions: [
                {
                    name: "ComputerIp",
                    operator: azure_native.monitor.DimensionOperator.Exclude,
                    values: ["192.168.1.1"],
                },
                {
                    name: "OSType",
                    operator: azure_native.monitor.DimensionOperator.Include,
                    values: ["*"],
                },
            ],
            failingPeriods: {
                minFailingPeriodsToAlert: 1,
                numberOfEvaluationPeriods: 1,
            },
            metricMeasureColumn: "% Processor Time",
            operator: azure_native.monitor.ConditionOperator.GreaterThan,
            query: "Perf | where ObjectName == \"Processor\"",
            resourceIdColumn: "resourceId",
            threshold: 70,
            timeAggregation: azure_native.monitor.TimeAggregation.Average,
        }],
    },
    description: "Performance rule",
    enabled: true,
    evaluationFrequency: "PT5M",
    location: "eastus",
    muteActionsDuration: "PT30M",
    resolveConfiguration: {
        autoResolved: true,
        timeToResolve: "PT10M",
    },
    resourceGroupName: "QueryResourceGroupName",
    ruleName: "perf",
    scopes: ["/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1"],
    severity: 4,
    skipQueryValidation: true,
    windowSize: "PT10M",
});
import pulumi
import pulumi_azure_native as azure_native

scheduled_query_rule = azure_native.monitor.ScheduledQueryRule("scheduledQueryRule",
    actions={
        "action_groups": ["/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup"],
        "action_properties": {
            "Icm.Title": "Custom title in ICM",
            "Icm.TsgId": "https://tsg.url",
        },
        "custom_properties": {
            "key11": "value11",
            "key12": "value12",
        },
    },
    check_workspace_alerts_storage_configured=True,
    criteria={
        "all_of": [{
            "dimensions": [
                {
                    "name": "ComputerIp",
                    "operator": azure_native.monitor.DimensionOperator.EXCLUDE,
                    "values": ["192.168.1.1"],
                },
                {
                    "name": "OSType",
                    "operator": azure_native.monitor.DimensionOperator.INCLUDE,
                    "values": ["*"],
                },
            ],
            "failing_periods": {
                "min_failing_periods_to_alert": 1,
                "number_of_evaluation_periods": 1,
            },
            "metric_measure_column": "% Processor Time",
            "operator": azure_native.monitor.ConditionOperator.GREATER_THAN,
            "query": "Perf | where ObjectName == \"Processor\"",
            "resource_id_column": "resourceId",
            "threshold": 70,
            "time_aggregation": azure_native.monitor.TimeAggregation.AVERAGE,
        }],
    },
    description="Performance rule",
    enabled=True,
    evaluation_frequency="PT5M",
    location="eastus",
    mute_actions_duration="PT30M",
    resolve_configuration={
        "auto_resolved": True,
        "time_to_resolve": "PT10M",
    },
    resource_group_name="QueryResourceGroupName",
    rule_name="perf",
    scopes=["/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1"],
    severity=4,
    skip_query_validation=True,
    window_size="PT10M")
package main

import (
	monitor "github.com/pulumi/pulumi-azure-native-sdk/monitor/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := monitor.NewScheduledQueryRule(ctx, "scheduledQueryRule", &monitor.ScheduledQueryRuleArgs{
			Actions: &monitor.ActionsArgs{
				ActionGroups: pulumi.StringArray{
					pulumi.String("/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup"),
				},
				ActionProperties: pulumi.StringMap{
					"Icm.Title": pulumi.String("Custom title in ICM"),
					"Icm.TsgId": pulumi.String("https://tsg.url"),
				},
				CustomProperties: pulumi.StringMap{
					"key11": pulumi.String("value11"),
					"key12": pulumi.String("value12"),
				},
			},
			CheckWorkspaceAlertsStorageConfigured: pulumi.Bool(true),
			Criteria: &monitor.ScheduledQueryRuleCriteriaArgs{
				AllOf: monitor.ConditionArray{
					&monitor.ConditionArgs{
						Dimensions: monitor.DimensionArray{
							&monitor.DimensionArgs{
								Name:     pulumi.String("ComputerIp"),
								Operator: pulumi.String(monitor.DimensionOperatorExclude),
								Values: pulumi.StringArray{
									pulumi.String("192.168.1.1"),
								},
							},
							&monitor.DimensionArgs{
								Name:     pulumi.String("OSType"),
								Operator: pulumi.String(monitor.DimensionOperatorInclude),
								Values: pulumi.StringArray{
									pulumi.String("*"),
								},
							},
						},
						FailingPeriods: &monitor.ConditionFailingPeriodsArgs{
							MinFailingPeriodsToAlert:  pulumi.Float64(1),
							NumberOfEvaluationPeriods: pulumi.Float64(1),
						},
						MetricMeasureColumn: pulumi.String("% Processor Time"),
						Operator:            pulumi.String(monitor.ConditionOperatorGreaterThan),
						Query:               pulumi.String("Perf | where ObjectName == \"Processor\""),
						ResourceIdColumn:    pulumi.String("resourceId"),
						Threshold:           pulumi.Float64(70),
						TimeAggregation:     pulumi.String(monitor.TimeAggregationAverage),
					},
				},
			},
			Description:         pulumi.String("Performance rule"),
			Enabled:             pulumi.Bool(true),
			EvaluationFrequency: pulumi.String("PT5M"),
			Location:            pulumi.String("eastus"),
			MuteActionsDuration: pulumi.String("PT30M"),
			ResolveConfiguration: &monitor.RuleResolveConfigurationArgs{
				AutoResolved:  pulumi.Bool(true),
				TimeToResolve: pulumi.String("PT10M"),
			},
			ResourceGroupName: pulumi.String("QueryResourceGroupName"),
			RuleName:          pulumi.String("perf"),
			Scopes: pulumi.StringArray{
				pulumi.String("/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1"),
			},
			Severity:            pulumi.Float64(4),
			SkipQueryValidation: pulumi.Bool(true),
			WindowSize:          pulumi.String("PT10M"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var scheduledQueryRule = new AzureNative.Monitor.ScheduledQueryRule("scheduledQueryRule", new()
    {
        Actions = new AzureNative.Monitor.Inputs.ActionsArgs
        {
            ActionGroups = new[]
            {
                "/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup",
            },
            ActionProperties = 
            {
                { "Icm.Title", "Custom title in ICM" },
                { "Icm.TsgId", "https://tsg.url" },
            },
            CustomProperties = 
            {
                { "key11", "value11" },
                { "key12", "value12" },
            },
        },
        CheckWorkspaceAlertsStorageConfigured = true,
        Criteria = new AzureNative.Monitor.Inputs.ScheduledQueryRuleCriteriaArgs
        {
            AllOf = new[]
            {
                new AzureNative.Monitor.Inputs.ConditionArgs
                {
                    Dimensions = new[]
                    {
                        new AzureNative.Monitor.Inputs.DimensionArgs
                        {
                            Name = "ComputerIp",
                            Operator = AzureNative.Monitor.DimensionOperator.Exclude,
                            Values = new[]
                            {
                                "192.168.1.1",
                            },
                        },
                        new AzureNative.Monitor.Inputs.DimensionArgs
                        {
                            Name = "OSType",
                            Operator = AzureNative.Monitor.DimensionOperator.Include,
                            Values = new[]
                            {
                                "*",
                            },
                        },
                    },
                    FailingPeriods = new AzureNative.Monitor.Inputs.ConditionFailingPeriodsArgs
                    {
                        MinFailingPeriodsToAlert = 1,
                        NumberOfEvaluationPeriods = 1,
                    },
                    MetricMeasureColumn = "% Processor Time",
                    Operator = AzureNative.Monitor.ConditionOperator.GreaterThan,
                    Query = "Perf | where ObjectName == \"Processor\"",
                    ResourceIdColumn = "resourceId",
                    Threshold = 70,
                    TimeAggregation = AzureNative.Monitor.TimeAggregation.Average,
                },
            },
        },
        Description = "Performance rule",
        Enabled = true,
        EvaluationFrequency = "PT5M",
        Location = "eastus",
        MuteActionsDuration = "PT30M",
        ResolveConfiguration = new AzureNative.Monitor.Inputs.RuleResolveConfigurationArgs
        {
            AutoResolved = true,
            TimeToResolve = "PT10M",
        },
        ResourceGroupName = "QueryResourceGroupName",
        RuleName = "perf",
        Scopes = new[]
        {
            "/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1",
        },
        Severity = 4,
        SkipQueryValidation = true,
        WindowSize = "PT10M",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.monitor.ScheduledQueryRule;
import com.pulumi.azurenative.monitor.ScheduledQueryRuleArgs;
import com.pulumi.azurenative.monitor.inputs.ActionsArgs;
import com.pulumi.azurenative.monitor.inputs.ScheduledQueryRuleCriteriaArgs;
import com.pulumi.azurenative.monitor.inputs.RuleResolveConfigurationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var scheduledQueryRule = new ScheduledQueryRule("scheduledQueryRule", ScheduledQueryRuleArgs.builder()
            .actions(ActionsArgs.builder()
                .actionGroups("/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup")
                .actionProperties(Map.ofEntries(
                    Map.entry("Icm.Title", "Custom title in ICM"),
                    Map.entry("Icm.TsgId", "https://tsg.url")
                ))
                .customProperties(Map.ofEntries(
                    Map.entry("key11", "value11"),
                    Map.entry("key12", "value12")
                ))
                .build())
            .checkWorkspaceAlertsStorageConfigured(true)
            .criteria(ScheduledQueryRuleCriteriaArgs.builder()
                .allOf(ConditionArgs.builder()
                    .dimensions(                    
                        DimensionArgs.builder()
                            .name("ComputerIp")
                            .operator("Exclude")
                            .values("192.168.1.1")
                            .build(),
                        DimensionArgs.builder()
                            .name("OSType")
                            .operator("Include")
                            .values("*")
                            .build())
                    .failingPeriods(ConditionFailingPeriodsArgs.builder()
                        .minFailingPeriodsToAlert(1.0)
                        .numberOfEvaluationPeriods(1.0)
                        .build())
                    .metricMeasureColumn("% Processor Time")
                    .operator("GreaterThan")
                    .query("Perf | where ObjectName == \"Processor\"")
                    .resourceIdColumn("resourceId")
                    .threshold(70.0)
                    .timeAggregation("Average")
                    .build())
                .build())
            .description("Performance rule")
            .enabled(true)
            .evaluationFrequency("PT5M")
            .location("eastus")
            .muteActionsDuration("PT30M")
            .resolveConfiguration(RuleResolveConfigurationArgs.builder()
                .autoResolved(true)
                .timeToResolve("PT10M")
                .build())
            .resourceGroupName("QueryResourceGroupName")
            .ruleName("perf")
            .scopes("/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1")
            .severity(4.0)
            .skipQueryValidation(true)
            .windowSize("PT10M")
            .build());

    }
}
resources:
  scheduledQueryRule:
    type: azure-native:monitor:ScheduledQueryRule
    properties:
      actions:
        actionGroups:
          - /subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup
        actionProperties:
          Icm.Title: Custom title in ICM
          Icm.TsgId: https://tsg.url
        customProperties:
          key11: value11
          key12: value12
      checkWorkspaceAlertsStorageConfigured: true
      criteria:
        allOf:
          - dimensions:
              - name: ComputerIp
                operator: Exclude
                values:
                  - 192.168.1.1
              - name: OSType
                operator: Include
                values:
                  - '*'
            failingPeriods:
              minFailingPeriodsToAlert: 1
              numberOfEvaluationPeriods: 1
            metricMeasureColumn: '% Processor Time'
            operator: GreaterThan
            query: Perf | where ObjectName == "Processor"
            resourceIdColumn: resourceId
            threshold: 70
            timeAggregation: Average
      description: Performance rule
      enabled: true
      evaluationFrequency: PT5M
      location: eastus
      muteActionsDuration: PT30M
      resolveConfiguration:
        autoResolved: true
        timeToResolve: PT10M
      resourceGroupName: QueryResourceGroupName
      ruleName: perf
      scopes:
        - /subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1
      severity: 4
      skipQueryValidation: true
      windowSize: PT10M

The criteria property defines what to evaluate. The query runs against Log Analytics data, and dimensions filter results by excluding specific IPs or including all OS types. When the metricMeasureColumn (% Processor Time) exceeds the threshold for the specified failingPeriods, the rule fires. The evaluationFrequency controls how often the query runs, and windowSize determines the time range for each evaluation. Actions trigger notifications through the referenced action group.

Monitor resource groups with type filtering

When monitoring entire resource groups, scoping alerts to specific resource types prevents noise from unrelated resources.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const scheduledQueryRule = new azure_native.monitor.ScheduledQueryRule("scheduledQueryRule", {
    actions: {
        actionGroups: ["/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup"],
        actionProperties: {
            "Icm.Title": "Custom title in ICM",
            "Icm.TsgId": "https://tsg.url",
        },
        customProperties: {
            key11: "value11",
            key12: "value12",
        },
    },
    checkWorkspaceAlertsStorageConfigured: true,
    criteria: {
        allOf: [{
            dimensions: [],
            failingPeriods: {
                minFailingPeriodsToAlert: 1,
                numberOfEvaluationPeriods: 1,
            },
            operator: azure_native.monitor.ConditionOperator.GreaterThan,
            query: "Heartbeat",
            threshold: 360,
            timeAggregation: azure_native.monitor.TimeAggregation.Count,
        }],
    },
    description: "Health check rule",
    enabled: true,
    evaluationFrequency: "PT5M",
    location: "eastus",
    muteActionsDuration: "PT30M",
    resolveConfiguration: {
        autoResolved: true,
        timeToResolve: "PT10M",
    },
    resourceGroupName: "QueryResourceGroupName",
    ruleName: "heartbeat",
    scopes: ["/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1"],
    severity: 4,
    skipQueryValidation: true,
    targetResourceTypes: ["Microsoft.Compute/virtualMachines"],
    windowSize: "PT10M",
});
import pulumi
import pulumi_azure_native as azure_native

scheduled_query_rule = azure_native.monitor.ScheduledQueryRule("scheduledQueryRule",
    actions={
        "action_groups": ["/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup"],
        "action_properties": {
            "Icm.Title": "Custom title in ICM",
            "Icm.TsgId": "https://tsg.url",
        },
        "custom_properties": {
            "key11": "value11",
            "key12": "value12",
        },
    },
    check_workspace_alerts_storage_configured=True,
    criteria={
        "all_of": [{
            "dimensions": [],
            "failing_periods": {
                "min_failing_periods_to_alert": 1,
                "number_of_evaluation_periods": 1,
            },
            "operator": azure_native.monitor.ConditionOperator.GREATER_THAN,
            "query": "Heartbeat",
            "threshold": 360,
            "time_aggregation": azure_native.monitor.TimeAggregation.COUNT,
        }],
    },
    description="Health check rule",
    enabled=True,
    evaluation_frequency="PT5M",
    location="eastus",
    mute_actions_duration="PT30M",
    resolve_configuration={
        "auto_resolved": True,
        "time_to_resolve": "PT10M",
    },
    resource_group_name="QueryResourceGroupName",
    rule_name="heartbeat",
    scopes=["/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1"],
    severity=4,
    skip_query_validation=True,
    target_resource_types=["Microsoft.Compute/virtualMachines"],
    window_size="PT10M")
package main

import (
	monitor "github.com/pulumi/pulumi-azure-native-sdk/monitor/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := monitor.NewScheduledQueryRule(ctx, "scheduledQueryRule", &monitor.ScheduledQueryRuleArgs{
			Actions: &monitor.ActionsArgs{
				ActionGroups: pulumi.StringArray{
					pulumi.String("/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup"),
				},
				ActionProperties: pulumi.StringMap{
					"Icm.Title": pulumi.String("Custom title in ICM"),
					"Icm.TsgId": pulumi.String("https://tsg.url"),
				},
				CustomProperties: pulumi.StringMap{
					"key11": pulumi.String("value11"),
					"key12": pulumi.String("value12"),
				},
			},
			CheckWorkspaceAlertsStorageConfigured: pulumi.Bool(true),
			Criteria: &monitor.ScheduledQueryRuleCriteriaArgs{
				AllOf: monitor.ConditionArray{
					&monitor.ConditionArgs{
						Dimensions: monitor.DimensionArray{},
						FailingPeriods: &monitor.ConditionFailingPeriodsArgs{
							MinFailingPeriodsToAlert:  pulumi.Float64(1),
							NumberOfEvaluationPeriods: pulumi.Float64(1),
						},
						Operator:        pulumi.String(monitor.ConditionOperatorGreaterThan),
						Query:           pulumi.String("Heartbeat"),
						Threshold:       pulumi.Float64(360),
						TimeAggregation: pulumi.String(monitor.TimeAggregationCount),
					},
				},
			},
			Description:         pulumi.String("Health check rule"),
			Enabled:             pulumi.Bool(true),
			EvaluationFrequency: pulumi.String("PT5M"),
			Location:            pulumi.String("eastus"),
			MuteActionsDuration: pulumi.String("PT30M"),
			ResolveConfiguration: &monitor.RuleResolveConfigurationArgs{
				AutoResolved:  pulumi.Bool(true),
				TimeToResolve: pulumi.String("PT10M"),
			},
			ResourceGroupName: pulumi.String("QueryResourceGroupName"),
			RuleName:          pulumi.String("heartbeat"),
			Scopes: pulumi.StringArray{
				pulumi.String("/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1"),
			},
			Severity:            pulumi.Float64(4),
			SkipQueryValidation: pulumi.Bool(true),
			TargetResourceTypes: pulumi.StringArray{
				pulumi.String("Microsoft.Compute/virtualMachines"),
			},
			WindowSize: pulumi.String("PT10M"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var scheduledQueryRule = new AzureNative.Monitor.ScheduledQueryRule("scheduledQueryRule", new()
    {
        Actions = new AzureNative.Monitor.Inputs.ActionsArgs
        {
            ActionGroups = new[]
            {
                "/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup",
            },
            ActionProperties = 
            {
                { "Icm.Title", "Custom title in ICM" },
                { "Icm.TsgId", "https://tsg.url" },
            },
            CustomProperties = 
            {
                { "key11", "value11" },
                { "key12", "value12" },
            },
        },
        CheckWorkspaceAlertsStorageConfigured = true,
        Criteria = new AzureNative.Monitor.Inputs.ScheduledQueryRuleCriteriaArgs
        {
            AllOf = new[]
            {
                new AzureNative.Monitor.Inputs.ConditionArgs
                {
                    Dimensions = new() { },
                    FailingPeriods = new AzureNative.Monitor.Inputs.ConditionFailingPeriodsArgs
                    {
                        MinFailingPeriodsToAlert = 1,
                        NumberOfEvaluationPeriods = 1,
                    },
                    Operator = AzureNative.Monitor.ConditionOperator.GreaterThan,
                    Query = "Heartbeat",
                    Threshold = 360,
                    TimeAggregation = AzureNative.Monitor.TimeAggregation.Count,
                },
            },
        },
        Description = "Health check rule",
        Enabled = true,
        EvaluationFrequency = "PT5M",
        Location = "eastus",
        MuteActionsDuration = "PT30M",
        ResolveConfiguration = new AzureNative.Monitor.Inputs.RuleResolveConfigurationArgs
        {
            AutoResolved = true,
            TimeToResolve = "PT10M",
        },
        ResourceGroupName = "QueryResourceGroupName",
        RuleName = "heartbeat",
        Scopes = new[]
        {
            "/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1",
        },
        Severity = 4,
        SkipQueryValidation = true,
        TargetResourceTypes = new[]
        {
            "Microsoft.Compute/virtualMachines",
        },
        WindowSize = "PT10M",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.monitor.ScheduledQueryRule;
import com.pulumi.azurenative.monitor.ScheduledQueryRuleArgs;
import com.pulumi.azurenative.monitor.inputs.ActionsArgs;
import com.pulumi.azurenative.monitor.inputs.ScheduledQueryRuleCriteriaArgs;
import com.pulumi.azurenative.monitor.inputs.RuleResolveConfigurationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var scheduledQueryRule = new ScheduledQueryRule("scheduledQueryRule", ScheduledQueryRuleArgs.builder()
            .actions(ActionsArgs.builder()
                .actionGroups("/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup")
                .actionProperties(Map.ofEntries(
                    Map.entry("Icm.Title", "Custom title in ICM"),
                    Map.entry("Icm.TsgId", "https://tsg.url")
                ))
                .customProperties(Map.ofEntries(
                    Map.entry("key11", "value11"),
                    Map.entry("key12", "value12")
                ))
                .build())
            .checkWorkspaceAlertsStorageConfigured(true)
            .criteria(ScheduledQueryRuleCriteriaArgs.builder()
                .allOf(ConditionArgs.builder()
                    .dimensions()
                    .failingPeriods(ConditionFailingPeriodsArgs.builder()
                        .minFailingPeriodsToAlert(1.0)
                        .numberOfEvaluationPeriods(1.0)
                        .build())
                    .operator("GreaterThan")
                    .query("Heartbeat")
                    .threshold(360.0)
                    .timeAggregation("Count")
                    .build())
                .build())
            .description("Health check rule")
            .enabled(true)
            .evaluationFrequency("PT5M")
            .location("eastus")
            .muteActionsDuration("PT30M")
            .resolveConfiguration(RuleResolveConfigurationArgs.builder()
                .autoResolved(true)
                .timeToResolve("PT10M")
                .build())
            .resourceGroupName("QueryResourceGroupName")
            .ruleName("heartbeat")
            .scopes("/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1")
            .severity(4.0)
            .skipQueryValidation(true)
            .targetResourceTypes("Microsoft.Compute/virtualMachines")
            .windowSize("PT10M")
            .build());

    }
}
resources:
  scheduledQueryRule:
    type: azure-native:monitor:ScheduledQueryRule
    properties:
      actions:
        actionGroups:
          - /subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup
        actionProperties:
          Icm.Title: Custom title in ICM
          Icm.TsgId: https://tsg.url
        customProperties:
          key11: value11
          key12: value12
      checkWorkspaceAlertsStorageConfigured: true
      criteria:
        allOf:
          - dimensions: []
            failingPeriods:
              minFailingPeriodsToAlert: 1
              numberOfEvaluationPeriods: 1
            operator: GreaterThan
            query: Heartbeat
            threshold: 360
            timeAggregation: Count
      description: Health check rule
      enabled: true
      evaluationFrequency: PT5M
      location: eastus
      muteActionsDuration: PT30M
      resolveConfiguration:
        autoResolved: true
        timeToResolve: PT10M
      resourceGroupName: QueryResourceGroupName
      ruleName: heartbeat
      scopes:
        - /subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1
      severity: 4
      skipQueryValidation: true
      targetResourceTypes:
        - Microsoft.Compute/virtualMachines
      windowSize: PT10M

The scopes property points to a resource group rather than individual resources. The targetResourceTypes array limits evaluation to specific resource types within that scope, so the heartbeat query only monitors VMs. This approach scales monitoring across dynamic resource sets without hardcoding individual resource IDs.

Create simple alerts without aggregation

Some scenarios need alerts that fire whenever a query returns results, without threshold evaluation or metric aggregation.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const scheduledQueryRule = new azure_native.monitor.ScheduledQueryRule("scheduledQueryRule", {
    actions: {
        actionGroups: ["/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup"],
        actionProperties: {
            "Icm.Title": "Custom title in ICM",
            "Icm.TsgId": "https://tsg.url",
        },
        customProperties: {
            key11: "value11",
            key12: "value12",
        },
    },
    autoMitigate: false,
    checkWorkspaceAlertsStorageConfigured: true,
    criteria: {
        allOf: [{
            query: "Perf | where ObjectName == \"Processor\"",
        }],
    },
    description: "Performance rule",
    enabled: true,
    kind: azure_native.monitor.Kind.SimpleLogAlert,
    location: "eastus",
    resourceGroupName: "QueryResourceGroupName",
    ruleName: "perf",
    scopes: ["/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1"],
    severity: 4,
    skipQueryValidation: true,
});
import pulumi
import pulumi_azure_native as azure_native

scheduled_query_rule = azure_native.monitor.ScheduledQueryRule("scheduledQueryRule",
    actions={
        "action_groups": ["/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup"],
        "action_properties": {
            "Icm.Title": "Custom title in ICM",
            "Icm.TsgId": "https://tsg.url",
        },
        "custom_properties": {
            "key11": "value11",
            "key12": "value12",
        },
    },
    auto_mitigate=False,
    check_workspace_alerts_storage_configured=True,
    criteria={
        "all_of": [{
            "query": "Perf | where ObjectName == \"Processor\"",
        }],
    },
    description="Performance rule",
    enabled=True,
    kind=azure_native.monitor.Kind.SIMPLE_LOG_ALERT,
    location="eastus",
    resource_group_name="QueryResourceGroupName",
    rule_name="perf",
    scopes=["/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1"],
    severity=4,
    skip_query_validation=True)
package main

import (
	monitor "github.com/pulumi/pulumi-azure-native-sdk/monitor/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := monitor.NewScheduledQueryRule(ctx, "scheduledQueryRule", &monitor.ScheduledQueryRuleArgs{
			Actions: &monitor.ActionsArgs{
				ActionGroups: pulumi.StringArray{
					pulumi.String("/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup"),
				},
				ActionProperties: pulumi.StringMap{
					"Icm.Title": pulumi.String("Custom title in ICM"),
					"Icm.TsgId": pulumi.String("https://tsg.url"),
				},
				CustomProperties: pulumi.StringMap{
					"key11": pulumi.String("value11"),
					"key12": pulumi.String("value12"),
				},
			},
			AutoMitigate:                          pulumi.Bool(false),
			CheckWorkspaceAlertsStorageConfigured: pulumi.Bool(true),
			Criteria: &monitor.ScheduledQueryRuleCriteriaArgs{
				AllOf: monitor.ConditionArray{
					&monitor.ConditionArgs{
						Query: pulumi.String("Perf | where ObjectName == \"Processor\""),
					},
				},
			},
			Description:       pulumi.String("Performance rule"),
			Enabled:           pulumi.Bool(true),
			Kind:              pulumi.String(monitor.KindSimpleLogAlert),
			Location:          pulumi.String("eastus"),
			ResourceGroupName: pulumi.String("QueryResourceGroupName"),
			RuleName:          pulumi.String("perf"),
			Scopes: pulumi.StringArray{
				pulumi.String("/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1"),
			},
			Severity:            pulumi.Float64(4),
			SkipQueryValidation: pulumi.Bool(true),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var scheduledQueryRule = new AzureNative.Monitor.ScheduledQueryRule("scheduledQueryRule", new()
    {
        Actions = new AzureNative.Monitor.Inputs.ActionsArgs
        {
            ActionGroups = new[]
            {
                "/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup",
            },
            ActionProperties = 
            {
                { "Icm.Title", "Custom title in ICM" },
                { "Icm.TsgId", "https://tsg.url" },
            },
            CustomProperties = 
            {
                { "key11", "value11" },
                { "key12", "value12" },
            },
        },
        AutoMitigate = false,
        CheckWorkspaceAlertsStorageConfigured = true,
        Criteria = new AzureNative.Monitor.Inputs.ScheduledQueryRuleCriteriaArgs
        {
            AllOf = new[]
            {
                new AzureNative.Monitor.Inputs.ConditionArgs
                {
                    Query = "Perf | where ObjectName == \"Processor\"",
                },
            },
        },
        Description = "Performance rule",
        Enabled = true,
        Kind = AzureNative.Monitor.Kind.SimpleLogAlert,
        Location = "eastus",
        ResourceGroupName = "QueryResourceGroupName",
        RuleName = "perf",
        Scopes = new[]
        {
            "/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1",
        },
        Severity = 4,
        SkipQueryValidation = true,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.monitor.ScheduledQueryRule;
import com.pulumi.azurenative.monitor.ScheduledQueryRuleArgs;
import com.pulumi.azurenative.monitor.inputs.ActionsArgs;
import com.pulumi.azurenative.monitor.inputs.ScheduledQueryRuleCriteriaArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var scheduledQueryRule = new ScheduledQueryRule("scheduledQueryRule", ScheduledQueryRuleArgs.builder()
            .actions(ActionsArgs.builder()
                .actionGroups("/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup")
                .actionProperties(Map.ofEntries(
                    Map.entry("Icm.Title", "Custom title in ICM"),
                    Map.entry("Icm.TsgId", "https://tsg.url")
                ))
                .customProperties(Map.ofEntries(
                    Map.entry("key11", "value11"),
                    Map.entry("key12", "value12")
                ))
                .build())
            .autoMitigate(false)
            .checkWorkspaceAlertsStorageConfigured(true)
            .criteria(ScheduledQueryRuleCriteriaArgs.builder()
                .allOf(ConditionArgs.builder()
                    .query("Perf | where ObjectName == \"Processor\"")
                    .build())
                .build())
            .description("Performance rule")
            .enabled(true)
            .kind("SimpleLogAlert")
            .location("eastus")
            .resourceGroupName("QueryResourceGroupName")
            .ruleName("perf")
            .scopes("/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1")
            .severity(4.0)
            .skipQueryValidation(true)
            .build());

    }
}
resources:
  scheduledQueryRule:
    type: azure-native:monitor:ScheduledQueryRule
    properties:
      actions:
        actionGroups:
          - /subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup
        actionProperties:
          Icm.Title: Custom title in ICM
          Icm.TsgId: https://tsg.url
        customProperties:
          key11: value11
          key12: value12
      autoMitigate: false
      checkWorkspaceAlertsStorageConfigured: true
      criteria:
        allOf:
          - query: Perf | where ObjectName == "Processor"
      description: Performance rule
      enabled: true
      kind: SimpleLogAlert
      location: eastus
      resourceGroupName: QueryResourceGroupName
      ruleName: perf
      scopes:
        - /subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1
      severity: 4
      skipQueryValidation: true

The kind property set to SimpleLogAlert changes the evaluation model. Instead of comparing aggregated metrics against thresholds, the rule fires whenever the query returns any results. The autoMitigate property controls whether alerts automatically resolve when the condition clears. Simple log alerts omit evaluationFrequency and windowSize because they don’t perform time-based aggregation.

Use machine learning for adaptive thresholds

Static thresholds often generate false positives during expected traffic patterns like business hours or seasonal changes.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const scheduledQueryRule = new azure_native.monitor.ScheduledQueryRule("scheduledQueryRule", {
    actions: {
        actionGroups: ["/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup"],
        actionProperties: {
            "Icm.Title": "Custom title in ICM",
            "Icm.TsgId": "https://tsg.url",
        },
        customProperties: {
            key11: "value11",
            key12: "value12",
        },
    },
    checkWorkspaceAlertsStorageConfigured: true,
    criteria: {
        allOf: [{
            alertSensitivity: "Medium",
            criterionType: azure_native.monitor.CriterionType.DynamicThresholdCriterion,
            dimensions: [
                {
                    name: "ComputerIp",
                    operator: azure_native.monitor.DimensionOperator.Exclude,
                    values: ["192.168.1.1"],
                },
                {
                    name: "OSType",
                    operator: azure_native.monitor.DimensionOperator.Include,
                    values: ["*"],
                },
            ],
            ignoreDataBefore: "2024-06-01T21:00:00.000Z",
            metricMeasureColumn: "% Processor Time",
            operator: azure_native.monitor.ConditionOperator.GreaterOrLessThan,
            query: "Perf | where ObjectName == \"Processor\"",
            resourceIdColumn: "resourceId",
            timeAggregation: azure_native.monitor.TimeAggregation.Average,
        }],
    },
    description: "Performance rule",
    enabled: true,
    evaluationFrequency: "PT5M",
    location: "eastus",
    muteActionsDuration: "PT30M",
    resourceGroupName: "QueryResourceGroupName",
    ruleName: "perf",
    scopes: ["/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1"],
    severity: 4,
    skipQueryValidation: true,
    windowSize: "PT10M",
});
import pulumi
import pulumi_azure_native as azure_native

scheduled_query_rule = azure_native.monitor.ScheduledQueryRule("scheduledQueryRule",
    actions={
        "action_groups": ["/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup"],
        "action_properties": {
            "Icm.Title": "Custom title in ICM",
            "Icm.TsgId": "https://tsg.url",
        },
        "custom_properties": {
            "key11": "value11",
            "key12": "value12",
        },
    },
    check_workspace_alerts_storage_configured=True,
    criteria={
        "all_of": [{
            "alert_sensitivity": "Medium",
            "criterion_type": azure_native.monitor.CriterionType.DYNAMIC_THRESHOLD_CRITERION,
            "dimensions": [
                {
                    "name": "ComputerIp",
                    "operator": azure_native.monitor.DimensionOperator.EXCLUDE,
                    "values": ["192.168.1.1"],
                },
                {
                    "name": "OSType",
                    "operator": azure_native.monitor.DimensionOperator.INCLUDE,
                    "values": ["*"],
                },
            ],
            "ignore_data_before": "2024-06-01T21:00:00.000Z",
            "metric_measure_column": "% Processor Time",
            "operator": azure_native.monitor.ConditionOperator.GREATER_OR_LESS_THAN,
            "query": "Perf | where ObjectName == \"Processor\"",
            "resource_id_column": "resourceId",
            "time_aggregation": azure_native.monitor.TimeAggregation.AVERAGE,
        }],
    },
    description="Performance rule",
    enabled=True,
    evaluation_frequency="PT5M",
    location="eastus",
    mute_actions_duration="PT30M",
    resource_group_name="QueryResourceGroupName",
    rule_name="perf",
    scopes=["/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1"],
    severity=4,
    skip_query_validation=True,
    window_size="PT10M")
package main

import (
	monitor "github.com/pulumi/pulumi-azure-native-sdk/monitor/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := monitor.NewScheduledQueryRule(ctx, "scheduledQueryRule", &monitor.ScheduledQueryRuleArgs{
			Actions: &monitor.ActionsArgs{
				ActionGroups: pulumi.StringArray{
					pulumi.String("/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup"),
				},
				ActionProperties: pulumi.StringMap{
					"Icm.Title": pulumi.String("Custom title in ICM"),
					"Icm.TsgId": pulumi.String("https://tsg.url"),
				},
				CustomProperties: pulumi.StringMap{
					"key11": pulumi.String("value11"),
					"key12": pulumi.String("value12"),
				},
			},
			CheckWorkspaceAlertsStorageConfigured: pulumi.Bool(true),
			Criteria: &monitor.ScheduledQueryRuleCriteriaArgs{
				AllOf: monitor.ConditionArray{
					&monitor.ConditionArgs{
						AlertSensitivity: pulumi.String("Medium"),
						CriterionType:    pulumi.String(monitor.CriterionTypeDynamicThresholdCriterion),
						Dimensions: monitor.DimensionArray{
							&monitor.DimensionArgs{
								Name:     pulumi.String("ComputerIp"),
								Operator: pulumi.String(monitor.DimensionOperatorExclude),
								Values: pulumi.StringArray{
									pulumi.String("192.168.1.1"),
								},
							},
							&monitor.DimensionArgs{
								Name:     pulumi.String("OSType"),
								Operator: pulumi.String(monitor.DimensionOperatorInclude),
								Values: pulumi.StringArray{
									pulumi.String("*"),
								},
							},
						},
						IgnoreDataBefore:    pulumi.String("2024-06-01T21:00:00.000Z"),
						MetricMeasureColumn: pulumi.String("% Processor Time"),
						Operator:            pulumi.String(monitor.ConditionOperatorGreaterOrLessThan),
						Query:               pulumi.String("Perf | where ObjectName == \"Processor\""),
						ResourceIdColumn:    pulumi.String("resourceId"),
						TimeAggregation:     pulumi.String(monitor.TimeAggregationAverage),
					},
				},
			},
			Description:         pulumi.String("Performance rule"),
			Enabled:             pulumi.Bool(true),
			EvaluationFrequency: pulumi.String("PT5M"),
			Location:            pulumi.String("eastus"),
			MuteActionsDuration: pulumi.String("PT30M"),
			ResourceGroupName:   pulumi.String("QueryResourceGroupName"),
			RuleName:            pulumi.String("perf"),
			Scopes: pulumi.StringArray{
				pulumi.String("/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1"),
			},
			Severity:            pulumi.Float64(4),
			SkipQueryValidation: pulumi.Bool(true),
			WindowSize:          pulumi.String("PT10M"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var scheduledQueryRule = new AzureNative.Monitor.ScheduledQueryRule("scheduledQueryRule", new()
    {
        Actions = new AzureNative.Monitor.Inputs.ActionsArgs
        {
            ActionGroups = new[]
            {
                "/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup",
            },
            ActionProperties = 
            {
                { "Icm.Title", "Custom title in ICM" },
                { "Icm.TsgId", "https://tsg.url" },
            },
            CustomProperties = 
            {
                { "key11", "value11" },
                { "key12", "value12" },
            },
        },
        CheckWorkspaceAlertsStorageConfigured = true,
        Criteria = new AzureNative.Monitor.Inputs.ScheduledQueryRuleCriteriaArgs
        {
            AllOf = new[]
            {
                new AzureNative.Monitor.Inputs.ConditionArgs
                {
                    AlertSensitivity = "Medium",
                    CriterionType = AzureNative.Monitor.CriterionType.DynamicThresholdCriterion,
                    Dimensions = new[]
                    {
                        new AzureNative.Monitor.Inputs.DimensionArgs
                        {
                            Name = "ComputerIp",
                            Operator = AzureNative.Monitor.DimensionOperator.Exclude,
                            Values = new[]
                            {
                                "192.168.1.1",
                            },
                        },
                        new AzureNative.Monitor.Inputs.DimensionArgs
                        {
                            Name = "OSType",
                            Operator = AzureNative.Monitor.DimensionOperator.Include,
                            Values = new[]
                            {
                                "*",
                            },
                        },
                    },
                    IgnoreDataBefore = "2024-06-01T21:00:00.000Z",
                    MetricMeasureColumn = "% Processor Time",
                    Operator = AzureNative.Monitor.ConditionOperator.GreaterOrLessThan,
                    Query = "Perf | where ObjectName == \"Processor\"",
                    ResourceIdColumn = "resourceId",
                    TimeAggregation = AzureNative.Monitor.TimeAggregation.Average,
                },
            },
        },
        Description = "Performance rule",
        Enabled = true,
        EvaluationFrequency = "PT5M",
        Location = "eastus",
        MuteActionsDuration = "PT30M",
        ResourceGroupName = "QueryResourceGroupName",
        RuleName = "perf",
        Scopes = new[]
        {
            "/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1",
        },
        Severity = 4,
        SkipQueryValidation = true,
        WindowSize = "PT10M",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.monitor.ScheduledQueryRule;
import com.pulumi.azurenative.monitor.ScheduledQueryRuleArgs;
import com.pulumi.azurenative.monitor.inputs.ActionsArgs;
import com.pulumi.azurenative.monitor.inputs.ScheduledQueryRuleCriteriaArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var scheduledQueryRule = new ScheduledQueryRule("scheduledQueryRule", ScheduledQueryRuleArgs.builder()
            .actions(ActionsArgs.builder()
                .actionGroups("/subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup")
                .actionProperties(Map.ofEntries(
                    Map.entry("Icm.Title", "Custom title in ICM"),
                    Map.entry("Icm.TsgId", "https://tsg.url")
                ))
                .customProperties(Map.ofEntries(
                    Map.entry("key11", "value11"),
                    Map.entry("key12", "value12")
                ))
                .build())
            .checkWorkspaceAlertsStorageConfigured(true)
            .criteria(ScheduledQueryRuleCriteriaArgs.builder()
                .allOf(ConditionArgs.builder()
                    .alertSensitivity("Medium")
                    .criterionType("DynamicThresholdCriterion")
                    .dimensions(                    
                        DimensionArgs.builder()
                            .name("ComputerIp")
                            .operator("Exclude")
                            .values("192.168.1.1")
                            .build(),
                        DimensionArgs.builder()
                            .name("OSType")
                            .operator("Include")
                            .values("*")
                            .build())
                    .ignoreDataBefore("2024-06-01T21:00:00.000Z")
                    .metricMeasureColumn("% Processor Time")
                    .operator("GreaterOrLessThan")
                    .query("Perf | where ObjectName == \"Processor\"")
                    .resourceIdColumn("resourceId")
                    .timeAggregation("Average")
                    .build())
                .build())
            .description("Performance rule")
            .enabled(true)
            .evaluationFrequency("PT5M")
            .location("eastus")
            .muteActionsDuration("PT30M")
            .resourceGroupName("QueryResourceGroupName")
            .ruleName("perf")
            .scopes("/subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1")
            .severity(4.0)
            .skipQueryValidation(true)
            .windowSize("PT10M")
            .build());

    }
}
resources:
  scheduledQueryRule:
    type: azure-native:monitor:ScheduledQueryRule
    properties:
      actions:
        actionGroups:
          - /subscriptions/1cf177ed-1330-4692-80ea-fd3d7783b147/resourcegroups/sqrapi/providers/microsoft.insights/actiongroups/myactiongroup
        actionProperties:
          Icm.Title: Custom title in ICM
          Icm.TsgId: https://tsg.url
        customProperties:
          key11: value11
          key12: value12
      checkWorkspaceAlertsStorageConfigured: true
      criteria:
        allOf:
          - alertSensitivity: Medium
            criterionType: DynamicThresholdCriterion
            dimensions:
              - name: ComputerIp
                operator: Exclude
                values:
                  - 192.168.1.1
              - name: OSType
                operator: Include
                values:
                  - '*'
            ignoreDataBefore: 2024-06-01T21:00:00.000Z
            metricMeasureColumn: '% Processor Time'
            operator: GreaterOrLessThan
            query: Perf | where ObjectName == "Processor"
            resourceIdColumn: resourceId
            timeAggregation: Average
      description: Performance rule
      enabled: true
      evaluationFrequency: PT5M
      location: eastus
      muteActionsDuration: PT30M
      resourceGroupName: QueryResourceGroupName
      ruleName: perf
      scopes:
        - /subscriptions/aaf177ed-1330-a9f2-80ea-fd3d7783b147/resourceGroups/scopeResourceGroup1/providers/Microsoft.Compute/virtualMachines/vm1
      severity: 4
      skipQueryValidation: true
      windowSize: PT10M

The criterionType set to DynamicThresholdCriterion enables machine learning-based evaluation. Instead of comparing against a fixed threshold, the rule learns normal behavior and alerts on deviations. The alertSensitivity controls how sensitive the detection is (Low, Medium, High), and ignoreDataBefore sets a cutoff date for training data, useful after infrastructure changes that invalidate historical patterns.

Beyond these examples

These snippets focus on specific scheduled query rule features: static and dynamic threshold evaluation, dimension filtering and resource type scoping, and simple log alerts and metric-based alerts. They’re intentionally minimal rather than full monitoring solutions.

The examples may reference pre-existing infrastructure such as action groups for notifications, VMs, resource groups, or subscriptions to monitor, and Log Analytics workspaces (implied by query syntax). They focus on configuring the rule rather than provisioning everything around it.

To keep things focused, common scheduled query rule patterns are omitted, including:

  • Alert resolution configuration (resolveConfiguration)
  • Action muting and suppression (muteActionsDuration)
  • Custom properties and ICM integration details
  • Identity configuration for managed identity scenarios
  • Query validation controls (skipQueryValidation)
  • Workspace storage configuration (checkWorkspaceAlertsStorageConfigured)

These omissions are intentional: the goal is to illustrate how each scheduled query rule feature is wired, not provide drop-in monitoring modules. See the ScheduledQueryRule resource reference for all available configuration options.

Let's create Azure Monitor Scheduled Query Rules

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Scope & Targeting
How do I monitor a single resource vs a resource group or subscription?
For a single resource, set scopes to the specific resource ID. For a resource group or subscription, set scopes to the group/subscription ID and use targetResourceTypes to specify which resource types should trigger alerts (e.g., Microsoft.Compute/virtualMachines).
When do I need to specify targetResourceTypes?
Use targetResourceTypes when your scope is a resource group or subscription. This filters alerts to specific resource types within that scope. It’s not needed when monitoring a single resource directly.
Time Windows & Evaluation
What's the ISO 8601 duration format used for time settings?
Use PT prefix followed by time units: PT5M (5 minutes), PT10M (10 minutes), PT30M (30 minutes), PT1H (1 hour). This format is required for evaluationFrequency, windowSize, and muteActionsDuration.
What's the difference between evaluationFrequency and windowSize?
evaluationFrequency controls how often the query runs, while windowSize defines the time range of data each query analyzes. For example, PT5M evaluation with PT10M window checks the last 10 minutes of data every 5 minutes.
Alert Types & Thresholds
What's the difference between LogAlert and SimpleLogAlert?
LogAlert requires evaluationFrequency, windowSize, and severity, and supports thresholds, dimensions, and advanced features. SimpleLogAlert only requires a query in criteria and is simpler to configure for basic alerting.
How do I use dynamic thresholds instead of static thresholds?
Set criterionType to DynamicThresholdCriterion in your condition. Configure alertSensitivity (Low, Medium, or High) instead of a static threshold value. Use operator: GreaterOrLessThan for bidirectional anomaly detection.
What severity levels are available and what do they mean?
Severity is an integer between 0-4, where 0 is most severe. This property is required for LogAlert kind rules.
Filtering & Conditions
How do dimension filters work with Include and Exclude operators?
Dimensions filter query results by specific values. Use operator: Include to alert only on specified values, or operator: Exclude to alert on everything except specified values. Use wildcard * to include all values for a dimension.
How do failingPeriods control when alerts fire?
Configure minFailingPeriodsToAlert and numberOfEvaluationPeriods to control alert sensitivity. For example, setting both to 1 fires an alert immediately when the condition is met. Higher values require multiple consecutive failures before alerting.
Actions & Resolution
How do I mute actions after an alert fires?
Set muteActionsDuration to an ISO 8601 duration (e.g., PT30M for 30 minutes). Actions will be suppressed for this period after the alert fires, preventing notification fatigue.
Can alerts automatically resolve when conditions return to normal?
Yes, set autoMitigate to true (the default) for automatic resolution. Configure resolveConfiguration with autoResolved: true and timeToResolve to control when alerts auto-resolve.
Updates & Immutability
Can I change the location of a scheduled query rule after creation?
No, the location property is immutable. To change the location, you must delete and recreate the rule.

Using a different cloud?

Explore monitoring guides for other cloud providers: