2026年7月27日

2026年7月27日

AWS CloudWatchでログ監視とアラート設定|WordPressのエラーログ収集・メトリクスフィルター・SNS通知

EC2で動かしているWordPressをCloudWatchで監視するには、CloudWatchエージェントでWebサーバーとPHPのログを送り、メトリクスフィルターで「PHPの致命的エラー」や「5xxの応答」を数え、その数にアラームを設定してSNSでメール通知する、という流れが基本です。あわせて、EC2の標準メトリクスでは取れないメモリとディスクの使用率もエージェントで送っておくと、障害の前触れに気付けます。この記事では、IAMロールの準備からエージェントの設定、アラームの作成、通知のテスト、ログの調べ方までを順番に説明します。

コマンドや設定ファイルは、Amazon LinuxやUbuntuのEC2でNginxとPHP-FPMを使う構成を例にしています。ファイルのパスは自分の環境に合わせて読み替え、まずステージング環境で試してください。

監視の全体像

CloudWatchで使う主な機能は次の4つです。

  • CloudWatch Logs:ログファイルの中身を保管し、検索する場所。ロググループ(用途ごとの入れ物)とログストリーム(送信元ごとの流れ)で整理します
  • メトリクス:数値の時系列データ。EC2のCPU使用率などは標準で送られます
  • メトリクスフィルター:ログの中から特定の文字列やパターンに一致した行を数え、メトリクスに変える仕組み
  • アラーム:メトリクスがしきい値を超えたときに状態が変わり、SNSなどに通知する仕組み

つまり「ログ → メトリクスフィルター → メトリクス → アラーム → SNS → メール」という順にデータが流れます。どこか1か所が欠けると通知が来ないため、最後にテストで流れを通しで確認することが大切です。

ステップ1:EC2にIAMロールを付ける

エージェントがCloudWatchにデータを送るには権限が必要です。EC2に付けているIAMロールに、AWS管理ポリシーの CloudWatchAgentServerPolicy を追加します。ロールがまだ無い場合は作成してインスタンスに付けます。アクセスキーをサーバーに置く方法は避けてください。

ステップ2:CloudWatchエージェントを入れて設定する

エージェントは amazon-cloudwatch-agent というパッケージで提供されています。Amazon Linuxなら次のように入れられます。ほかのOSではAWSが配布するパッケージを使います。

sudo dnf install -y amazon-cloudwatch-agent

設定ファイルは対話式のウィザード(amazon-cloudwatch-agent-config-wizard)でも作れますが、内容を理解するために手で書く例を示します。

{
  "metrics": {
    "namespace": "CWAgent",
    "append_dimensions": {
      "InstanceId": "${aws:InstanceId}"
    },
    "metrics_collected": {
      "mem": {
        "measurement": ["mem_used_percent"]
      },
      "disk": {
        "measurement": ["used_percent"],
        "resources": ["/"]
      }
    }
  },
  "logs": {
    "logs_collected": {
      "files": {
        "collect_list": [
          {
            "file_path": "/var/log/nginx/error.log",
            "log_group_name": "/wordpress/nginx/error",
            "log_stream_name": "{instance_id}",
            "retention_in_days": 30
          },
          {
            "file_path": "/var/log/nginx/access.log",
            "log_group_name": "/wordpress/nginx/access",
            "log_stream_name": "{instance_id}",
            "retention_in_days": 30
          },
          {
            "file_path": "/var/log/php/error.log",
            "log_group_name": "/wordpress/php/error",
            "log_stream_name": "{instance_id}",
            "retention_in_days": 90
          }
        ]
      }
    }
  }
}

ポイントは retention_in_days(保持期間)です。ロググループの保持期間は、指定しないと「失効しない」になり、ログが溜まり続けて保管の料金も増えていきます。アクセスログには訪問者のIPアドレスなど個人に関わる情報が含まれるため、必要な期間だけ残すという意味でも保持期間を決めておきます。何日にするかは、サイトのプライバシーポリシーや社内の規程と合わせて決めてください。

保存したら、設定を読み込んでエージェントを起動します。

sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
  -a fetch-config -m ec2 -s \
  -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json

# 状態を確認
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a status

ログが届かないときは、エージェント自身のログ(/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log)を見ます。多い原因は、IAMロールの権限不足と、エージェントの実行ユーザーが対象のログファイルを読めないことです。

PHPのエラーをファイルに出す

WordPressの致命的エラーを拾うには、PHPのエラーがファイルに書き出されている必要があります。本番環境では、WP_DEBUG を有効にするより、PHPの設定(php.ini やPHP-FPMのプール設定)で log_errors を有効にし、error_log にWebから見えない場所のファイルを指定する方法が向いています。

一時的にWordPressのデバッグログを使う場合は、WP_DEBUG_LOG にファイルのパスを指定できます。初期値の wp-content/debug.log はWebから読める場所にあるため、公開ディレクトリの外を指定します。

// wp-config.php(調査の間だけ有効にする)
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_DISPLAY', false );
define( 'WP_DEBUG_LOG', '/var/log/php/wp-debug.log' );

ログには、利用者が入力した内容やメールアドレスが含まれることがあります。プラグインやテーマの独自ログでパスワードや認証コードを書き出していないかも確認しておきます。

ステップ3:メトリクスフィルターでエラーを数える

ログが届いたら、メトリクスフィルターを作ります。まずPHPの致命的エラーの行を数える例です。

aws logs put-metric-filter \
  --log-group-name /wordpress/php/error \
  --filter-name php-fatal \
  --filter-pattern '"PHP Fatal error"' \
  --metric-transformations \
    metricName=PhpFatalCount,metricNamespace=WordPress,metricValue=1,defaultValue=0

ダブルクォートで囲んだ部分は、その語句がそのまま含まれる行に一致します。次は、Nginxのアクセスログで5xxの応答を数える例です。Nginxの標準の combined 形式を前提に、空白区切りの各項目に名前を付けています。角かっことダブルクォートで囲まれた部分は1つの項目として扱われます。

aws logs put-metric-filter \
  --log-group-name /wordpress/nginx/access \
  --filter-name http-5xx \
  --filter-pattern '[ip, id, user, timestamp, request, status_code=5*, size, referrer, agent]' \
  --metric-transformations \
    metricName=Http5xxCount,metricNamespace=WordPress,metricValue=1,defaultValue=0

ログの形式を変えている場合は、項目の数と並びが合わないと一致しません。コンソールのメトリクスフィルター作成画面では、実際のログを使ってパターンをテストできるので、登録前に一致する行が出るか確かめます。

ステップ4:SNSのトピックとアラームを作る

通知先のSNSトピックを作り、メールアドレスを登録します。登録すると確認メールが届くので、本文のリンクから承認するまで通知は送られません。ここを忘れて「アラームが鳴ったのにメールが来ない」となる例は多いです。

aws sns create-topic --name wp-alerts
aws sns subscribe \
  --topic-arn arn:aws:sns:ap-northeast-1:123456789012:wp-alerts \
  --protocol email \
  --notification-endpoint you@example.com

次に、致命的エラーが5分間に1件以上出たら通知するアラームを作ります。

aws cloudwatch put-metric-alarm \
  --alarm-name wp-php-fatal \
  --namespace WordPress \
  --metric-name PhpFatalCount \
  --statistic Sum \
  --period 300 \
  --evaluation-periods 1 \
  --threshold 1 \
  --comparison-operator GreaterThanOrEqualToThreshold \
  --treat-missing-data notBreaching \
  --alarm-actions arn:aws:sns:ap-northeast-1:123456789012:wp-alerts \
  --ok-actions arn:aws:sns:ap-northeast-1:123456789012:wp-alerts

--treat-missing-data notBreaching は、ログが1行も無い時間帯を「正常」とみなす指定です。エラーが出たときだけデータが入るメトリクスでは、これを付けないとデータ不足の状態が続いて分かりにくくなります。--ok-actions を付けておくと、正常に戻ったときにも通知が届きます。

5xxの数は、少数なら一時的なこともあるため、しきい値を数件以上にしたり、評価期間を2回連続にしたりして、通知が多すぎないように調整します。通知が多すぎると誰も見なくなるので、最初はゆるめに設定し、実際の発生状況を見ながら詰めていきます。

サーバー自体のアラーム

ログとは別に、次のアラームもあると安心です。

  • AWS/EC2 名前空間の StatusCheckFailed:インスタンスやその下のハードウェアの異常
  • CWAgent 名前空間のディスク使用率(disk_used_percent):ディスクがいっぱいになるとWordPressの更新やアップロードが失敗します
  • CWAgent 名前空間のメモリ使用率(mem_used_percent):PHP-FPMやMySQLのメモリ不足の前触れ

エージェントのメトリクスは、パスやデバイス名などのディメンションが付いた状態で送られます。アラームではディメンションをすべて一致させる必要があるため、コンソールのメトリクス画面で実際に付いているディメンションを確認してから設定します。

ステップ5:通知を試し、ログを調べる

アラームを作ったら、通知が届くかを試します。CLIでアラームの状態を一時的に変えると、SNSへの通知が送られます。

aws cloudwatch set-alarm-state \
  --alarm-name wp-php-fatal \
  --state-value ALARM \
  --state-reason "通知テスト"

メールが届けば、アラームからSNS、メールまでの経路は動いています。ログからメトリクスまでの経路は、ステージング環境でわざとエラーを起こすなどして確かめます。

通知が来たあとの調査には、CloudWatch Logs Insightsが便利です。ロググループを選んで、次のようなクエリを実行します。

fields @timestamp, @message
| filter @message like /PHP Fatal error/
| sort @timestamp desc
| limit 50

エラーの行には、原因になったファイルのパスが含まれることが多く、wp-content/plugins/ の下ならどのプラグインかが分かります。Logs Insightsはスキャンしたデータ量に応じて料金がかかるため、対象の期間を必要な範囲に絞って実行します。CloudWatchの料金体系や機能は変わることがあるので、AWSの公式ページで確認してください(2026年10月現在)。

まとめ

  • 流れは「ログ → メトリクスフィルター → メトリクス → アラーム → SNS → メール」。最後に通しで試す
  • EC2のロールに CloudWatchAgentServerPolicy を付け、エージェントでログとメモリ・ディスクを送る
  • ロググループには保持期間を設定する。アクセスログの個人に関わる情報の扱いもあわせて決める
  • PHPのエラーはWebから見えない場所のファイルに出し、"PHP Fatal error" などで数える
  • SNSのメール登録は承認が必要。set-alarm-state で通知をテストし、調査はLogs Insightsで行う

お気軽にご相談ください

お見積りへ お問い合わせへ
▲