Partition Projection を使って AWS WAF のログを分析してみた
Amazon Athena(以降、Athena)の利用料金とパフォーマンスは、スキャン対象のデータ量に比例します。
Athena では、パーティションを追加することによって、スキャン対象のデータ量を絞り、コストを減らしスキャン速度を向上できます。
パーティションを追加するには、
- ALTER TABLE ADD PARTITION を実行
- Glue のクローラで Glue Data Catalog にパーティションを登録
といった方法がございますが、これらはクエリを実行する度に実行しなくてはなりません。
また、多くのパーティションが存在するケースでは Glue Data Catalog からパーティションを取得する API の呼び出しがクエリパフォーマンスのボトルネックとなる可能性がございました。
これらの課題を解決するために Partition Projection を使うことで、パーティション化されたテーブルのクエリ処理を高速化し、パーティション管理を自動化することができます。詳細は以下のブログを参照ください。
本記事では、AWS WAF のログを Athena で分析するのに、Partition Projection を使ってコストと手間を効率化する方法を紹介します。
やってみた
まず Athena でテーブルを作成します。テーブル定義は以下のブログをベースにしております。
39 行目から 46 行目で、Partition Projection の設定をしています。
CREATE EXTERNAL TABLE IF NOT EXISTS waflogs_all_partitioned
(
`timestamp` bigint,
formatVersion int,
webaclId string,
terminatingRuleId string,
terminatingRuleType string,
action string,
terminatingRuleMatchDetails array < struct <
conditionType: string,
location: string,
matchedData: array < string >
> >,
httpSourceName string,
httpSourceId string,
ruleGroupList array < struct <
ruleGroupId: string,
terminatingRule: struct < ruleId: string, action: string >,
nonTerminatingMatchingRules: array < struct < action: string, ruleId: string > >,
excludedRules: array < struct < exclusionType: string, ruleId: string > >
> >,
rateBasedRuleList array < struct < rateBasedRuleId: string, limitKey: string, maxRateAllowed: int > >,
nonTerminatingMatchingRules array < struct < action: string, ruleId: string > >,
httpRequest struct <
clientIp: string,
country: string,
headers: array < struct < name: string, value: string > >,
uri: string,
args: string,
httpVersion: string,
httpMethod: string,
requestId: string
>
)
PARTITIONED BY (
`date` string)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://aws-waf-logs-123456789012/${date}'
TBLPROPERTIES (
'projection.enabled' = 'true',
'projection.date.type' = 'date',
'projection.date.range' = 'NOW-1YEARS,NOW',
'projection.date.format' = 'yyyy/MM/dd',
'projection.date.interval' = '1',
'projection.date.interval.unit' = 'DAYS',
'storage.location.template' = 's3://aws-waf-logs-123456789012/${date},
'classification'='csv',
'compressionType'='gzip',
'delimiter'='|',
'typeOfData'='file');
Partitioned されたテーブルが作成されました。
では、クエリを投げてみます。特定の日付けのカウントログを出力します。
SELECT from_unixtime(timestamp/1000, 'Asia/Tokyo') AS JST, *
FROM waflogs, UNNEST(nonTerminatingMatchingRules) t(nonTermRule)
WHERE nonTermRule.action = 'COUNT' AND date = '2020/09/07';
出力できていることを確認できました。
さいごに
Partition Projection を使った、WAF ログの分析をやってみました。
パーティションを使うことで Athena のコストを最適化できますが、Partition Projection を使うことでパーティション追加手順も不要にできました。
特定の日や時間に絞って都度テーブルすることもできますが、複数の日や時間にまたがって分析するにはパーティションを作ることが有効ですので、ぜひ活用ください!