Crea políticas de alertas con la API

Una política de alertas se representa en la API de Cloud Monitoring con un objeto AlertPolicy, que describe un conjunto de condiciones que indican un estado potencialmente en mal estado en tu sistema.

En este documento, se describe lo siguiente:

  • Cómo la API de Monitoring representa las políticas de alertas
  • Los tipos de condiciones que proporciona la API de Monitoring para las políticas de alertas
  • Cómo crear una política de alertas mediante Google Cloud CLI o las bibliotecas cliente

Estructura de una política de alertas

La estructura AlertPolicy define los componentes de una política de alertas. Cuando creas una política, especificas valores para los siguientes campos AlertPolicy:

  • displayName: Es una etiqueta descriptiva de la política.
  • documentation: Toda la información que se proporcione para ayudar a las personas que responden. Este campo es opcional. El objeto documentation incluye lo siguiente:
    • content: Es el texto definido por el usuario que aparece en el cuerpo de la notificación.
    • subject: Es el asunto de la notificación. Las líneas de asunto tienen un límite de 255 caracteres.
  • userLabels: Cualquier etiqueta definida por el usuario adjunta a la política. Para obtener información sobre el uso de etiquetas con alertas, consulta Anota alertas con etiquetas.
  • conditions[]: Es un array de estructuras Condition.
  • combiner: Es un operador lógico que determina cómo controlar varias condiciones.
  • notificationChannels[]: Es un array de nombres de recursos, cada uno de los cuales identifica una NotificationChannel.
  • alertStrategy: Especifica la rapidez con la que Monitoring cierra incidentes cuando dejan de llegar datos. Este objeto también especifica si las notificaciones repetidas están habilitadas para las alertas basadas en métricas y el intervalo entre esas notificaciones. Para obtener más información, consulta Cómo enviar notificaciones repetidas.

También puedes especificar el campo severity cuando usas la API de Cloud Monitoring y la consola de Google Cloud. Este campo te permite definir el nivel de gravedad de los incidentes. Si no especificas una gravedad, Cloud Monitoring establece la gravedad de la política de alertas en No Severity.

Hay otros campos que podrías usar, según las condiciones que crees.

Si una política de alertas contiene una condición, se envía una notificación cuando se cumple esa condición. Para obtener información sobre las notificaciones cuando las políticas de alertas contienen varias condiciones, consulta Políticas con varias condiciones y Cantidad de notificaciones por política.

Cuando creas o modificas la política de alertas, Monitoring también establece otros campos, incluido el campo name. El valor del campo name es el nombre del recurso de la política de alertas, que identifica la política. El nombre del recurso tiene la siguiente forma:

projects/PROJECT_ID/alertPolicies/POLICY_ID

Tipos de condiciones en la API

La API de Cloud Monitoring admite una variedad de tipos de condiciones en la estructura Condition. Existen varios tipos de condiciones para las políticas de alertas basadas en métricas y uno para las políticas de alertas basadas en registros. En las siguientes secciones, se describen los tipos de condiciones disponibles.

Condiciones para las políticas de alertas basadas en métricas

Para crear una política de alertas que supervise datos de métricas, incluidas las métricas basadas en registros, puedes usar los siguientes tipos de condiciones:

Condiciones de métricas basadas en filtros

Las condiciones MetricAbsence y MetricThreshold usan filtros de supervisión para seleccionar los datos de series temporales que se supervisarán. Otros campos en la estructura de condición especifican cómo filtrar, agrupar y agregar los datos. Para obtener más información sobre estos conceptos, consulta Filtra y agrega: manipula series temporales.

Si usas el tipo de condición MetricAbsence, puedes crear una condición que se cumpla solo cuando falten todas las series temporales. Esta condición usa el parámetro aggregations para agregar varias series temporales en una sola serie temporal. Para obtener más información, consulta la referencia de MetricAbsence en la documentación de la API.

Una política de alertas de ausencia de métricas requiere que algunos datos se hayan escrito con anterioridad. Para obtener más información, consulta Crea políticas de alertas de ausencia de métricas.

Si deseas recibir notificaciones en función de un valor previsto, configura la política de alertas para usar el tipo de condición MetricThreshold y establecer el campo forecastOptions. Si no se establece este campo, los datos medidos se comparan con un umbral. Sin embargo, cuando se configura este campo, los datos previstos se comparan con un umbral. Para obtener más información, consulta Crea políticas de alertas sobre valores de métricas previstos.

