Hekaで始めるログ収集
ログ収集ツールといえば fluentd が有名ですが、最近 mozilla が作っている Heka はご存知でしょうか? この Heak プロジェクト、将来 fluentd の対抗馬になる予感を感じるのですが、現在ベータ版なこともあって、ドキュメントと実態が乖離しているためちょっと手が出しづらいです。 そこで、軽く使い方を紹介しようと思います。
※以下は Heka 0.3.0 について書いています。
Heka って?
Go で書かれた hekad によって構成されるログ収集・解析システムです。面白いのは statsd にインスパイアされた統計・解析用のプラグインがデフォルトで入っていることで、例えば直近1分のログのうち、エラーがある一定値を超えたら何かをする、というリアルタイム解析が簡単に出来るようになっています。
hekad のプラグインは以下の4つのタイプに分かれており、これらを組み合わせることでログ収集を行います(このあたりは fluentd とほぼ同じですね)。
Input
: 様々なプロトコルでログを突っ込んだり、ローカルファイルの更新を検知してログを収集しますDecoder
: input されたログを扱いやすいように構造化し、メタデータを付加しますFilter
: ログデータを処理し、単位時間あたりのログ数などにして出力しますOutput
: ログをローカルファイルに書き出したり、別の hekad に転送したりします
ユーザーがメインで作成するのは Filter
になるでしょう。そのため LUA でコンパイルし直さずにプラグインを追加できるようになっています。
上記の Input -> Decoder -> Filter -> Outpu の流れは一台で完結させることもできますが、複数の hekad の Output, Input をつなげることでを使うことで、下図のような大規模なログ収集システムを構築できます。
from Heka Documentation
参考
インストールと起動
Ubuntu ならここから最新版のアーカイブをダウンロードしてきて、dpkg
一発です。
$ dpkg -i hekad_*.deb
起動時は -config
オプションで設定ファイルを指定します。
※man を読むとデフォルトは /etc/hekad.toml
と書いてありますが、該当のファイルを置いても config の指定を求められます。
$ hekad -config config.toml
はまりどころと対策
まず公式ドキュメントが master の最新版を反映しているようで、存在しないプラグインが書いてあったり、デフォルト値が違っていたりします。
$ man hekad.plugin
でインストールされたバージョンのマニュアルを確認するのが一番確実です。
さらに、上記のマニュアルでも若干間違いがあります。ここで結構はまるので、以下の設定を参考にしてみて下さい。
また、matcher を書く際にログの type
をよく使うのですが、どのプラグインがどの type
になるのか書いてありません。最終的にはソースを読むのが確実です。
基本編(syslog を収集)
ローカルの syslog を読み、ログを stderr に出力するための設定です。
[debug] type = "LogOutput" message_matcher = "Type == 'logfile'" # "Type =~ /.*/" でもOK [syslog] type = "LogfileInput" logfile = "/var/log/syslog"
LogileInput の seek journal (どこまでファイルを読んだかを記録しておいて、再起動時に続きから読むための設定) を ON にしている場合、seek journal 用のファイルを作成するディレクトリの作成、及び権限設定が必要です。seek journal の詳細は LogfileInput を参照して下さい。
応用編(Apache のアクセスログ解析)
ロードバランシングされた複数台の Apache のログを収集し、それらをまとめて解析するための設定です。 Apache 側は access log を LogfileInput で収集、解析し、 TcpOutput で後段の hekad に流します。 後段では複数の Apache から送られてきたログの解析を行い、各 Virtual Host 毎のエラー率や、平均応答時間をリアルタイムで Graphite に流して描画します。
※Graphite のインストールはこちらを参考に
Apache 用
[access_log] type = "LogfileInput" logfile = "/PATH/TO/LOGFILE" logger = "access_log" decoders = ["access_log_decoder"] [aaccess_log_decoder] type = "LoglineDecoder" match_regex = '^(?P<Target>\S+) (?P<PTime>\d+) (?P<RemoteIP>\S+) \S+ \S+ \[(?P<Timestamp>[^\]]+)\] "(?P<Method>[A-Z]+) (?P<Url>[^\s]+)[^"]*" (?P<StatusCode>\d+) (?P<RequestSize>\d+) "(?P<Referer>[^"]*)" "(?P<Browser>[^"]*)"' timestamp_layout = "02/Jan/2006:15:04:05 -0700" [aaccess_log_decoder.message_fields] Type = "ApacheLogfile" Logger = "apache" Target = "%Target%" Url|uri = "%Url%" Method = "%Method%" Status = "%StatusCode%" RequestSize|B = "%RequestSize%" Referer = "%Referer%" PTime|us = "%PTime%" Browser = "%Browser%" [upstream] type = "TcpOutput" address = "x.x.x.x:8081" message_matcher = "Type == 'ApacheLogfile'"
注意点
- log のローテーションに rotatelogs を使っている場合は適切にログを収集できません。。
- ドキュメントに載っている match_regx の 最初と最後のスラッシュ(/)は不要です。ハマります。
解析用
[TcpInput] address = ":8081" [StatAccumInput] [access_log_filter] type = "StatFilter" message_matcher = 'Type == "ApacheLogfile"' [access_log_filter.Metric.error] type = "Counter" name = "stats.apache.%Target%.%Status%" value = "1" [CarbonOutput] message_matcher = "Type == 'heka.statmetric'" address = "localhost:2003"
注意点
StatFilter
の man には stat_accum_name というオプションがあるが、指定するとUnknown config setting: ...
といって怒られます。