AWSが提供するアカウント・アクティビティのリアルタイム分析のダッシュボードをカスタマイズする

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

先日、アマゾンがアカウント・アクティビティのリアルタイムタイム分析ソリューションのリファレンス実装を公開しました。

Introducing the Real-Time Insights on AWS Account Activity

AWSが提供するアカウント・アクティビティのリアルタイム分析ソリューションを試してみた

AWS CloudTrailでアカウント・アクティビティを取得し、Amazon Kinesis Data Analyticsでリアルタイム分析し、DynamoDB に保存したメトリクスをダッシュボード表示します。

リージョン情報のメトリクスを追加

次の公式ドキュメントにて、ダッシュボードにリージョン毎のAPI呼び出し数のメトリクスを追加する手順が紹介されていたため、実際にやってみました。

AWS Documentation » AWS Answers » Real-Time Insights on AWS Account Activity » Appendix B: Customizing the Dashboard

AWS CloudTrail ログに含まれるリージョン情報を活用します

{
  "eventVersion": "1.03",
  "userIdentity": {
      "type": "IAMUser",
      "principalId": "111122223333",
      "arn": "arn:aws:iam::111122223333:user/myUserName",
      "accountId": "111122223333",
      "accessKeyId": "AKIAIOSFODNN7EXAMPLE",
      "userName": "myUserName"
    },
  "eventTime": "2015-08-26T20:46:31Z",
  "eventSource": "s3.amazonaws.com",
  "eventName": "GetBucketVersioning",
  "awsRegion": "us-west-2",
  "sourceIPAddress": "",
  "userAgent": "[]",
  "requestParameters": {
      "bucketName": "myawsbucket"
  },
  "responseElements": null,
  "requestID": "07D681279BD94AED",
  "eventID": "f2b287f3-0df1-4961-a2f4-c4bdfed47657",
  "eventType": "AwsApiCall",
  "recipientAccountId": "111122223333"
}

メトリクスを追加する流れ

以下を修正します。

  • ストリームデータを分析する Amazon Kinesis Data Analytics
  • DynamoDB に保存されたメトリクスを表示するダッシュボードの HTML

対して

  • アカウントアクティビティの記録するAWS CloudTrail
  • Kinesis Analytics のアウトプットを DynamoDB に保存する Lambda

などは修正不要です。

リファレンス実装らしく、コア機能だけを提供し、ユーザーがカスタマイズしやすいソリューションとなっています。

Amazon Kinesis Data Analytics の修正

ソーススキーマにリージョン情報を追加し、リージョン毎の集計を行う PUMP を追加します。

ソーススキーマの変更

データソースを SQL 操作するために、JSON で渡ってくるインプットレコードと SQL 操作するためのスキーマのマッピングを行います。

Amazon Kinesis Data Analytics のコンソールに移動します

アプリケーション「RealTimeInsightsAccountActivityApp」を選択し、「Go to SQL results」をクリックします。

「Source Data」タブで「Edit schema」をクリックします。

「+ Add column」ボタンから添付画像のようにリージョン用カラムを追加し、「Save schema and update stream samples」ボタンをクリックして、スキーマ変更を保存します。

最後に先程の「Go to SQL results」から「awsRegion」カラムが追加されていることを確認します。

PUMP の変更

PUMP ではデータソースのストリーミングデータに対して SQL を実行します。 今回はリージョンを切り口とした分析を追加します。

「SQL Editor」ページから「Real-time analytics」タブを選択し、次の SQL を最後に追加します。

