Como gerenciar políticas de alertas pela API

Nesta página, ilustramos como usar a API Stackdriver Monitoring para criar e gerenciar políticas de alertas de maneira programática. Ela também ilustra o uso da interface de linha de comando do Cloud SDK para gerenciar políticas de alertas.

Muitas dessas tarefas também podem ser realizadas usando-se o console do Stackdriver Monitoring. Consulte Como usar políticas de alertas para uma introdução à criação e ao gerenciamento de políticas de alerta com o console do Stackdriver Monitoring.

Antes de começar

Para escrever código na API, você precisa cumprir estes requisitos:

  • Ter um espaço de trabalho que monitore os projetos para os quais você quer criar políticas de alerta.
  • Estar familiarizado com os conceitos gerais e terminologia usados com políticas de alerta. Consulte Introdução a alertas para saber mais informações.
  • Certificar-se de que a API esteja ativada para uso. Consulte Como ativar a API para saber mais informações.
  • Instalar as bibliotecas de cliente das linguagens que você quer usar. Consulte Bibliotecas de cliente para saber detalhes. Atualmente, a API é compatível com alertas somente em C#, Go, Java, Node.js e Python.

  • Instalar o SDK do Cloud. Isso dará acesso à interface de linha de comando gcloud, onde você também pode realizar essas tarefas. Se for usar o Cloud Shell, utilize-o em vez de instalar o SDK do Cloud.

    Os exemplos que usam a interface gcloud também são fornecidos aqui. Em todos os exemplos do gcloud, supomos que o projeto atual já tenha sido definido como o destino (gcloud config set project [PROJECT_ID]). Dessa maneira, as invocações omitem a sinalização --project explícita. O código do projeto atual nos exemplos é a-gcp-project.

Sobre políticas de alertas

Uma política de alertas é representada por um objeto AlertPolicy, que descreve um conjunto de condições que indicam um status de possível falta de integridade no sistema. As políticas de alertas referenciam canais de notificação, que permitem especificar como você quer ser informado de que uma política de alertas foi acionada.

Cada política de alertas pertence a um espaço de trabalho individual e cada espaço de trabalho pode conter até 500 políticas. O espaço de trabalho é indicado pelo código, chamado de “código do projeto” no material de referência. Nestes exemplos, o código do espaço de trabalho é a-gcp-project.

O recurso AlertPolicy aceita cinco operações:

  • criação de novas políticas
  • exclusão de políticas existentes
  • recuperação de políticas específicas
  • recuperação de todas as políticas
  • modificação de políticas existentes

As políticas de alertas podem ser expressas em JSON ou YAML, o que permite gravar políticas em arquivos e usar arquivos para fazer backup e restaurar políticas. Com o Cloud SDK, você pode criar políticas com base em arquivos de qualquer formato. Com a API REST, você pode criar políticas com base em arquivos JSON. Consulte Políticas de amostra para uma seleção de políticas de alertas em formato JSON.

Os exemplos a seguir usam a interface gcloud e a API para ilustrar esses casos de uso básicos. As amostras de API são extraídas de um programa de amostra que usa a API para implementar um sistema de backup e restauração para políticas de alertas. As amostras mais completas são mostradas em Exemplo: backup e restauração.

Como criar políticas

Para criar uma política de alertas em um projeto, use o método alertPolicies.create.

Você pode criar políticas com base em arquivos JSON ou YAML. A interface de linha de comando gcloud aceita esses arquivos como argumentos, e é possível ler arquivos JSON de maneira programática, convertê-los em objetos AlertPolicy e criar políticas com base neles usando o método alertPolicies.create.

Nos exemplos a seguir, veja a criação de políticas de alertas.

COMANDO GCLOUD

Para criar uma política de alertas em um projeto, use o comando gcloud alpha monitoring policies create. No seguinte exemplo, criamos uma política de alertas em a-gcp-project com base no arquivo rising-cpu-usage.json:

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

