Webサーバーのアクセスログでサーバーエラーの5xxのレスポンスが発生したことを検知したいのですが、
無視したいリクエストもあります。
色々試行錯誤したので、備忘録的に。
ログの収集
アイテムを作成してログを収集します。
詳細はマニュアルを見てください。
ローテートされるログにも対応してます。
log[/var/log/nginx/access_log, "\" 5[0-9]{2} "]
アクセスログすべてを収集すると件数が多くて大変なので、レスポンスコードが5xxのログのみ収集します。
トリガーの設定
検知したい条件
まず、検知したいログ条件をはっきりさせます。
- 30秒以内の間に5xx系のログが出力された
- ただし、sitemap.xmlへのアクセスは対象外とする
これを元にトリガーの条件を組み合わせます。
ログの収集時点で5xx系のみに絞っていますので、
全体のログ件数が除外したいsitemap.xmlが含まれるログ件数よりも多ければ、
異常があったと判断してよいかと思います。
5xx系ログ件数のカウント
{web:log[/var/log/nginx/access_log, "\" 5[0-9]{2} "].count(30)}
除外したいsitemap.xmlが含まれるログ件数のカウント
{web:log[/var/log/nginx/access_log, "\" 5[0-9]{2} "].count(30, "sitemap.xml")}
2つを合わせる
{web:log[/var/log/nginx/access_log, "\" 5[0-9]{2} "].count(30)} > {web:log[/var/log/nginx/access_log, "\" 5[0-9]{2} "].count(30, "sitemap.xml")}
これで良さそうにも見えます。
試してみると、異常検知はできるのですが、5xx系のログが最後に出力されてから30秒を経過しても正常状態へ復帰しません。
なので条件を追加します。
30秒間5xx系のログがでなければ復帰させる
{web:log[/var/log/nginx/access_log, "\" 5[0-9]{2} "].count(30)} > {web:log[/var/log/nginx/access_log, "\" 5[0-9]{2} "].count(30, "sitemap.xml")} and {web:log[/var/log/nginx/access_log, "\" 5[0-9]{2} "].nodata(30)} = 0
.nodata()
で30秒間ログの出力が無ければ、条件式が偽になるようにして、正常状態へ復帰したと判定させます。