長生村本郷Engineers'Blog

千葉県長生村本郷育ちのエンジニアが書いているブログ

エラーログをSlack通知する

環境

  • CentOS Linux release 7.1.1503 (Core)
  • td-agent: 0.12.12
  • Nginx: 1.8.0

概要

社内でSlackによる連携が進み ログ管理もfluentdにまとめつつあるので エラーログで何かあったらSlack通知させようと思いチャレンジ♪

以下のような流れを想定しています。

Nginx error.log ---> fluentd ---> slack

gemでも作るか!と思ったら既にSlack Pluginは豊富なので あやからせていただきます!

準備

fluentdが/var/log/nginx/error.log にアクセスできるようにしておいてください。

ログがtailできないなんてときは以下参照♪

kenzo0107.hatenablog.com

利用するfluentd Plugin

td-agent.conf設定

gist.github.com

error.logフォーマット設定

  • Nginxのエラーログが以下のようにフォーマットされ出力されているとします。
2015/11/18 18:01:47 [error] 23029#0: *9086 open() "/var/golang/src/img/tmp.png" failed (2: No such file or directory), client: ***.**.**.****, server: hogehoge.jp, request: "GET /img/tmp.png HTTP/2.0", host: "hogehoge.jp", referrer: "http://hogehoge.jp"
  • fluentdのformat設定
format /^(?<time>.+) \[(?<level>[^\]]+)\] *(?<message>.*)$/

上記fomat設定によって以下のように key : value 構成で取得できます。

time : 2015/11/18 18:01
level : error
message : or] 23029#0: *9086 open() "/var/www/html/img/tmp.png" failed (2: No such file or directory), client: ***.**.**.****, server: hogehoge.jp, request: "GET /img/tmp.png HTTP/2.0", host: "hogehoge.jp", referrer: "http://hogehoge.jp"

設定によってはうまく通知させずハマりました汗

tag名をリライト

上記 で取得した key:value を元に tagを書き換えます。

以下の例だと、 levelerror の場合、 slack.error.${tag} (slack.error.nginx.error) にタグを書き換えてます。 他、warn, fatal も同様です。

<match nginx.error>
  type rewrite_tag_filter
  rewriterule1 level error slack.error.${tag}
  rewriterule2 level warn slack.warn.${tag}
  rewriterule3 level fatal  slack.fatal.${tag}
</match>

また message で取得した値の中に
特定文字列が含まれている場合等も可能です。

例) message に 「PHP Fatal Error」 で始まる文字列が含まれている場合にslack.fatal.${tag}に書き換える。

<match nginx.error>
  type rewrite_tag_filter
  rewriterule1 level error slack.error.${tag}
  rewriterule2 level warn slack.warn.${tag}
  rewriterule3 level fatal  slack.fatal.${tag}

  rewriterule4 message ^PHP Fatal Error.*$ slack.fatal.${fatal}    # 追加
</match>

フィールド追加

  • source_id 追加

time, level, message 以外に source_id を追加してます。 以下の例では source_id` に tag_suffix[1] を指定しています。

<match slack.**>
  type record_reformer
  tag reformed.${tag}
  <record>
    source_id ${tag_suffix[1]}
  </record>
</match>

tag_suffix について

tag が reformed.slack.error.nginx.error とすると 以下のような仕様です。

tag_suffix[0] → reformed.slack.error.nginx.error
tag_suffix[1] → slack.error.nginx.error
tag_suffix[2] → error.nginx.error

tag_suffix[-1] → error
tag_suffix[-2] → nginx.error

slack通知

  • incoming WebhookからWebhookURLを設定
<match reformed.slack.**>
  type slack
  webhook_url https://hooks.slack.com/services/xxxxxxxxx/xxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxx
  channel flag_production
  username fluentd
  title_keys source_id
  title %s
  color danger
  flush_interval 5s
</match>

通知結果

f:id:kenzo0107:20150924011032p:plain

余談

Slackに通知しても休日で業務連絡を見ないということは往々にしてあるので Twillioで電話通知するpluginもあります。

github.com

株式会社KDDIウェブコミュニケーションズが提供する有料サービスです。 比較的安価なので導入検討してみてください。

Twillio 料金表

twilio.kddi-web.com

かつての「メール見てませんでした?」 なんてことがなくなりそうなのは良いですね

以上です。