AWS SDK for PHP を利用してCloudWatchのメトリクスとCloudWatchLogsのログを送信する


AWS SDK for PHP を利用して CloudWatchのメトリクスとCloudWatchLogにログを送信した時のメモです。

環境

  • PHP 5.6
  • AWS SDK for PHP version 3.77

AIMの権限

Amazon CloudWatch の権限リファレンス を参照して必要な権限を付与します。

今回は強めの権限がついていたので省略したのですが、これらが必要だと思います。

  • メトリクス
    • cloudwatch:PutMetricData
  • ログ
    • logs:DescribeLogStreams
    • logs:PutLogEvents
  • ログ(必要に応じて)
    • logs:CreateLogGroup
    • logs:CreateLogStream
    • logs:DescribeLogGroups

ログはhttps://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/QuickStartEC2Instance.html#cloudwatchlogs_iam_role_procedure を参考にしてざっくり設定するのが楽チンでした。

実装

メトリクスは CloudWatchClient::PutMetricData(array) で、ログは CloudWatchLogs:: putLogEvents(array) 送信します。

ただ、ぞれぞれに考えなければならないことがあります。

メトリクスのディメンジョン is 何

PutMetricData のParameter Syntax にある Dimensions が謎パラメータでした。

$result = $client->putMetricData([
    'MetricData' => [ // REQUIRED
        [
            'Counts' => [<float>, ...],
            'Dimensions' => [
                [
                    'Name' => '<string>', // REQUIRED
                    'Value' => '<string>', // REQUIRED
                ],
                // ...
            ],
            'MetricName' => '<string>', // REQUIRED
            'StatisticValues' => [
                'Maximum' => <float>, // REQUIRED
                'Minimum' => <float>, // REQUIRED
                'SampleCount' => <float>, // REQUIRED
                'Sum' => <float>, // REQUIRED
            ],
            'StorageResolution' => <integer>,
            'Timestamp' => <integer || string || DateTime>,
            'Unit' => 'Seconds|Microseconds|Milliseconds|Bytes|Kilobytes|Megabytes|Gigabytes|Terabytes|Bits|Kilobits|Megabits|Gigabits|Terabits|Percent|Count|Bytes/Second|Kilobytes/Second|Megabytes/Second|Gigabytes/Second|Terabytes/Second|Bits/Second|Kilobits/Second|Megabits/Second|Gigabits/Second|Terabits/Second|Count/Second|None',
            'Value' => <float>,
            'Values' => [<float>, ...],
        ],
        // ...
    ],
    'Namespace' => '<string>', // REQUIRED
]);

CloudWatch の メトリクスを選択するときに空間の次に選択するやつで、メトリクス名の左側に表示されているものです。

RDSの ディメンジョンから 「DbClusterIdentifier, EngineName」を選択すると、下の様に表示され、赤枠で囲った部分がディメンジョンです。

この場合であれば VolumeBytesUsed の値を渡す時に、Dimensions を下の様に指定しています。

'Dimensions' => [
    ['Name' => 'DbClusterIdentifier', 'Value' => rdsのクラスターメ名],
    ['Name' => 'EngineName', 'Value' => 'aurora' ]
]

CloudWatchLogsの putLogEvents のパラメータ sequenceToken

APIリファレンスに書いてある通り、ログストリームが空の時以外は指定しなければなりません。
空ではない場合は、前回の putLogEvents の戻り値から sequenceToken を得て、次回のパラメターに利用します。

You must include the sequence token obtained from the response of the previous call. An upload in a newly created log stream does not require a sequence token. You can also get the sequence token using DescribeLogStreams. If you call PutLogEvents twice within a narrow time period using the same value for sequenceToken, both calls may be successful, or one may be rejected.

https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-logs-2014-03-28.html#putlogevents より

処理としては下の様になります。

  1. describeLogStreams でログストリームの情報を取得。得られた場合は uploadSequenceToken を控えておく。
  2. putLogEvenssequenceToken に 1. で得られた uploadSequenceTokenを設定する。得られなかった場合は 設定しない。
  3. putLogEvens が成功したら、戻り値の連想配列から nextSequenceToken を取得する。
  4. その次の putLogEvenssequenceToken には 3. の nextSequenceToken を指定する。
  5. putLogEvens が成功したら、戻り値の連想配列から nextSequenceToken を取得する。

あとは、4と5の繰り返し。

これを守らないと putLogEventsInvalidSequenceTokenException が発生します。

InvalidSequenceTokenException (client): The given sequenceToken is invalid. The next expected sequenceToken is: 49590143729088555375190966164052711632594785739741365618

これは、気づくまで、意味不明なエラーでした。