Se bem-sucedido, este comando retornará o nome da nova política. Por exemplo:

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

O arquivo rising-cpu-usage.json contém o JSON de uma política com o nome de exibição "Alta taxa de mudança da CPU". Essa política é descrita em Uma política de taxa de mudança.

Consulte a referência de gcloud alpha monitoring policies create para saber mais informações.

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

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

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

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

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

    # Restore the alerts
    alert_client = monitoring_v3.AlertPolicyServiceClient()

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

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

        updated = False

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

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

O objeto AlertPolicy criado terá outros campos. A política propriamente dita terá campos name, creationRecord e mutationRecord. Além disso, cada condição na política também recebe um name. Esses campos não podem ser modificados externamente. Dessa maneira, não é necessário configurá-los durante a criação de uma política. Nenhum dos exemplos JSON usados para criar políticas os inclui, mas, se as políticas criadas com base neles forem recuperadas depois da criação, os campos estarão presentes.

Como recuperar políticas

Para recuperar uma lista das políticas em um projeto, use o método alertPolicies.list. Use esse método para recuperar políticas e aplicar uma ação a cada uma delas, por exemplo, fazendo backup delas. Esse método também aceita opções filter e orderBy para restringir e classificar os resultados. Consulte Como classificar e filtrar.

Se estiver procurando uma política específica e souber o nome dela, use o método alertPolicies.get para recuperar apenas essa política. O nome de uma política é o valor do campo name, e não o displayName, no objeto AlertPolicy. O nome de uma política tem o formato projects/[PROJECT_ID]/alertPolicies/[POLICY_ID]. Por exemplo:

projects/a-gcp-project/alertPolicies/12669073143329903307

COMANDO GCLOUD

Para listar todas as políticas de alertas em um projeto, use o comando gcloud alpha monitoring policies list:

gcloud alpha monitoring policies list

Se for bem-sucedido, o comando list fornecerá uma listagem de todas as políticas no projeto especificado, formatadas como YAML. Por exemplo, a política com o nome de exibição “Alta taxa de mudança de CPU” no projeto a-gcp-project é listada entre outras políticas da seguinte maneira:

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

Para listar uma única política de alertas, use gcloud alpha monitoring policies describe, em vez disso, e especifique o nome da política. Por exemplo, este comando retorna apenas a listagem acima:

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

Consulte as referências de gcloud alpha monitoring policies list e describe para saber mais informações. O comando describe corresponde ao método alertPolicies.get na 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')))

Como excluir políticas

Para excluir uma política de um projeto, use o método alertPolicies.delete e forneça o nome da política de alertas a ser excluída.

COMANDO GCLOUD

Para excluir uma política de alertas, use gcloud alpha monitoring policies delete e especifique o nome da política a ser excluída. Por exemplo, o seguinte comando exclui a política "Alta taxa de mudança de CPU":

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

Consulte a referência de gcloud alpha monitoring policies delete para saber mais informações.

Como modificar políticas

Para modificar uma política de alertas, use o método alertPolicies.patch (na API REST). Outras implementações de API e a interface do gcloud chamam update, em vez de patch.

Uma operação de atualização pode substituir toda a política existente ou modificar um subconjunto de campos. Uma operação de atualização utiliza um novo objeto AlertPolicy e uma máscara de campo opcional.

Se uma máscara de campo for especificada, todos os campos listados na máscara de campo serão atualizados com o valor na política fornecida. Se a política fornecida não incluir um campo mencionado na máscara de campo, esse campo será apagado e definido como o valor padrão dele. Qualquer campo não listado na máscara mantém o valor anterior dele.

Se nenhuma máscara de campo for especificada, a política existente será substituída pela fornecida, mas o nome (projects/[PROJECT_ID]/alertPolicies/[POLICY_ID]) será reutilizado. Quaisquer condições na nova política que tenham valores name que incluam um CONDITION_ID manterão esses nomes. Do contrário, novos nomes de condição e política são criados.

