バイト先(大学)で、syslog-ngに流れてくるログをfluentdに流し込もう事になった。最終的にMongoDBに入れる。
windows/mac/unix系など色々なOSが入り乱れた環境なので、各ホストからはsyslogで飛ばすのがいいらしい。んで、最終的にモダーンなfluentdやmongodbに通して使おうという感じ。
(特にnt-syslogがすごいよくできてて、windowsなのにちゃんとutf-8で送ってくれるしえらい)

fluentdのプラグインを作り始めたけどまだ完成してない。なんか間違ってるとかこうした方がいいという情報あったら教えてください。

(ちなみにgem search fluent –remote | grep tail で見つかる物は全部ソース読んだり試したけど要求仕様を満たすgemは無かったです)


syslogをfluentdに流し込む

fluentdのtailプラグインにはsyslogフォーマットがあるので、こんな感じで読める

<source>
type tail
path /var/log/path/to/syslog_file
tag syslog.test
format syslog
</source>

<match syslog.**>
type mongo
database fluent
collection syslog
host localhost
port 27017
</match>
mongodbに貯まる。

syslog-ngの出す複数のログファイルをfluentdに流し込みたい


syslog-ngの書き出し先はこんな感じになっていたので
destination d_erns { file (/var/log/syslogs/$HOST_FROM/$HOST_FROM-$YEAR$MONTH.log);};

ログを送りつけてくるホストの数だけディレクトリが生成され、月毎のファイルに書き込まれる。
複数ファイルをtailしなければならない。


ワイルドカードでtailできるfluentd input pluginを作る

tailプラグインを見てみると、fseekなどを駆使して自前でtail -F相当の処理をするように実装されていた。
で、ソースを読むとtailプラグインはカンマ区切りで複数ファイルを監視できるようになっている。
じゃあこれをちょっと拡張すればいいのでは?と思って、pathをワイルドカードで指定できるinput pluginを作った。


in_wildtail.rb
module Fluent
class WildTailInput < TailInput
Plugin.register_input('wildtail', self)

def configure(conf)
conf["path"] = Dir.glob(conf["path"]).join(',')
super
end
end
end

/etc/fluent/plugin/in_wildtail.rb として保存して、

<source>
type wildtail
path /var/log/syslogs/*/*.log
tag syslog.test
format syslog
</source>

これで全てのログファイルを追えるようになった。


毎月のログファイル切り替えに追随する

月毎に新しいログファイルに追記されるようになっている。
また、新しいホストが増えたら自動的にディレクトリが掘られて、そこにログファイルが書き出される。

ファイルやディレクトリが増えたことを検知する機能をwildtailプラグインに追加したい。しかしThreadで定期的に回すのはfluentdの動作の妨げになりそう。

fluentdのgemspecを見るとcool.ioというイベント駆動ライブラリを使っていた。
cool.ioの作法に従って書けばfluentdの動作の邪魔にはなりにくそう。


というわけでcool.ioでディレクトリ監視するのを試しに書いてみた。
require 'cool.io'

class LogFileWatcher < Cool.io::StatWatcher

def initialize(path)
super path, 0.1
end

def on_change(previous, current)
p previous
p current
puts "-"*5
end
end

reactor = Cool.io::Loop.new
watcher = LogFileWatcher.new "/Users/sho/src/ruby/tmp/coolio"

reactor.attach watcher
reactor.run

扱い方がよくわからないオブジェクトで通知されるけど、とにかく指定したディレクトリで何か変更があるとイベントが起こる。
lsするだけで反応するけど。

これを組み込めばなんとかなるのではないか?
という所までがんばった。

うまくいったらgemする。