☺️

Amazon API Gatewayの使用量プランをモニタリングする

2024/06/09に公開

はじめに

Amazon API Gatewayは、RESTful APIやWebSocketなどを通じてサービスを提供するためのサーバーレスAPIサービスです。
LambdaをはじめとしたさまざまなAWSのサービスと連携させることで簡単にAPIの作成と外部公開が可能となります。

使用量プラン

API Gatewayは、APIの構築、APIキーの設定、使用量プランの作成などを行うことができます。
使用量プランという設定を初めて聞く方もいるかもしれません。
使用量プランは、APIキー毎にアクセス制限を設定することで、APIの利用を管理し、無制限にアクセスされることなくコストを抑えるために重要です。

使用量プランには、スロットリング制限やクォータ制限があり、これらのパラメータを使って制御できます。

  • スロットリング:ユーザーが1秒間あたりにAPIを呼び出しできる回数
  • クォータ:ユーザーがAPIを呼び出しできる総回数のこと

つまりAPIキー(ユーザごと)にAPIの起動回数や同時実行数をコントロールできるということです。
例えばAPIを公開した時に料金プラン等を設定し、契約ごとに使用回数を制御したい場合にも活用できます。

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-api-usage-plans.html

使用量プランの確認方法

使用量プランは下図のようにAPI Gatewayの使用量プランから確認できます。

使用量データをエクスポートすると下記のようなJSONもしくはCSV形式でダウンロード可能です。
1APIだけならまぁなんとかといった感じですが、大量の使用量プランがあるとわかりづらいですね…

{
  "cmnybyxewj": [
    [
      0,
      10
    ],
    [
      0,
      10
    ],
    [
      0,
      10
    ],
    [
      0,
      10
    ],
    [
      0,
      10
    ],
    [
      0,
      10
    ],
    [
      0,
      10
    ],
    [
      0,
      10
    ],
    [
      1,
      9
    ]
  ],
  "wmzndd3bs0": [
    [
      0,
      10
    ],
    [
      0,
      10
    ],
    [
      0,
      10
    ],
    [
      0,
      10
    ],
    [
      0,
      10
    ],
    [
      0,
      10
    ],
    [
      0,
      10
    ],
    [
      4,
      6
    ],
    [
      1,
      5
    ]
  ]

使用量プランをCloudWatchで確認する

CloudWatchの標準メトリクスではAPI Gatewayの使用量プランの状態を確認することはできません。
※リクエスト数は確認できますが、厳密に使用量プランの回数と一致するわけではありません。

通常だと先ほどのJSONまたはCSVもしくはAPIGatewayのダッシュボードで確認することとなりますが、それだと確認しづらかったりします。

そこで今回は使用料プランをCloudWatchで確認できるようにします。

Lambdaの作成

ポイントとなるのは使用量をどのように取得するかですが、下記の流れで使用量を取得することができます。

  1. アカウントに紐づく使用量プランを取得
  2. 使用量プランに紐づくキー情報の取得
  3. キー情報に紐づく使用量の取得

https://docs.aws.amazon.com/ja_jp/apigateway/latest/api/API_GetUsagePlans.html

https://docs.aws.amazon.com/ja_jp/apigateway/latest/api/API_GetUsagePlanKeys.html

https://docs.aws.amazon.com/ja_jp/apigateway/latest/api/API_GetUsage.html

下記サンプルです。
メトリクスを取得してCloudWatchにputするだけのシンプルなものです。

今回は残量をパーセントで表示するように設定しました。
もし残数が数値でほしい場合は
下記のように残数を取得するようにすればOKです。
var utilization = usage.items[apiKey][0][1];

index.mjs
import { APIGateway } from "@aws-sdk/client-api-gateway";
import { CloudWatch } from "@aws-sdk/client-cloudwatch";
const apiGateway = new APIGateway();
const cloudWatch = new CloudWatch();

const nameSpace = process.env.METRIC_NAMESPACE;

export const handler = async (event, context) => {

  // メトリクスの取得
  const currentDate = new Date().toISOString().split('T')[0];
  console.log("currentDate: ", currentDate);

  try {
    const usagePlans = await apiGateway
      .getUsagePlans()
      .then((usagePlans) => usagePlans);

    console.log("UsagePlans: ", usagePlans);

    for (var item of usagePlans.items) {
      const usagePlan = item.name;

      console.log("UsagePlans: ", item);

      const usagePlanKeys = await apiGateway
        .getUsagePlanKeys({ usagePlanId: item.id })
        .then((usagePlanKeys) => usagePlanKeys);

      console.log("usagePlanKeys: ", usagePlanKeys);

      for (var key of usagePlanKeys.items) {
        const keyName = key.name;

        const usage = await apiGateway
          .getUsage({
            usagePlanId: item.id,
            keyId: key.id,
            startDate: currentDate,
            endDate: currentDate,
          })
          .then((usage) => usage);

        console.log("Usage: ", usage);

        if (usage.items) {
          for (var apiKey in usage.items) {

            console.log("usage.items: ", usage.items);
            console.log("item.limit: ", item.quota.limit);

            var utilization = parseFloat(
              (usage.items[apiKey][0][1] / item.quota.limit) * 100
            );

            console.log("apiKey: ", apiKey);
            console.log("usagePlan: ", usagePlan);
            console.log("keyName: ", keyName);

            // CloudWatchに出力
            const response = await cloudWatch
              .putMetricData({
                Namespace: nameSpace,
                MetricData: [
                  {
                    MetricName: "API Gateway Usage",
                    Dimensions: [
                      {
                        Name: "Usage Plan",
                        Value: usagePlan,
                      },
                      {
                        Name: "API Key",
                        Value: keyName,
                      },
                    ],
                    Value: utilization,
                    StorageResolution: 60,
                    Unit: "Percent",
                  },
                ],
              })
              .then((response) => response);
          }
        }
      }
    }
  } catch (error) {
    console.error("getUsage Error: ", error);
  }
};

EventBridgeの設定

EventBridgeで定期実行します。

実行結果

このような感じで出力されます。
複数の使用量プラン、キーごとの使用量がまとめて確認可能です。
※サンプルでは1つの使用量プランと2つのキーを出力しています。

↓残り回数がパーセンテージで表示される。(ゲージで見るとわかりやすいかも)

さらに機能を拡張する

CloudWatchにアラームを設定してSNS経由でオペレータに通知が行くようにすると便利です。

ちなみにダッシュボードより上限を拡張することができます。

また、UpdateUsageでも同様にクォータを拡張できるのでアラーム⇒SNS⇒拡張用のLambdaを起動するようにしてもいいかもしれません。
※拡張要否を判断するロジックを組んで条件によって拡張するような動きがいいかなと思います。

https://docs.aws.amazon.com/ja_jp/apigateway/latest/api/API_UpdateUsage.html

注意事項

getUsageで取得する使用量ですが、反映までタイムラグがあるようです。
アラームを出すタイミングとしては使用量のギリギリではなく、少し余裕を持った閾値としておいたほうがよさそうです。

まとめ

API Gatewayの使用量確認の手順について紹介しました。
API Gatewayの使用量プランはリソースのアクセス量を制御するために非常に有効な手段です。

システムの稼働当初や新サービス導入直後等リクエストの量が予測できない場合、制限を超過してしまいサービスが使用不可となることが考えられます。
こういったことを回避するために使用量のトラッキングは必要不可欠となります。

CloudWatchの標準メトリクスでは確認できないので今回のように自作で監視と通知を行えるようにしておくともしもの時の保険になると思います。

Discussion