Condiciones de las métricas basadas en MQL

La condición MonitoringQueryLanguageCondition usa el lenguaje de consulta de Monitoring (MQL) para seleccionar y manipular los datos de series temporales que se supervisarán. Puedes crear políticas de alertas que comparen valores con un umbral o comprueben la ausencia de valores con este tipo de condición. Si usas una condición MonitoringQueryLanguageCondition, debe ser la única condición de la política de alertas. Para obtener más información, consulta Políticas de alertas con MQL.

Condiciones de las métricas basadas en PromQL

La condición PrometheusQueryLanguageCondition usa consultas de Prometheus Query Language (PromQL) para seleccionar y manipular datos de series temporales para supervisar. Puedes crear una consulta simple o compleja y usar estructuras de consulta como límites dinámicos, proporciones, comparaciones de métricas y mucho más.

Si usas una condición PrometheusQueryLanguageCondition, debe ser la única condición de la política de alertas. Para obtener más información, consulta Políticas de alertas con PromQL.

Condiciones para generar alertas sobre las proporciones

Puedes crear políticas de alertas sobre el umbral de métricas para supervisar la proporción de dos métricas. Puedes crear estas políticas con el tipo de condición MetricThreshold o MonitoringQueryLanguageCondition. También puedes usar MQL directamente en la consola de Google Cloud. No puedes crear ni administrar condiciones basadas en la proporción mediante la interfaz gráfica para crear condiciones de umbral.

Recomendamos usar MQL para crear políticas de alertas basadas en la proporción. MQL te permite compilar consultas más potentes y flexibles de las que puedes compilar mediante el tipo de condición MetricTheshold y los filtros de Monitoring. Por ejemplo, con una condición MonitoringQueryLanguageCondition, puedes calcular la proporción entre una métrica de indicador y una métrica delta. Para ver ejemplos, consulta Ejemplos de política de alertas de MQL.

Si usas la condición MetricThreshold, el numerador y el denominador de la proporción deben tener el mismo MetricKind. Para obtener una lista de las métricas y sus propiedades, consulta Listas de métricas.

En general, es mejor calcular las proporciones según las series temporales recopiladas para un solo tipo de métrica mediante el uso de valores de etiquetas. Una proporción calculada sobre dos tipos de métricas diferentes está sujeta a anomalías debido a diferentes períodos de muestreo y ventanas de alineación.

Por ejemplo, supongamos que tienes dos tipos de métricas, un recuento total de RPC y un recuento de errores de RPC, y deseas calcular la proporción de las RPC del recuento de errores sobre el total de RPC. Las RPC con errores se cuentan en las series temporales de ambos tipos de métricas. Por lo tanto, existe la posibilidad de que, cuando alinees las series temporales, una RPC con errores no aparezca en el mismo intervalo de alineación para ambas series temporales. Esta diferencia puede ocurrir por varias razones, incluidas las siguientes:

  • Debido a que hay dos series temporales diferentes que registran el mismo evento, hay dos valores de contador subyacentes que implementan la colección y no se actualizan de forma atómica.
  • Las tasas de muestreo pueden variar. Cuando las series temporales se alinean con un período común, los recuentos de un solo evento pueden aparecer en intervalos de alineación adyacentes en las series temporales para las diferentes métricas.

La diferencia en la cantidad de valores en los intervalos de alineación correspondientes puede generar valores de proporción error/total sin sentido, como 1/0 o 2/1.

Es menos probable que las proporciones de números más grandes den como resultado valores sin sentido. Puedes obtener números más grandes mediante la agregación, ya sea con una ventana de alineación más larga que el período de muestreo o mediante la agrupación de datos para ciertas etiquetas. Estas técnicas minimizan el efecto de pequeñas diferencias en la cantidad de puntos en un intervalo determinado. Es decir, una disparidad de dos puntos es más significativa cuando la cantidad esperada de puntos en un intervalo es 3 que cuando el número esperado es 300.

Si usas tipos de métricas integradas, es posible que no tengas más opción que calcular las proporciones entre los tipos de métricas para obtener el valor que necesitas.

