えいのうにっき

a-knowの日記です

Mackerelログ監視プラグイン・check-log 完全解説

この記事は、Mackerel アドベントカレンダー(全部CRE)の9日目の記事です。

数あるMackerelのプラグインの中でもダントツの人気(僕調べ)を誇る check-log プラグイン。

github.com

その人気ゆえ、度重なる開発、有志の方々による Contribute により、今やその多機能っぷりもMackerelプラグイン随一(僕調べ)のものになりました。ということで今回は、この check-log プラグインを完全解説したいと思います!

前提となるバージョン

この記事では、v0.26.0を前提とします。

指定可能なオプション類

まずは、check-log プラグインに指定可能なオプション類を見ていきましょう。

v0.26.0 では、以下のようなオプションを指定することが可能です。

  • --file , -f
  • --file-pattern , -F
  • --missing
  • --pattern , -p
  • --suppress-pattern
  • --exclude , -E
  • --warning-over , -w / --critical-over , -c
  • --warning-level / --critical-level
  • --return , -r
  • --icase , -i
  • --state-dir , -s
  • --no-state
  • --encoding
  • --check-first
  • --help

これらをひとつずつ見ていきましょう!

--file , -f

監視対象ファイルを指定するのに使用します。

[plugin.checks.access_log]
command = "check-log --file /var/log/access.log --pattern FATAL"

このオプションには、glob形式で対象を指定することも可能です。

[plugin.checks.access_log]
command = '''
check-log --file "/var/log/*.log" --pattern FATAL
'''

便利ですが、一度にたくさんのファイルが監視対象にならないように気をつけましょう。

--file-pattern , -F

このオプションも同じく、監視対象ファイルを指定するのに使用します。--file オプションとの相違点としては、こちらのオプションだと監視対象としたいファイル名の条件を正規表現で指定することができます。

[plugin.checks.access_log]
command = '''
check-log --file-pattern /var/log/access.log.\\d{4}-\\d{2}-\\d{2} \
--pattern FATAL
'''

--file オプションのglob形式で指定することができないときだけ、使うようにしましょう。

--missing

通常、check-logでは監視対象ファイルが存在しない場合には UNKNOWN アラートが発報します。その挙動をコントロールするためのオプションです。

[plugin.checks.access_log]
command = '''
check-log --file "/var/log/*.log" --pattern FATAL --missing OK
'''

上記の設定例では、ファイルが存在しない場合にはアラートとなりません。

実はこのオプション、僕がcontributeしたものだったりします(●´ω`●)

github.com

--pattern , -p

すでにここまでの例示でも出てきていますが、検出対象文字列を正規表現で指定するためのオプションです。

[plugin.checks.access_log]
command = "check-log --file /var/log/access.log --pattern='(FATAL|ERROR)'"

この例は、FATAL または ERROR の文字列を含むログ出力行を検出するためのものになります。また、このオプションは複数指定することができ、その場合 AND 条件(指定された全てのパターンを満たすログ出力行のみ検出)として扱われます。

[plugin.checks.access_log]
command = "check-log --file /var/log/access.log --pattern FATAL --pattern ERROR"

この例は、FATALERROR の文字列の両方を含むログ出力行を検出するためのものになります。

--suppress-pattern

通常、check-logによるログ監視をおこなった結果、アラートが発報した場合、以下のような表示がされます。

f:id:a-know:20181209194421p:plain

--suppress-pattern オプションを指定しておくと、この for pattern /error/ の部分の表示を抑制することが可能になります。

--exclude , -E

--pattern とは逆で、「このオプションで指定された文字列が含まれるログ出力行は検出対象としない」という挙動になります。

[plugin.checks.access_log]
command = '''
check-log --file "/var/log/*.log" --pattern FATAL --exclude TEST
'''

この例だと、FATAL の出力行を検知するが、同じ行に TEST という出力があった場合は検出しない。という設定になります。

--warning-over , -w / --critical-over , -c

エラー文言が1回だけ出る分には問題ないが、頻発した場合にアラートを上げたいケースに対して有効なオプション群です。

--warning-over , -w で指定した数 より 多くのエラー行が検出された場合には Warning アラートを、--critical-over , -c で指定した数 より 多くのエラー行が検出された場合には Critical アラートを、発報させるためのオプションになります。それぞれのオプションで指定した数以上、ではないことに注意してください。

--warning-level / --critical-level

こちら、個人的に一番難解なオプションだと思っています。まずは例示から。

[plugin.checks.appcalition_log]
command = "check-log --file /var/log/application.log --pattern='ERRORLEVEL:(\d+)' --warning-level 6 --critical-level 9"

上記のような設定をしていた場合に。

2018-12-09 01:23:45.678 APPLICATION ERROR!! ERRORLEVEL:6

上記のようなログ出力行があった場合、アラートは発報されません。

2018-12-09 01:23:45.678 APPLICATION ERROR!! ERRORLEVEL:7

上記のようなログ出力行があった場合、WARNING アラートが発報されます。

2018-12-09 01:23:45.678 APPLICATION ERROR!! ERRORLEVEL:10

上記のようなログ出力行があった場合、CRITICAL アラートが発報されます。

まずは例示から、と書きましたが、この例示で十分伝わりますよね......w おもしろオプションだと思ってます。

このオプションは、 --pattern オプションを複数指定していた場合には指定できません。

--return , -r

実際に検出されたログの内容を、アラート詳細画面や外部への通知内容に含めるためのオプションになります。

[plugin.checks.access_log]
command = '''
check-log --file "/var/log/*.log" --pattern error --return
'''

こんなかんじに指定しておくと。

f:id:a-know:20181209194510p:plain

こんなかんじに表示されます(適当すぎる例示ですみません💦)。

ログに出力されているセンシティブな内容が外部に送信されることになるので、その点は考慮の上、ご利用ください。

--icase , -i

このオプションを指定すると、検出条件がケースインセンシティブに、つまり、大文字と小文字を区別せずに検出するようになります。

--state-dir , -s

check-log は、デフォルトで1分ごとに、その間出力されたログ出力に対してチェック処理をおこないます。それを実現するために、「前回どこまでチェックしたか」といった情報をstateファイルに出力をしておくのですが、そのファイルをどのディレクトリに出力するか、を指定できるオプションです。

ちなみに /var/log/hoge.log を監視する設定である場合、そのstateファイルが出力されるデフォルトの位置は、/var/tmp/mackerel-agent/check-log/var/log/hoge.log-<ハッシュ文字列> となります。このstateファイルのファイル名については、このあとの 気をつけておきたい仕様 にて触れます。

--no-state

上記のstateファイルをつかわない、というオプションです。つまり、毎分のチェック処理ごとに、そのファイルの内容を全てチェックする挙動になります。

--encoding

チェック対象ログファイルのエンコーディングを指定できます。このオプションに指定できるアイテムについては go-check-plugins/check-log at master · mackerelio/go-check-plugins · GitHub のREADMEに列挙されています。

--check-first

現在の check-log プラグインでは、設定されて初回の実行時にはそのときすでにあるログ・ログ出力行のチェックはおこなわない仕様になっています。--check-first オプションは、その挙動をコントロールするためのものになります。

[plugin.checks.access_log]
command = '''
check-log --file "/var/log/*.log" --pattern FATAL --check-first
'''

このように設定しておくと、初回実行時点で既に出力されているログ内容に対しても監視処理をおこなうかたちになります。注意の上、使ってみてください。

......ふぅ。指定できるオプションについては、これで全部ですね!......っと、ひとつ忘れていました。

--help

これは、監視設定のためのオプションとしては使うことはできないので注意です。

$ check-log --help
Usage:
  check-log [OPTIONS]

Application Options:
  -f, --file=FILE                                Path to log file
  -p, --pattern=PAT                              Pattern to search for. If specified multiple, they will be treated together with the AND
                                                 operator
      --suppress-pattern                         Suppress pattern display
  -E, --exclude=PAT                              Pattern to exclude from matching
  -w, --warning-over=                            Trigger a warning if matched lines is over a number
  -c, --critical-over=                           Trigger a critical if matched lines is over a number
      --warning-level=N                          Warning level if pattern has a group
      --critical-level=N                         Critical level if pattern has a group
  -r, --return                                   Return matched line
  -F, --file-pattern=FILE                        Check a pattern of files, instead of one file
  -i, --icase                                    Run a case insensitive match
  -s, --state-dir=DIR                            Dir to keep state files under
      --no-state                                 Don't use state file and read whole logs
      --encoding=                                Encoding of log file
      --missing=(CRITICAL|WARNING|OK|UNKNOWN)    Exit status when log files missing (default: UNKNOWN)
      --check-first                              Check the log on the first run

Help Options:
  -h, --help                                     Show this help message

......はい。ここまで長々と書いてきましたが、わからなくなったらまず --help 。僕との約束だよ!

気をつけておきたいポイント、仕様など

check-log のオプションなのか、チェック監視のオプションなのか、の意識をもっておく

上記のとおり、check-log プラグインはたくさんのオプションをサポートしていますが、「デフォルト毎分のチェック間隔を変更したり」「command で指定したコマンドのタイムアウトを決定したり」は、ここまでの紹介では出てきませんでした。なぜでしょうか。

......理由は、それらは今回の check-log だけに依らない、全てのチェック監視において共通する設定だから、です。チェック間隔(check_interval)のみならず、以下のようなオプションは全て、それが特定のプラグインかどうかに関わらず、指定することができます。

  • notification_interval
  • max_check_attempts
  • timeout_seconds
  • prevent_alert_auto_closed
  • env
  • action
  • memo

それぞれの設定の詳細については、以下のヘルプを参照してください。知っていると役に立つものばかりです。

mackerel.io

先日のアドベントカレンダー記事、Mackerel のカスタムプラグインを作るのは実は簡単だよという話 - えいのうにっき でも書いたことを思いだしてください。プラグインの実行主体はエージェント、です。これらのオプションは、エージェントがチェックプラグインを実行するときのオプション、と考えるとイメージしてもらいやすいかと思います。

どういうときにアラートが発報され、そのアラートはどういうときにクローズされるのか?

繰り返しになりますが、Mackerel のログ監視(チェック監視)は、デフォルトで毎分、チェック処理をおこないます。ログ監視プラグインについては、前回走査位置をstateファイルに記録しておき、次回の走査はその位置からの出力差分について実施・その出力分について検出対象文字列をチェックする、という動作となります。

そのチェックの結果、検出対象文字列が発見された場合は「CRITICAL(もしくはWARNING)」、発見されなかった場合には「OK」として、チェック結果を返送します。CRITICAL(もしくはWARNING)のステータスとなったときにアラートをオープンし、OK のステータスになったらアラートを自動クローズする、というのは、Mackerelのサービスとしての仕様です。

そのため、毎分ごとのログチェック処理ごとに検出対象文字列が検出された場合には、開かれたアラートの状態はそのまま継続しますが、そうではなかった場合(次のログチェック時には検出対象文字列が検出されなかった場合)、オープンされたアラートは自動でクローズされます。

この挙動は、「ログの監視とそれによるアラート」ということを考えたときの直感と微妙に異なる挙動となっているせいか、つまづく人が多いです。いちおう、この挙動を変える(自動クローズされないアラートを発報させることができる)prevent_alert_auto_closed オプションが、チェック監視のオプションとしてサポートされてはいますが、これはこれでクセのあるオプションなので、利用を検討する際にはあらかじめその挙動を十分確認してみてもらえたら、と思います。

stateファイルのファイル名について

先述のとおり、stateファイルのパス・ファイル名は /var/tmp/mackerel-agent/check-log/<監視対象ファイルのパス>/hoge.log-<ハッシュ文字列> という形式になっています。この <ハッシュ文字列> がどのように決められているかというと、check-logに渡されたオプションを連結したものをMD5ハッシュすることによって生成されています(該当の実装箇所)。

つまり、check-log に渡すオプションの種類や内容を変更した場合、stateファイルも別ファイルを作成・参照しようとします。そしてここで思い出して欲しいのが --check-first オプションの指定有無。check-log に渡すオプションの種類や内容を変更した場合、stateファイルが無いので、それはつまり初回チェック時と同じ挙動( --check-first が指定されていなかったら、その時点で出力されているログについては監視対象とはならない)になります。--check-first オプションを指定していたほうがいいのか?そうでないのか?は、頭の片隅に置いておいて欲しいところです。

ログローテート時の追尾仕様について

こちら、みなさんが気になるところかと思います。こちらについては、以下の記事(これも僕が書いています)で具体的に触れられていますので、ぜひご一読ください。

mackerel.io

ちなみにこちらの記事では、stateファイルにどんな情報を書き出しているのか、についても触れられています。

まとめ

ここでとりあげた check-log プラグインについては、僕が Mackerel のテクニカルサポートに携わったこの2年半の間で、非常にたくさんの質問をいただきました。その都度、ヘルプやREADMEに記述を増やせそうなものについてはできるだけ対応してきてはいるのですが、check-log をはじめとしたプラグインはOSSということもあり、その追随を完璧におこなうことも簡単ではありません(往々にして、そうした作業に充てられる時間はなかなか確保できないものです;))。今回、アドベントカレンダーという絶好の機会と、個人のブログという気楽に書ける場を生かして、思いのままにまとめてみました。

そしてここに書いてある内容も、そのうちまた check-log 自体に Pull Request をいただいたりして、すぐに陳腐化すると思います。check-log は、私がcontributeしたことがあるというくらいなので、コードも非常に読みやすいものになっています。check-log をはじめとしたプラグインのコードを読んで仕様を把握することをきっかけに、「OSSのコードを読む」というきっかけにもしてもらえたら嬉しいです。