Managing Alerting Policies by API

This page illustrates using the Stackdriver Monitoring API to create and manage alerting policies programmatically. It also illustrates the use of the Cloud SDK command-line interface for managing alerting policies.

Many of these tasks can also be performed by using the Stackdriver Monitoring console; see Using Alerting Policies for an introduction to creating and managing alerting policies with the Stackdriver Monitoring console.

Before you begin

Before writing code against the API, you should:

  • Have a Stackdriver account that monitors the projects for which you want to create alerting policies.
  • Be familiar with the general concepts and terminology used with alerting policies; see Introduction to Alerting for more information.
  • Ensure that the API is enabled for use; see Enabling the API for more information.
  • Install the client libraries for the languages you want to use; see Client Libraries for details. Currently, API support for alerting is available only for C#, Go, Java, Node.js, and Python.

  • Install Cloud SDK. This gives you the access to the gcloud command-line interface, from which you can also do these tasks. If you use Cloud Shell, you use that instead of installing Cloud SDK.

    Examples using the gcloud interface are also provided here. Note that the gcloud examples all assume that the current project has already been set as the target (gcloud config set project [PROJECT_ID]) so invocations omit the explicit --project flag. The ID of the current project in the examples is a-gcp-project.

About alerting policies

An alerting policy is represented by an AlertPolicy object, which describes a set of conditions indicating a potentially unhealthy status in your system. Alerting policies reference notification channels, which let you specify how you want to be informed that an alerting policy has been triggered.

Each alerting policy belongs to an individual Stackdriver Monitoring account, and each account can contain up to 500 policies. The account is indicated by its ID, which is called the “project ID” in reference material. In these examples, the ID of the Stackdriver Monitoring account is a-gcp-project.

The AlertPolicy resource supports five operations:

  • Creating new policies
  • Deleting existing policies
  • Retrieving specific policies
  • Retrieving all policies
  • Modifying existing policies

Alerting policies can be expressed in JSON or YAML, which lets you record policies in files, and use files to back up and restore policies. With Cloud SDK, you can create policies from files in either format. With the REST API, you can create policies from JSON files. See Sample policies for a selection of alerting policies in JSON format.

The following examples use the gcloud interface and the API to illustrate these basic use cases. The API samples are excerpted from a sample program that uses the API to implement a back-up and restore system for alerting policies. Fuller samples are shown in Example: backup and restore.

Creating policies

To create an alerting policy in a project, use the alertPolicies.create method.

You can create policies from JSON or YAML files. The gcloud command-line interface accepts these files as arguments, and you can programmatically read JSON files, convert them to AlertPolicy objects, and create policies from them by using the alertPolicies.create method.

The following examples illustrate the creation of alerting policies.

GCLOUD COMMAND

To create an alerting policy in a project, use the glcoud alpha monitoring policies create command. The following example creates an alerting policy in a-gcp-project from the rising-cpu-usage.json file:

gcloud alpha monitoring policies create --policy-from-file="rising-cpu-usage.json"

If successful, this command returns the name of the new policy, for example:

Created alert policy [projects/a-gcp-project/alertPolicies/12669073143329903307].

The file rising-cpu-usage.json file contains the JSON for a policy with the display name “High CPU rate of change”. This policy is described in A rate-of-change policy.

See the gcloud alpha monitoring policies create reference for more information.

C#

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

static void RestorePolicies(string projectId, string filePath)
{
    var policyClient = AlertPolicyServiceClient.Create();
    var channelClient = NotificationChannelServiceClient.Create();
    List<Exception> exceptions = new List<Exception>();
    var backup = JsonConvert.DeserializeObject<BackupRecord>(
        File.ReadAllText(filePath), new ProtoMessageConverter());
    var projectName = new ProjectName(projectId);
    bool isSameProject = projectId == backup.ProjectId;
    // When a channel is recreated, rather than updated, it will get
    // a new name.  We have to update the AlertPolicy with the new
    // name.  Track the names in this map.
    var channelNameMap = new Dictionary<string, string>();
    foreach (NotificationChannel channel in backup.Channels)
    {
    }
    foreach (AlertPolicy policy in backup.Policies)
    {
        string policyName = policy.Name;
        // These two fields cannot be set directly, so clear them.
        policy.CreationRecord = null;
        policy.MutationRecord = null;
        // Update channel names if the channel was recreated with
        // another name.
        for (int i = 0; i < policy.NotificationChannels.Count; ++i)
        {
            if (channelNameMap.ContainsKey(policy.NotificationChannels[i]))
            {
                policy.NotificationChannels[i] =
                    channelNameMap[policy.NotificationChannels[i]];
            }
        }
        try
        {
            Console.WriteLine("Updating policy.\n{0}",
                policy.DisplayName);
            bool updated = false;
            if (isSameProject)
                try
                {
                    policyClient.UpdateAlertPolicy(null, policy);
                    updated = true;
                }
                catch (Grpc.Core.RpcException e)
                when (e.Status.StatusCode == StatusCode.NotFound)
                { }
            if (!updated)
            {
                // The policy no longer exists.  Recreate it.
                policy.Name = null;
                foreach (var condition in policy.Conditions)
                {
                    condition.Name = null;
                }
                policyClient.CreateAlertPolicy(projectName, policy);
            }
            Console.WriteLine("Restored {0}.", policyName);
        }
        catch (Exception e)
        {
            // If one failed, continue trying to update the others.
            exceptions.Add(e);
        }
    }
    if (exceptions.Count > 0)
    {
        throw new AggregateException(exceptions);
    }
}

Go

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

// restorePolicies updates the project with the alert policies and
// notification channels in r.
func restorePolicies(w io.Writer, projectID string, r io.Reader) error {
	b := backup{}
	if err := json.NewDecoder(r).Decode(&b); err != nil {
		return err
	}
	sameProject := projectID == b.ProjectID

	ctx := context.Background()

	alertClient, err := monitoring.NewAlertPolicyClient(ctx)
	if err != nil {
		return err
	}
	channelClient, err := monitoring.NewNotificationChannelClient(ctx)
	if err != nil {
		return err
	}

	// When a channel is recreated, rather than updated, it will get
	// a new name.  We have to update the AlertPolicy with the new
	// name.  channelNames keeps track of the new names.
	channelNames := make(map[string]string)
	for _, c := range b.Channels {
		fmt.Fprintf(w, "Updating channel %q\n", c.GetDisplayName())
		c.VerificationStatus = monitoringpb.NotificationChannel_VERIFICATION_STATUS_UNSPECIFIED
		updated := false
		if sameProject {
			req := &monitoringpb.UpdateNotificationChannelRequest{
				NotificationChannel: c.NotificationChannel,
			}
			_, err := channelClient.UpdateNotificationChannel(ctx, req)
			if err == nil {
				updated = true
			}
		}
		if !updated {
			req := &monitoringpb.CreateNotificationChannelRequest{
				Name:                "projects/" + projectID,
				NotificationChannel: c.NotificationChannel,
			}
			oldName := c.GetName()
			c.Name = ""
			newC, err := channelClient.CreateNotificationChannel(ctx, req)
			if err != nil {
				return err
			}
			channelNames[oldName] = newC.GetName()
		}
	}

	for _, policy := range b.AlertPolicies {
		fmt.Fprintf(w, "Updating alert %q\n", policy.GetDisplayName())
		policy.CreationRecord = nil
		policy.MutationRecord = nil
		for i, aChannel := range policy.GetNotificationChannels() {
			if c, ok := channelNames[aChannel]; ok {
				policy.NotificationChannels[i] = c
			}
		}
		updated := false
		if sameProject {
			req := &monitoringpb.UpdateAlertPolicyRequest{
				AlertPolicy: policy.AlertPolicy,
			}
			_, err := alertClient.UpdateAlertPolicy(ctx, req)
			if err == nil {
				updated = true
			}
		}
		if !updated {
			req := &monitoringpb.CreateAlertPolicyRequest{
				Name:        "projects/" + projectID,
				AlertPolicy: policy.AlertPolicy,
			}
			if _, err = alertClient.CreateAlertPolicy(ctx, req); err != nil {
				log.Fatal(err)
			}
		}
	}
	fmt.Fprintf(w, "Successfully restored alerts.")
	return nil
}

