使用 API 管理通知渠道

当提醒政策被触发的时候,系统通常会通过一些途径通知您。这些“通知您的途径”被称为通知渠道。目前有几种可用的渠道类型,每种类型都在通知渠道描述符中进行描述。某种类型的通知渠道是该类型描述符的实例。您的提醒政策包括对通知渠道的引用,这些通知渠道要用作通知路径。

通知渠道必须事先存在,才能用于提醒政策。系统已经提供了通知渠道描述符,但您必须先创建渠道然后才能使用这些渠道。

此处所示的代码示例提取自示例:备份和恢复中描述的提醒政策 API 示例。

渠道描述符

Stackdriver 提供了许多内置的通知渠道类型,每一种类型都由一个 NotificationChannelDescriptor 描述。这些描述符都有一个 type 字段,在创建该渠道类型的实例时,该字段的值用作其标识符。您可以使用以下命令检索可用的渠道类型,通知选项中较为广泛地描述了这些类型:

$ gcloud alpha monitoring channel-descriptors list --format='value(type)'
email
hipchat
pagerduty
slack
sms
webhook_basicauth
webhook_tokenauth

要检索项目中的所有渠道描述符,请使用 notificationChannelDescriptors.list 方法。检索到的描述符均为只读。

如果您要查找特定的描述符且知道其名称,则可使用 notificationChannelDescriptors.get 方法仅检索该渠道描述符。渠道描述符名称的格式为 projects/[PROJECT_ID]/notificationChannelDescriptors/[CHANNEL_TYPE][CHANNEL_TYPE] 必须是以上列出的类型之一,例如:

projects/a-gcp-project/notificationChannelDescriptors/email

GCLOUD 命令

要列出项目中的所有通知渠道描述符,请使用 gcloud alpha monitoring channel-descriptors list 命令:

gcloud alpha monitoring channel-descriptors list

如果成功,该 list 命令将以列表显示指定项目中所有的渠道描述符。例如,email 渠道描述符将以如下形式显示在列表中:

---
description: A channel that sends notifications via email.
displayName: Email
labels:
- description: An address to send email.
  key: email_address
name: projects/a-gcp-project/notificationChannelDescriptors/email
type: email
---

要列出单个渠道描述符,请使用 gcloud alpha monitoring channel-descriptors describe,并指定渠道描述符的名称。例如,此命令仅返回上面所列出的描述符:

gcloud alpha monitoring channel-descriptors describe projects/a-gcp-project/notificationChannelDescriptors/email

如需了解详情,请参阅 gcloud alpha monitoring channel-descriptors listdescribe 参考。describe 命令与 API 中的 notificationChannelDescriptors.get 方法相对应。

通知渠道

通知渠道是通知渠道描述符的实例,渠道描述符中介绍了这些渠道描述符。

NotificationChannel 资源支持 5 种操作:

  • 创建新渠道
  • 删除现有渠道
  • 检索特定渠道
  • 检索所有渠道
  • 修改现有渠道

另外还有三个与管理渠道的 verificationStatus 字段相关的操作:

  • 发送验证码
  • 生成代码,用于将已验证渠道的验证状态复制到同一项目或新项目的其他相同渠道
  • 使用前两个操作创建的代码验证渠道

如需了解详情,请参阅 notificationChannels 参考。

创建渠道

您可以使用 gcloud 命令行工具从 JSON 或 YAML 文件创建通知渠道,也可以通过编程方式创建。

要创建通知渠道,必须为其描述符中的字段提供值。其中大多数字段在所有通知渠道描述符中都很常见,如 type;请参阅 notificationChannelDescriptors

每个描述符均有一组标签,且各不相同。要查看特定描述符的标签集,请使用渠道描述符中介绍的 gcloud alpha monitoring channel-descriptors describe 命令检索描述符。例如,检索 email 渠道描述符会显示单个标签:

labels:
- description: An address to send email.
  key: email_address

检索 webhook_basicauth 渠道描述符会显示多个标签:

labels:
- description: The password. The field is obfuscated when the channel is fetched.
  key: password
- description: The URL to which to publish the webhook.
  key: url
- description: The username.
  key: username

