AWSが提供するアカウント・アクティビティのリアルタイム分析のダッシュボードをカスタマイズする
先日、アマゾンがアカウント・アクティビティのリアルタイムタイム分析ソリューションのリファレンス実装を公開しました。
Introducing the Real-Time Insights on AWS Account Activity
AWS CloudTrailでアカウント・アクティビティを取得し、Amazon Kinesis Data Analyticsでリアルタイム分析し、DynamoDB に保存したメトリクスをダッシュボード表示します。
リージョン情報のメトリクスを追加
次の公式ドキュメントにて、ダッシュボードにリージョン毎のAPI呼び出し数のメトリクスを追加する手順が紹介されていたため、実際にやってみました。
AWS CloudTrail ログに含まれるリージョン情報を活用します
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | { "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 を最後に追加します。
1 2 3 4 5 6 | 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 で指定したバケットを指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | $ 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 の修正
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | @@ -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 の修正
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @@ -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)で実行します。
1 2 3 | $ 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が提供するアカウント・アクティビティのリアルタイム分析ソリューションにメトリウスを追加する方法を紹介しました。
各サービス間のデータ結合部分やデータベースは修正せずに、分析・表示レイヤーでメトリクスのバリエーションを増やすだけでカスタマイズが完了しました
データ基盤を作る際は、このように分離度・拡張性の高いシステムを作りたいものです。