Java

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

private void restoreRevisedPolicies(String projectId,
                                    boolean isSameProject,
                                    List<AlertPolicy> policies) {
  for (AlertPolicy policy : policies) {
    if (!isSameProject) {
      policy = alertPolicyClient.createAlertPolicy(ProjectName.of(projectId), policy);
    } else {
      try {
        alertPolicyClient.updateAlertPolicy(null, policy);
      } catch (Exception e) {
        policy = alertPolicyClient.createAlertPolicy(ProjectName.of(projectId),
            policy.toBuilder().clearName().build());
      }
    }
    outputStream.println(String.format("Restored %s", policy.getName()));
  }
}

Node.js

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

const fs = require('fs');

// Imports the Google Cloud client library
const monitoring = require('@google-cloud/monitoring');

// Creates a client
const client = new monitoring.AlertPolicyServiceClient();

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';

console.log('Loading policies from ./policies_backup.json');
const fileContent = fs.readFileSync('./policies_backup.json', 'utf-8');
const policies = JSON.parse(fileContent);

let promise = Promise.resolve();

policies.forEach(policy => {
  // Restore each policy one at a time
  promise = promise
    .then(() => doesAlertPolicyExist(policy.name))
    .then(exists => {
      if (exists) {
        return client.updateAlertPolicy({alertPolicy: policy});
      }

      // Clear away output-only fields
      delete policy.name;
      delete policy.creationRecord;
      delete policy.mutationRecord;
      policy.conditions.forEach(condition => delete condition.name);

      return client.createAlertPolicy({
        name: client.projectPath(projectId),
        alertPolicy: policy,
      });
    })
    .then(response => {
      const policy = response[0];
      console.log(`Restored ${policy.name}.`);
    });
});

promise.catch(err => {
  console.error('ERROR:', err);
});

function doesAlertPolicyExist(name) {
  return client
    .getAlertPolicy({name: name})
    .then(() => true)
    .catch(err => {
      if (err && err.code === 5) {
        // Error code 5 comes from the google.rpc.code.NOT_FOUND protobuf
        return false;
      }
      return Promise.reject(err);
    });
}

Python

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

def restore(project_name):
    print('Loading alert policies and notification channels from backup.json.')
    record = json.load(open('backup.json', 'rt'))
    is_same_project = project_name == record['project_name']
    # Convert dicts to AlertPolicies.
    policies_json = [json.dumps(policy) for policy in record['policies']]
    policies = [google.protobuf.json_format.Parse(
        policy_json, monitoring_v3.types.alert_pb2.AlertPolicy())
        for policy_json in policies_json]
    # Convert dicts to NotificationChannels
    channels_json = [json.dumps(channel) for channel in record['channels']]
    channels = [google.protobuf.json_format.Parse(
        channel_json, monitoring_v3.types.notification_pb2.
        NotificationChannel()) for channel_json in channels_json]

    # Restore the channels.
    channel_client = monitoring_v3.NotificationChannelServiceClient()
    channel_name_map = {}

    for channel in channels:
        updated = False
        print('Updating channel', channel.display_name)
        # This field is immutable and it is illegal to specify a
        # non-default value (UNVERIFIED or VERIFIED) in the
        # Create() or Update() operations.
        channel.verification_status = monitoring_v3.enums.NotificationChannel.\
            VerificationStatus.VERIFICATION_STATUS_UNSPECIFIED

        if is_same_project:
            try:
                channel_client.update_notification_channel(channel)
                updated = True
            except google.api_core.exceptions.NotFound:
                pass  # The channel was deleted.  Create it below.

        if not updated:
            # The channel no longer exists.  Recreate it.
            old_name = channel.name
            channel.ClearField("name")
            new_channel = channel_client.create_notification_channel(
                project_name, channel)
            channel_name_map[old_name] = new_channel.name

    # Restore the alerts
    alert_client = monitoring_v3.AlertPolicyServiceClient()

    for policy in policies:
        print('Updating policy', policy.display_name)
        # These two fields cannot be set directly, so clear them.
        policy.ClearField('creation_record')
        policy.ClearField('mutation_record')

        # Update old channel names with new channel names.
        for i, channel in enumerate(policy.notification_channels):
            new_channel = channel_name_map.get(channel)
            if new_channel:
                policy.notification_channels[i] = new_channel

        updated = False

        if is_same_project:
            try:
                alert_client.update_alert_policy(policy)
                updated = True
            except google.api_core.exceptions.NotFound:
                pass  # The policy was deleted.  Create it below.
            except google.api_core.exceptions.InvalidArgument:
                # Annoying that API throws InvalidArgument when the policy
                # does not exist.  Seems like it should throw NotFound.
                pass  # The policy was deleted.  Create it below.

        if not updated:
            # The policy no longer exists.  Recreate it.
            old_name = policy.name
            policy.ClearField("name")
            for condition in policy.conditions:
                condition.ClearField("name")
            policy = alert_client.create_alert_policy(project_name, policy)
        print('Updated', policy.name)

The created AlertPolicy object will have additional fields. The policy itself will have name, creationRecord, and mutationRecord fields. Additionally, each condition in the policy is also given a name. These fields cannot be modified externally, so there is no need to set them when creating a policy. None of the JSON examples used for creating policies include them, but if policies created from them are retrieved after creation, the fields will be present.

Retrieving policies

To retrieve a list of the policies in a project, use the alertPolicies.list method. Use this method to retrieve policies and apply some action to each of them, for example, backing them up. This method also supports filter and orderBy options to restrict and sort the results; see Sorting and Filtering.

If you are looking for a specific policy and you know its name, you can use the alertPolicies.get method to retrieve only that policy. The name of a policy is the value of the name field, not the displayName, in the AlertPolicy object. The name of a policy has the format projects/[PROJECT_ID]/alertPolicies/[POLICY_ID], for example:

projects/a-gcp-project/alertPolicies/12669073143329903307

GCLOUD COMMAND

To list all alerting policies in a project, use the gcloud alpha monitoring policies list command:

gcloud alpha monitoring policies list

If successful, the list command provides a listing of all the policies in the specified project, formatted as YAML. For example, the policy with the display name “High CPU rate of change” in the project a-gcp-project is listed like this, among the other policies listed:

---
combiner: OR
conditions:
- conditionThreshold:
    aggregations:
    - alignmentPeriod: 900s
      perSeriesAligner: ALIGN_PERCENT_CHANGE
    comparison: COMPARISON_GT
    duration: 180s
    filter: metric.type="compute.googleapis.com/instance/cpu/utilization" AND resource.type="gce_instance"
    thresholdValue: 0.5
    trigger:
      count: 1
  displayName: CPU usage is increasing at a high rate
  name: projects/a-gcp-project/alertPolicies/12669073143329903307/conditions/12669073143329903008
creationRecord:
  mutateTime: '2018-03-26T18:52:39.363601689Z'
  mutatedBy: [USER@DOMAIN]
