0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS AthenaでS3 アクセスログの集計を行うメモ

Posted at

これは何?

AWS S3のアクセスログをAthenaで集計するまでの手順のメモです。

手順

ログ保存用バケット作成

以下の名前で作成:

  • 名前:example-access-logs

ログ配信グループ(ACL)を許可するポリシーの設定

S3ログ配信グループ ACLを許可する設定を行う。
example-access-logs バケットのポリシーに以下を設定。
example-main-bucket が集計対象のバケット。
"StringEquals": { "aws:SourceAccount": "123456789012" } にはアカウントIDを設定。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "S3ServerAccessLogsPolicy",
            "Effect": "Allow",
            "Principal": {
                "Service": "logging.s3.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::example-access-logs/*",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "123456789012"
                },
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:s3:::example-main-bucket"
                }
            }
        }
    ]
}

アクセスログの有効化

example-main-bucket の設定で「サーバーアクセスのログ記録」を有効化。

設定例:

  • 送信先バケット: s3://example-access-logs
  • ログオブジェクトキー形式:
    123456789012/ap-northeast-1/example-main-bucket/[YYYY]/[MM]/[DD]/[YYYY]-[MM]-[DD]-[hh]-[mm]-[ss]-[UniqueString]
  • ここは好きな形式で設定できる。ファイルが増えたとき、日付などでパーティションを区切る方が集計しやすそうなので上記形式とした
  • ログオブジェクトキーの形式で使用される日付のソース
    • S3 イベントの時刻で設定

設定後, 15分くらいしたらアクセルログファイルが作成され始めた。

Athenaで集計

参考: AWS公式ドキュメント

データベース作成

CREATE DATABASE s3_access_logs_db;

これで作成できるはずだが、以下のエラーが出た。

No output location provided. An output location is required either through the Workgroup result configuration setting or as an API input.

クエリ結果出力先のs3が必要らしいので、バケット aws-athena-query-results-ap-northeast-1-12345678 を作成し、保存先とする。
※バケット名は適当な名前でOK

athena → クエリエディタ → 設定 → 管理 から保存先バケットを設定可能。

もう一度クエリを実行したところ、DBを作成できた。

Athenaテーブル作成

クエリ実行し、集計用テーブル example_bucket_logs を作成

CREATE EXTERNAL TABLE s3_access_logs_db.example_bucket_logs( 
 `bucketowner` STRING, 
 `bucket_name` STRING, 
 `requestdatetime` STRING, 
 `remoteip` STRING, 
 `requester` STRING, 
 `requestid` STRING, 
 `operation` STRING, 
 `key` STRING, 
 `request_uri` STRING, 
 `httpstatus` STRING, 
 `errorcode` STRING, 
 `bytessent` BIGINT, 
 `objectsize` BIGINT, 
 `totaltime` STRING, 
 `turnaroundtime` STRING, 
 `referrer` STRING, 
 `useragent` STRING, 
 `versionid` STRING, 
 `hostid` STRING, 
 `sigv` STRING, 
 `ciphersuite` STRING, 
 `authtype` STRING, 
 `endpoint` STRING, 
 `tlsversion` STRING,
 `accesspointarn` STRING,
 `aclrequired` STRING)
 PARTITIONED BY (`timestamp` string)
ROW FORMAT SERDE 
 'org.apache.hadoop.hive.serde2.RegexSerDe' 
WITH SERDEPROPERTIES ( 
 'input.regex'='([^ ]*) ([^ ]*) \\[(.*?)\\] ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) (\"[^\"]*\"|-) (-|[0-9]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) (\"[^\"]*\"|-) ([^ ]*)(?: ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*))?.*$') 
STORED AS INPUTFORMAT 
 'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://example-access-logs/123456789012/ap-northeast-1/example-main-bucket/'
TBLPROPERTIES (
  'projection.enabled'='true', 
  'projection.timestamp.format'='yyyy/MM/dd', 
  'projection.timestamp.interval'='1', 
  'projection.timestamp.interval.unit'='DAYS', 
  'projection.timestamp.range'='2024/01/01,NOW', 
  'projection.timestamp.type'='date', 
  'storage.location.template'='s3://example-access-logs/123456789012/ap-northeast-1/example-main-bucket/${timestamp}')                    

以下を環境に合わせて修正してください。

修正箇所 意味・修正方法
s3_access_logs_db Athenaのデータベース名。自分の環境で作成したDB名に変更する CREATE DATABASE my_s3_logs;my_s3_logs.example_bucket_logs
example_bucket_logs 作成するテーブル名。任意で変更可能(プロジェクト名などに合わせる) my_access_logs
LOCATION ログを保存しているS3バケットのパス。
アクセスログを出力した「保存先バケット」に合わせる
s3://my-access-logs/111122223333/ap-northeast-1/my-source-bucket/
'storage.location.template' 上記LOCATIONと対応させる。パス構造(日付階層)が違う場合は修正が必要 s3://my-access-logs/111122223333/ap-northeast-1/my-source-bucket/${timestamp}
"projection.timestamp.range" ログの保管開始時期に合わせて適宜修正 '2023/01/01,NOW' など
"ap-northeast-1" ログを保存しているリージョンに変更 us-east-1, eu-west-1 など
"123456789012" 自分のAWSアカウントIDに置き換える (例)463737866732
'input.regex' S3アクセスログ形式に基づく正規表現。基本的に変更不要だが、フォーマットを変えている場合は要調整 通常はそのままでOK

PV集計クエリ

Athenaのクエリエディタで以下を実行する

SELECT
  regexp_extract(key, '^([^/]+)/', 1) AS user_id,
  COUNT(*) AS pv_count
FROM s3_access_logs_db.example_bucket_logs
WHERE
  operation = 'REST.GET.OBJECT'
  AND httpstatus = '200'
GROUP BY regexp_extract(key, '^([^/]+)/', 1)
ORDER BY pv_count DESC;

日付別集計例

SELECT
  regexp_extract(key, '^([^/]+)/', 1) AS user_id,
  timestamp AS log_date,
  COUNT(*) AS pv_count
FROM s3_access_logs_db.example_bucket_logs
WHERE
  operation = 'REST.GET.OBJECT'
  AND httpstatus = '200'
  AND timestamp BETWEEN '2025/05/01' AND '2025/05/31'
  AND regexp_extract(key, '^([^/]+)/', 1) = '13'
GROUP BY regexp_extract(key, '^([^/]+)/', 1), timestamp
ORDER BY timestamp, pv_count DESC;

WHEREにユーザーIDを指定したり、日付範囲を指定したりすれば、自由に集計できそう。

コストについて

Athenaはスキャン量に応じて課金。
2025年現在、$5 / TB

  • 1回のクエリ実行で、最低でも10MBスキャン分の料金がかかる
  • WHERE句で範囲を絞るとコスト削減可能
  • 正常終了しなかったクエリには課金されない
  • 日付ごとのパーティション設計で効率化できる

まとめ

S3サーバーアクセスログをAthenaで可視化することで、どのオブジェクトがどれだけアクセスされたかを簡単に集計可能です。定期的に分析する場合は、クエリを自動実行するLambdaなども検討するとよさそうです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?