Si diseñas métricas personalizadas que pueden contar lo mismo, como las RPC que muestran el estado del error, en dos métricas diferentes, considera una sola métrica, que incluye cada recuento solo una vez. Por ejemplo, supongamos que estás contando RPC y deseas realizar un seguimiento de la proporción de RPC con errores a todas las RPC. Para resolver este problema, crea un solo tipo de métrica para contar las RPC y usa una etiqueta a fin de registrar el estado de la invocación, incluido el estado “OK”. Luego, cada valor de estado (error o "OK") se registra mediante la actualización de un solo contador para ese caso.

Condición para las políticas de alertas basadas en registros

Para crear una política de alertas basada en registros que te notifique cuando aparece un mensaje que coincide con el filtro en tus entradas de registro, usa el tipo de condición LogMatch. Si usas una condición LogMatch, debe ser la única condición de tu política de alertas.

No intentes usar el tipo de condición LogMatch junto con métricas basadas en registros. Las políticas de alertas que supervisan las métricas basadas en registros son políticas basadas en métricas. Para obtener más información sobre cómo elegir entre las políticas de alertas que supervisan las métricas basadas en registros o las entradas de registro, consulta Supervisa tus registros.

Las políticas de alertas que se usan en los ejemplos del documento Administra las políticas de alertas por API son políticas de alertas basadas en métricas, aunque los principios son los mismos para las políticas de alertas basadas en registros. Para obtener información específica de las políticas de alertas basadas en registros, consulta Crea una alerta basada en registros mediante la API de Monitoring en la documentación de Cloud Logging.

Antes de comenzar

Antes de escribir el código en la API, debes cumplir con lo siguiente:

  • Familiarízate con los conceptos generales y la terminología que se usa con las políticas de alertas; consulta Descripción general de las alertas para obtener más información.
  • Asegúrate de que la API de Cloud Monitoring esté habilitada para su uso; consulta Cómo habilitar la API para obtener más información.
  • Si planeas usar bibliotecas cliente, instálalas correspondientes a los lenguajes que deseas usar. Consulta Bibliotecas cliente para obtener más información. Actualmente, la asistencia de la API para alertas está disponible solo para C#, Go, Java, Node.js y Python.
  • Si planeas usar Google Cloud CLI, instálalo. Sin embargo, si usas Cloud Shell, Google Cloud CLI ya está instalado.

    También se proporcionan aquí los ejemplos que usan la interfaz de gcloud. Ten en cuenta que en los ejemplos de gcloud se da por sentado que el proyecto actual ya se estableció como el objetivo (gcloud config set project [PROJECT_ID]), por lo que las invocaciones omiten la marca --project explícita. El ID del proyecto actual en los ejemplos es a-gcp-project.

  • Si quieres obtener los permisos que necesitas para crear y modificar las políticas de alertas con la API de Cloud Monitoring, pídele a tu administrador que te otorgue el rol de IAM Editor de políticas de alertas de Monitoring (roles/monitoring.alertPolicyEditor) en tu proyecto. Si quieres obtener más información para otorgar funciones, consulta Administra el acceso.

    Es posible que también puedas obtener los permisos necesarios a través de los roles personalizados o de otros roles predefinidos.

    Si deseas obtener información detallada sobre las funciones de IAM para Monitoring, consulta Controla el acceso con Identity and Access Management.

  • Diseña tu aplicación para llamadas a la API de Cloud Monitoring de un solo subproceso que modifiquen el estado de una política de alertas en un proyecto de Google Cloud. Por ejemplo, llamadas a la API de un solo subproceso que crean, actualizan o borran una política de alertas.

Crea una política de alertas

Para crear una política de alertas en un proyecto, usa el método alertPolicies.create. Si deseas obtener información para invocar este método, sus parámetros y los datos de respuesta, consulta la página de referencia de alertPolicies.create.

Puedes crear políticas desde archivos JSON o YAML. Google Cloud CLI acepta estos archivos como argumentos y puedes leer archivos JSON de manera programática, convertirlos en objetos AlertPolicy y crear políticas a partir de ellos con el método alertPolicies.create. Si tienes un archivo de configuración JSON o YAML de Prometheus con una regla de alertas, gcloud CLId puede migrarlo a una política de alertas de Cloud Monitoring con una condición de PromQL. Para obtener más información, consulta Migra las reglas y los receptores de alertas desde Prometheus.