Ao usar a linha de comando gcloud para atualizar políticas, as sinalizações da linha de comando, em vez de uma máscara de campo, são usadas para especificar campos a serem atualizados. Consulte o gcloud alpha monitoring policies update para saber mais detalhes.

Como ativar ou desativar uma política

Para ativar ou desativar uma política, altere o valor do campo booleano enabled no objeto AlertPolicy. Depois que você ativar uma política, ela ainda poderá ser acionada por dados coletados enquanto estiver desativada.

COMANDO GCLOUD

Para desativar uma política de alertas, use o comando gcloud alpha monitoring policies update e forneça a sinalização --no-enabled. O seguinte comando desativa a política de alertas "Alta taxa de mudança de CPU" no projeto a-gcp-project:

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

Para ativar a política, use o mesmo comando e forneça a sinalização --enabled. Consulte a referência de gcloud alpha monitoring policies update para saber mais informações. O comando update corresponde ao método alertPolicies.patch na 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: ['disabled']},
        alertPolicy: {
          name: policy.name,
          disabled: enabled ? false : true,
        },
      };
    })
    .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)

Como atualizar canais de notificação em uma política

Também é possível atualizar os canais de notificação referenciados por uma política de alertas. As políticas de alertas se referem a canais de notificação por nome. Os canais precisam existir para serem usados em uma política de alertas.

É possível criar e gerenciar canais de notificação de maneira programática com o uso dos recursos NotificationChannel e NotificationChannelDescriptors. Nos exemplos desta seção, supomos que esses canais já existam, e os usos dessas APIs também são exibidos nas amostras programáticas.

Para mais discussão dos objetos do canal de notificação, consulte Como gerenciar canais por API.

COMANDO GCLOUD

Para modificar os canais de notificação em uma política de alertas, use o comando gcloud alpha monitoring policies update. Há várias sinalizações relacionadas aos canais de notificação, permitindo remover canais de notificação, substituir canais de notificação e adicionar novos canais de notificação.

Por exemplo, a política com o nome de exibição "Alta taxa de mudança de CPU" no projeto a-gcp-project foi criada sem canais de notificação.

Para adicionar um canal de notificação a essa política, use o comando gcloud alpha monitoring policies update e especifique o canal a ser adicionado à sinalização --add-notification-channels:

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

Consulte a referência de gcloud alpha monitoring policies update para saber mais informações. O comando update corresponde ao método alertPolicies.patch na API REST.

O canal de notificação adicionado aqui já precisa existir. Consulte Como criar canais para mais informações.

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.notificationChannelPath(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.alertPolicyPath(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)

Como modificar a documentação em uma política

Uma política pode apresentar documentação com incidentes e notificações associados à política. Use esse campo a fim de incluir informações para ajudar os responsáveis pela resposta a entender e processar o problema indicado pela política de alertas. A documentação está incluída em notificações por e-mail e tipos de notificação que permitam isso. Outros tipos de canal podem omiti-la.

COMANDO GCLOUD

Para adicionar documentação a uma política ou substituir documentação existente, use o comando gcloud alpha monitoring policies update e forneça a sinalização --documentation-format="text/markdown" (o único formato compatível) e a sinalização --documentation (para inserir o valor da linha de comando) ou a sinalização --documentation-from-file (para ler o valor de um arquivo).

Por exemplo, a política com o nome de exibição "Alta taxa de mudança de CPU" no projeto a-gcp-project foi criada sem documentação.

O seguinte comando define o campo documentation na política especificada como o conteúdo do arquivo 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"

Consulte a referência de gcloud alpha monitoring policies update para saber mais informações. O comando update corresponde ao método alertPolicies.patch na API REST.

Exemplo: backup e restauração

Todos os exemplos da API mostrados são extraídos de um aplicativo maior que pode fazer backup das políticas de alerta em um projeto para um arquivo e pode restaurar as políticas, possivelmente para outro projeto. Se os projetos usados em backup e restauração forem diferentes, o aplicativo exportará e importará efetivamente políticas de um projeto para outro.

Esta seção mostra o código para backup e restauração no contexto, e não como um conjunto de pequenos trechos isolados.

Como fazer backup de políticas

A operação de backup é simples. O conjunto de políticas de alertas e o conjunto de canais de notificação em cada projeto são coletados e salvos no armazenamento externo em 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):
    alert_client = monitoring_v3.AlertPolicyServiceClient()
    channel_client = monitoring_v3.NotificationChannelServiceClient()
    record = {'project_name': project_name,
              'policies': list(alert_client.list_alert_policies(project_name)),
              'channels': list(channel_client.list_notification_channels(
                  project_name))}
    json.dump(record, open('backup.json', 'wt'), cls=ProtoEncoder, indent=2)
    print('Backed up alert policies and notification channels to backup.json.')

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

