API를 통한 알림 채널 관리

알림 정책에는 일반적으로 트리거 시기를 알려주는 몇 가지 방법이 있는데 이 같은 방법을 알림 채널이라고 부릅니다. 채널 유형에는 여러 가지가 있으며 각 유형은 알림 채널 설명자를 통해 설명됩니다. 일정 유형의 알림 채널은 해당 유형의 설명자 인스턴스입니다. 알림 정책에는 알림 경로로 사용되는 알림 채널에 대한 참조가 포함됩니다.

알림 정책에서 사용하려면 먼저 알림 채널이 존재해야 합니다. 알림 채널 설명자가 제공되지만 사용하기 전에 채널을 만들어야 합니다.

여기에는 예: 백업 및 복원에서 설명한 알림 정책 API 예에서 추출한 코드 샘플이 사용되었습니다.

채널 설명자

Monitoring은 여러 개의 기본 제공 알림 채널 유형을 제공합니다. 각 유형은 NotificationChannelDescriptor를 통해 설명됩니다. 이 설명자에는 type 필드가 있으며 채널 유형의 인스턴스를 만들 때 이 필드의 값이 식별자로 기능합니다. 다음 명령어를 사용하여 사용 가능한 채널 유형을 검색할 수 있습니다(자세한 설명은 알림 옵션 참조).

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

프로젝트의 모든 채널 설명자를 검색하려면 notificationChannelDescriptors.list 메서드를 사용하세요. 검색된 설명자는 읽기 전용입니다.

특정 설명자를 찾고 있는 경우 설명자 이름을 알면 notificationChannelDescriptors.get 메서드를 사용하여 해당 정책만 검색할 수 있습니다. 채널 설명자의 이름은 projects/[PROJECT_ID]/notificationChannelDescriptors/[CHANNEL_TYPE][CHANNEL_TYPE] 형식이며 위에 나열된 유형 중 하나여야 합니다.

    projects/[PROJECT_ID]/notificationChannelDescriptors/email
    

gcloud 명령

프로젝트의 모든 알림 채널 설명자를 나열하려면 gcloud beta monitoring channel-descriptors list 명령어를 사용합니다.

gcloud beta 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/[PROJECT_ID]/notificationChannelDescriptors/email
        type: email
        ---
    

모든 채널 설명자에는 다음 필드가 포함됩니다.

  • name: 채널 설명자의 정규화된 리소스 이름입니다.
  • type: 채널 유형을 나타내는 이름 부분
  • displayName: 표시를 위한 type 필드에 대한 설명
  • description: 채널에 대한 간단한 설명
  • labels: 채널 유형과 관련된 필드 집합입니다. 각 채널 유형에는 고유한 라벨 집합이 있습니다.

채널이 생성되면 기본적으로 true 값을 가진 enabled 필드도 가져옵니다.

단일 채널 설명자를 나열하려면 대신 gcloud beta monitoring channel-descriptors describe를 사용하고 채널 설명자의 이름을 지정합니다. 정규화된 이름을 지정할 필요가 없습니다. 예를 들어 두 명령어 모두 위의 목록을 반환합니다.

gcloud beta monitoring channel-descriptors describe email

    gcloud beta monitoring channel-descriptors describe projects/[PROJECT_ID]/notificationChannelDescriptors/email
    

자세한 내용은 gcloud beta monitoring channel-descriptors listdescribe 참조를 확인하세요. describe 명령어는 API의 notificationChannelDescriptors.get 메서드에 해당합니다.

알림 채널

알림 채널은 채널 설명자에서 다룬 알림 채널 설명자의 인스턴스입니다.

NotificationChannel 리소스는 다음 5개 작업을 지원합니다.

  • 새 채널 만들기
  • 기존 채널 삭제
  • 특정 채널 검색
  • 모든 채널 검색
  • 기존 채널 수정

채널의 verificationStatus 필드 관리와 관련된 3개 작업도 가능합니다.

  • 인증 코드 전송
  • 확인된 채널의 인증 상태를 동일 또는 새 프로젝트의 동일한 다른 채널에 복사하는 코드 생성
  • 이전 두 작업으로 만든 코드를 사용한 채널 확인

자세한 내용은 notificationChannels 참조를 확인하세요.

채널 만들기

gcloud 명령줄 도구를 사용하여 JSON 또는 YAML 파일에서 알림 채널을 만들 수 있으며 프로그래매틱 방식으로 만들 수 있습니다.

알림 채널을 만들려면 해당 설명자의 필드에 값을 제공해야 합니다. 이 중 대부분은 type와 같이 모든 알림 채널 설명자를 통틀어 공통입니다(notificationChannelDescriptors 참조).

각 설명자에는 일련의 라벨이 있으며, 이는 설명자별로 다릅니다. 특정 설명자의 라벨 집합을 보려면 채널 설명자에 설명된 gcloud beta 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 형식의 새 pubsub 알림 채널 사양을 보여줍니다.

        {
          "type": "pubsub",
          "displayName": "Alert notifications",
          "description": "Pub/Sub channel for alert notifications",
          "labels": {
            "topic": "projects/[PROJECT_ID]/topics/notificationTopic"
          },
        }
    

type 값(pubsub) 및 단일 라벨 키(topic)는 해당 채널 설명 자의 typelabels.key 필드와 일치합니다.

