Edited at

LTSV のログを jq でフィルタする

More than 3 years have passed since last update.

アクセスログ等を LTSV で保存している方は多いことでしょう。

LTSV は行指向データフォーマットなので、grep 等の UNIX ツールでのフィルタリングも簡単にできる上、拡張性にも優れていて便利です。

そして、grep のような単純なツールではできない、より複雑なフィルタリングを行いたいときは jq が便利です。

LTSV も JSON に変換してしえば jq によるフィルタリングが可能になります。


方法 1: ltsview を使う

ltsview は Ruby で実装された、LTSV を YAML や JSON に変換するツールです。

インストールは gem コマンド一発。

$ gem i ltsview --no-ri --no-rdoc

実をいうと Perl で実装された同名のツールも Text::LTSV に同梱されているようですが、個人的にはツールまわりは RubyGems で入れることが多いので、Ruby 版の方を使っています。

今回の用途にはどちらも使えると思うので、好きな方を使えばいいと思います。

LTSV のアクセスログを ltsview 経由で jq に渡すには以下のようにします。

$ tail -F access.ltsv | ltsview -j --no-color | jq 'select(.status >= "500") | {req: .req, referer: .referer, ua: .ua}'

ltsview はデフォルトでは YAML で出力するので -j で JSON 出力するようにしたり、色付けが問題でそのままでは jq に渡せないので --no-color を指定する必要があります。


方法 2: ltsv2json を使う

ltsv2json は拙作の Ruby 製ツールです。

ltsview のコマンドラインオプションがめんどくさいというだけの理由で昼休みに作りました。

これもインストールは gem コマンド一発。

$ gem i ltsv2json --no-ri --no-rdoc

ltsv2json を使う場合は以下のようにします。

$ tail -F access.ltsv | ltsv2json | jq 'select(.status >= "500") | {req: .req, referer: .referer, ua: .ua}'

そんなに変わらないですね!


おまけ: Rubyist はフィルタリングに jr を使おう

jr は、これも拙作の Ruby 製 JSON フィルタリングツールです。

jq はとても便利で個人的にも良く使うのですが、複雑なフィルタリングをやろうとすると「どうやって書けばいいんだ?」ということになりがちです。

書きなれた Ruby で同じことができれば、ということで作ったのが jr です。

インストールはこれだけ。

$ gem i jr-cli --no-ri --no-rdoc

jr を使うと同じ事が以下のようにできます。

$ tail -F access.ltsv | ltsv2json | jr 'select{|j| j[:status] >= "500" }.map{|j| {req: j[:req], referer: j[:referer], ua: j[:ua]} }'

jq はフィルタリングに特化したツールだけあって、短く書けて良いのですが、記法が少し独特なので覚えるのが面倒という問題があります。

Ruby なら目をつぶっても書ける、という方にはオススメのツールです。