Cada política de alertas pertenece a un proyecto de permisos de un permiso de métricas. Cada proyecto puede contener hasta 500 políticas. Para las llamadas a la API, debes proporcionar un “ID del proyecto”. Usa el ID del proyecto de permisos de un permiso de métricas como el valor. En estos ejemplos, el ID del proyecto de permisos de un permiso de métricas es a-gcp-project.

En los siguientes ejemplos, se ilustra la creación de políticas de alertas, pero no se describe cómo crear un archivo JSON o YAML en el que se describa una política de alertas. En cambio, las muestras suponen que existe un archivo con formato JSON y, además, ilustran cómo emitir la llamada a la API. Para ejemplos de archivos JSON, consulta Políticas de muestra. Para obtener información general sobre la supervisión de las proporciones de las métricas, consulta Proporción de las métricas.

gcloud

Para crear una política de alertas en un proyecto, usa el comando gcloud alpha monitoring policies create. En el siguiente ejemplo, se crea una política de alertas en a-gcp-project del archivo rising-cpu-usage.json:

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

Si funciona, este comando muestra el nombre de la política nueva, por ejemplo:

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

El archivo rising-cpu-usage.json contiene el JSON de una política con el nombre visible “Tasa de cambio de CPU alta”. Para obtener detalles sobre esta política, consulta la Política de tasa de cambio.

Consulta la referencia de gcloud alpha monitoring policies create para obtener más información.

C#

Para autenticarte en Monitoring, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.

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

Para autenticarte en Monitoring, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.


// 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
	}
	defer alertClient.Close()
	channelClient, err := monitoring.NewNotificationChannelClient(ctx)
	if err != nil {
		return err
	}
	defer channelClient.Close()

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

Para autenticarte en Monitoring, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.

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

Para autenticarte en Monitoring, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.

const fs = require('fs');

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

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

async function restorePolicies() {
  // Note: The policies are restored one at a time due to limitations in
  // the API. Otherwise, you may receive a 'service unavailable'  error
  // while trying to create multiple alerts simultaneously.

  /**
   * 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;
    }
  }
}
restorePolicies();

PHP

Para autenticarte en Monitoring, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.

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

/**
 * @param string $projectId Your project ID
 */
function alert_create_policy($projectId)
{
    $alertClient = new AlertPolicyServiceClient([
        'projectId' => $projectId,
    ]);
    $projectName = 'projects/' . $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,
        ])
    ])]);
    $createAlertPolicyRequest = (new CreateAlertPolicyRequest())
        ->setName($projectName)
        ->setAlertPolicy($policy);

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

Python

Para autenticarte en Monitoring, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para un entorno de desarrollo local.

def restore(project_name, backup_filename):
    """Restore alert policies in a project.

    Arguments:
        project_name (str): The Google Cloud Project to use. The project name
            must be in the format - 'projects/<PROJECT_NAME>'.
        backup_filename (str): Name of the file (along with its path) from
            which the alert policies will be restored.
    """
    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 = [
        monitoring_v3.AlertPolicy.from_json(policy_json)
        for policy_json in policies_json
    ]
    # Convert dicts to NotificationChannels
    channels_json = [json.dumps(channel) for channel in record["channels"]]
    channels = [
        monitoring_v3.NotificationChannel.from_json(channel_json)
        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.NotificationChannel.VerificationStatus.VERIFICATION_STATUS_UNSPECIFIED
        )

        if is_same_project:
            try:
                channel_client.update_notification_channel(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
            del channel.name
            new_channel = channel_client.create_notification_channel(
                name=project_name, notification_channel=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.
        del policy.creation_record
        del policy.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(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
            del policy.name
            for condition in policy.conditions:
                del condition.name
            policy = alert_client.create_alert_policy(
                name=project_name, alert_policy=policy
            )
        print("Updated", policy.name)

El objeto AlertPolicy creado tendrá campos adicionales. La política en sí tendrá los campos name, creationRecord y mutationRecord. Además, cada condición en la política también recibe un name. Estos campos no pueden modificarse de forma externa, por lo que no es necesario configurarlos cuando creas una política. Ninguno de los ejemplos de JSON usados para crear políticas los incluye, pero si las políticas creadas a partir de ellas se recuperan después de la creación, los campos estarán presentes.

¿Qué sigue?