Amazon QuickSightダッシュボードのアクセス数をAthena/CloudTrailで調べる
はじめに
Amazon QuickSightは、分析結果をダッシュボードとして公開すると、参照のみ可能なリーダーと分析結果を共有出来ます。
ダッシュボードを公開した以上は、ダッシュボードのアクセス状況が気になるところです。
残念ながら、現在のAmazon QuickSightの管理画面はSPICE使用量などごく一部のメトリクスしか提供されておらず、CloudWatch連携もありません。
一方で、ダッシュボードへのアクセス(GetDashboard
API)はAWS CloudTrailに記録されます。
今回は、このAWS CloudTrailのAPIログにAmazon AthenaからSQLを投げてダッシュボードのアクセス数を復元する方法を紹介します。
AWS CloudTrailログクエリー用のAthenaテーブルを作成
AWS CloudTrailのEvent historyページからウィザード形式で作成出来ます。
詳細は次のページを参照ください。
GetDashboard APIのログ形式を確認
GetDashboard APIのログ形式を
- IAMユーザー経由のAuthorロール
- Readerロール
それぞれでアクセスして確認します。
違いは userIdentity
だけです。
IAMユーザー経由のAuthorには、principalId
の属性が存在します。
残りのフィールドは一緒です。
重要なフィールド
今回の目的では以下の3つのフィールドが重要です。
- 誰がアクセス? :
userIdentity
- どのダッシュボードにアクセス? :
serviceEventDetails.eventRequestDetails.dashboardId
- いつアクセス? :
eventTime
Readerロールの場合のログ形式
{ "eventVersion": "1.05", "userIdentity": { "arn": "arn:aws:ds:us-east-1:123456789012:user/d-90672e24b8/bf1c0629-5635-407f-9d5f-e67defed5c3a", "accountId": "123456789012", "userName": "alice@example.com", "type": "Directory" }, "eventTime": "2018-12-17T18:24:06Z", "eventSource": "quicksight.amazonaws.com", "eventName": "GetDashboard", "awsRegion": "us-east-1", "requestParameters": null, "responseElements": null, "eventID": "3288f81f-6e7d-4a15-ab6e-f071b3fc0a62", "readOnly": true, "eventType": "AwsServiceEvent", "recipientAccountId": "123456789012", "serviceEventDetails": { "eventRequestDetails": { "dashboardId": "arn:aws:quicksight:us-east-1:123456789012:dashboard/5b1eb242-b3b9-461d-82ac-910a0b5435fe" }, "eventResponseDetails": { "dashboardDetails": { "dashboardName": "dashboard name", "dashboardId": "arn:aws:quicksight:us-east-1:123456789012:dashboard/5b1eb242-b3b9-461d-82ac-910a0b5435fe", "analysisIdList": [ "arn:aws:quicksight:us-east-1:123456789012:analysis/cc5cc305-0e90-4a4a-8d4b-f9a1be821b3c" ], "dataSetIdList": [ "arn:aws:quicksight:us-east-1:123456789012:dataset/e1115401-2d74-41e7-ab70-728efad7a289" ] } } } }
IAMユーザー経由のAuthorロールの場合のログ形式
userIdentity
以外の出力は Readerロールと同じ為、異なる箇所だけを抜粋します。
{ "eventVersion": "1.05", "userIdentity": { "type": "IAMUser", "principalId": "DUMMY-PRINCIPAL-ID", "arn": "arn:aws:iam::123456789012:user/cm-jane.doe", "accountId": "123456789012", "userName": "cm-jane.doe" }, ... }
Amazon Athena からAWS CloudTrailログに問い合わせる
Amazon AthenaからこのAWS CloudTrailログに問い合わせる上では
- userIdentity
- serviceEventDetails
の操作がややこしそうです。
userIdentityの操作
userIdentity
は次のように STRUCT
型をしています。
userIdentity STRUCT< type: STRING, principalId: STRING, arn: STRING, ...
そのためuserIdentity
内の各値にはuserIdentity.principalId
というようにドットでアクセスできます。
serviceEventDetailsの操作
serviceEventDetails
はSTRING
型です。
"serviceEventDetails": { "eventRequestDetails": { "dashboardId": "arn:aws:quicksight:us-east-1:123456789012:dashboard/5b1eb242-b3b9-461d-82ac-910a0b5435fe" }, "eventResponseDetails": { "dashboardDetails": { "dashboardName": "dashboard name", "dashboardId": "arn:aws:quicksight:us-east-1:123456789012:dashboard/5b1eb242-b3b9-461d-82ac-910a0b5435fe", "analysisIdList": [ "arn:aws:quicksight:us-east-1:123456789012:analysis/cc5cc305-0e90-4a4a-8d4b-f9a1be821b3c" ], "dataSetIdList": [ "arn:aws:quicksight:us-east-1:123456789012:dataset/e1115401-2d74-41e7-ab70-728efad7a289" ] } } }
という形をしているため、json_extract 関数を使い JSONPath 書式でエレメントを抽出してアクセスします。
json_extract のレスポンスは JSON 型であり、JSON型は順序関係が定まっていないため、ORDER BY したいときは cast(json_extract(serviceeventdetails, '$.eventRequestDetails.dashboardId') AS VARCHAR)
というように順序関係が定まっている型に CAST します。
目的別SQL例
ダッシュボード別アクセス数を知りたい
アクセスの多いダッシュボード上位5件を表示
SELECT cast(json_extract(serviceeventdetails, '$.eventRequestDetails.dashboardId') AS VARCHAR) AS dashboardid , count(*) cnt FROM cloudtrail_logs_cloudtrail_tbl WHERE eventsource = 'quicksight.amazonaws.com' AND eventname = 'GetDashboard' AND eventtime >= '2018-12-01T00:00:00Z' GROUP BY 1 ORDER BY 1 LIMIT 5
ユーザー別アクセス数を知りたい
アクセスの多いユーザー上位5件を表示
SELECT useridentity.type , useridentity.username , count(*) cnt FROM cloudtrail_logs_cloudtrail_us_east_1_123456789012 WHERE eventsource = 'quicksight.amazonaws.com' AND eventname = 'GetDashboard' AND eventtime >= '2018-12-01T00:00:00Z' GROUP BY 1,2 ORDER BY 3 desc, 1, 2 LIMIT 5
ダッシュボード x ユーザー別アクセス数を知りたい
SELECT cast(json_extract(serviceeventdetails, '$.eventRequestDetails.dashboardId') AS VARCHAR) AS dashboardid , useridentity.type , useridentity.username , count(*) cnt FROM cloudtrail_logs_cloudtrail_us_east_1_123456789012 WHERE eventsource = 'quicksight.amazonaws.com' AND eventname = 'GetDashboard' AND eventtime >= '2018-12-01T00:00:00Z' GROUP BY 1,3, 2 ORDER BY 1, 2,3
謝辞
AWS CloudTrailからAmazon QuickSightダッシュボードのアクセス数を集計できることは、AWS re:Invent開催中にAmazon QuickSightのエンジニアから教わりました。
実際にサービス開発に携わっているエンジニアに直接質問できるのは、re:Inventの醍醐味の一つですね。