displayName: High CPU rate of change
enabled: true
mutationRecord:
  mutateTime: '2018-03-26T18:52:39.363601689Z'
  mutatedBy: [USER@DOMAIN]
name: projects/a-gcp-project/alertPolicies/12669073143329903307
---

To list a single alerting policy, use gcloud alpha monitoring policies describe, instead, and specify the name of the policy. For example, this command returns only the listing above:

gcloud alpha monitoring policies describe projects/a-gcp-project/alertPolicies/12669073143329903307

See the gcloud alpha monitoring policies list and describe references for more information. The describe command corresponds to the alertPolicies.get method in the API.

C#

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

static void ListAlertPolicies(string projectId)
{
    var client = AlertPolicyServiceClient.Create();
    var response = client.ListAlertPolicies(new ProjectName(projectId));
    foreach (AlertPolicy policy in response)
    {
        Console.WriteLine(policy.Name);
        if (policy.DisplayName != null)
        {
            Console.WriteLine(policy.DisplayName);
        }
        if (policy.Documentation?.Content != null)
        {
            Console.WriteLine(policy.Documentation.Content);
        }
        Console.WriteLine();
    }
}

Go

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

// listAlertPolicies lists the alert policies in the project.
func listAlertPolicies(w io.Writer, projectID string) error {
	ctx := context.Background()
	client, err := monitoring.NewAlertPolicyClient(ctx)
	if err != nil {
		return err
	}

	req := &monitoringpb.ListAlertPoliciesRequest{
		Name: "projects/" + projectID,
		// Filter:  "", // See https://cloud.google.com/monitoring/api/v3/sorting-and-filtering.
		// OrderBy: "", // See https://cloud.google.com/monitoring/api/v3/sorting-and-filtering.
	}
	it := client.ListAlertPolicies(ctx, req)
	for {
		resp, err := it.Next()
		if err == iterator.Done {
			fmt.Fprintln(w, "Done")
			break
		}
		if err != nil {
			return err
		}
		fmt.Fprintf(w, "  Name: %q\n", resp.GetName())
		fmt.Fprintf(w, "  Display Name: %q\n", resp.GetDisplayName())
		fmt.Fprintf(w, "  Documentation Content: %q\n\n", resp.GetDocumentation().GetContent())
	}
	return nil
}

Java

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

void listAlertPolicies(String projectId) {
  ListAlertPoliciesPagedResponse response = alertPolicyClient.listAlertPolicies(ProjectName.of(
      projectId));

  for (AlertPolicy policy : response.iterateAll()) {
    outputStream.println(policy.getDisplayName());
    if (policy.hasDocumentation() && policy.getDocumentation().getContent() != null) {
      outputStream.println(policy.getDocumentation().getContent());
    }
  }
}

Node.js

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

// Imports the Google Cloud client library
const monitoring = require('@google-cloud/monitoring');

// Creates a client
const client = new monitoring.AlertPolicyServiceClient();

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';

const listAlertPoliciesRequest = {
  name: client.projectPath(projectId),
};

client
  .listAlertPolicies(listAlertPoliciesRequest)
  .then(results => {
    const policies = results[0];

    console.log('Policies:');
    policies.forEach(policy => {
      console.log(`  Display name: ${policy.displayName}`);
      if (policy.documentation && policy.documentation.content) {
        console.log(`     Documentation: ${policy.documentation.content}`);
      }
    });
  })
  .catch(err => {
    console.error('ERROR:', err);
  });

Python

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

def list_alert_policies(project_name):
    client = monitoring_v3.AlertPolicyServiceClient()
    policies = client.list_alert_policies(project_name)
    print(tabulate.tabulate(
        [(policy.name, policy.display_name) for policy in policies],
        ('name', 'display_name')))

Deleting policies

To delete a policy from a project, use the alertPolicies.delete method and supply the name of the alerting policy to delete.

GCLOUD COMMAND

To delete an alerting policy, use gcloud alpha monitoring policies delete, and specify the name of the policy to delete. For example, the following command deletes the “High CPU rate of change” policy:

gcloud alpha monitoring policies delete projects/a-gcp-project/alertPolicies/12669073143329903307

See the gcloud alpha monitoring policies delete reference for more information.

Modifying policies

To modify an alerting policy, use the alertPolicies.patch method (in the REST API). Other API implementations and the gcloud interface call this update instead of patch.

An update operation can wholly replace the existing policy, or it can modify a subset of fields. An update operation takes a new AlertPolicy object and an optional field mask.

If a field mask is specified, then any field listed in the field mask is updated with the value in the supplied policy. If the supplied policy does not include a field mentioned in the field mask, then that field is cleared and set to its default value. Any field not listed in the mask retains its previous value.

If no field mask is specified, then the existing policy is replaced by the supplied one, but the name (projects/[PROJECT_ID]/alertPolicies/[POLICY_ID]) is reused. Any conditions in the new policy that have name values that include a CONDITION_ID will keep those names. If not, new condition and policy names are created.

When using the gcloud command-line to update policies, command-line flags rather than a field mask are used to specify fields to update. See the gcloud alpha monitoring policies update for details.

Enabling or disabling a policy

To enable or disable a policy, change the value of the boolean enabled field in the AlertPolicy object. Note that after you enable a policy, it can still be triggered by data collected while it was disabled.

GCLOUD COMMAND

To disable an alerting policy, use the gcloud alpha monitoring policies update command and provide the --no-enabled flag. The following command disables the “High CPU rate of change” alerting policy in the project a-gcp-project:

gcloud alpha monitoring policies update projects/a-gcp-project/alertPolicies/12669073143329903307 --no-enabled

To enable the policy, use the same command and provide the --enabled flag. See the gcloud alpha monitoring policies update reference for more information. The update command corresponds to the alertPolicies.patch method in the REST API.

C#

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

static object EnablePolicies(string projectId, string filter, bool enable)
{
    var client = AlertPolicyServiceClient.Create();
    var request = new ListAlertPoliciesRequest()
    {
        ProjectName = new ProjectName(projectId),
        Filter = filter
    };
    var response = client.ListAlertPolicies(request);
    int result = 0;
    foreach (AlertPolicy policy in response)
    {
        try
        {
            if (policy.Enabled == enable)
            {
                Console.WriteLine("Policy {0} is already {1}.",
                    policy.Name, enable ? "enabled" : "disabled");
                continue;
            }
            policy.Enabled = enable;
            var fieldMask = new FieldMask { Paths = { "enabled" } };
            client.UpdateAlertPolicy(fieldMask, policy);
            Console.WriteLine("{0} {1}.", enable ? "Enabled" : "Disabled",
                policy.Name);
        }
        catch (Grpc.Core.RpcException e)
        when (e.Status.StatusCode == StatusCode.InvalidArgument)
        {
            Console.WriteLine(e.Message);
            result -= 1;
        }
    }
    // Return a negative count of how many enable operations failed.
    return result;
}

Go

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

// enablePolicies enables or disables all alert policies in the project.
func enablePolicies(w io.Writer, projectID string, enable bool) error {
	ctx := context.Background()

	client, err := monitoring.NewAlertPolicyClient(ctx)
	if err != nil {
		return err
	}

	req := &monitoringpb.ListAlertPoliciesRequest{
		Name: "projects/" + projectID,
		// Filter:  "", // See https://cloud.google.com/monitoring/api/v3/sorting-and-filtering.
		// OrderBy: "", // See https://cloud.google.com/monitoring/api/v3/sorting-and-filtering.
	}
	it := client.ListAlertPolicies(ctx, req)
	for {
		a, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return err
		}
		if a.GetEnabled().GetValue() == enable {
			fmt.Fprintf(w, "Policy %q already has enabled=%v", a.GetDisplayName(), enable)
			continue
		}
		a.Enabled = &wrappers.BoolValue{Value: enable}
		req := &monitoringpb.UpdateAlertPolicyRequest{
			AlertPolicy: a,
			UpdateMask: &fieldmask.FieldMask{
				Paths: []string{"enabled"},
			},
		}
		if _, err := client.UpdateAlertPolicy(ctx, req); err != nil {
			return err
		}
	}
	fmt.Fprintln(w, "Successfully updated alerts.")
	return nil
}

Java

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

void enablePolicies(String projectId,
                    String filter,
                    boolean enable) {
  ListAlertPoliciesPagedResponse response = alertPolicyClient
      .listAlertPolicies(ListAlertPoliciesRequest.newBuilder()
          .setName(projectId)
          .setFilter(filter)
          .build());

  for (AlertPolicy policy : response.iterateAll()) {
    if (policy.getEnabled().getValue() == enable) {
      outputStream.println(String.format("Policy %s is already %b.", policy.getName(), enable));
      continue;
    }
    AlertPolicy updatedPolicy = AlertPolicy
        .newBuilder()
        .setName(AlertPolicyName.of(projectId, policy.getName()).toString())
        .setEnabled(BoolValue.newBuilder().setValue(enable))
        .build();
    AlertPolicy result = alertPolicyClient.updateAlertPolicy(
        FieldMask.newBuilder().addPaths("enabled").build(), updatedPolicy);
    outputStream.println(String.format(
        "%s %s", result.getName(), result.getEnabled().getValue() ? "Enabled" : "Disabled"));
  }

}

Node.js

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

// Imports the Google Cloud client library
const monitoring = require('@google-cloud/monitoring');

// Creates a client
const client = new monitoring.AlertPolicyServiceClient();

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const enabled = true;
// const filter = 'A filter for selecting policies, e.g. description:"cloud"';

const listAlertPoliciesRequest = {
  name: client.projectPath(projectId),
  // See https://cloud.google.com/monitoring/alerting/docs/sorting-and-filtering
  filter: filter,
};

client
  .listAlertPolicies(listAlertPoliciesRequest)
  .then(results => {
    const policies = results[0];

    const tasks = policies
      .map(policy => {
        return {
          updateMask: {paths: ['disabled']},
          alertPolicy: {
            name: policy.name,
            disabled: enabled ? false : true,
          },
        };
      })
      .map(updateAlertPolicyRequest =>
        client.updateAlertPolicy(updateAlertPolicyRequest)
      );

    // Wait for all policies to be enabled
    return Promise.all(tasks);
  })
  .then(responses => {
    responses.forEach(response => {
      const alertPolicy = response[0];
      console.log(`${enabled ? 'Enabled' : 'Disabled'} ${alertPolicy.name}.`);
    });
  })
  .catch(err => {
    console.error('ERROR:', err);
  });

Python

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

def enable_alert_policies(project_name, enable, filter_=None):
    """Enable or disable alert policies in a project.

    Arguments:
        project_name (str)
        enable (bool): Enable or disable the policies.
        filter_ (str, optional): Only enable/disable alert policies that match
            this filter_.  See
            https://cloud.google.com/monitoring/api/v3/sorting-and-filtering
    """

    client = monitoring_v3.AlertPolicyServiceClient()
    policies = client.list_alert_policies(project_name, filter_=filter_)

    for policy in policies:
        if bool(enable) == policy.enabled.value:
            print('Policy', policy.name, 'is already',
                  'enabled' if policy.enabled.value else 'disabled')
        else:
            policy.enabled.value = bool(enable)
            mask = monitoring_v3.types.field_mask_pb2.FieldMask()
            mask.paths.append('enabled')
            client.update_alert_policy(policy, mask)
            print('Enabled' if enable else 'Disabled', policy.name)

Updating notification channels in a policy

You can also update the notification channels referenced by an alerting policy. Alerting policies refer to notification channels by name. The channels must exist before they can be used in an alerting policy.

You create and manage notification channels programmatically by using the NotificationChannel and NotificationChannelDescriptors resources. These examples in this section assume these channels already exist, and uses of these APIs also appear in the programmatic samples.

For more discussion of the notification-channel objects, see Managing Channels by API.

GCLOUD COMMAND

To modify the notification channels in an alerting policy, use the gcloud alpha monitoring policies update command. There are several flags related to notification channels, letting you remove notification channels, replace notification channels, and add new notification channels.

For example, the policy with the display name “High CPU rate of change” in the project a-gcp-project was created with no notification channels.

To add a notification channel to this policy, use the gcloud alpha monitoring policies update command, and specify the channel to add with the --add-notification-channels flag:

gcloud alpha monitoring policies update projects/a-gcp-project/alertPolicies/12669073143329903307 \
--add-notification-channels="projects/a-gcp-project/notificationChannels/1355376463305411567"

See the gcloud alpha monitoring policies update reference for more information. The update command corresponds to the alertPolicies.patch method in the REST API.

The notification channel added here must already exist; see Creating channels for more information.

C#

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

static void ReplaceChannels(string projectId, string alertPolicyId,
    IEnumerable<string> channelIds)
{
    var alertClient = AlertPolicyServiceClient.Create();
    var policy = new AlertPolicy()
    {
        Name = new AlertPolicyName(projectId, alertPolicyId).ToString()
    };
    foreach (string channelId in channelIds)
    {
        policy.NotificationChannels.Add(
            new NotificationChannelName(projectId, channelId)
            .ToString());
    }
    var response = alertClient.UpdateAlertPolicy(
        new FieldMask { Paths = { "notification_channels" } }, policy);
    Console.WriteLine("Updated {0}.", response.Name);
}

Go

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

// replaceChannels replaces the notification channels in the alert policy
// with channelIDs.
func replaceChannels(w io.Writer, projectID, alertPolicyID string, channelIDs []string) error {
	ctx := context.Background()

	client, err := monitoring.NewAlertPolicyClient(ctx)
	if err != nil {
		return err
	}

	policy := &monitoringpb.AlertPolicy{
		Name: "projects/" + projectID + "/alertPolicies/" + alertPolicyID,
	}
	for _, c := range channelIDs {
		c = "projects/" + projectID + "/notificationChannels/" + c
		policy.NotificationChannels = append(policy.NotificationChannels, c)
	}
	req := &monitoringpb.UpdateAlertPolicyRequest{
		AlertPolicy: policy,
		UpdateMask: &fieldmask.FieldMask{
			Paths: []string{"notification_channels"},
		},
	}
	if _, err := client.UpdateAlertPolicy(ctx, req); err != nil {
		return fmt.Errorf("UpdateAlertPolicy: %v", err)
	}
	fmt.Fprintf(w, "Successfully replaced channels.")
	return nil
}

Java

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

void replaceChannels(String projectId, String alertPolicyId, String[] channelIds) {
  AlertPolicy.Builder policyBuilder = AlertPolicy
      .newBuilder()
      .setName(AlertPolicyName.of(projectId, alertPolicyId).toString());
  for (String channelId : channelIds) {
    policyBuilder.addNotificationChannels(
        NotificationChannelName.of(projectId, channelId).toString());
  }
  AlertPolicy result = alertPolicyClient.updateAlertPolicy(
      FieldMask.newBuilder().addPaths("notification_channels").build(), policyBuilder.build());
  outputStream.println(String.format("Updated %s", result.getName()));
}

Node.js

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

// Imports the Google Cloud client library
const monitoring = require('@google-cloud/monitoring');

// Creates clients
const alertClient = new monitoring.AlertPolicyServiceClient();
const notificationClient = new monitoring.NotificationChannelServiceClient();

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const alertPolicyId = '123456789012314';
// const channelIds = [
//   'channel-1',
//   'channel-2',
//   'channel-3',
// ];

const notificationChannels = channelIds.map(id =>
  notificationClient.notificationChannelPath(projectId, id)
);

const updateAlertPolicyRequest = {
  updateMask: {paths: ['notification_channels']},
  alertPolicy: {
    name: alertClient.alertPolicyPath(projectId, alertPolicyId),
    notificationChannels: notificationChannels,
  },
};

alertClient
  .updateAlertPolicy(updateAlertPolicyRequest)
  .then(results => {
    const alertPolicy = results[0];
    console.log(`Updated ${alertPolicy.name}.`);
  })
  .catch(err => {
    console.error('ERROR:', err);
  });

Python

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

def replace_notification_channels(project_name, alert_policy_id, channel_ids):
    _, project_id = project_name.split('/')
    alert_client = monitoring_v3.AlertPolicyServiceClient()
    channel_client = monitoring_v3.NotificationChannelServiceClient()
    policy = monitoring_v3.types.alert_pb2.AlertPolicy()
    policy.name = alert_client.alert_policy_path(project_id, alert_policy_id)

    for channel_id in channel_ids:
        policy.notification_channels.append(
            channel_client.notification_channel_path(project_id, channel_id))

    mask = monitoring_v3.types.field_mask_pb2.FieldMask()
    mask.paths.append('notification_channels')
    updated_policy = alert_client.update_alert_policy(policy, mask)
    print('Updated', updated_policy.name)

Modifying documentation in a policy

A policy can include documentation that is included with incidents and notifications associated with the policy. Use this field to include information to help responders understand and handle the problem indicated by the alert policy. Documentation is included in email notifications and notification types that allow for it; other channel types may omit it.

GCLOUD COMMAND

To add documentation to a policy, or replace existing documentation, use the gcloud alpha monitoring policies update command and provide the --documentation-format="text/markdown" flag (the only supported format) and either the --documentation flag (to enter the value from the command line) or the --documentation-from-file flag (to read the value from a file).

For example, the policy with the display name “High CPU rate of change” in the project a-gcp-project was created with no documentation.

The following command sets the documentation field in the specified policy to the contents of the cpu-usage-doc.md file:

gcloud alpha monitoring policies update projects/a-gcp-project/alertPolicies/12669073143329903307 \
--documentation-format="text/markdown" \
--documentation-from-file="cpu-usage-doc.md"

See the gcloud alpha monitoring policies update reference for more information. The update command corresponds to the alertPolicies.patch method in the REST API.

Example: backup and restore

All of the API examples shown are pulled from a larger application that can back up the alerting policies in a project to a file and can restore the policies, possibly to another project. If the projects used for backup and restore are different, the application effectively exports and imports policies from one project to another.

This section shows the code for backup and restore in context rather than as a set of small, isolated excerpts.

Backing up policies

The back-up operation is straight-forward. The set of alerting policies and the set of notification channels in each project is collected and saved to external storage in JSON.

C#

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

        static void BackupPolicies(string projectId, string filePath)
        {
            var policyClient = AlertPolicyServiceClient.Create();
            var channelClient = NotificationChannelServiceClient.Create();
            var projectName = new ProjectName(projectId);
            File.WriteAllText(filePath, JsonConvert.SerializeObject(
                new BackupRecord()
                {
                    ProjectId = projectId,
                    Policies = policyClient.ListAlertPolicies(projectName),
                    Channels = channelClient.ListNotificationChannels(projectName)
                }, new ProtoMessageConverter()));
        }
        class BackupRecord
        {
            public string ProjectId { get; set; }
            public IEnumerable<AlertPolicy> Policies { get; set; }
            public IEnumerable<NotificationChannel> Channels { get; set; }
        }

        /// <summary>
        /// Lets Newtonsoft.Json and Protobuf's json converters play nicely
        /// together.  The default Netwtonsoft.Json Deserialize method will
        /// not correctly deserialize proto messages.
        /// </summary>
        class ProtoMessageConverter : JsonConverter
        {
            public override bool CanConvert(System.Type objectType)
            {
                return typeof(Google.Protobuf.IMessage)
                    .IsAssignableFrom(objectType);
            }

            public override object ReadJson(JsonReader reader,
                System.Type objectType, object existingValue,
                JsonSerializer serializer)
            {
                // Read an entire object from the reader.
                var converter = new ExpandoObjectConverter();
                object o = converter.ReadJson(reader, objectType, existingValue,
                    serializer);
                // Convert it back to json text.
                string text = JsonConvert.SerializeObject(o);
                // And let protobuf's parser parse the text.
                IMessage message = (IMessage)Activator
                    .CreateInstance(objectType);
                return Google.Protobuf.JsonParser.Default.Parse(text,
                    message.Descriptor);
            }

            public override void WriteJson(JsonWriter writer, object value,
                JsonSerializer serializer)
            {
                writer.WriteRawValue(Google.Protobuf.JsonFormatter.Default
                    .Format((IMessage)value));
            }
        }

Go

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

// backupPolicies writes a JSON representation of the project's alert
// policies and notification channels.
func backupPolicies(w io.Writer, projectID string) error {
	b := backup{ProjectID: projectID}
	ctx := context.Background()

	alertClient, err := monitoring.NewAlertPolicyClient(ctx)
	if err != nil {
		return err
	}
	alertReq := &monitoringpb.ListAlertPoliciesRequest{
		Name: "projects/" + projectID,
		// Filter:  "", // See https://cloud.google.com/monitoring/api/v3/sorting-and-filtering.
		// OrderBy: "", // See https://cloud.google.com/monitoring/api/v3/sorting-and-filtering.
	}
	alertIt := alertClient.ListAlertPolicies(ctx, alertReq)
	for {
		resp, err := alertIt.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return err
		}
		b.AlertPolicies = append(b.AlertPolicies, &alertPolicy{resp})
	}

	channelClient, err := monitoring.NewNotificationChannelClient(ctx)
	if err != nil {
		return err
	}
	channelReq := &monitoringpb.ListNotificationChannelsRequest{
		Name: "projects/" + projectID,
		// Filter:  "", // See https://cloud.google.com/monitoring/api/v3/sorting-and-filtering.
		// OrderBy: "", // See https://cloud.google.com/monitoring/api/v3/sorting-and-filtering.
	}
	channelIt := channelClient.ListNotificationChannels(ctx, channelReq)
	for {
		resp, err := channelIt.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return err
		}
		b.Channels = append(b.Channels, &channel{resp})
	}
	bs, err := json.MarshalIndent(b, "", "  ")
	if err != nil {
		return err
	}
	if _, err := w.Write(bs); err != nil {
		return err
	}
	return nil
}

// alertPolicy is a wrapper around the AlertPolicy proto to
// ensure JSON marshaling/unmarshaling works correctly.
type alertPolicy struct {
	*monitoringpb.AlertPolicy
}

// channel is a wrapper around the NotificationChannel proto to
// ensure JSON marshaling/unmarshaling works correctly.
type channel struct {
	*monitoringpb.NotificationChannel
}

// backup is used to backup and restore a project's policies.
type backup struct {
	ProjectID     string
	AlertPolicies []*alertPolicy
	Channels      []*channel
}

func (a *alertPolicy) MarshalJSON() ([]byte, error) {
	m := &jsonpb.Marshaler{EmitDefaults: true}
	b := new(bytes.Buffer)
	m.Marshal(b, a.AlertPolicy)
	return b.Bytes(), nil
}

func (a *alertPolicy) UnmarshalJSON(b []byte) error {
	u := &jsonpb.Unmarshaler{}
	a.AlertPolicy = new(monitoringpb.AlertPolicy)
	return u.Unmarshal(bytes.NewReader(b), a.AlertPolicy)
}

func (c *channel) MarshalJSON() ([]byte, error) {
	m := &jsonpb.Marshaler{}
	b := new(bytes.Buffer)
	m.Marshal(b, c.NotificationChannel)
	return b.Bytes(), nil
}

func (c *channel) UnmarshalJSON(b []byte) error {
	u := &jsonpb.Unmarshaler{}
	c.NotificationChannel = new(monitoringpb.NotificationChannel)
	return u.Unmarshal(bytes.NewReader(b), c.NotificationChannel)
}

Java

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

void backupPolicies(String projectId, String filePath) throws IOException {
  List<AlertPolicy> alertPolicies = getAlertPolicies(projectId);
  List<NotificationChannel> notificationChannels = getNotificationChannels(projectId);
  writePoliciesBackupFile(projectId, filePath, alertPolicies, notificationChannels);
  outputStream.println(String.format("Saved policies to %s", filePath));
}

private List<AlertPolicy> getAlertPolicies(String projectId) {
  List<AlertPolicy> alertPolicies = Lists.newArrayList();
  ListAlertPoliciesPagedResponse response =
      alertPolicyClient.listAlertPolicies(ProjectName.of(projectId));

  for (AlertPolicy policy : response.iterateAll()) {
    alertPolicies.add(policy);
  }
  return alertPolicies;
}

private List<NotificationChannel> getNotificationChannels(String projectId) {
  List<NotificationChannel> notificationChannels = Lists.newArrayList();
  ListNotificationChannelsPagedResponse listNotificationChannelsResponse =
      notificationChannelClient.listNotificationChannels(ProjectName.of(projectId));
  for (NotificationChannel channel : listNotificationChannelsResponse.iterateAll()) {
    notificationChannels.add(channel);
  }
  return notificationChannels;
}

private void writePoliciesBackupFile(String projectId,
                                     String filePath,
                                     List<AlertPolicy> alertPolicies,
                                     List<NotificationChannel> notificationChannels)
    throws IOException {
  JsonObject backupContents = new JsonObject();
  backupContents.add("project_id", new JsonPrimitive(projectId));
  JsonArray policiesJson = new JsonArray();
  for (AlertPolicy policy : alertPolicies) {
    policiesJson.add(gson.toJsonTree(policy));
  }
  backupContents.add("policies", policiesJson);

  JsonArray notificationsJson = new JsonArray();
  for (NotificationChannel channel : notificationChannels) {
    notificationsJson.add(gson.toJsonTree(channel));
  }
  backupContents.add("notification_channels", notificationsJson);

  FileWriter writer = new FileWriter(filePath);
  writer.write(backupContents.toString());
  writer.close();
}

Node.js

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

const fs = require('fs');

// Imports the Google Cloud client library
const monitoring = require('@google-cloud/monitoring');

// Creates a client
const client = new monitoring.AlertPolicyServiceClient();

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';

const listAlertPoliciesRequest = {
  name: client.projectPath(projectId),
};

client
  .listAlertPolicies(listAlertPoliciesRequest)
  .then(results => {
    const policies = results[0];

    fs.writeFileSync(
      './policies_backup.json',
      JSON.stringify(policies, null, 2),
      'utf-8'
    );

    console.log('Saved policies to ./policies_backup.json');
  })
  .catch(err => {
    console.error('ERROR:', err);
  });

Python

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

def backup(project_name):
    alert_client = monitoring_v3.AlertPolicyServiceClient()
    channel_client = monitoring_v3.NotificationChannelServiceClient()
    record = {'project_name': project_name,
              'policies': list(alert_client.list_alert_policies(project_name)),
              'channels': list(channel_client.list_notification_channels(
                  project_name))}
    json.dump(record, open('backup.json', 'wt'), cls=ProtoEncoder, indent=2)
    print('Backed up alert policies and notification channels to backup.json.')


class ProtoEncoder(json.JSONEncoder):
    """Uses google.protobuf.json_format to encode protobufs as json."""
    def default(self, obj):
        if type(obj) in (monitoring_v3.types.alert_pb2.AlertPolicy,
                         monitoring_v3.types.notification_pb2.
                         NotificationChannel):
            text = google.protobuf.json_format.MessageToJson(obj)
            return json.loads(text)
        return super(ProtoEncoder, self).default(obj)

Restoring the backed-up policies

The restoration process is more complex than the original back-up. You can restore to the project you originally backed up. You can also restore to a different project, effectively providing import of alerting policies.

If restoring to the same project, any existing channels or policies are updated if they still exist. If they do not, they are recreated. Read-only fields from the backed-up policies, which are managed by the server automatically, are cleared before policies and notifications are recreated.

Alerting policies have creation and mutation records that are managed internally. These are cleared before policies are restored. Additionally, if the policy is being recreated in a new project, the names of any conditions in the backed-up policies are cleared.

Additionally, when a notification channel is recreated in a different project, it gets a different name, so the restore process has to map the names of channels in backed-up alerting policies to their new names, and replace the old names with the new ones.

In addition to the names of notification channels, the value of the verificationStatus field cannot be set when the channel is created or updated, so a special value, unspecified is used. After channels have been restored into a new project, they must be explicitly verified.

C#

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

        static void RestorePolicies(string projectId, string filePath)
        {
            var policyClient = AlertPolicyServiceClient.Create();
            var channelClient = NotificationChannelServiceClient.Create();
            List<Exception> exceptions = new List<Exception>();
            var backup = JsonConvert.DeserializeObject<BackupRecord>(
                File.ReadAllText(filePath), new ProtoMessageConverter());
            var projectName = new ProjectName(projectId);
            bool isSameProject = projectId == backup.ProjectId;
            // When a channel is recreated, rather than updated, it will get
            // a new name.  We have to update the AlertPolicy with the new
            // name.  Track the names in this map.
            var channelNameMap = new Dictionary<string, string>();
            foreach (NotificationChannel channel in backup.Channels)
            {
                try
                {
                    bool updated = false;
                    Console.WriteLine("Updating channel.\n{0}",
                        channel.DisplayName);
                    // This field is immutable and it is illegal to specify a
                    // non-default value (UNVERIFIED or VERIFIED) in the
                    // Create() or Update() operations.
                    channel.VerificationStatus = NotificationChannel.Types
                        .VerificationStatus.Unspecified;
                    if (isSameProject)
                        try
                        {
                            channelClient.UpdateNotificationChannel(
                                null, channel);
                            updated = true;
                        }
                        catch (Grpc.Core.RpcException e)
                        when (e.Status.StatusCode == StatusCode.NotFound)
                        { }
                    if (!updated)
                    {
                        // The channel no longer exists.  Recreate it.
                        string oldName = channel.Name;
                        channel.Name = null;
                        var response = channelClient.CreateNotificationChannel(
                            projectName, channel);
                        channelNameMap.Add(oldName, response.Name);
                    }
                }
                catch (Exception e)
                {
                    // If one failed, continue trying to update the others.
                    exceptions.Add(e);
                }
            }
            foreach (AlertPolicy policy in backup.Policies)
            {
                string policyName = policy.Name;
                // These two fields cannot be set directly, so clear them.
                policy.CreationRecord = null;
                policy.MutationRecord = null;
                // Update channel names if the channel was recreated with
                // another name.
                for (int i = 0; i < policy.NotificationChannels.Count; ++i)
                {
                    if (channelNameMap.ContainsKey(policy.NotificationChannels[i]))
                    {
                        policy.NotificationChannels[i] =
                            channelNameMap[policy.NotificationChannels[i]];
                    }
                }
                try
                {
                    Console.WriteLine("Updating policy.\n{0}",
                        policy.DisplayName);
                    bool updated = false;
                    if (isSameProject)
                        try
                        {
                            policyClient.UpdateAlertPolicy(null, policy);
                            updated = true;
                        }
                        catch (Grpc.Core.RpcException e)
                        when (e.Status.StatusCode == StatusCode.NotFound)
                        { }
                    if (!updated)
                    {
                        // The policy no longer exists.  Recreate it.
                        policy.Name = null;
                        foreach (var condition in policy.Conditions)
                        {
                            condition.Name = null;
                        }
                        policyClient.CreateAlertPolicy(projectName, policy);
                    }
                    Console.WriteLine("Restored {0}.", policyName);
                }
                catch (Exception e)
                {
                    // If one failed, continue trying to update the others.
                    exceptions.Add(e);
                }
            }
            if (exceptions.Count > 0)
            {
                throw new AggregateException(exceptions);
            }
        }

        class BackupRecord
        {
            public string ProjectId { get; set; }
            public IEnumerable<AlertPolicy> Policies { get; set; }
            public IEnumerable<NotificationChannel> Channels { get; set; }
        }

        /// <summary>
        /// Lets Newtonsoft.Json and Protobuf's json converters play nicely
        /// together.  The default Netwtonsoft.Json Deserialize method will
        /// not correctly deserialize proto messages.
        /// </summary>
        class ProtoMessageConverter : JsonConverter
        {
            public override bool CanConvert(System.Type objectType)
            {
                return typeof(Google.Protobuf.IMessage)
                    .IsAssignableFrom(objectType);
            }

            public override object ReadJson(JsonReader reader,
                System.Type objectType, object existingValue,
                JsonSerializer serializer)
            {
                // Read an entire object from the reader.
                var converter = new ExpandoObjectConverter();
                object o = converter.ReadJson(reader, objectType, existingValue,
                    serializer);
                // Convert it back to json text.
                string text = JsonConvert.SerializeObject(o);
                // And let protobuf's parser parse the text.
                IMessage message = (IMessage)Activator
                    .CreateInstance(objectType);
                return Google.Protobuf.JsonParser.Default.Parse(text,
                    message.Descriptor);
            }

            public override void WriteJson(JsonWriter writer, object value,
                JsonSerializer serializer)
            {
                writer.WriteRawValue(Google.Protobuf.JsonFormatter.Default
                    .Format((IMessage)value));
            }
        }

Go

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

// restorePolicies updates the project with the alert policies and
// notification channels in r.
func restorePolicies(w io.Writer, projectID string, r io.Reader) error {
	b := backup{}
	if err := json.NewDecoder(r).Decode(&b); err != nil {
		return err
	}
	sameProject := projectID == b.ProjectID

	ctx := context.Background()

	alertClient, err := monitoring.NewAlertPolicyClient(ctx)
	if err != nil {
		return err
	}
	channelClient, err := monitoring.NewNotificationChannelClient(ctx)
	if err != nil {
		return err
	}

	// When a channel is recreated, rather than updated, it will get
	// a new name.  We have to update the AlertPolicy with the new
	// name.  channelNames keeps track of the new names.
	channelNames := make(map[string]string)
	for _, c := range b.Channels {
		fmt.Fprintf(w, "Updating channel %q\n", c.GetDisplayName())
		c.VerificationStatus = monitoringpb.NotificationChannel_VERIFICATION_STATUS_UNSPECIFIED
		updated := false
		if sameProject {
			req := &monitoringpb.UpdateNotificationChannelRequest{
				NotificationChannel: c.NotificationChannel,
			}
			_, err := channelClient.UpdateNotificationChannel(ctx, req)
			if err == nil {
				updated = true
			}
		}
		if !updated {
			req := &monitoringpb.CreateNotificationChannelRequest{
				Name:                "projects/" + projectID,
				NotificationChannel: c.NotificationChannel,
			}
			oldName := c.GetName()
			c.Name = ""
			newC, err := channelClient.CreateNotificationChannel(ctx, req)
			if err != nil {
				return err
			}
			channelNames[oldName] = newC.GetName()
		}
	}

	for _, policy := range b.AlertPolicies {
		fmt.Fprintf(w, "Updating alert %q\n", policy.GetDisplayName())
		policy.CreationRecord = nil
		policy.MutationRecord = nil
		for i, aChannel := range policy.GetNotificationChannels() {
			if c, ok := channelNames[aChannel]; ok {
				policy.NotificationChannels[i] = c
			}
		}
		updated := false
		if sameProject {
			req := &monitoringpb.UpdateAlertPolicyRequest{
				AlertPolicy: policy.AlertPolicy,
			}
			_, err := alertClient.UpdateAlertPolicy(ctx, req)
			if err == nil {
				updated = true
			}
		}
		if !updated {
			req := &monitoringpb.CreateAlertPolicyRequest{
				Name:        "projects/" + projectID,
				AlertPolicy: policy.AlertPolicy,
			}
			if _, err = alertClient.CreateAlertPolicy(ctx, req); err != nil {
				log.Fatal(err)
			}
		}
	}
	fmt.Fprintf(w, "Successfully restored alerts.")
	return nil
}

Java

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

void restorePolicies(String projectId, String filePath) throws IOException {
  FileReader reader = new FileReader(filePath);
  BufferedReader bufferedReader = new BufferedReader(reader);

  JsonObject backupContent = getPolicyJsonContents(filePath, bufferedReader, gson);
  String backupProjectId = backupContent.get("project_id").getAsString();
  boolean isSameProject = projectId.equals(backupProjectId);

  AlertPolicy[] policies = gson.fromJson(backupContent.get("policies"), AlertPolicy[].class);
  List<NotificationChannel> notificationChannels = readNotificationChannelsJson(backupContent);
  Map<String, String> restoredChannelIds = restoreNotificationChannels(projectId,
      notificationChannels,
      isSameProject);
  List<AlertPolicy> policiesToRestore = reviseRestoredPolicies(policies,
      isSameProject,
      restoredChannelIds);

  restoreRevisedPolicies(projectId, isSameProject, policiesToRestore);
}

private List<AlertPolicy> reviseRestoredPolicies(AlertPolicy[] policies,
                                                 boolean isSameProject,
                                                 Map<String, String> restoredChannelIds) {
  List<AlertPolicy> newPolicies = Lists.newArrayListWithCapacity(policies.length);
  for (AlertPolicy policy : policies) {
    AlertPolicy.Builder policyBuilder = policy
        .toBuilder()
        .clearNotificationChannels()
        .clearMutationRecord()
        .clearCreationRecord();
    // Update restored notification channel names.
    for (String channelName : policy.getNotificationChannelsList()) {
      String newChannelName = restoredChannelIds.get(channelName);
      if (!Strings.isNullOrEmpty(newChannelName)) {
        policyBuilder.addNotificationChannels(newChannelName);
      }
    }
    if (!isSameProject) {
      policyBuilder.clearName();
      policyBuilder.clearConditions();
      for (AlertPolicy.Condition condition : policy.getConditionsList()) {
        policyBuilder.addConditions(condition.toBuilder().clearName());
      }
    }
    newPolicies.add(policyBuilder.build());
  }
  return newPolicies;
}

private void restoreRevisedPolicies(String projectId,
                                    boolean isSameProject,
                                    List<AlertPolicy> policies) {
  for (AlertPolicy policy : policies) {
    if (!isSameProject) {
      policy = alertPolicyClient.createAlertPolicy(ProjectName.of(projectId), policy);
    } else {
      try {
        alertPolicyClient.updateAlertPolicy(null, policy);
      } catch (Exception e) {
        policy = alertPolicyClient.createAlertPolicy(ProjectName.of(projectId),
            policy.toBuilder().clearName().build());
      }
    }
    outputStream.println(String.format("Restored %s", policy.getName()));
  }
}

private List<NotificationChannel> readNotificationChannelsJson(JsonObject backupContent) {
  if (backupContent.has("notification_channels")) {
    NotificationChannel[] channels = gson.fromJson(backupContent.get("notification_channels"),
        NotificationChannel[].class);
    return Lists.newArrayList(channels);
  }
  return Lists.newArrayList();
}

private Map<String, String> restoreNotificationChannels(String projectId,
                                                        List<NotificationChannel> channels,
                                                        boolean isSameProject) {
  Map<String, String> newChannelNames = Maps.newHashMap();
  for (NotificationChannel channel : channels) {
    // Update channel name if project ID is different.
    boolean channelUpdated = false;
    if (isSameProject) {
      try {
        NotificationChannel updatedChannel = notificationChannelClient.updateNotificationChannel(
            NOTIFICATION_CHANNEL_UPDATE_MASK,
            channel);
        newChannelNames.put(channel.getName(), updatedChannel.getName());
        channelUpdated = true;
      } catch (Exception e) {
        channelUpdated = false;
      }
    }
    if (!channelUpdated) {
      NotificationChannel newChannel = notificationChannelClient.createNotificationChannel(
          ProjectName.of(projectId),
          channel
              .toBuilder()
              .clearName()
              .clearVerificationStatus()
              .build());
      newChannelNames.put(channel.getName(), newChannel.getName());
    }
  }
  return newChannelNames;
}

private JsonObject getPolicyJsonContents(String filePath, BufferedReader content, Gson gson) {
  try {
    return gson.fromJson(content, JsonObject.class);
  } catch (JsonSyntaxException jse) {
    throw new RuntimeException(String.format("Could not parse policies file %s", filePath), jse);
  }
}

Node.js

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

const fs = require('fs');

// Imports the Google Cloud client library
const monitoring = require('@google-cloud/monitoring');

// Creates a client
const client = new monitoring.AlertPolicyServiceClient();

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';

console.log('Loading policies from ./policies_backup.json');
const fileContent = fs.readFileSync('./policies_backup.json', 'utf-8');
const policies = JSON.parse(fileContent);

let promise = Promise.resolve();

policies.forEach(policy => {
  // Restore each policy one at a time
  promise = promise
    .then(() => doesAlertPolicyExist(policy.name))
    .then(exists => {
      if (exists) {
        return client.updateAlertPolicy({alertPolicy: policy});
      }

      // Clear away output-only fields
      delete policy.name;
      delete policy.creationRecord;
      delete policy.mutationRecord;
      policy.conditions.forEach(condition => delete condition.name);

      return client.createAlertPolicy({
        name: client.projectPath(projectId),
        alertPolicy: policy,
      });
    })
    .then(response => {
      const policy = response[0];
      console.log(`Restored ${policy.name}.`);
    });
});

promise.catch(err => {
  console.error('ERROR:', err);
});

function doesAlertPolicyExist(name) {
  return client
    .getAlertPolicy({name: name})
    .then(() => true)
    .catch(err => {
      if (err && err.code === 5) {
        // Error code 5 comes from the google.rpc.code.NOT_FOUND protobuf
        return false;
      }
      return Promise.reject(err);
    });
}

Python

For more on installing and creating a Stackdriver Monitoring client, refer to Stackdriver Monitoring Client Libraries.

def restore(project_name):
    print('Loading alert policies and notification channels from backup.json.')
    record = json.load(open('backup.json', 'rt'))
    is_same_project = project_name == record['project_name']
    # Convert dicts to AlertPolicies.
    policies_json = [json.dumps(policy) for policy in record['policies']]
    policies = [google.protobuf.json_format.Parse(
        policy_json, monitoring_v3.types.alert_pb2.AlertPolicy())
        for policy_json in policies_json]
    # Convert dicts to NotificationChannels
    channels_json = [json.dumps(channel) for channel in record['channels']]
    channels = [google.protobuf.json_format.Parse(
        channel_json, monitoring_v3.types.notification_pb2.
        NotificationChannel()) for channel_json in channels_json]

    # Restore the channels.
    channel_client = monitoring_v3.NotificationChannelServiceClient()
    channel_name_map = {}

    for channel in channels:
        updated = False
        print('Updating channel', channel.display_name)
        # This field is immutable and it is illegal to specify a
        # non-default value (UNVERIFIED or VERIFIED) in the
        # Create() or Update() operations.
        channel.verification_status = monitoring_v3.enums.NotificationChannel.\
            VerificationStatus.VERIFICATION_STATUS_UNSPECIFIED

        if is_same_project:
            try:
                channel_client.update_notification_channel(channel)
                updated = True
            except google.api_core.exceptions.NotFound:
                pass  # The channel was deleted.  Create it below.

        if not updated:
            # The channel no longer exists.  Recreate it.
            old_name = channel.name
            channel.ClearField("name")
            new_channel = channel_client.create_notification_channel(
                project_name, channel)
            channel_name_map[old_name] = new_channel.name

    # Restore the alerts
    alert_client = monitoring_v3.AlertPolicyServiceClient()

    for policy in policies:
        print('Updating policy', policy.display_name)
        # These two fields cannot be set directly, so clear them.
        policy.ClearField('creation_record')
        policy.ClearField('mutation_record')

        # Update old channel names with new channel names.
        for i, channel in enumerate(policy.notification_channels):
            new_channel = channel_name_map.get(channel)
            if new_channel:
                policy.notification_channels[i] = new_channel

        updated = False

        if is_same_project:
            try:
                alert_client.update_alert_policy(policy)
                updated = True
            except google.api_core.exceptions.NotFound:
                pass  # The policy was deleted.  Create it below.
            except google.api_core.exceptions.InvalidArgument:
                # Annoying that API throws InvalidArgument when the policy
                # does not exist.  Seems like it should throw NotFound.
                pass  # The policy was deleted.  Create it below.

        if not updated:
            # The policy no longer exists.  Recreate it.
            old_name = policy.name
            policy.ClearField("name")
            for condition in policy.conditions:
                condition.ClearField("name")
            policy = alert_client.create_alert_policy(project_name, policy)
        print('Updated', policy.name)

Alerting and Cloud SDK

In Cloud SDK, the command group for managing alerting policies and notification channels is monitoring, which is in alpha release. The monitoring group is available in the alpha component. That is, these commands will all begin with:

gcloud alpha monitoring

To check if you have the alpha component installed, run this command:

gcloud components list

If you do not have the alpha component installed, run this command to install it:

gcloud components install alpha

If you do have the alpha component, check for the monitoring group by running this command:

gcloud alpha monitoring --help

If the monitoring group is not included, Cloud SDK will prompt you to add it:

You do not currently have this command group installed.
[...]
Do you want to continue (Y/n)?  y

Send feedback about...

Stackdriver Monitoring