CloudWatch Logsで大文字と小文字を区別せずにキーワードを検知する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、虎塚です。

CloudWatch Logsを使うと、OSやミドルウェア、アプリケーションなどのログファイルをAWSに転送できます。転送したログを文字列でフィルターし、アラートメールを送ることもできて、便利です。

しかし、フィルターパターンの記述には正規表現を使うことができず、文字列はcase sensitiveに指定することしかできません。とはいえ、「ERROR」と「Error」の文字列を両方検知したい場合がありますよね。今日は、そんな時の設定方法を紹介します。

概要

たとえば、「ERROR」という文字列を大文字小文字の区別なく検知したい場合を考えます。

まず、監視したいLog Groupに対して、Metric Filterを3種類作成します。それぞれのMetric Filterで、Filter Patternを次のように設定します。

  • "ERROR"
  • "Error"
  • "error"

この時、すべてのMetric Filterに共通のMetric NamespaceとMetric Nameを設定します。つまり、Metric Nameが同じでFilter Patternが異なるMetric Filterを作成するわけです。

次に、アラームを設定します。アラームの作成画面で、Metric Nameとして先ほどの共通の名前を設定します。こうすることで、複数のMetric Filterを対象にアラームを定義できます。

これで、「ログに『ERROR』『Error』『error』のいずれかが5分間に20回検知されたら、アラームを上げてメールを自動送信する」といった設定が可能になりました。

注意点として、上記の設定では、大文字小文字を区別しないといいつつ、「ErRor」や「errOR」などをカバーしていません(それぞれFilter Patternを定義すれば可能です)。しかし、「ERROR」「Error」「error」あたりを定義しておけば、実用上は問題ないかと思います。

動作確認

文章だけでは分かりづらいので、スクリーンショットをまじえて具体的に設定方法を説明します。

実際に、Apache HTTP Serverのログを使って実験してみましょう。今回は、フィルタ対象の文字列を「ZZZ」と「zzz」とします。両方の文字列を時間を空けてログに出力し、どちらの文字列だった場合も検知されて、メールが送信されれば、実験成功とします。

0. インスタンスの準備

ログの生成元となるインスタンスを準備しましょう。

まず、CentOS 7のEC2インスタンスを起動します。インスタンスに関連づけるSecurityGroupでは、SSHログインのための22番ポートと、ブラウザからHTTPアクセスするための80番ポートを開けておきます。また、起動時にPublic IPアドレスが自動的にアサインされる設定にしておきます。

次に、インスタンスにSSHログインして、Apacheをパッケージインストールします。サービスを開始するとともに、インスタンス起動時にサービスが自動的に開始するように設定しておきます。

$ sudo yum -y install httpd
$ sudo systemctl start httpd.service
$ sudo systemctl enable httpd.service

CentOSは初期設定のままではHTTPでアクセスできません。iptablesの80番ポートを開けておきます。

$ sudo firewall-cmd --permanent --add-service=http --zone=public
$ sudo reboot

それから、肝心のCloudWatch Logs Agentをインストールします。公式ドキュメントの動作対象OSにはCentOS 7が含まれませんが、ここでは検証ですので気にせずインストールします。

$ sudo yum -y install wget
$ wget https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py
$ chmod +x awslogs-agent-setup.py
$ sudo python ./awslogs-agent-setup.py --region ap-northeast-1

インストール時には、初期値をそのまま適用して/var/log/messagesの転送設定をしてしまうとよいでしょう。その後、設定ファイルawslogs.confを開き、次の記述を末尾に追加します。

[/etc/httpd/logs/access_log]
datetime_format = %d/%b/%Y:%H:%M:%S
file = /etc/httpd/logs/access_log
buffer_duration = 5000
log_stream_name = apache_access
initial_position = start_of_file
log_group_name = /etc/httpd/logs

設定ファイルを変更したら、Agentを再起動します。

$ sudo service awslogs restart

最後に、インスタンスのPublic IPアドレスにブラウザからアクセスします。AWS Management Consoleにログインして、CloudWatchのダッシュボードの[Logs]メニューから、Apacheアクセスログが転送されてきていることを確認しておきましょう。

1. SNSのTopicとSubscriberの登録

アラームを発生させてメールを受け取るために、SNSのトピックを作成します。SNSのダッシュボードで、任意の名前をつけたSNS Topicを作成します。

Topics一覧でそのTopicを選び、[Other actions]から[Subscribe to topic]を選びます。ProtocolにEmailを選び、EndpointにEメールアドレスを入力して保存します。

入力したメールアドレスに、Subscribe確認のメールがno-reply@sns.amazonaws.comから届きます。メール本文のリンクをクリックしましょう。

2. Metric Filterの作成

Apacheのアクセスログに対して、Metric Filterを2つ作成します。CloudWatchのダッシュボードに戻り、左ペインから[Logs]メニューを選びます。Log Groups一覧で、「/etc/httpd/logs」をチェックし、[Create Metric Filter]ボタンを押します。

[Filter Pattern]として、1つ目のMetric Filterでは「"ZZZ"」、2つ目のMetric Filterでは「"zzz"」を入力します。そして、どちらのMetric Filterでも、Metric Namespaceは「LogMetrics」、Metric Nameは「check_zzz」と設定します。

1つ目のMetric Filter

Filter Pattern「ZZZ」のMetric Filter

2つ目のMetric Filter

Filter Pattern「zzz」のMetric Filter

設定が完了した時の「/etc/httpd/logs」のフィルタ一覧を次に示します。

Filter Patternが異なるMetric Filterを、同じMetric名で作成する

同じMetric名でFilter Patternが異なる2つのMetric Filterが作成されました。

3. Alarmの作成

作成したMetricに対して、通知の設定を行います。上の画面で、どちらかのMetric Filterの[Create Alarm]リンクをクリックします。(2つあるうちのどちらでも構いません)

Alarmの作成画面

Name
任意の名前をつけます(check_zzz_and_ZZZ)
Whenever
5分間に1回以上の検出でアラーム状態になるようにします
Metric Name
2つのMetric Filterに共通するMetric Nameを入力します(check_zzz)
Send notification to
手順1で設定したSNSのTopicを選択します

設定が完了した時の「/etc/httpd/logs」のフィルタ一覧を次に示します。

設定されたAlarm

作成したAlarmが、両方のMetric Filterに関連づけられました。

4. ブラウザアクセスによるログ生成とメールの確認

Apacheログの出力フォーマットの設定がデフォルト状態の場合、アクセスログに「ZZZ」や「zzz」の文字列を出すには、Public IPアドレスの後に文字列を続けてブラウザアクセスするだけで十分です。たとえば、「http://XXX.XXX.XXX.XXX/ZZZ.html」などにアクセスします。

大文字「ZZZ」をURLに付けて一度アクセスし、CloudWatch Logsにログが転送されたことを確認します。次のようなログが来ていればOKです。

ZZZが含まれるログ

手順3で設定したAlarmが上がり、メールが自動送信されることを確認してください。

その後、ALARM状態が解除された(InsufficientもしくはOKの状態になった)ことを確認してから、今度は小文字「zzz」をURLに付けてアクセスします。ふたたびCloudWatch Logsにログが転送されたことを確認します。次のようなログが来ていればOKです。

zzzが含まれるログ

先ほどと同じく、手順3で設定したAlarmが上がり、メールが自動送信されることを確認してください。

ログに「ZZZ」が含まれていても「zzz」が含まれていても、1つのAlarmで検知できることを確認できました。

おわりに

今回のような設定を行うことで、「ログに『ERROR』『Error』『error』のいずれかが5分間に20回検知されたら、アラームを上げてメールを自動送信する」といった設定ができます。よかったら試してみてくださいね。

もちろん、いずれはFilter Patternに正規表現が使えるようになる機能アップデートを期待しています!

それでは、また。