カスタマイズ済みのApacheログ書式もパースする Apache::Log::Parser の話
さて、Perlといえばテキスト処理、テキスト処理といえばPerlですね。そしてこのビッグでデータな現代においてテキスト処理といえばログの処理に決まっています。
ログの処理といってもいろいろですが、もちろん強く逞しく生きる現代っ子の我々は以下のようなログを扱います。
そのような素敵な問題を解決するためのモジュールがCPANにあります。Apache::Log::Parserです。
あっ、そのページはダメ、こっち、こっちな。
Apache::Log::Parser
Apache::Log::Parserは内部に2種類の解析器を備えており、パーサを初期化するときにどちらかを選びます。それぞれ以下のように動作します。
- fast mode
- strict mode
- どのような書式のログに対してもマッチ
- ただし少し遅く動作する
- タブ区切りなどのログでも対応可能
- チェッカを渡し、正しくパースできたかどうかをパース結果を見て判定させられる
どちらのモードでも複数の書式を設定可能で、パーサは設定されたものの中で最も長くパースに成功するものにマッチしたものとしてパース結果を返します。
使うときの例はだいたいこんな感じですね。
my @customized_fields = qw( rhost logname user datetime request status bytes referer agent vhost usertrack mobileid request_duration ); my $custom_fast = Apache::Log::Parser->new( fast => [\@customized_fields], 'combined', 'common'] ); my $custom_strict = Apache::Log::Parser->new( strict => [ [" ", \@customized_fields, sub{my $x=shift;defined($x->{vhost}) and defined($x->{usertrack}) and defined($x->{mobileid})}], 'combined', 'common', ]); $custom_fast->parse($log_line); #=> hashref of parse result, keys are @customized_fields $custom_strict->parse($log_line); # same with $custom_fast
大抵は fast mode でパースできるはずなので、fastで試してダメそうならstrictでもう一度やってみる、くらいでいいと思います。CPANには書式をカスタマイズしたログをパースできるモジュールがほとんどなく、それだけでもこのモジュールの価値はあるかなあ、と思います。
速度
速度は大事です。特に、ちょっと秒間10万行ばかりよろしく、とか言われた時とかに大事ですね。
で、Apache::Log::Parserですが、だいたい以下のような速度になっております。
こちらが専用の正規表現および fast/strict と ApacheLog::Parser というCPANモジュールでcombinedのログに対してベンチをとった結果です。default_* は combined が試行最長パターンのパーサ設定で custom_* は combined よりも長い書式でのパースも試すパーサ設定です*3。
Rate custom_strict default_strict custom_fast default_fast apachelog_parser combined_regex custom_strict 8799/s -- -1% -72% -80% -80% -94% default_strict 8868/s 1% -- -71% -79% -80% -94% custom_fast 31012/s 252% 250% -- -28% -30% -80% default_fast 42986/s 389% 385% 39% -- -3% -73% apachelog_parser 44480/s 406% 402% 43% 3% -- -72% combined_regex 157284/s 1687% 1674% 407% 266% 254% --
まあ遅いじゃないかと言われるかもしれませんが、でも、5種類とかそれ以上ログ書式が混ざっているときにですね、いちいち全部正規表現とか書いてらんない、というかメンテできないんですよ。しょうがないじゃないですか。カスタマイズ可能な機構になっていながら combined 専門にしか対応していない ApacheLog::Parser とほとんど速度が変わらないことを褒めるべき。キリッ。
結論
みんなLTSVでログを吐きましょう。
さいごに
このエントリは Perl Advent Calendar 2013 の 12月9日 (……26時!) の記事でした。
http://qiita.com/advent-calendar/2013/perl
明日がいない!