そんな今日この頃でして、、、

コード書いたり映画みたり。努力は苦手だから「楽しいこと」を探していきたい。

LTSVでログ保存すると超捗る

たまにはエンジニアっぽい記事を。




Webサービスを運営していると、何かとログについて悩ませられる機会が多い。

単に残せば良いというだけではなく、後々で解析を行うことを考えた保存をしなければならない。



可用性の観点だけで言えば、量的に問題が無ければDBにテーブル作って書き込んでいくのがベターである。

しかし頻度が高く量的に多い場合、それによるパフォーマンスの低下が無視できない。

なにより「ちょっと」レベルの用途でテーブル設計して書き込むロジックを組み込んで・・・というのは面倒だ。



そんなわけで昔ながらのファイル書き込みでログを残すことが多い。

出力形式あれこれ


定形のデータであればcsvやtsvがよく使われる。

単純に要素をカンマやタブで区切ってファイル出力するだけでよいため組み込むには容易だが、出力要素が変化したり後で追加した場合、解析用のスクリプトを修正する必要性があるのが面倒臭い。


データをテキストとして扱う手法としてはJSONにするという手もあるが、この場合ライブラリが必要だったりと手軽さに欠ける。


そんなわけで、そこまで一時の連想配列で収まる程度の複雑でないデータをログとして扱う場合にはLTSVが有効である。


LTSV形式とは

キーと値をコロン(:)で紐付けたものを1要素として、それらをタブで区切ったもの。
Labeled Tab-separated Values (LTSV)

キー1:値1¥tキー2:値2¥t……¥n

この形式の最大の利点は、変換が非常に楽にできる点に尽きる。

データをltsv化

データにタブが含まれないことや、必ず一次の連想配列であることが条件とはなるが、そのようなデータをltsv化するのは例えばperlなら下記のコードのみで対応できる。

open my $log, '>>', '[ログのパス]';
print $log join '¥t', map {"$_:$data{$_}"} grep {defined $date{$_}} keys %data;

ltsvテキストを復元

一行ずつ読み込んだltsvテキストは下記のコードのより元のデータに復元できる

open my $log, '<', '[ログのパス]';
while (my $ltsv = <$log>){
my %data = map {split /:/, $_, 2} split "¥t", $ltsv;

※splitの第三引数を指定しておくのがポイント。URLのようなコロンが含まれる文字列も扱うことができる。


CSVのように予めデータの項目を把握してる必要はないし、ログが目視でも分かりやすいのが地味に楽。

WEB+DB PRESS Vol.74

WEB+DB PRESS Vol.74