CREATE OR REPLACE PUMP "PUMP_FOR_CALLS_BY_REGION" AS
  INSERT INTO "DESTINATION_SQL_STREAM"
    SELECT eventTimeStamp, 'CallsPerRegion', "awsRegion" , 'None', 'Sum', callsPerRegion FROM (
       SELECT STREAM STEP(cloudtraillogs."eventTimestamp" BY INTERVAL '10' SECOND) as eventTimeStamp, COUNT(*) callsPerRegion, "awsRegion"
       FROM "SOURCE_SQL_STREAM_001" cloudtraillogs
       GROUP BY "awsRegion", STEP(cloudtraillogs.ROWTIME BY INTERVAL '10' SECOND), STEP(cloudtraillogs."eventTimestamp" BY INTERVAL '10' SECOND));

入力ストリーム「DESTINATION_SQL_STREAM」に対してSQLを実行し、出力ストリーム「DESTINATION_SQL_STREAM」に結果を出力する PUMP「PUMP_FOR_CALLS_BY_REGION」 です。

SQL 修正後は「Save and run SQL」ボタンをクリックします。

DynamoDB からこのPUMPに対応するメトリクスが追加されていることを確認します。

ダッシュボードの修正

最後にダッシュボードを作成します。

ダッシュボードは S3 の Static website hosting 機能 を利用して HTML/JavaScript だけで実装されています。

ダッシュボードにメトリクスを追加するために、一部修正します。

ソースコードの取得

まずは、ローカルに HTML/JavaScript ファイルを取得します。

S3 バケット名には、 CloudFormation で指定したバケットを指定します。

$ aws s3 sync s3://YOUR-BUCKET-NAME .
download: s3://YOUR-BUCKET-NAME/css/font-awesome.min.css to css/font-awesome.min.css
download: s3://YOUR-BUCKET-NAME/fonts/fontawesome-webfont.woff to fonts/fontawesome-webfont.woff
download: s3://YOUR-BUCKET-NAME/css/custom.css to css/custom.css
download: s3://YOUR-BUCKET-NAME/fonts/fontawesome-webfont.eot to fonts/fontawesome-webfont.eot
download: s3://YOUR-BUCKET-NAME/fonts/fontawesome-webfont.woff2 to fonts/fontawesome-webfont.woff2
download: s3://YOUR-BUCKET-NAME/help.html to ./help.html
download: s3://YOUR-BUCKET-NAME/fonts/FontAwesome.otf to fonts/FontAwesome.otf
download: s3://YOUR-BUCKET-NAME/fonts/fontawesome-webfont.ttf to fonts/fontawesome-webfont.ttf
download: s3://YOUR-BUCKET-NAME/css/bootstrap.min.css to css/bootstrap.min.css
download: s3://YOUR-BUCKET-NAME/js/app-variables.js to js/app-variables.js
download: s3://YOUR-BUCKET-NAME/js/amazon-cognito-identity.min.js to js/amazon-cognito-identity.min.js
download: s3://YOUR-BUCKET-NAME/js/dash.js to js/dash.js
download: s3://YOUR-BUCKET-NAME/js/bootstrap.min.js to js/bootstrap.min.js
download: s3://YOUR-BUCKET-NAME/js/dashboard-use.js to js/dashboard-use.js
download: s3://YOUR-BUCKET-NAME/fonts/fontawesome-webfont.svg to fonts/fontawesome-webfont.svg
download: s3://YOUR-BUCKET-NAME/js/jquery.min.js to js/jquery.min.js
download: s3://YOUR-BUCKET-NAME/js/Chart.js to js/Chart.js
download: s3://YOUR-BUCKET-NAME/dash.html to ./dash.html
download: s3://YOUR-BUCKET-NAME/js/aws-cognito-sdk.min.js to js/aws-cognito-sdk.min.js

$ tree .
.
├── css
│   ├── bootstrap.min.css
│   ├── custom.css
│   └── font-awesome.min.css
├── dash.html
├── fonts
│   ├── FontAwesome.otf
│   ├── fontawesome-webfont.eot
│   ├── fontawesome-webfont.svg
│   ├── fontawesome-webfont.ttf
│   ├── fontawesome-webfont.woff
│   └── fontawesome-webfont.woff2
├── help.html
└── js
    ├── Chart.js
    ├── amazon-cognito-identity.min.js
    ├── app-variables.js
    ├── aws-cognito-sdk.min.js
    ├── bootstrap.min.js
    ├── dash.js
    ├── dashboard-use.js
    └── jquery.min.js

3 directories, 19 files

js/dash.js の修正

@@ -294,6 +294,11 @@ function init() {
     var serviceCallQueryTime = getTimeSecsAgo(15*60, currentTime);
     var serviceCallChart = generateLineChart("callsByServiceCanvas", "No of service calls");

+    var regionCallChartData = {'labels': [], 'times': [], 'values': {}}
+    var regionCallQueryTime = getTimeSecsAgo(15*60, currentTime);
+    var regionCallChart = generateLineChart("callsByRegionCanvas", "No of region calls");
+
+
     var ec2CallChartData = {'labels': [], 'times': [], 'values': {"ec2.amazonaws.com|null": []}}
     var ec2CallQueryTime = getTimeSecsAgo(15*60, currentTime);
     var ec2CallChart = generateLineChart("callsByEC2Canvas", "No of EC2 calls");
@@ -638,6 +643,14 @@ function init() {

         });

+        var awsRegionParams = retrieveParams("CallsPerRegion", regionCallQueryTime);
+        docClient.query(awsRegionParams, function(err, data) {
+            if (err) console.log(err);
+            else {
+                regionCallChartData = updateLineChart(data, regionCallChartData, regionCallChart, splitFunc);
+            }
+        });
+
         ec2CallQueryTime = getTimeSecsAgo(15*60);
         docClient.query(ec2Params, function(err, data) {
             if (err) console.log(err);
@@ -694,6 +707,16 @@ function init() {

         });

+        var regionParams = retrieveParams("CallsPerRegion", regionCallQueryTime);
+
+        docClient.query(regionParams, function(err, data) {
+            if (err) console.log(err);
+            else {
+                regionCallQueryTime = fastUpdateLineChart(data, regionCallChartData, regionCallChart, regionCallQueryTime, splitFunc) ;
+            }
+
+        });
+

         var ec2Params = retrieveParams("EC2Calls", ec2CallQueryTime);
         docClient.query(ec2Params, function(err, data) {

dash.html の修正

@@ -300,7 +300,15 @@
                     </div>
                 </div>
                 <div class="row aws-mb-l">
-                    <div class="col-xs-10 col-xs-offset-1 col-xs-12">
+                    <div class="col-md-5 col-md-offset-1 col-xs-12">
+                        <div class="x_title">
+                            <h3>Calls per AWS region <small> Over the last hour </small></h3>
+                        </div>
+                        <div class="x_content">
+                            <canvas id="callsByRegionCanvas"/>
+                        </div>
+                    </div>
+                    <div class="col-xs-5 col-xs-offset-1 col-xs-12">
                         <div class="x_title">
                             <h3>EC2 Calls <small> over the last hour </small></h3>
                         </div>

ソースコードを S3 に戻す

aws s3 sync コマンドを先程とは逆方向(ローカル→S3)で実行します。

$ aws s3 sync . s3://YOUR-BUCKET-NAME
upload: ./dash.html to s3://YOUR-BUCKET-NAME/dash.html
upload: js/dash.js to s3://YOUR-BUCKET-NAME/js/dash.js

差分ファイルだけがアップロードされます。

動作確認

最後に、ダッシュボードにログインして確認します。

"Calls per AWS region" が追加されています。

まとめ

今回はAWSが提供するアカウント・アクティビティのリアルタイム分析ソリューションにメトリウスを追加する方法を紹介しました。

各サービス間のデータ結合部分やデータベースは修正せずに、分析・表示レイヤーでメトリクスのバリエーションを増やすだけでカスタマイズが完了しました

データ基盤を作る際は、このように分離度・拡張性の高いシステムを作りたいものです。

参考