无论是以编程方式还是从命令行创建新渠道,规范中 type 的值必须与相应通知渠道描述符中的 type 字段相匹配。任何必需的标签键也必须与渠道描述符中的字段相匹配。

一些标签对应着用来对提供商进行身份验证的凭据。创建渠道时,系统必须从提供商获取这些标签的值。获取凭据可能包含使用提供商网站上的 API 密钥生成页面或完成提供商的 OAuth 登录流程。获得这种凭据的方式的具体情况取决于特定的提供商。

例如,下面显示了 JSON 中新 email 通知渠道的规范:

{
  "type": "email",
  "displayName": "test e-mail channel",
  "description": "E-mail channel created by gcloud as a test",
  "labels": {
    "email_address": "user@example.com"
  },
  "enabled": false
}

type 值 (email) 和单个标签键 (email_address) 分别匹配相应渠道描述符中的 typelabels.key 字段。

下面举例说明了创建通知渠道的过程。

GCLOUD 命令

要在项目中创建通知渠道,请使用 gcloud alpha monitoring channels create 命令。要从文件加载渠道,请使用 --channel-content-from-file 标志指定文件。

以下示例从 new-email-channel.json 文件在 a-gcp-project 新建了一个电子邮件渠道。

gcloud alpha monitoring channels create --channel-content-from-file="new-email-channel.json"

如果成功,此命令将返回新渠道的名称,例如:

Created notification channel [projects/a-gcp-project/notificationChannels/1355376463305411567].

如需了解详情,请参阅 gcloud alpha monitoring channels create 参考。

C#