채널은 기본적으로 사용 설정됩니다. 비활성 채널을 만들려면 enabled 필드에 false 값을 포함할 수 있습니다.

다음 예에서는 알림 채널의 생성을 보여줍니다.

gcloud 명령

프로젝트에서 알림 채널을 만들려면 gcloud beta monitoring channels create 명령어를 사용합니다. 파일에서 채널을 로드하려면 --channel-content-from-file 플래그를 사용하여 파일을 지정합니다.

다음 예에서는 pubsub-channel.json 파일에서 새 Pub/Sub 채널을 만듭니다.

gcloud beta monitoring channels create --channel-content-from-file="pubsub-channel.json"
    

성공하면 이 명령어가 새 채널의 이름을 반환합니다. 예를 들면 다음과 같습니다.

        Created notification channel [projects/[PROJECT_ID]/notificationChannels/1355376463305411567].
    

자세한 내용은 gcloud beta 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.projectNotificationChannelPath(projectId, id)
    );

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

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

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
    }
    

자바

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

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

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

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

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

        # Restore the alerts
        alert_client = monitoring_v3.AlertPolicyServiceClient()

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

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

            updated = False

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

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

채널 검색

프로젝트의 모든 알림 채널을 검색하려면 notificationChannels.list 메서드를 사용합니다. 또한 이 메서드는 결과를 제한하고 정렬하는 filterorderBy 옵션을 지원합니다. 자세한 내용은 정렬 및 필터링하기를 참조하세요.

특정 채널을 찾고 있는 경우 채널 이름을 알면 notificationChannels.get 메서드를 사용하여 해당 채널만 검색할 수 있습니다. 채널 이름은 projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID] 형식입니다. 예를 들면 다음과 같습니다.

        projects/[PROJECT_ID]/notificationChannels/1355376463305411567
    

채널을 검색할 때 인증 토큰 및 API 키와 같은 중요한 값이 보안상의 이유로 난독화될 수 있습니다. 기존 채널을 복사하여 새로운 채널을 생성하는 경우 난독화된 값을 수정해야 합니다.

gcloud 명령

프로젝트의 모든 알림 채널을 나열하려면 gcloud beta monitoring channels list 명령어를 사용합니다.

gcloud beta 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/[PROJECT_ID]/notificationChannels/1355376463305411567
        type: email
        ---
        description: Pub/Sub channel for alert notifications
        displayName: Alert notifications
        enabled: true
        labels:
          topic: projects/[PROJECT_ID}/topics/notificationTopic
        name: projects/[PROJECT_ID]/notificationChannels/1355376463305411567
        type: pubsub
    

단일 채널을 나열하려면 대신 gcloud beta monitoring channels describe를 사용하고 채널 이름을 지정합니다. 예를 들어 이 명령어는 위 목록에 있는 Pub/Sub 채널을 반환합니다.

gcloud beta monitoring channels describe projects/[PROJECT_ID]/notificationChannels/1355376463305411567
    
    

자세한 내용은 gcloud beta 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})
    }

자바

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 인스턴스의 displayName가 아닌 name 필드의 값입니다. 채널 이름은 projects/[PROJECT_ID]/notificationChannels/[CHANNEL_ID] 형식입니다. 예를 들면 다음과 같습니다.

        projects/[PROJECT_ID]/notificationChannels/1355376463305411567
    

기본적으로 알림 정책에서 참조하는 채널을 삭제하려고 하면 채널이 삭제되지 않습니다. 알림 정책에서 참조를 강제로 삭제하고 채널을 삭제하려면 force 옵션을 true로 설정합니다.

gcloud 명령

알림 채널을 삭제하려면 gcloud beta monitoring channels delete를 사용하고 삭제할 채널의 이름을 지정합니다. 예를 들어 다음 명령어는 다른 예에서 만든 email 채널을 삭제합니다.

gcloud beta monitoring channels delete projects/[PROJECT_ID]/notificationChannels/1355376463305411567
    

자세한 내용은 gcloud beta 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
    }
    

자바

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 명령줄 도구는 patch 대신 이 update를 호출합니다.

업데이트 작업으로는 기존 채널을 완전히 대체하거나 필드 하위 집합을 수정할 수 있습니다. 예를 들어 채널의 사용 설정 및 사용 중지가 가능합니다. 채널을 사용 중지하면 채널에 알림이 전달되지 않습니다. 임시로 변경하려는 경우에는 일반적으로 채널을 참조하는 알림 정책에서 채널을 삭제하는 것보다 채널을 사용 중지하는 편이 훨씬 더 편합니다.

gcloud 명령

사용 중지된 알림 채널을 사용 설정하려면 gcloud beta monitoring channels update 명령어를 사용하고 --enabled 플래그를 제공합니다. 다음 명령어는 이전 예에서 사용 중지된 상태로 생성된 email 알림 채널을 사용 설정합니다.

gcloud beta monitoring channels update projects/[PROJECT_ID]/notificationChannels/1355376463305411567 --enabled
    

정책을 사용 중지하려면 동일한 명령어를 사용하고 --no-enabled 플래그를 제공합니다. 자세한 내용은 gcloud beta monitoring channels update 참조를 확인하세요. update 명령어는 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.projectNotificationChannelPath(projectId, id)
    );

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

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

자바

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

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

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

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

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

        # Restore the alerts
        alert_client = monitoring_v3.AlertPolicyServiceClient()

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

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

            updated = False

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

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