Amplify Logger から CloudWatchLogsに送信する

Amplify Logger というのだから、ただのログ出力じゃなくて CloudWatchLogsにいい感じインテグレーションしてくれるものと思っていたら全然そんなことはなかった。

通常の使い方は前回の記事を見てみてください。

jacoyutorius.hatenablog.com

で、issueを漁ってみたら同じことを考えている人はいて、AWSCloudWatchProvider を通してAmplify Loggerでログを出すだけで CloudWatchLogsにログを飛ばしてくれるようになるプルリクエストがあって、既にマージされていた。

github.com

マージされてはいるものの、公式のドキュメントには何も記載は無かったのでプルリクエストのコードとかコメントを読みつつ試してみた(ちなみに、かなり手間取った)

手順など

その前に余談

Amplify で Storage とか Geo を追加するときに、一緒に Auth関連のリソースも作らされるの、何でなんだろう?って思ってたんだけど、AmplifyのアプリケーションからAWSのリソースを操作するためのロールが必要だから一緒に作られるんですね。 なので、ログイン機能とかが不要な場合は後述する unauthRole だけ見ておけばいい。

(多分必要)ログ送信用のIAMロールを作る

amplify add auth で認証情報を作る。ログイン機能とかは付けないので、認証情報に関する問いには雑に回答して大丈夫。

XXXX-authRoleXXXX-unauthRole の2つのロールが作られる。認証していなくてもログを送信したいので、コンソールから unauthRole に以下のロールを付与する。 .amplify 配下に生成される parameters.json をいじればロールも一緒に登録できそうだけども、今回はマネジメントコンソールから登録した。

  • DescribeLogGroups
  • DescribeLogStreams
  • CreateLogGroup
  • CreateLogStream
  • PutLogEvents
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:DescribeLogGroups",
                "logs:DescribeLogStreams",
                "logs:CreateLogGroup",
                "logs:PutLogEvents"
            ],
            "Resource": "*"
        }
    ]
}

アプリケーションに Amplify Loggerを組み込む

プルリクのコメント欄にサンプルコードが記載されてたのでそれを参考に。

import { Amplify, Logger, AWSCloudWatchProvider } from 'aws-amplify';
import awsconfig from './aws-exports';

Amplify.configure({
  Logging: {
    logGroupName: 'app-logs',
    logStreamName: `${process.env.VUE_APP_ENV}_LOGS`,
  },
  ...awsconfig
});

const amplifyLogger = new Logger('app-logs', "INFO");
Amplify.register(amplifyLogger);
amplifyLogger.addPluggable(new AWSCloudWatchProvider());

ログを送信する

amplifyLogger.info("hello world!!");

これで送信されるはずなのだけど、こんなエラーになる。

Failed to load resource: the server responded with a status of 400 (Bad Request)
ConsoleLogger.js?7aaf:127 [ERROR] 31:13.887 AWSCloudWatch - failure during log push: InvalidParameterException: 1 validation error detected: Value '' at 'sequenceToken' failed to satisfy constraint: Member must have length greater than or equal to 1

sequenceToken がブランクなのでエラーになっている様子。

CloudWatchEventsにログを送信する場合は、sequenceTokenをパラメータに含めることでログの連続性を保つ仕組みになっているみたい。

この sequenceToken の解決自体は AWSCloudWatchProvider でやってくれているようなのだけど、最初のログ送信に失敗してしまう。

プルリクのコメントを見てみると同じ問題に遭遇した人がいて、曰く

After adding an event to the stream manually, the sequenceToken value was populated correctly and subsequent log calls worked without issue. 

ログストリームの中身が空なのが良くないみたい。

ということで、マネジメントコンソールから適当なログイベントを一個登録してみた。

このあとアプリケーションからログを出力してみると・・・!

f:id:jacoyutorius:20211029074929p:plain
1行目の 「Hello!」ってログがマネジメントコンソールから登録したやつ

ここまで長かった。。。

まとめ

AmplifyからカジュアルにCloudWatchLogsにログを送ることができるようになるとアプリケーションの監視やデータ分析がかなり便利になると思う。

エラーの収集はもとより、ユーザーの操作履歴などを CloudWatchLogs => S3 に溜めておいてS3 SelectとかAthenaで分析するみたいな使い方ができると絶対楽しい。

(ユーザーの行動分析は amplify analytics があるけど、あれは Amazon Pinpointとのインテグレーションなので、CloudWatchにログを飛ばしてざっくり検証してみたいな〜みたいのとは使い所が異なるという認識です)