static void RestorePolicies(string projectId, string filePath)
{
    var policyClient = AlertPolicyServiceClient.Create();
    var channelClient = NotificationChannelServiceClient.Create();
    List<Exception> exceptions = new List<Exception>();
    var backup = JsonConvert.DeserializeObject<BackupRecord>(
        File.ReadAllText(filePath), new ProtoMessageConverter());
    var projectName = new ProjectName(projectId);
    bool isSameProject = projectId == backup.ProjectId;
    // When a channel is recreated, rather than updated, it will get
    // a new name.  We have to update the AlertPolicy with the new
    // name.  Track the names in this map.
    var channelNameMap = new Dictionary<string, string>();
    foreach (NotificationChannel channel in backup.Channels)
    {
        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)
    {
    }
    if (exceptions.Count > 0)
    {
        throw new AggregateException(exceptions);
    }
}

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}.`);

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

PHP

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

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

    $channel = new NotificationChannel();
    $channel->setDisplayName('Test Notification Channel');
    $channel->setType('email');
    $channel->setLabels(['email_address' => 'fake@example.com']);

    $channel = $channelClient->createNotificationChannel($projectName, $channel);
    printf('Created notification channel %s' . PHP_EOL, $channel->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)

检索渠道

要检索项目中的所有通知渠道,请使用 notificationChannels.list 方法。此方法还支持使用 filterorderBy 选项对结果进行限制和排序;请参阅排序和过滤

如果您想要查找特定渠道且知道该渠道名称,可使用 notificationChannels.get 方法仅检索该渠道。渠道名称的格式为 projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID],例如:

projects/a-gcp-project/notificationChannels/1355376463305411567

检索渠道时,出于安全原因,系统可能会对身份验证令牌和 API 密钥等敏感值进行模糊处理。如果通过复制现有渠道来创建新渠道,则需要更正任何模糊处理的值。

GCLOUD 命令

要列出项目中的所有通知渠道描述符,请使用 gcloud alpha monitoring channels list 命令:

gcloud alpha monitoring channels list

如果成功,list 命令将以列表形式显示指定项目中的所有渠道。例如,上面的命令会生成一个包含以下内容的列表:

---
description: E-mail channel created by gcloud as a test
displayName: test e-mail channel
enabled: false
labels:
  email_address: user@example.com
name: projects/a-gcp-project/notificationChannels/1355376463305411567
type: email
---

要列出单个渠道,请使用 gcloud alpha monitoring channels describe,并指定渠道的名称。例如,此命令仅返回上面所列出的渠道:

gcloud alpha monitoring channels describe projects/a-gcp-project/notificationChannels/1355376463305411567

如需了解详情,请参阅 gcloud alpha monitoring channels listdescribe 参考。describe 命令与 API 中的 notificationChannels.get 方法相对应。

C#

static void ListNotificationChannels(string projectId)
{
    var client = NotificationChannelServiceClient.Create();
    var response = client.ListNotificationChannels(new ProjectName(projectId));
    foreach (NotificationChannel channel in response)
    {
        Console.WriteLine(channel.Name);
        if (channel.DisplayName != null)
        {
            Console.WriteLine(channel.DisplayName);
        }
        Console.WriteLine();
    }
}

Node.js

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

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

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

const request = {name: client.projectPath(projectId), filter};
const channels = await client.listNotificationChannels(request);
console.log(channels);
for (const channel of channels[0]) {
  console.log(`Deleting channel ${channel.displayName}`);
  try {
    await client.deleteNotificationChannel({
      name: channel.name,
    });
  } catch (err) {
    // ignore error
  }
}

Go

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

Java

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

PHP

use Google\Cloud\Monitoring\V3\NotificationChannelServiceClient;

/**
 * @param string $projectId Your project ID
 */
function alert_list_channels($projectId)
{
    $channelClient = new NotificationChannelServiceClient([
        'projectId' => $projectId,
    ]);

    $channels = $channelClient->listNotificationChannels(
        $channelClient->projectName($projectId)
    );
    foreach ($channels->iterateAllElements() as $channel) {
        printf('Name: %s (%s)' . PHP_EOL, $channel->getDisplayName(), $channel->getName());
    }
}

Python

def list_notification_channels(project_name):
    client = monitoring_v3.NotificationChannelServiceClient()
    channels = client.list_notification_channels(project_name)
    print(tabulate.tabulate(
        [(channel.name, channel.display_name) for channel in channels],
        ('name', 'display_name')))

删除渠道

要从项目中删除通知渠道,请使用 notificationChannels.delete 方法,并提供要删除的通知渠道的名称。渠道名称是 name 字段的值,而不是 NotificationChannel 实例中的 displayName。渠道名称的格式为 projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID],例如:

projects/a-gcp-project/notificationChannels/1355376463305411567

默认情况下,如果您尝试删除被提醒政策引用的渠道,则该渠道将不会被删除。要强制移除提醒政策的引用,并删除渠道,请将 force 选项设置为 true

GCLOUD 命令

要删除通知渠道,请使用 gcloud alpha monitoring channels delete 方法,并指定要删除的渠道的名称。例如,以下命令将删除在另一个示例中创建的 email 渠道:

gcloud alpha monitoring channels delete projects/a-gcp-project/notificationChannels/1355376463305411567

如需了解详情,请参阅 gcloud alpha monitoring channels delete 参考。

C#

using Google.Cloud.Monitoring.V3;
using System;

partial class AlertSnippets
{
    public void DeleteNotificationChannel(
        string channelName = "projects/your-project-id/notificationChannels/123")
    {
        var client = NotificationChannelServiceClient.Create();
        client.DeleteNotificationChannel(
            name: NotificationChannelName.Parse(channelName),
            force: true);
        Console.WriteLine("Deleted {0}.", channelName);
    }
}

Go

import (
	"context"
	"fmt"
	"io"

	monitoring "cloud.google.com/go/monitoring/apiv3"
	monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3"
)

// deleteChannel deletes the given channel. channelName should be of the form
// "projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID]".
func deleteChannel(w io.Writer, channelName string) error {
	ctx := context.Background()

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

	req := &monitoringpb.DeleteNotificationChannelRequest{
		Name: channelName,
	}

	if err := client.DeleteNotificationChannel(ctx, req); err != nil {
		return fmt.Errorf("DeleteNotificationChannel: %v", err)
	}

	fmt.Fprintf(w, "Deleted channel %q", channelName)
	return nil
}

Java

static void deleteNotificationChannel(String channelName) throws IOException {
  String projectId = System.getProperty("projectId");
  try (NotificationChannelServiceClient client = NotificationChannelServiceClient.create()) {
    NotificationChannelName name = NotificationChannelName.of(projectId, channelName);
    client.deleteNotificationChannel(channelName, false);
    System.out.println("Deleted notification channel " + channelName);
  }
}

PHP

use Google\Cloud\Monitoring\V3\NotificationChannelServiceClient;

/**
 * @param string $projectId Your project ID
 */
function alert_delete_channel($projectId, $channelId)
{
    $channelClient = new NotificationChannelServiceClient([
        'projectId' => $projectId,
    ]);
    $channelName = $channelClient->notificationChannelName($projectId, $channelId);

    $channelClient->deleteNotificationChannel($channelName);
    printf('Deleted notification channel %s' . PHP_EOL, $channelName);
}

Node.js

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

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

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

const request = {name: client.projectPath(projectId), filter};
const channels = await client.listNotificationChannels(request);
console.log(channels);
for (const channel of channels[0]) {
  console.log(`Deleting channel ${channel.displayName}`);
  try {
    await client.deleteNotificationChannel({
      name: channel.name,
    });
  } catch (err) {
    // ignore error
  }
}

Python

def delete_notification_channels(project_name, channel_ids, force=None):
    channel_client = monitoring_v3.NotificationChannelServiceClient()
    for channel_id in channel_ids:
        channel_name = '{}/notificationChannels/{}'.format(
            project_name, channel_id)
        try:
            channel_client.delete_notification_channel(
                channel_name, force=force)
            print('Channel {} deleted'.format(channel_name))
        except ValueError:
            print('The parameters are invalid')
        except Exception as e:
            print('API call failed: {}'.format(e))

修改渠道

要修改通知渠道,请使用 REST API 中的 notificationChannels.patch 方法。其他 API 实现和 gcloud 界面称之为 update,而不是 patch

更新操作可以完全替换现有的渠道,也可以修改其中一部分字段。例如,您可以启用或停用渠道。停用渠道会阻止通知发送到该渠道。通常情况下,如果只是想暂时不使用某渠道,则将被提醒政策引用的渠道停用比将其删除更简便一些。

GCLOUD 命令

要启用已停用的通知渠道,请使用 gcloud alpha monitoring channels update 命令,并提供 --enabled 标志。以下命令可启用前一示例创建的 email 通知渠道(当时处于停用状态)。

gcloud alpha monitoring channels update projects/a-gcp-project/notificationChannels/1355376463305411567 --enabled

要停用某政策,请使用同一命令,并提供 --no-enabled 标志。如需了解详情,请参阅 gcloud alpha monitoring channels update 参考。update 命令与 REST API 中的 notificationChannels.patch 方法相对应。

C#

using Google.Cloud.Monitoring.V3;
using Google.Protobuf.WellKnownTypes;
using System;

partial class AlertSnippets
{
    public NotificationChannel EnableNotificationChannel(
        string channelName = "projects/your-project-id/notificationChannels/123")
    {
        var client = NotificationChannelServiceClient.Create();
        NotificationChannel channel = new NotificationChannel();
        channel.Enabled = true;
        channel.Name = channelName;
        var fieldMask = new FieldMask { Paths = { "enabled" } };
        channel = client.UpdateNotificationChannel(
            updateMask: fieldMask,
            notificationChannel: channel);
        Console.WriteLine("Enabled {0}.", channel.Name);
        return channel;
    }
}

Go

import (
	"context"
	"fmt"
	"io"

	monitoring "cloud.google.com/go/monitoring/apiv3"
	"github.com/golang/protobuf/ptypes/wrappers"
	monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3"
	"google.golang.org/genproto/protobuf/field_mask"
)

// enableChannel enables the given channel. channelName should be of the form
// "projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID]".
func enableChannel(w io.Writer, channelName string) error {
	ctx := context.Background()

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

	req := &monitoringpb.UpdateNotificationChannelRequest{
		UpdateMask: &field_mask.FieldMask{Paths: []string{"enabled"}},
		NotificationChannel: &monitoringpb.NotificationChannel{
			Name:    channelName,
			Enabled: &wrappers.BoolValue{Value: true},
		},
	}

	if _, err := client.UpdateNotificationChannel(ctx, req); err != nil {
		return fmt.Errorf("EnableNotificationChannel: %v", err)
	}

	fmt.Fprintf(w, "Enabled channel %q", channelName)
	return nil
}

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}.`);

Java

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

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)

此页内容是否有用?请给出您的反馈和评价:

发送以下问题的反馈:

此网页
Stackdriver Monitoring
需要帮助?请访问我们的支持页面