由 API 管理通知管道

快訊政策通常可以透過某種方式讓您知道何時已觸發快訊政策。這些「讓您知道的方式」稱為通知管道。目前有一些可用的管道類型;每一種類型都在通知管道描述元中說明。某種類型的通知管道就是該類型描述元的執行個體。 您的快訊政策包含做為通知途徑使用的通知管道參照。

必須先存在通知管道,才能在快訊政策中使用通知管道。 系統為您提供了通知管道描述元,但您必須先建立管道,才能使用管道。

在這裡使用的程式碼範例是從快訊政策 API 範例中擷取出來的,我們會在範例:備份與還原中加以說明。

管道描述元

Stackdriver 提供一些內建的通知管道類型,每一種類型都會在 NotificationChannelDescriptor 中說明。這些描述元具有 type 欄位,這個欄位的值可在建立該管道類型的執行個體時做為 ID 使用。您可以使用下列指令擷取可用的頻道類型 (在通知選項中有更廣泛的說明):

$ 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 資源支援五種作業:

  • 建立新管道
  • 刪除現有管道
  • 擷取特定管道
  • 擷取所有管道
  • 修改現有管道

還有其他三種作業與管理管道的 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 標記來指定檔案。

以下範例在 a-gcp-project 中從 new-email-channel.json 檔案建立了新電子郵件管道:

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 方法,並提供要刪除的通知管道名稱。在 NotificationChannel 執行個體中,管道的名稱是 name 欄位的值,不是 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))

修改管道

如要修改通知管道,請使用 notificationChannels.patch 方法 (在 REST API 中)。其他 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
需要協助嗎?請前往我們的支援網頁