Como restaurar as políticas em backup

O processo de restauração é mais complexo que o backup original. Você pode restaurar o backup original do projeto. Também é possível restaurar para um projeto diferente, fornecendo efetivamente a importação das políticas de alertas.

Em caso de restauração do mesmo projeto, todos os canais ou as políticas existentes serão atualizados, se ainda existirem. Do contrário, eles serão recriados. Os campos somente leitura como os registros de criação e mutação nas políticas de backup são apagados pelo processo de restauração antes que políticas e notificações sejam recriadas.

É possível usar uma política salva em um projeto para criar uma nova ou semelhante em outro projeto. No entanto, você precisa primeiro fazer as seguintes alterações em uma cópia da política salva:

  • Remova os seguintes campos de qualquer canal de notificação:
    • name
    • verificationStatus
  • Crie canais de notificação antes de consultar os canais nas políticas de alertas. São necessários os novos identificadores de canal.
  • Remova os seguintes campos de qualquer política de alertas que estiver recriando:
    • name
    • condition.name
    • creationRecord
    • mutationRecord

Se a política estiver sendo recriada em um novo projeto, os nomes de quaisquer condições nas políticas armazenadas em backup serão apagados, além dos registros de criação e mutação.

Quando é recriado em um projeto distinto, um canal de notificação recebe um nome diferente. Assim, o processo de restauração precisa mapear os nomes de canais em políticas de alertas armazenadas em backup para os novos nomes deles e substituir os nomes anteriores pelos novos.

Além dos nomes dos canais de notificação, o valor do campo verificationStatus não pode ser definido quando o canal é criado ou atualizado. Dessa maneira, um valor especial, unspecified, é usado. Depois que tiverem sido restaurados em um novo projeto, os canais precisarão ser verificados explicitamente.

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

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

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

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

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

    # Restore the alerts
    alert_client = monitoring_v3.AlertPolicyServiceClient()

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

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

        updated = False

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

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

Alertas e o SDK do Cloud

No SDK do Cloud, o grupo de comandos para gerenciar políticas de alertas e canais de notificação é monitoring, que está em versão alfa. O grupo monitoring está disponível no componente alpha. Ou seja, todos esses comandos começarão com:

gcloud alpha monitoring

Para verificar se você tem o componente alpha instalado, execute este comando:

gcloud components list

Se você não tiver o componente alpha instalado, execute esse comando para instalá-lo:

gcloud components install alpha

Se você tiver o componente alpha, verifique o grupo monitoring executando este comando:

gcloud alpha monitoring --help

Se o grupo monitoring não estiver incluído, o SDK do Cloud solicitará a adição dele:

You do not currently have this command group installed.
[...]
Do you want to continue (Y/n)?  y
Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…

Stackdriver Monitoring
Precisa de ajuda? Acesse nossa página de suporte.