CloudFront Functions の新機能「logCustomData」で任意のデータをアクセスログに記録してみた

CloudFront Functions の新機能「logCustomData」で任意のデータをアクセスログに記録してみた

CloudFront Functions に新たに追加された `cf.logCustomData()` で任意のデータをアクセスログに記録し、標準ログv2(CloudWatch Logs、JSON形式)での出力を確認しました。
2026.07.15

はじめに

2026年7月14日、CloudFront Functions がアクセスログへのカスタムデータ記録に対応しました。

https://aws.amazon.com/jp/about-aws/whats-new/2026/07/cloudfront-functions-access-logs/

新たに追加された cf.logCustomData() API を使うと、CloudFront Functions の実行時に任意のデータを CloudFront のアクセスログ(リアルタイムログおよび標準ログv2)に記録できます。viewer-request / viewer-response の両イベントで利用可能です。本記事では、標準ログv2(CloudWatch Logs、JSON形式)への出力を検証します。

標準ログv2 自体の概要については以下の記事を参照ください。

https://dev.classmethod.jp/articles/cloudfront-access-log-update-202411/

検証内容

cf.logCustomData() の公式ドキュメントはこちらです。

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/general-helper-methods.html#log-custom-data-method

以下の流れで検証しました。

  1. 標準ログv2 を CloudWatch Logs(JSON形式)に配信する設定を行う
  2. cf.logCustomData() を呼び出す CloudFront Functions を作成し、ディストリビューションに関連付ける
  3. リクエストを送信し、CloudWatch Logs でカスタムデータが記録されていることを確認する

前提: 標準ログv2 の設定

cf.logCustomData() で記録したデータを確認するには、標準ログv2 の配信設定が必要です。以下の手順で CloudWatch Logs へ JSON 形式で配信する構成を作ります。標準ログv2 の配信設定は us-east-1 リージョンで実行します。

ロググループの作成とリソースポリシー設定

aws logs create-log-group \
  --log-group-name cloudfront-cf2-logcustomdata-test \
  --region us-east-1

delivery.logs.amazonaws.com サービスプリンシパルに書き込みを許可するリソースポリシーを設定します。

aws logs put-resource-policy \
  --policy-name cf-logcustomdata-delivery-policy \
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Sid": "AllowCloudFrontLogDelivery",
      "Effect": "Allow",
      "Principal": {"Service": "delivery.logs.amazonaws.com"},
      "Action": ["logs:CreateLogStream", "logs:PutLogEvents"],
      "Resource": "arn:aws:logs:us-east-1:123456789012:log-group:cloudfront-cf2-logcustomdata-test:*",
      "Condition": {
        "StringEquals": {"aws:SourceAccount": "123456789012"},
        "ArnLike": {"aws:SourceArn": "arn:aws:logs:us-east-1:123456789012:delivery-source:*"}
      }
    }]
  }' \
  --region us-east-1

Delivery Source の作成

aws logs put-delivery-source \
  --name cf2-logcustomdata-source \
  --resource-arn arn:aws:cloudfront::123456789012:distribution/E1234567890ABC \
  --log-type ACCESS_LOGS \
  --region us-east-1

Delivery Destination の作成

aws logs put-delivery-destination \
  --name cf2-logcustomdata-destination \
  --delivery-destination-configuration '{"destinationResourceArn": "arn:aws:logs:us-east-1:123456789012:log-group:cloudfront-cf2-logcustomdata-test"}' \
  --output-format json \
  --region us-east-1

Delivery の作成

aws logs create-delivery \
  --delivery-source-name cf2-logcustomdata-source \
  --delivery-destination-arn arn:aws:logs:us-east-1:123456789012:delivery-destination:cf2-logcustomdata-destination \
  --record-fields date time x-edge-location sc-status cs-method cs-uri-stem \
    x-edge-result-type x-edge-request-id cs-protocol \
    viewer-request-log-data viewer-response-log-data \
  --region us-east-1

CloudFront Functions の作成

cf.logCustomData() は JavaScript runtime 2.0(import cf from 'cloudfront')で利用できます。以下の関数を作成しました。User-Agent、URI、メソッド、関数実行開始時刻(Date.now() が返す Unix 時間・ミリ秒)を JSON 文字列にして cf.logCustomData() に渡します。

import cf from 'cloudfront';

function handler(event) {
    var request = event.request;

    var logData = JSON.stringify({
        ua: request.headers['user-agent'] ? request.headers['user-agent'].value.substring(0, 50) : '-',
        uri: request.uri,
        method: request.method,
        ts: Date.now()
    });

    cf.logCustomData(logData);

    return request;
}

以下のコマンドで関数を作成します。

aws cloudfront create-function \
  --name cf2-log-custom-data-test \
  --function-config '{"Comment": "Test cf.logCustomData()", "Runtime": "cloudfront-js-2.0"}' \
  --function-code fileb://cf2-log-custom-data.js \
  --region us-east-1

テスト実行の結果、ComputeUtilization は 7(上限100)でエラーなく実行されました。Publish 後、ディストリビューションの DefaultCacheBehavior に viewer-request イベントとして関連付けました。

cf.logCustomData() には以下の制約があります。

  • 引数は単一の文字列(オブジェクトは JSON.stringify() で変換する)
  • 1回の cf.logCustomData() で記録できるデータは最大 800バイト。CloudFront がログ書き込み時に自動でURLエンコードし、エンコード後に 800バイトを超えた分は切り詰められる
  • 同一実行内で複数回呼び出した場合、最後の値のみ有効

動作確認

ディストリビューションのデプロイ完了後、curl でリクエストを送信しました。

curl -sI https://d1234567abcdef.cloudfront.net/

リクエスト送信から約13秒後、CloudWatch Logs にログが到着しました(配信までの時間は状況により変動します)。以下が記録されたログレコードです。

{
  "viewer-request-log-data": "%7B%22ua%22:%22curl/8.18.0%22,%22uri%22:%22/%22,%22method%22:%22HEAD%22,%22ts%22:1784050437859%7D",
  "viewer-response-log-data": "-",
  "date": "2026-07-14",
  "time": "17:33:58",
  "x-edge-location": "SEA900-P9",
  "sc-status": "200",
  "cs-method": "HEAD",
  "cs-uri-stem": "/",
  "x-edge-result-type": "Miss",
  "x-edge-request-id": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==",
  "cs-protocol": "https"
}

viewer-request-log-data フィールドに、CloudFront Functions で記録したデータがURLエンコードされた状態で含まれています。デコードすると以下の通りです。

{"ua":"curl/8.18.0","uri":"/","method":"HEAD","ts":1784050437859}

複数のリクエストを送信し、すべてのリクエストでカスタムデータが正しく記録されることを確認しました。

時刻 メソッド/パス ステータス キャッシュ log-data(デコード後)
17:33:58 HEAD / 200 Miss {"ua":"curl/8.18.0","uri":"/","method":"HEAD","ts":1784050437859}
17:34:09 GET /mesoko_01.png 200 Miss {"ua":"curl/8.18.0","uri":"/mesoko_01.png","method":"GET","ts":1784050448545}
17:34:10 GET /404.html 200 Miss {"ua":"curl/8.18.0","uri":"/404.html","method":"GET","ts":1784050449752}
17:34:11 GET /nonexistent.html 404 Error {"ua":"curl/8.18.0","uri":"/nonexistent.html","method":"GET","ts":1784050450649}

viewer-response-log-data はすべてのレコードで - でした。これは viewer-response 関数を関連付けていないためです。viewer-response 関数を関連付けて cf.logCustomData() を呼び出すと、viewer-response 関数が実行されたリクエストでは viewer-response-log-data フィールドに別のデータを記録できます。なお、オリジンが HTTP 400 以上のステータスコードを返した場合、viewer-response 関数は実行されません。

まとめ

cf.logCustomData() により、CloudFront Functions の実行時に任意のデータを CloudFront のアクセスログへ記録できるようになりました。関数で判定した値がアクセスログの同一レコードに入るので、カスタムデータの確認に複数のログを突き合わせる必要がありません。

A/Bテストの振り分け結果やデバッグ情報をリクエスト単位で記録したいケースなどに便利です。ぜひお試しください。

参考リンク

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事