UNIX的なアレ

UNIX的なこととかいろいろ

fluentdで集約したerror_logをslackに流すと捗る

f:id:wadap:20140819095929j:plain

nanapiでは社内のチャットツールに、Slackを導入しています。Slackの便利なところはintegration周りで、要するに他のツールとの連携が非常にし易いんですね。そういった、Chatを中心にした業務効率化を最近ではChatOpsと呼んだりします。

http://nanapi.co.jp/blog/2014/07/24/nanapi_chatops/

ChatOpsの重要な点はコンテキストを共有できる点ですよね。「○○ってエラーログが出てるよ」みたいな情報を直接誰かに伝えるのではなく、ログが出ているという状態をChatを経由して同じものを見ることで、説明が非常にラクになります。

ほかにもデプロイをHubot経由で指示したり、ステータス取得をしたりなど様々な使い方がありますがやはり重要なのは同じ画面を皆が見ているということですね。そういった点がChatOpsの大きなメリットとしてあると思います。

集約したログもchatに流す

というわけで、error_logもChatに流したほうが捗るよねという話です。fluentdはみんな使っていると思うのでこのあたりの細かい説明は割愛します。Slackに流すためのpluginもすでに開発されています。

GitHub - sowawa/fluent-plugin-slack

これをつかうことで簡単に流すことができます。ただ、そのままだと若干不便なのでnanapiの設定の仕方を紹介します。使用するPluginはこのあたりです。

次からは、設定方法を紹介します。

環境構築用のVagrant

とりあえず試すにはVagrant + Chef + Berkshelfを使うのが便利です。td-agent用のcookbookが用意されているので、それを使ってインストールがラクでしょう。Vagrantfileは以下のようになります。

# -*- coding:utf-8 mode:ruby -*-
Vagrant.configure('2') do |config|
  config.berkshelf.enabled = true

  config.vm.define :vm do |config|
    config.vm.box     = 'centos-6.4'
    config.vm.box_url = 'http://developer.nrel.gov/downloads/vagrant-boxes/CentOS-6.4-x86_64-v20130731.box'
    config.vm.provision :chef_solo do |chef|
      chef.json = {
        'td_agent' => {
          'plugins' => [
            'file-alternative',
            'forest',
            'slack',
            'rewrite-tag-filter',
          ],
        }
      }
      chef.run_list = [
        'recipe[td-agent]',
      ]
    end
  end
end

ログ送信側のtd-agent.conf

まず、error_logを集約する必要があります。fluentdは標準でapacheもcombinedをparseする設定をもってくれていますが、error_logはそのままだと動きません。以下のようにして、設定することでerror_logをちゃんと取得できます。

<source>
  type forward
  port 24224
</source>

<source>
  type tail
  format apache
  path /var/log/httpd/access_log
  pos_file /tmp/access_log.pos
  tag nanapi.httpd.access_log
</source>

<source>
  type tail
  format /^\[[^ ]* (?<time>[^\]]*)\] \[(?<level>[^\]]*)\] (?<message>.*)$/
  time_format %b %d %H:%M:%S.%L %Y
  pos_file /tmp/error_log.pos
  path /var/log/httpd/error_log
  tag nanapi.httpd.error_log
</source>

# apache logs
<match **.**>
  type forward
  <server>
    host forward_host
    port 24224
  </server>
</match>

APIKEYの発行

f:id:wadap:20140819094826j:plain

SlackのIncomingWebHookという機能を使います。以下のURLからアクセスできます。

https://xxx.slack.com/services/new

f:id:wadap:20140819094914j:plain

ここから設定すると、この画面にいきます。このURLの中で指定されているTokenがあとで使用するAPIKEYになります。

集約した側のtd-agent.conf

さて、つぎは集約してSlackに送る側の設定です。まずディレクティブで受け取ります。nanapiでは、タグの先頭をサービス名にするというルールで運用しているので、先頭に複数のサービス名をmatchさせるルールを書いています。

そして、そのあと、rewrite_tag_filterを経由してerror_logのlog_levelをみてタグを付け直しています。これによってというディレクティブにマッチします。このあたりは、実際に本番で運用している設定の簡易版となっていますので、実運用に合わせて変更すると良いと思います。

<source>
  type forward
</source>

<match {nanapi,nanapiworks}.httpd.error_log>
  type copy
  <store>
    type forest
    subtype file_alternative
    <template>
      buffer_chunk_limit 2g
      path /var/log/fluent/${tag_parts[0]}/httpd/%Y/%m%d/${tag_parts[2]}.%Y%m%d
      time_slice_format %Y%m%d
      compress gzip
    </template>
  </store>

  <store>
    type rewrite_tag_filter
    rewriterule1 level error slack.error
  </store>
</match>

<match slack.**>
  type buffered_slack
  api_key xxxxxxxxxxxxxx
  team xxxxxx
  channel %23fluentd
  username fluentd
  color danger
  icon_emoji :fluentd:
  buffer_path /tmp/td_slack_buffer
  flush_interval 5s
</match>

より効率的なchannel運用を

さて、こんな感じでerror_logを運用していたりします。slackのpluginは設定にもある通り、colorなども設定できます。このあたりと、投稿するchannelをうまく設定することでベストなerror_log運用を目指したいですね。