LTSV のもうひとつのメリット、あるいは、プログラムでログを出力する際に気をつけるべきこと
Labeled Tab-separated Values (LTSV) がブームのようです。
LTSV については、ラベルをつけることで柔軟に拡張できるという点が、その特徴として取り上げられますが、もう一点、タブをセパレータに使うことでログのパースが簡単になった、という点を忘れるべきではないでしょう。
特に httpd のログは NCSA httpd という HTTP/0.9 時代のWebサーバのログフォーマットがベースに拡張されてきたため、以下のようにセパレータとして空白、[]、ダブルクォート ("")*1が混在するという、とても処理しづらいものになっていました。どれほど複雑かは「404 Blog Not Found:perl - Apache Combined Log を LTSV に」の実装を見れば明らかでしょう。
127.0.0.1 - - [08/Feb/2012:23:52:42 +0900] "GET /favicon.ico HTTP/1.1" 404 209 "-" "Mozilla/5.0 AppleWebKit/534.10 Chrome/8.0.552.215 Safari/534.10"
これに対し、LTSVはタブをセパレータに使うことで、ログのパースがとても簡単になっています。
time:28/Feb/2013:12:00:00 +0900<TAB>host:192.168.0.1<TAB>req:GET /list HTTP/1.1<TAB>status:200
えっ? タブがログの、User-Agent 等の文字列中に現れることはないのかって?
ありません。
というのは、かつて、Apacheに送信するHTTPリクエストに制御文字を含めることでサーバ運用者に対して攻撃が可能になるという脆弱性*2が発見され、その結果として Apache のログにおいては制御文字が全てエスケープされるようになったという経緯があるのです。
タブ(という制御文字)をセパレータに用いる、というLTSVの手法は、この脆弱性対応の副産物として生まれた、そしてそれがゆえに汎用性をもったアプローチなのです。
また、上にあげたように、プログラムからユーザー由来の文字列を含むログを出力する際は、適切なエスケープを行わないと脆弱性として取り扱われる可能性がありますので、注意が必要です*3。
PS. あと、今からLTSVでhttpdのログを扱い始めるなら、リクエストを「req:GET / HTTP/1.0」のように単一のフィールドに入れるのは避けるべきだと思います。HTTP/2.0 になった時に対応できない可能性があるので…*4