fluentdでレコードにhostnameを入れてからサーバーに送信する

複数のクライアントから一つのサーバーにログを集める事をしていたのですが、hostnameを入れておかないと後で『どこの鯖のログだこれ？（＾ｑ＾』となってしまうので。
なお、今回初めてfluentd（というかtd-agentを）触りましたｗ

# とりあえず、初心者らしく
td-agentはバージョン 1.1.19を利用しています。
なお、この項はhostnameを入れる件とは関係ないので、hostnameを入れる部分を読みたい方は、ページ中段の「hostnameを入れる」の項を参照してください。
インストール等々、以下のサイトが分かりやすかったです。
[fluentd(td-agent) の導入](http://techblog.raccoon.ne.jp/archives/35031163.html)

## td-agent？
> Fluentdは拡張しやすいようRubyで実装され、一部の性能に直結する部分はC言語で実装されています。
> しかしライトユーザーにとってRubyのデーモンをインストールし運用することは難しい場合があります。

* 以上[公式サイト](http://docs.fluentd.org/ja/articles/install-by-rpm)より
* そもそものfluentdの解説も[公式サイト](http://docs.fluentd.org/articles/architecture)にお任せ

## どんなプラグインをインストール済みなのか見たい時
基本的にgemでインストールしていくスタイルのようなので以下を見ると良いっぽいですね。

```bash
ls /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems/
```

その他irbやrubyコマンドも以下のパスにあるので、既にインストール済みのrubyのバージョン等に影響が出なくて良いですね。

```bash
ls /usr/lib64/fluent/ruby/bin/
```

## 例えばプラグインを追加したい時は？
素でgemを叩くと既存のやつに影響が出たりして嫌なので、先程見たところにインストールされるようにしたい

```bash
$ sudo /usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-forest --no-rdoc --no-ri
```

以上で、先程のところにインストールされるようです

```bash
$ ls /usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems | grep forest
fluent-plugin-forest-0.2.4
```

# hostnameを入れる
ここから本題です。

## 設定
今回は[record-reformer](https://github.com/sonots/fluent-plugin-record-reformer)を利用してみました。

```text
<source>
  type tail
  format ltsv
  path /var/log/httpd/access_log
  pos_file /var/log/td-agent/access_log.pos
  tag development.access_log.addHostname
</source>

<match **.addHostname.**>
  type record_reformer
  renew_record false
  enable_ruby true
  output_tag ${(tag_parts - ["addHostname"]).join(".")}

  <record>
    hostname ${hostname}
  </record>
</match>

<match development.access_log>
  type forward
  flush_interval 5s
  buffer_type file
  buffer_path /var/log/td-agent/buffer/access_log

  <server>
    host logserver.example.com
    port 24224
  </server>
</match>
```

* 以上で、以下のようになります。
 1. tagのどこかに"addHostname"がある場合、レコードにhostnameを記録する
 1. 記録後tagから"addHostname"を削除して、次のmatchへ行く
 1. 今回の場合、サーバーへ送るmatchに拾われる

ltsvフォーマットにしている部分等は不要ですが・・・ご愛嬌でｗ

# サーバーに送るmatchをまとめたい
上記のようにhostnameが入るようになったところで、思いました。
『全部のログをlogserver.example.comに送るのに、ログファイル毎にmatch書くの・・・？（＝ｗ＝；』
以下のような感じに出来ないの？

```text
<match **>
  type forward
  flush_interval 5s
  buffer_type file
  buffer_path /var/log/td-agent/buffer/${tag}

  <server>
    host logserver.example.com
    port 24224
  </server>
</match>
```

しかし、単純にコレだけだと・・・サーバーに送りたくないものがあったとしても送られてしまいます。
送られた側でほっとくという手もあるかもしれませんが、hostnameを追加した子だけ送信したい気がします。

## 設定
今回は[forest](https://github.com/tagomoris/fluent-plugin-forest)を利用してみました

* 似たような設定をまとめたりcaseを利用して設定の上書きが出来るプラグインのようです

```text
<source>
  type tail
  format ltsv
  path /var/log/httpd/access_log
  pos_file /var/log/td-agent/access_log.pos
  tag development.access_log.addHostname
</source>

<match **.addHostname.**>
  type record_reformer
  renew_record false
  enable_ruby true
  output_tag ${(["sendLogServer"] + tag_parts - ["addHostname"]).join(".")}

  <record>
    hostname ${hostname}
  </record>
</match>

<match sendLogServer.**>
  type forest
  subtype forward
  remove_prefix sendLogServer
  output_tag ${tag}
 
  <template>
    flush_interval 5s
    buffer_type file
    buffer_path /var/log/td-agent/buffer/${tag}

    <server>
      host logserver.example.com
      port 24224
    </server>
  </template>
</match>
```

* 以上で、以下のようになります。
 1. tagのどこかに"addHostname"がある場合、レコードにhostnameを記録する
 1. 記録後tagから"addHostname"を削除して"sendLogServer"を追加し、次のmatchへ行く
 1. サーバーへ送るmatchに拾われ、タグから"sendLogServer"を外してサーバーに送る

こうしておけば、"addHostname"がタグにあった子は勝手にサーバーに送られます。
本当にtagの編集だけなら、forestじゃなくて違うpluginの方が良いと思います。
今回の例だと、tagの編集だけではあるのですが・・・（＝ｗ＝

# おまけ：サーバー側の例
こんな感じですかね？

```text
<source>
  type forward
  port 24224
</source>

<match **>
  type forest
  subtype file
  <template>
    path /var/log/gathered/${tag}
    time_slice_format %Y/%m/%d
    flush_interval 12h
    buffer_type file
    buffer_path /var/log/fluentd/buffer/${tag}
  </template>
</match>
```

あとは、S3に上げたりとか色々と設定を変えてみると良いですね。

# まとめ
* record-reformerやforest等、便利なpluginを公開されている方が多数居らっしゃるので、その辺りを探して利用すると色々出来そうです！！

今回触っていて感じたのですが、使っているtd-agentのバージョンの性なのか割と再起動等に弱い印象があります。
複数起動を許可していたりもするので、設定を変えて再起動とかしていると、いつの間にかプロセス自体が増えていて、予期せぬ動作に悩まされます。
再起動毎にプロセスの数と起動時刻を見て、適切にkillをしたりして、少しゆったりとtry&errorをすると良さそうです。

全体的にもっとスマートな記述にしたいですが、自分の習熟度不足のため・・・（＝ｗ＝；