CDKをv1からv2に移行した際に気づいたAmazon CloudWatch Alarmのアラーム定義の変化

2023.06.26

はじめに

CDKv1は23年6月1日でサポートが終了したということも有り、CDKv2への移行を検討している方も多いと思います。
AWS CDKv2 への移行
v2に移行した際に、CloudWatchのアラーム設定のプロパティの1つである期間(period)の定義の仕方に変化が有りました。
具体的には元々Alarmクラスで定義できたpriodプロパティがなくなっており、別のクラスを使って定義する事になっていました。

periodについて

periodは指定した値分の時間毎にデータの評価するというものです。
似たようなプロパティにevaluationPeriodsも有るのですが、こちらはいくつのperiodを評価するかというものです。
例えばperiodを2分、evaluationPeriodsを3とした場合、2分毎に1度のデータ評価を3回することになります。連続して3回ともしきい値の条件に該当する場合にアラームが発報します。
詳しくは公式ドキュメントの説明を御覧ください。
Amazon CloudWatch でのアラームの使用 -アラームの評価-

リソースの構成

CDKv2に移行していたリソースの構成は、以下の通りです。
Lambda関数がInvokeErrorを起こした際にロググループのエラーログをメトリクスフィルターで拾い、Amazon CloudWatch Alarmでアラームを発報させるといったものです。

CDKv1の場合

まずv1の時の設定を見ていきます。 periodとevaluationPeriodsの設定値は以下です。

  • period = 2分
  • evaluationPeriods = 3つ

コードは以下のように書きました。

Dockerfile

  import * as cdk from '@aws-cdk/core';
  import * as CloudWatch from '@aws-cdk/aws-CloudWatch';
  import * as logs from '@aws-cdk/aws-logs';
  export class cwAlarmStack extends cdk.Stack {
    constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
      super(scope, id, props);

      const logGroup = logs.LogGroup.fromLogGroupArn(
        this,
        'logGroup',
        this.node.tryGetContext('logGroup'),
      );

      const metricNamespace = 'AWS/Lambda';
      const metricName = 'InvokeErrors';

      const filter = new logs.MetricFilter(this, 'errorLogfilter', {
        filterPattern: {
          logPatternString: '"Error"',
        },
        metricNamespace: metricNamespace,
        metricName: metricName,
        logGroup: logGroup,
      });

      const alarmName = `lambdaErrorAlarm`;
      new cloudwatch.Alarm(this, alarmName, {
        alarmName: alarmName,
        alarmDescription: 'Lambda関数のInvokeエラーが発生しました',
        metric: filter.metric(),
        actionsEnabled: true,
        period: cdk.Duration.minutes(2),
        threshold: 1,
        evaluationPeriods: 3,
        comparisonOperator:
          cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
        treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,
      });
    }
  }

v1のアラーム設定

先程のコード中でCloudWatch Alarmのプロパティを指定する箇所は以下となります。

Dockerfile

  new CloudWatch.Alarm(this, alarmName, {
    alarmName: alarmName,
    alarmDescription: 'Lambda関数のInvokeエラーが発生しました',
    metric: filter.metric(),
    actionsEnabled: true,
    period: cdk.Duration.minutes(2),
    threshold: 1,
    evaluationPeriods: 3,
    comparisonOperator:
      CloudWatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
    treatMissingData: CloudWatch.TreatMissingData.NOT_BREACHING,
  });

今回取り上げるプロパティがperiodです。 CDKv1の場合は、Alarmクラスがこのプロパティを持っています。 ですが、v2ではこのプロパティが無くなっており、VS code上で以下のようなプロパティが存在しない旨の警告がでしまいます。 v2のリファレンスをみるとやはりAlarmクラスのページにはなくなっておりました。
CDKv2 class Alarm (construct)

そこでリファレンスを探ってみるとperiodはMetricクラスが持っていることがわかりました。
CDKv2 Metric objects
こちらのページに有る例を参考にコードを書き換えて見ました。

※ v1もMetricクラスがperiodを持っており、MetricクラスでもAlarmクラスでも指定できていた状況が見直されたのかもしれません。
CDKv1 Metric objects

CDKv2の場合

v2に移行したコードが以下のコードになります。

Dockerfile

import {
  Stack,
  StackProps,
  aws_logs,
  aws_cloudwatch,
  Duration,
} from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class cwAlarmStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const logGroup = aws_logs.LogGroup.fromLogGroupArn(
      this,
      'logGroup',
      this.node.tryGetContext('logGroup'),
    );

    const metricNamespace = 'AWS/Lambda';
    const metricName = 'InvokeErrors';

    new aws_logs.MetricFilter(this,'errorLogfilter',{
        filterPattern: {
          logPatternString: '"Error"',
        },
        metricNamespace: metricNamespace,
        metricName: metricName,
        logGroup,
      },
    );

    const metric = new aws_cloudwatch.Metric({
      namespace: metricNamespace,
      metricName: metricName,
      period: Duration.minutes(2),
    });

    const alarmName = `lambdaErrorAlarm`;
    new aws_cloudwatch.Alarm(this, alarmName, {
      alarmName,
      alarmDescription: 'Lambda関数のInvokeエラーが発生しました',
      metric: metric,
      actionsEnabled: true,
      threshold: 1,
      evaluationPeriods: 3,
      comparisonOperator:
        aws_cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
      treatMissingData: aws_cloudwatch.TreatMissingData.NOT_BREACHING,
    });
  }
}

v2のアラーム設定

変更箇所が以下ハイライト部分となります。

Dockerfile

  const metric = new aws_cloudwatch.Metric({
    namespace: metricNamespace,
    metricName: metricName,
    period: Duration.minutes(2),
  });

  const alarmName = `lambdaErrorAlarm`;
  new aws_cloudwatch.Alarm(this, alarmName, {
    alarmName,
    alarmDescription: 'Lambda関数のInvokeエラーが発生しました',
    metric: metric,
    actionsEnabled: true,
    threshold: 1,
    evaluationPeriods: 3,
    comparisonOperator:
      aws_cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
    treatMissingData: aws_cloudwatch.TreatMissingData.NOT_BREACHING,
  });

peridの値の指定のためMetricオブジェクトを作成し、Alarmクラスのmetricプロパティに指定しています。 v1のときと同じでDurationクラスを使用して値を設定します。

デプロイされたアラームの確認

デプロイ後にCloudWatchのアラームを確認してみます。
2分間に1回の評価を3回実行するので、マネジメントコンソール上では6 分内の3データポイントのtest >= 1となっております。
想定通りのアラーム発報条件となりました。

さいごに

Amazon CloudWatch Alarmについて細かい内容でしたがCDKがv2になったことによるアラーム定義の変化について書かせていただきました。
CDKv2になって今回のようにところどころプロパティの指定方法が変わっていて、移行の時に今まで有ったプロパティが無い!という状況になることが結構有りました。
今後も気づいたらブログに残したいと思います。