Fluentd入門


# 概要
以下の記事に分かりやすく書いてる

* [Fluentdとはどのようなソフトウェアなのか](http://tagomoris.hatenablog.com/entry/2013/12/03/150656)
* [柔軟なログ収集を可能にする「fluentd」入門](http://knowledge.sakura.ad.jp/tech/1336/)


# 実際に使ってみる

## インストール・起動

### 環境
* Ruby 2.1.0
* fluentd 0.10.43

### gemでインストール（Mac）

```
$ gem install fluentd --no-ri --no-rdoc

$ fluentd --setup ./fluent
```

`./fluent/fluent.conf` という設定ファイルができる

### 起動
```
$ fluentd -c ./fluent/fluent.conf
```

## 試してみる
### echo
fluentd を起動しておいて、

```
$ echo '{"json":"message"}' | fluent-cat debug.test
```

を実行すると、fluentd 実行側に

```
2014-02-23 17:09:58 +0900 debug.test: {"json":"message"}
```

のようなログが流れる。

#### curl

```
$ curl http://localhost:8888/debug.http -F 'json={"foo":"bar"}'
```

を実行すると、同様に

```
2014-02-23 17:17:36 +0900 debug.http: {"foo":"bar"}
```

と出力される。

### Ruby から

```
$ gem i fluent-logger --no-ri --no-rdoc
```

コンソール起ちあげて以下を実行

```
$ pry
> require 'fluent-logger'
> Fluent::Logger::FluentLogger.open(nil, :host => 'localhost', :port => 24224)
> Fluent::Logger.post("debug.ruby", { "from" => "userA", "to" => "userB" })
```

```
2014-02-23 17:27:07 +0900 debug.ruby: {"from":"userA","to":"userB"}
```

が出力される。

## 設定ファイル

基本的に、`./fluent/fluent.conf`に設定を書く。
デフォルト設定（の一部）は以下。

```./fluent/fluent.conf
## built-in TCP input
## $ echo <json> | fluent-cat <tag>
<source>
  type forward
</source>

# HTTP input
# http://localhost:8888/<tag>?json=<json>
<source>
  type http
  port 8888
</source>

## match tag=debug.** and dump to console
<match debug.**>
  type stdout
</match>

# match tag=system.** and forward to another fluent server
<match system.**>
  type forward
  host 192.168.0.11
  <secondary>
    host 192.168.0.12
  </secondary>
</match>
```

### ルール
1. source ディレクティブは入力元を決定。
2. match ディレクティブは出力先を決定。
3. include ディレクティブで他のファイルをインクルード。

細かくは[公式サイト](http://docs.fluentd.org/ja/articles/config-file)で確認

### デフォルト設定について

デフォルトでは、

* TCP（24220）, HTTP(8888)の入力を受け付ける
* `debug.**`というタグを持ったログの時、標準出力。`system.**`というタグのときは、ログを別のサーバーへ転送

# Railsアプリの開発環境でも使ってみる

MongoDBになんか出力してみる。

## mongodbインストール

mongodb 入ってなかったのでインストール。

```
$ brew install mongodb

$ mongod
```

## まずはコマンドラインからMongoに出力
### fluentdプラグインをインストール

```
$ gem i fluent-plugin-mongo --no-ri --no-rdoc
```

[公式サイト](http://docs.fluentd.org/ja/articles/out_mongo)に載ってる

### 設定書く

新しいディレクティブ追加

```fluent/fluent.conf
<match mongo.**>
  type mongo
  host localhost
  database fluent
  collection debug
</match>
```

fluentd を再起動したら、`bson_ext`もインストールしたほうが良いとNoticeが出る。

```
$ gem i bson_ext --no-ri --no-rdoc
```

### 試す

```
$ curl http://localhost:8888/mongo.test -F 'json={"hoge":"fuga"}'
```

```
$ mongo fluent
> db.debug.find()
{ "_id" : ObjectId("5309cbfbf0c4082be4000001"), "hoge" : "fuga", "time" : ISODate("2014-02-23T10:22:04Z") }
```

ちゃんとログが格納されてた、やっほい。

### Railsアプリの中で利用する
twitter gemと、http_parser.rb に関する依存関係で競合した。
本番で使う時はgemでfluentdを入れないほうが良い気がする。
いったんtwitterの方をコメントアウトした

```ruby:Gemfile
# for log collection by fluentd
gem 'http_parser.rb', '~> 0.5.1'
gem 'fluentd'
gem 'fluent-logger'
gem 'fluent-plugin-mongo'
gem 'bson_ext'
```

ロギング用の適当なモジュール書く。ログの中身は適当。

```ruby:fluentd_logger.rb
require 'fluent-logger'

module FluentdLogger

  def self.output(request, controller_name, action_name, params, session, current_user)
    Fluent::Logger::FluentLogger.open(nil, :host => 'localhost', :port => 24224)
    channel = {
      "time" => Time.now,
      "method" => request.request_method,
      "request_path" => request.fullpath,
      "ip" => request.ip,
      "referer" => request.referer,
      "UA" => request.user_agent,
      "controller" => controller_name,
      "action" => action_name,
      "params" => params,
      "session" => session,
      "user_id" => current_user.try(:id)
    }
    
    Fluent::Logger.post("mongo.channel", channel)
  end

end
```

これを適当なコントローラーで読み込み、試しに`before_filter`で使ってみた。
ちゃんと出力できてた。

```
$ mongo fluent
> db.debug.find({"user_id":4})
{ "_id" : ObjectId("5309f4a2f0c4084221000003"), "time" : ISODate("2014-02-23T13:15:57Z"), "method" : "GET", "request_path" : "/hoge", "ip" : "127.0.0.1", "referer" : "http://localhost:3000/", "UA" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Safari/537.36", "controller" : "hoge", "action" : "index", "params" : { "action" : "index", "controller" : "hoge" }, "session" : { (色々) }, "user_id" : 4 }
```

こんな感じで（もうちょっとちゃんとした設計が必要だろうけど）、
ユーザーの動きを追ったり、A/Bテスト検証に使ったりできそう。