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: threshold-based alerting on single resources, resource group and subscription-level scoping, and simple log alerts with dynamic threshold detection.

Scheduled query rules reference Azure resources and Action Groups that must exist separately. The examples are intentionally small. Combine them with your own monitoring infrastructure and notification targets.

Monitor a single VM with threshold-based alerting

Most monitoring deployments track metrics from individual resources against static thresholds, providing baseline visibility into performance limits.

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 query property defines the KQL (Kusto Query Language) expression that extracts metrics from logs. The threshold and operator properties set the numeric boundary and comparison logic. The timeAggregation property controls how values are aggregated within the windowSize period. The dimensions array filters results by specific column values, allowing you to exclude certain IPs or include all OS types. The evaluationFrequency determines how often the query runs, while windowSize defines the time range for each evaluation. When the condition breaches, the rule notifies the Action Groups listed in actionGroups.

Monitor all VMs in a resource group

When managing fleets of similar resources, teams scope alerts to resource groups rather than individual resources, allowing a single rule to monitor all matching 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 a specific VM. The targetResourceTypes property filters which resource types within that group trigger alerts. Here, only Microsoft.Compute/virtualMachines are monitored. The query runs against all matching VMs, and the rule fires when the heartbeat count exceeds the threshold across any of them.

Create a simple log alert without thresholds

Some alerts fire whenever a query returns any results, without comparing against numeric thresholds.

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 checking threshold breaches, the rule fires whenever the query returns results. The autoMitigate property controls whether alerts automatically resolve when the condition clears. Simple log alerts omit evaluationFrequency, windowSize, threshold, and operator since they evaluate query presence rather than metric values.

Use dynamic thresholds for anomaly detection

Static thresholds generate false positives when workload patterns vary. Dynamic thresholds learn normal behavior and alert on deviations.

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 property set to DynamicThresholdCriterion enables machine learning-based baselines. The alertSensitivity property controls how aggressively the algorithm detects anomalies (Low, Medium, High). The operator GreaterOrLessThan alerts on deviations in either direction. The ignoreDataBefore property sets a cutoff date, excluding older data from baseline calculations. Dynamic thresholds require sufficient historical data to establish patterns.

Beyond these examples

These snippets focus on specific scheduled query rule features: threshold and dynamic anomaly-based evaluation, resource group and subscription-level scoping, and simple log alerts and KQL query execution. They’re intentionally minimal rather than full monitoring solutions.

The examples may reference pre-existing infrastructure such as Azure VMs, resource groups, or subscriptions to monitor, and Action Groups for alert notifications. They focus on configuring the query rule rather than provisioning everything around it.

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

  • Alert resolution configuration (resolveConfiguration)
  • Action muting and suppression (muteActionsDuration)
  • Custom properties and ICM integration (actionProperties)
  • Query validation controls (skipQueryValidation)

These omissions are intentional: the goal is to illustrate how each 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

Alert Types & Configuration
What's the difference between LogAlert and SimpleLogAlert?
LogAlert supports full configuration including evaluationFrequency, windowSize, and severity. SimpleLogAlert is a simplified version requiring only a query and actions, with minimal configuration options.
What properties are required for LogAlert rules?
LogAlert rules require criteria, scopes, enabled, location, evaluationFrequency, windowSize, and severity. SimpleLogAlert rules only require criteria, scopes, enabled, and location.
How do severity levels work?
Severity is an integer between 0 and 4, where 0 is the most severe. This property is required for LogAlert rules but not applicable to SimpleLogAlert.
Query Evaluation & Timing
What format do I use for time-based properties like evaluationFrequency and windowSize?
Use ISO 8601 duration format: PT5M for 5 minutes, PT10M for 10 minutes, PT30M for 30 minutes. This applies to evaluationFrequency, windowSize, muteActionsDuration, and overrideQueryTimeRange.
What are failingPeriods and how do they work?
failingPeriods controls alert triggering by specifying minFailingPeriodsToAlert (how many periods must fail) and numberOfEvaluationPeriods (total periods to evaluate). For example, setting both to 1 triggers an alert immediately on the first failure.
Scoping & Filtering
How do I monitor multiple resources in a resource group or subscription?
Set scopes to the resource group or subscription ID, then specify targetResourceTypes (e.g., Microsoft.Compute/virtualMachines). Azure creates a separate alert for each matching resource that meets the criteria.
How do dimension filters work?
Dimensions filter query results using Include or Exclude operators. Use * as a wildcard to include all values. For example, you can exclude specific IPs while including all OS types.
What properties can't be changed after creation?
The location, resourceGroupName, and ruleName properties are immutable and cannot be modified after the resource is created.
Alert Resolution & Actions
How do I configure automatic alert resolution?
Use autoMitigate (defaults to true) for basic auto-resolution, or configure resolveConfiguration with autoResolved and timeToResolve for more control. Both are relevant for LogAlert and SimpleLogAlert kinds.
How do I temporarily mute actions after an alert fires?
Set muteActionsDuration to an ISO 8601 duration (e.g., PT30M for 30 minutes). Actions are suppressed for this period after the alert triggers, relevant only for LogAlert rules.
Advanced Features
How do I create a dynamic threshold alert instead of a static threshold?
Set criterionType to DynamicThresholdCriterion, specify alertSensitivity (Low, Medium, or High), and use operator set to GreaterOrLessThan. Optionally use ignoreDataBefore to exclude historical data.
When should I use skipQueryValidation?
Set skipQueryValidation to true to bypass query validation during rule creation. The default is false. This is relevant only for LogAlert rules and should be used cautiously.

Using a different cloud?

Explore monitoring guides for other cloud providers: