Gérer des règles d'alertes à l'aide d'API

Cette page explique comment utiliser l'API Cloud Monitoring pour créer, modifier et gérer des règles d'alerte de manière automatisée. En outre, elle aborde l'utilisation de l'interface de ligne de commande du SDK Cloud pour la gestion des règles d'alerte.

La plupart de ces tâches peuvent également être effectuées à l'aide de la console Cloud Monitoring. Consultez la section Utiliser des règles d'alerte pour une introduction à la création et à la gestion de règles d'alerte depuis la console Cloud Monitoring.

Avant de commencer

Avant d'écrire du code sur l'API, vous devez :

  • Vous devez disposer d'un espace de travail qui surveille les projets pour lesquels vous souhaitez créer des règles d'alerte. Pour en savoir plus, consultez la section Créer un espace de travail.
  • Vous devez connaître la terminologie et les concepts généraux utilisés avec les règles d'alerte. Pour en savoir plus, consultez la page Présentation des alertes.
  • Vous devez vérifier que l'API est activée. Pour en savoir plus, consultez la page relative à l'activation de l'API.
  • Les bibliothèques clientes pour les langages que vous souhaitez utiliser doivent être installées. Pour en savoir plus, consultez la page relative aux bibliothèques clientes. Actuellement, la fonctionnalité d'alerte de l'API n'est compatible qu'avec les langages C#, Go, Java, Node.js et Python.

  • Le SDK Cloud doit être installé. Il vous donne accès à l'interface de ligne de commande gcloud, à partir de laquelle vous pouvez également réaliser ces tâches. Si vous disposez de Cloud Shell, utilisez-le au lieu d'installer le SDK Cloud.

    Des exemples utilisant l'interface gcloud sont également fournis sur cette page. Notez que, dans tous ces exemples gcloud, nous partons du principe que le projet en cours a déjà été défini comme cible (gcloud config set project [PROJECT_ID]). Ainsi, les appels omettent l'option explicite --project. L'ID du projet en cours dans les exemples est a-gcp-project.

  • Vérifiez que vous disposez des autorisations appropriées pour le projet Google Cloud. Pour en savoir plus, consultez la section Autorisations.

À propos des règles d'alerte

Une règle d'alerte est représentée par un objet AlertPolicy, qui décrit un ensemble de conditions indiquant un état potentiellement non opérationnel dans votre système. Les règles d'alerte peuvent référencer des canaux de notification, ce qui vous permet d'indiquer comment vous souhaitez être informé lorsqu'une règle d'alerte est déclenchée.

Chaque règle d'alerte appartient à un espace de travail individuel. Chaque espace de travail peut contenir jusqu'à 500 règles. L'espace de travail est indiqué par son ID, dénommé "ID du projet" dans la documentation de référence. Dans les exemples figurant sur cette page, l'ID de l'espace de travail est a-gcp-project.

La ressource AlertPolicy prend en charge cinq opérations :

  • Créer de nouvelles règles
  • Supprimer des règles existantes
  • Récupérer des règles spécifiques
  • Récupérer toutes les règles
  • Modifier les règles existantes

Les règles d'alertes peuvent être au format JSON ou YAML, ce qui vous permet d'enregistrer des règles dans des fichiers, et d'utiliser ces fichiers pour les sauvegarder et les restaurer. Avec le SDK Cloud, vous pouvez créer des règles à partir de fichiers des deux formats. Avec l'API REST, vous ne pouvez créer des règles qu'à partir de fichiers JSON. Consultez la section Exemples de règles pour une sélection de règles d'alerte au format JSON.

Les exemples suivants utilisent l'interface gcloud et l'API pour illustrer ces cas d'utilisation de base. Ces exemples supposent l'existence d'un programme qui utilise l'API pour implémenter un système de sauvegarde et de restauration pour les règles d'alerte. Des exemples plus complets sont présentés dans la section Exemples : Sauvegarder et restaurer.

Créer des règles

Pour créer une règle d'alerte dans un projet, utilisez la méthode alertPolicies.create.

Vous pouvez créer des règles à partir de fichiers JSON ou YAML. L'interface de ligne de commande gcloud accepte ces fichiers comme arguments. Avec la méthode alertPolicies.create, vous pouvez ainsi lire les fichiers JSON de manière automatisée, les convertir en objets AlertPolicy et créer des règles.

Les exemples suivants illustrent la création de règles d'alerte.

Commande gcloud

Pour créer une règle d'alerte dans un projet, exécutez la commande gcloud alpha monitoring policies create. L'exemple suivant crée une règle d'alerte dans a-gcp-project à partir du fichier rising-cpu-usage.json :

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

Si la commande réussit, elle renvoie le nom de la nouvelle règle, par exemple :

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

Le fichier rising-cpu-usage.json contient le code JSON d'une règle dont le nom à afficher est "High CPU rate of change" ("Haute variation de l'utilisation du processeur"). Cette règle est décrite dans la section Règle de taux d'évolution.

Pour plus d'informations, consultez la documentation de référence sur gcloud alpha monitoring policies create.

C#

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


// 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

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

Node.js

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);

for (const index in policies) {
  // Restore each policy one at a time
  let policy = policies[index];
  if (await doesAlertPolicyExist(policy.name)) {
    policy = await client.updateAlertPolicy({
      alertPolicy: policy,
    });
  } else {
    // Clear away output-only fields
    delete policy.name;
    delete policy.creationRecord;
    delete policy.mutationRecord;
    policy.conditions.forEach(condition => delete condition.name);

    policy = await client.createAlertPolicy({
      name: client.projectPath(projectId),
      alertPolicy: policy,
    });
  }

  console.log(`Restored ${policy[0].name}.`);
}
async function doesAlertPolicyExist(name) {
  try {
    const [policy] = await client.getAlertPolicy({
      name,
    });
    return policy ? true : false;
  } catch (err) {
    if (err && err.code === 5) {
      // Error code 5 comes from the google.rpc.code.NOT_FOUND protobuf
      return false;
    }
    throw err;
  }
}

PHP

use Google\Cloud\Monitoring\V3\AlertPolicyServiceClient;
use Google\Cloud\Monitoring\V3\AlertPolicy;
use Google\Cloud\Monitoring\V3\ComparisonType;
use Google\Cloud\Monitoring\V3\AlertPolicy\Condition;
use Google\Cloud\Monitoring\V3\AlertPolicy\Condition\MetricThreshold;
use Google\Cloud\Monitoring\V3\AlertPolicy\ConditionCombinerType;
use Google\Protobuf\Duration;

/**
 * @param string $projectId Your project ID
 */
function alert_create_policy($projectId)
{
    $alertClient = new AlertPolicyServiceClient([
        'projectId' => $projectId,
    ]);
    $projectName = $alertClient->projectName($projectId);

    $policy = new AlertPolicy();
    $policy->setDisplayName('Test Alert Policy');
    $policy->setCombiner(ConditionCombinerType::PBOR);
    /** @see https://cloud.google.com/monitoring/api/resources for a list of resource.type */
    /** @see https://cloud.google.com/monitoring/api/metrics_gcp for a list of metric.type */
    $policy->setConditions([new Condition([
        'display_name' => 'condition-1',
        'condition_threshold' => new MetricThreshold([
            'filter' => 'resource.type = "gce_instance" AND metric.type = "compute.googleapis.com/instance/cpu/utilization"',
            'duration' => new Duration(['seconds' => '60']),
            'comparison' => ComparisonType::COMPARISON_LT,
        ])
    ])]);

    $policy = $alertClient->createAlertPolicy($projectName, $policy);
    printf('Created alert policy %s' . PHP_EOL, $policy->getName());
}

Python

def restore(project_name, backup_filename):
    print('Loading alert policies and notification channels from {}.'.format(
        backup_filename)
    )
    record = json.load(open(backup_filename, '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)

L'objet AlertPolicy créé contiendra des champs supplémentaires. La règle en elle-même contiendra les champs name, creationRecord et mutationRecord. En outre, un champ name est également attribué à chaque condition de la règle. Ces champs ne peuvent pas être modifiés de manière externe, il n'est donc pas nécessaire de les définir lors de la création d'une règle. Aucun des exemples JSON de cette page ne les inclut, mais si les règles créées à partir de ces exemples sont récupérées après leur création, ces champs seront présents.

Récupérer des règles

Pour récupérer la liste des règles d'un projet, utilisez la méthode alertPolicies.list. Utilisez cette méthode pour répertorier vos règles et appliquer une action à chacune d'entre elles, les sauvegarder par exemple. Cette méthode est également compatible avec les options filter et orderBy, qui permettent de restreindre et de trier les résultats. Pour en savoir plus, consultez la page Trier et filtrer.

Si vous recherchez une règle spécifique dont vous connaissez le nom, récupérez-la à l'aide de la méthode alertPolicies.get. Le nom d'une règle correspond à la valeur du champ name de l'objet AlertPolicy, et non pas du champ displayName. Le nom d'une règle est au format projects/[PROJECT_ID]/alertPolicies/[POLICY_ID], par exemple :

projects/a-gcp-project/alertPolicies/12669073143329903307

Commande gcloud

Pour répertorier toutes les règles d'alerte d'un projet, exécutez la commande gcloud alpha monitoring policies list :

gcloud alpha monitoring policies list

Si la commande list aboutit, elle fournit la liste au format YAML de toutes les règles du projet spécifié. Par exemple, la règle "High CPU rate of change" ("Haute variation de l'utilisation du processeur") du projet a-gcp-project est répertoriée comme suit, parmi toutes les autres règles répertoriées :

---
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
---

Pour répertorier une seule règle d'alerte, utilisez plutôt gcloud alpha monitoring policies describe et spécifiez son nom. Par exemple, la commande suivante ne renvoie que la liste mentionnée ci-dessus :

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

Pour plus d'informations, consultez la documentation de référence sur gcloud alpha monitoring policies list et describe. La commande describe correspond à la méthode alertPolicies.get dans l'API.

C#

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


// 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

private static void listAlertPolicies(String projectId) throws IOException {
  try (AlertPolicyServiceClient client = AlertPolicyServiceClient.create()) {
    ListAlertPoliciesPagedResponse response = client.listAlertPolicies(ProjectName.of(projectId));

    System.out.println("Alert Policies:");
    for (AlertPolicy policy : response.iterateAll()) {
      System.out.println(
          String.format("\nPolicy %s\nalert-id: %s", policy.getDisplayName(), policy.getName()));
      int channels = policy.getNotificationChannelsCount();
      if (channels > 0) {
        System.out.println("notification-channels:");
        for (int i = 0; i < channels; i++) {
          System.out.println("\t" + policy.getNotificationChannels(i));
        }
      }
      if (policy.hasDocumentation() && policy.getDocumentation().getContent() != null) {
        System.out.println(policy.getDocumentation().getContent());
      }
    }
  }
}

Node.js

// 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),
};
const [policies] = await client.listAlertPolicies(listAlertPoliciesRequest);
console.log('Policies:');
policies.forEach(policy => {
  console.log(`  Display name: ${policy.displayName}`);
  if (policy.documentation && policy.documentation.content) {
    console.log(`     Documentation: ${policy.documentation.content}`);
  }
});

PHP

use Google\Cloud\Monitoring\V3\AlertPolicyServiceClient;

/**
 * Adds a new column to the Albums table in the example database.
 * Example:
 * ```
 * alert_list_policies($projectId);
 * ```
 *
 * @param string $projectId Your project ID
 */
function alert_list_policies($projectId)
{
    $alertClient = new AlertPolicyServiceClient([
        'projectId' => $projectId,
    ]);

    $policies = $alertClient->listAlertPolicies(
        $alertClient->projectName($projectId)
    );
    foreach ($policies->iterateAllElements() as $policy) {
        printf('Name: %s (%s)' . PHP_EOL, $policy->getDisplayName(), $policy->getName());
    }
}

Python

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')))

Supprimer des règles

Pour supprimer une règle d'un projet, utilisez la méthode alertPolicies.delete et indiquez le nom de la règle d'alerte à supprimer.

Commande gcloud

Pour supprimer une règle d'alerte, utilisez gcloud alpha monitoring policies delete et spécifiez son nom. Par exemple, la commande suivante supprime la règle "High CPU rate of change" ("Haute variation de l'utilisation du processeur") :

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

Pour plus d'informations, consultez la documentation de référence sur gcloud alpha monitoring policies delete.

Modifier des règles

Pour modifier une règle d'alerte, utilisez la méthode alertPolicies.patch (dans l'API REST). D'autres mises en œuvre d'API et l'interface gcloud appellent update plutôt que patch.

Une opération de mise à jour peut remplacer entièrement la règle existante ou modifier un sous-ensemble de champs. Une opération de mise à jour nécessite un nouvel objet AlertPolicy et, de manière facultative, un masque de champ.

Si un masque de champ est spécifié, tous les champs répertoriés qu'il comporte sont mis à jour avec les valeurs de la règle fournie. Si la règle n'inclut pas un champ mentionné par le masque de champ, ce champ reprend sa valeur par défaut. Tout champ non spécifié dans le masque de champ conserve sa valeur précédente.

Si aucun masque de champ n'est spécifié, la règle existante est remplacée par celle fournie, mais son nom (projects/[PROJECT_ID]/alertPolicies/[POLICY_ID]) est réutilisé. Toutes les conditions de la nouvelle règle dont la valeur name comprend une valeur pour CONDITION_ID conserveront les mêmes noms. Sinon, de nouveaux noms de condition et de règles sont créés.

Lorsque vous mettez à jour des règles avec la ligne de commande gcloud, des options de ligne de commande sont utilisées pour spécifier les champs à mettre à jour, plutôt qu'un masque de champ. Pour en savoir plus, consultez la page sur gcloud alpha monitoring policies update.

Activer ou désactiver une règle

Pour activer ou désactiver une règle, modifiez la valeur du champ booléen enabled de l'objet AlertPolicy. Notez qu'après avoir activé une règle, celle-ci peut toujours être déclenchée par les données collectées tandis qu'elle était désactivée.

Commande gcloud

Pour désactiver une règle d'alerte, exécutez la commande gcloud alpha monitoring policies update et spécifiez l'option --no-enabled. La commande suivante désactive la règle d'alerte "High CPU rate of change" ("Haute variation de l'utilisation du processeur") dans le projet a-gcp-project :

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

Pour activer la règle, exécutez la même commande et spécifiez l'option --enabled. Pour plus d'informations, consultez la documentation de référence sur gcloud alpha monitoring policies update. La commande update correspond à la méthode alertPolicies.patch dans l'API REST.

C#

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


// 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

private static void enablePolicies(String projectId, String filter, boolean enable)
    throws IOException {
  try (AlertPolicyServiceClient client = AlertPolicyServiceClient.create()) {
    ListAlertPoliciesPagedResponse response =
        client.listAlertPolicies(
            ListAlertPoliciesRequest.newBuilder()
                .setName(ProjectName.of(projectId).toString())
                .setFilter(filter)
                .build());

    for (AlertPolicy policy : response.iterateAll()) {
      if (policy.getEnabled().getValue() == enable) {
        System.out.println(
            String.format(
                "Policy %s is already %b.", policy.getName(), enable ? "enabled" : "disabled"));
        continue;
      }
      AlertPolicy updatedPolicy =
          AlertPolicy.newBuilder()
              .setName(policy.getName())
              .setEnabled(BoolValue.newBuilder().setValue(enable))
              .build();
      AlertPolicy result =
          client.updateAlertPolicy(
              FieldMask.newBuilder().addPaths("enabled").build(), updatedPolicy);
      System.out.println(
          String.format(
              "%s %s",
              result.getDisplayName(), result.getEnabled().getValue() ? "enabled" : "disabled"));
    }
  }
}

Node.js

// 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,
};

const [policies] = await client.listAlertPolicies(listAlertPoliciesRequest);
const tasks = await Promise.all(
  policies
    .map(policy => {
      return {
        updateMask: {
          paths: ['enabled'],
        },
        alertPolicy: {
          name: policy.name,
          enabled: {
            value: enabled,
          },
        },
      };
    })
    .map(updateAlertPolicyRequest =>
      client.updateAlertPolicy(updateAlertPolicyRequest)
    )
);
tasks.forEach(response => {
  const alertPolicy = response[0];
  console.log(`${enabled ? 'Enabled' : 'Disabled'} ${alertPolicy.name}.`);
});

PHP

use Google\Cloud\Monitoring\V3\AlertPolicyServiceClient;
use Google\Protobuf\FieldMask;

/**
 * Enable or disable alert policies in a project.
 *
 * @param string $projectId Your project ID
 * @param bool $enable Enable or disable the policies.
 * @param string $filter Only enable/disable alert policies that match a filter.
 *        See https://cloud.google.com/monitoring/api/v3/sorting-and-filtering
 */
function alert_enable_policies($projectId, $enable = true, $filter = null)
{
    $alertClient = new AlertPolicyServiceClient([
        'projectId' => $projectId,
    ]);
    $projectName = $alertClient->projectName($projectId);

    $policies = $alertClient->listAlertPolicies($projectName, [
        'filter' => $filter
    ]);
    foreach ($policies->iterateAllElements() as $policy) {
        $isEnabled = $policy->getEnabled()->getValue();
        if ($enable == $isEnabled) {
            printf('Policy %s is already %s' . PHP_EOL,
                $policy->getName(),
                $isEnabled ? 'enabled' : 'disabled'
            );
        } else {
            $policy->getEnabled()->setValue((bool) $enable);
            $mask = new FieldMask();
            $mask->setPaths(['enabled']);
            $alertClient->updateAlertPolicy($policy, [
                'updateMask' => $mask
            ]);
            printf('%s %s' . PHP_EOL,
                $enable ? 'Enabled' : 'Disabled',
                $policy->getName()
            );
        }
    }
}

Python

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)

Mettre à jour les canaux de notification d'une règle

Vous pouvez également mettre à jour les canaux de notification référencés par une règle d'alerte. Les règles d'alerte emploient des canaux de notification en les désignant par leur nom. Les canaux doivent donc exister avant de pouvoir être utilisés dans une règle d'alerte.

Créez et gérez de manière automatisée des canaux de notification à l'aide des ressources NotificationChannel et NotificationChannelDescriptors. Dans cette section, nous partons du principe que ces canaux existent déjà. Vous y trouverez également des exemples d'utilisations de ces API.

Pour plus d'informations sur les objets canaux de notification, reportez-vous à Gérer des canaux à l'aide d'API.

Commande gcloud

Pour modifier les canaux de notification d'une règle d'alerte, exécutez la commande gcloud alpha monitoring policies update. Plusieurs indicateurs sont associés aux canaux de notification, vous permettant de supprimer, de remplacer ou d'ajouter des canaux de notification.

Par exemple, la règle dénommée "High CPU rate of change" ("Haute variation de l'utilisation du processeur") dans le projet a-gcp-project a été créée sans canal de notification.

Pour ajouter un canal de notification à cette règle, exécutez la commande gcloud alpha monitoring policies update et spécifiez le canal à ajouter avec l'option --add-notification-channels :

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

Pour plus d'informations, consultez la documentation de référence sur gcloud alpha monitoring policies update. La commande update correspond à la méthode alertPolicies.patch dans l'API REST.

Le canal de notification ajouté dans cet exemple doit déjà exister. Reportez-vous à la section Créer des canaux pour plus d'informations.

C#

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


// 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

private static void replaceChannels(String projectId, String alertPolicyId, String[] channelIds)
    throws IOException {
  AlertPolicy.Builder policyBuilder =
      AlertPolicy.newBuilder().setName(AlertPolicyName.of(projectId, alertPolicyId).toString());
  for (String channelId : channelIds) {
    policyBuilder.addNotificationChannels(
        NotificationChannelName.of(projectId, channelId).toString());
  }
  try (AlertPolicyServiceClient client = AlertPolicyServiceClient.create()) {
    AlertPolicy result =
        client.updateAlertPolicy(
            FieldMask.newBuilder().addPaths("notification_channels").build(),
            policyBuilder.build());
    System.out.println(String.format("Updated %s", result.getName()));
  }
}

Node.js


// 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.projectNotificationChannelPath(projectId, id)
);

for (const channel of notificationChannels) {
  const updateChannelRequest = {
    updateMask: {
      paths: ['enabled'],
    },
    notificationChannel: {
      name: channel,
      enabled: {
        value: true,
      },
    },
  };
  try {
    await notificationClient.updateNotificationChannel(updateChannelRequest);
  } catch (err) {
    const createChannelRequest = {
      notificationChannel: {
        name: channel,
        notificationChannel: {
          type: 'email',
        },
      },
    };
    const newChannel = await notificationClient.createNotificationChannel(
      createChannelRequest
    );
    notificationChannels.push(newChannel);
  }
}

const updateAlertPolicyRequest = {
  updateMask: {
    paths: ['notification_channels'],
  },
  alertPolicy: {
    name: alertClient.projectAlertPolicyPath(projectId, alertPolicyId),
    notificationChannels: notificationChannels,
  },
};
const [alertPolicy] = await alertClient.updateAlertPolicy(
  updateAlertPolicyRequest
);
console.log(`Updated ${alertPolicy.name}.`);

PHP

use Google\Cloud\Monitoring\V3\AlertPolicyServiceClient;
use Google\Cloud\Monitoring\V3\NotificationChannelServiceClient;
use Google\Cloud\Monitoring\V3\AlertPolicy;
use Google\Protobuf\FieldMask;

/**
 * @param string $projectId Your project ID
 * @param string $alertPolicyId Your alert policy id ID
 * @param array $channelIds array of channel IDs
 */
function alert_replace_channels($projectId, $alertPolicyId, array $channelIds)
{
    $alertClient = new AlertPolicyServiceClient([
        'projectId' => $projectId,
    ]);

    $channelClient = new NotificationChannelServiceClient([
        'projectId' => $projectId,
    ]);
    $policy = new AlertPolicy();
    $policy->setName($alertClient->alertPolicyName($projectId, $alertPolicyId));

    $newChannels = [];
    foreach ($channelIds as $channelId) {
        $newChannels[] = $channelClient->notificationChannelName($projectId, $channelId);
    }
    $policy->setNotificationChannels($newChannels);
    $mask = new FieldMask();
    $mask->setPaths(['notification_channels']);
    $updatedPolicy = $alertClient->updateAlertPolicy($policy, [
        'updateMask' => $mask,
    ]);
    printf('Updated %s' . PHP_EOL, $updatedPolicy->getName());
}

Python

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)

Modifier la documentation d'une règle

Une règle peut fournir de la documentation lors des incidents et des notifications qui lui sont associés. Utilisez ce champ pour inclure des informations permettant aux personnes recevant la notification de comprendre et de gérer au mieux le problème indiqué par la règle d'alerte. La documentation est incluse dans les notifications par e-mail et les autres types de notification, le cas échéant. Certains types de canaux peuvent ne pas l'inclure.

Commande gcloud

Pour ajouter de la documentation à une règle ou remplacer la documentation existante, exécutez la commande gcloud alpha monitoring policies update. Spécifiez l'option --documentation-format="text/markdown" (seul format compatible), et l'option --documentation (pour spécifier sa valeur depuis la ligne de commande) ou l'option --documentation-from-file (pour lire la valeur depuis un fichier).

Par exemple, la règle dénommée "High CPU rate of change" ("Haute variation de l'utilisation du processeur") dans le projet a-gcp-project a été créée sans documentation.

La commande suivante définit le champ documentation de la règle spécifiée sur le contenu du fichier cpu-usage-doc.md :

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

Pour plus d'informations, consultez la documentation de référence sur gcloud alpha monitoring policies update. La commande update correspond à la méthode alertPolicies.patch dans l'API REST.

Exemples : Sauvegarder et restaurer

Tous les exemples d'API présentés ici supposent une application à même d'enregistrer dans un fichier les règles d'alerte d'un projet et de les restaurer, dans un autre projet le cas échéant. Si les projets désignés pour la sauvegarde et la restauration sont différents, l'application procède en réalité à une exportation et à une importation des règles d'alerte d'un projet à un autre.

Cette section présente le code pour la sauvegarde et la restauration de règles en contexte, plutôt que sous la forme d'un ensemble d'extraits isolés.

Sauvegarder des règles

L'opération de sauvegarde est simple. L'ensemble des règles d'alerte et des canaux de notification de chaque projet sont collectés et enregistrés dans un stockage externe au format JSON.

C#

        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


// 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

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

private static List<AlertPolicy> getAlertPolicies(String projectId) throws IOException {
  List<AlertPolicy> alertPolicies = Lists.newArrayList();
  try (AlertPolicyServiceClient client = AlertPolicyServiceClient.create()) {
    ListAlertPoliciesPagedResponse response = client.listAlertPolicies(ProjectName.of(projectId));

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

private static List<NotificationChannel> getNotificationChannels(String projectId)
    throws IOException {
  List<NotificationChannel> notificationChannels = Lists.newArrayList();
  try (NotificationChannelServiceClient client = NotificationChannelServiceClient.create()) {
    ListNotificationChannelsPagedResponse listNotificationChannelsResponse =
        client.listNotificationChannels(ProjectName.of(projectId));
    for (NotificationChannel channel : listNotificationChannelsResponse.iterateAll()) {
      notificationChannels.add(channel);
    }
  }
  return notificationChannels;
}

private static 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

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),
};

let [policies] = await client.listAlertPolicies(listAlertPoliciesRequest);

// filter out any policies created by tests for this sample
policies = policies.filter(policy => {
  return !policy.displayName.startsWith('gcloud-tests-');
});

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

console.log('Saved policies to ./policies_backup.json');

PHP

use Google\Cloud\Monitoring\V3\AlertPolicyServiceClient;
use Google\Cloud\Monitoring\V3\NotificationChannelServiceClient;

/**
 * Back up alert policies.
 *
 * @param string $projectId Your project ID
 */
function alert_backup_policies($projectId)
{
    $alertClient = new AlertPolicyServiceClient([
        'projectId' => $projectId,
    ]);
    $channelClient = new NotificationChannelServiceClient([
        'projectId' => $projectId,
    ]);
    $projectName = $alertClient->projectName($projectId);

    $record = [
        'project_name' => $projectName,
        'policies' => [],
        'channels' => [],
    ];
    $policies = $alertClient->listAlertPolicies($projectName);
    foreach ($policies->iterateAllElements() as $policy) {
        $record['policies'][] = json_decode($policy->serializeToJsonString());
    }
    $channels = $channelClient->listNotificationChannels($projectName);
    foreach ($channels->iterateAllElements() as $channel) {
        $record['channels'][] = json_decode($channel->serializeToJsonString());
    }
    file_put_contents('backup.json', json_encode($record, JSON_PRETTY_PRINT));
    print('Backed up alert policies and notification channels to backup.json.');
}

Python

def backup(project_name, backup_filename):
    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_filename, 'wt'), cls=ProtoEncoder, indent=2)
    print('Backed up alert policies and notification channels to {}.'.format(
        backup_filename)
    )

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)

Restaurer des règles sauvegardées

Le processus de restauration est plus complexe que la sauvegarde initiale. Vous pouvez restaurer le projet que vous avez sauvegardé à l'origine. Mais vous pouvez également restaurer un projet différent, ce qui revient à une importation de règles d'alerte.

Dans le cas d'une restauration du même projet, toutes les règles et tous les canaux existants sont mis à jour, à condition qu'ils existent toujours. Si ce n'est pas le cas, ils sont recréés. Dans les règles sauvegardées, les champs en lecture seule, tels que les enregistrements de création et de mutation, sont effacés par le processus de restauration avant que les règles et les notifications ne soient recréées.

Vous pouvez vous servir d'une règle enregistrée dans un projet pour créer une autre règle dans ce même projet, ou une règle similaire dans un autre projet. Toutefois, vous devez d'abord apporter les modifications suivantes à la copie de la règle enregistrée :

  • Supprimez les champs suivants des canaux de notification :
    • name
    • verificationStatus
  • Créez les canaux de notification avant d'y faire référence dans les règles d'alerte (les nouveaux identifiants des canaux sont nécessaires).
  • Supprimez les champs suivants de toute règle d'alerte que vous recréez :
    • name
    • condition.name
    • creationRecord
    • mutationRecord

Si la règle est recréée dans un nouveau projet, le nom de toutes les conditions des règles sauvegardées est effacé, ainsi que les enregistrements de création et de mutation.

De plus, lorsqu'un canal de notification est recréé dans un projet différent, il reçoit un nouveau nom. Le processus de restauration doit donc faire correspondre les anciens noms des canaux avec leurs nouveaux noms, puis remplacer les anciens par les nouveaux.

Outre la modification des noms des canaux de notification, la valeur du champ verificationStatus ne peut pas être définie lors de la création ou de la mise à jour du canal. Par conséquent, une valeur spéciale (unspecified) est utilisée. Une fois les canaux restaurés dans un nouveau projet, leur fonctionnement doit faire l'objet d'une vérification.

C#

        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


// 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

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

  JsonObject backupContent = getPolicyJsonContents(filePath, bufferedReader);
  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 static 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 static void restoreRevisedPolicies(
    String projectId, boolean isSameProject, List<AlertPolicy> policies) throws IOException {
  try (AlertPolicyServiceClient client = AlertPolicyServiceClient.create()) {
    for (AlertPolicy policy : policies) {
      if (!isSameProject) {
        policy = client.createAlertPolicy(ProjectName.of(projectId), policy);
      } else {
        try {
          client.updateAlertPolicy(null, policy);
        } catch (Exception e) {
          policy =
              client.createAlertPolicy(
                  ProjectName.of(projectId), policy.toBuilder().clearName().build());
        }
      }
      System.out.println(String.format("Restored %s", policy.getName()));
    }
  }
}

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

private static JsonObject getPolicyJsonContents(String filePath, BufferedReader content) {
  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

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);

for (const index in policies) {
  // Restore each policy one at a time
  let policy = policies[index];
  if (await doesAlertPolicyExist(policy.name)) {
    policy = await client.updateAlertPolicy({
      alertPolicy: policy,
    });
  } else {
    // Clear away output-only fields
    delete policy.name;
    delete policy.creationRecord;
    delete policy.mutationRecord;
    policy.conditions.forEach(condition => delete condition.name);

    policy = await client.createAlertPolicy({
      name: client.projectPath(projectId),
      alertPolicy: policy,
    });
  }

  console.log(`Restored ${policy[0].name}.`);
}
async function doesAlertPolicyExist(name) {
  try {
    const [policy] = await client.getAlertPolicy({
      name,
    });
    return policy ? true : false;
  } catch (err) {
    if (err && err.code === 5) {
      // Error code 5 comes from the google.rpc.code.NOT_FOUND protobuf
      return false;
    }
    throw err;
  }
}

PHP

use Google\Cloud\Monitoring\V3\AlertPolicyServiceClient;
use Google\Cloud\Monitoring\V3\NotificationChannelServiceClient;
use Google\Cloud\Monitoring\V3\AlertPolicy;
use Google\Cloud\Monitoring\V3\NotificationChannel;
use Google\Cloud\Monitoring\V3\NotificationChannel\VerificationStatus;
use Google\ApiCore\ApiException;

/**
 * @param string $projectId Your project ID
 */
function alert_restore_policies($projectId)
{
    $alertClient = new AlertPolicyServiceClient([
        'projectId' => $projectId,
    ]);

    $channelClient = new NotificationChannelServiceClient([
        'projectId' => $projectId,
    ]);

    print('Loading alert policies and notification channels from backup.json.' . PHP_EOL);
    $projectName = $alertClient->projectName($projectId);
    $record = json_decode(file_get_contents('backup.json'), true);
    $isSameProject = $projectName == $record['project_name'];

    # Convert dicts to AlertPolicies.
    $policies = [];
    foreach ($record['policies'] as $policyArray) {
        $policy = new AlertPolicy();
        $policy->mergeFromJsonString(json_encode($policyArray));
        $policies[] = $policy;
    }

    # Convert dicts to NotificationChannels
    $channels = [];
    foreach (array_filter($record['channels']) as $channelArray) {
        $channel = new NotificationChannel();
        $channel->mergeFromJsonString(json_encode($channelArray));
        $channels[] = $channel;
    }

    # Restore the channels.
    $channelNameMap = [];
    foreach ($channels as $channel) {
        $updated = false;
        printf('Updating channel %s' . PHP_EOL, $channel->getDisplayName());

        # This field is immutable and it is illegal to specify a
        # non-default value (UNVERIFIED or VERIFIED) in the
        # Create() or Update() operations.
        $channel->setVerificationStatus(
            VerificationStatus::VERIFICATION_STATUS_UNSPECIFIED
        );

        if ($isSameProject) {
            try {
                $channelClient->updateNotificationChannel($channel);
                $updated = true;
            } catch (ApiException $e) {
                # The channel was deleted.  Create it below.
                if ($e->getStatus() !== 'NOT_FOUND') {
                    throw $e;
                }
            }
        }

        if (!$updated) {
            # The channel no longer exists.  Recreate it.
            $oldName = $channel->getName();
            $channel->setName('');
            $newChannel = $channelClient->createNotificationChannel(
                $projectName,
                $channel
            );
            $channelNameMap[$oldName] = $newChannel->getName();
        }
    }

    # Restore the alerts
    foreach ($policies as $policy) {
        printf('Updating policy %s' . PHP_EOL, $policy->getDisplayName());
        # These two fields cannot be set directly, so clear them.
        $policy->setCreationRecord(null);
        $policy->setMutationRecord(null);

        $notificationChannels = $policy->getNotificationChannels();

        # Update old channel names with new channel names.
        foreach ($notificationChannels as $i => $channel) {
            if (isset($channelNameMap[$channel])) {
                $notificationChannels[$i] = $channelNameMap[$channel];
            }
        }

        $updated = false;
        if ($isSameProject) {
            try {
                $alertClient->updateAlertPolicy($policy);
                $updated = true;
            } catch (ApiException $e) {
                # The policy was deleted.  Create it below.
                if ($e->getStatus() !== 'NOT_FOUND') {
                    throw $e;
                }
            }
        }

        if (!$updated) {
            # The policy no longer exists.  Recreate it.
            $oldName = $policy->getName();
            $policy->setName('');
            foreach ($policy->getConditions() as $condition) {
                $condition->setName('');
            }
            $policy = $alertClient->createAlertPolicy($projectName, $policy);
        }
        printf('Updated %s' . PHP_EOL, $policy->getName());
    }
    print('Restored alert policies and notification channels from backup.json.');
}

Python

def restore(project_name, backup_filename):
    print('Loading alert policies and notification channels from {}.'.format(
        backup_filename)
    )
    record = json.load(open(backup_filename, '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)

Alertes et SDK Cloud

Dans le SDK Cloud, le groupe de commandes pour la gestion des règles d'alerte et des canaux de notification est monitoring (en version alpha). Le groupe monitoring est disponible dans le composant alpha. Ces commandes commenceront donc toutes par :

gcloud alpha monitoring

Pour vérifier si le composant alpha est installé, exécutez cette commande :

gcloud components list

Si le composant alpha n'est pas installé, exécutez cette commande pour l'installer :

gcloud components install alpha

Si vous possédez le composant alpha, recherchez le groupe monitoring en exécutant la commande suivante :

gcloud alpha monitoring --help

Si le groupe monitoring n'est pas inclus, le SDK Cloud vous invite à l'ajouter :

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