これは既にたくさんの人・企業が実践していることだと思うんですが、自分の周囲に対して明文化するのを主な目的として、記事にしようと思います。
TL;DR
ログは JSON またはそれに変換可能な LTSV のようなフォーマットで改行区切りに一次出力しよう
JSONable とは
私の造語1ですが、「JSON に変換可能である」ぐらいの意味です。
例えば、YAML, LTSV 等がそれにあたります。
これは完全に相互変換できる、というほど厳密な意味ではありません。
例えば YAML には アンカーやエイリアス という仕様がありますが、JSON ではそれを表現することはできません。
ですが、エイリアスを解決した上で、それを JSON に変換することはできます。
また、「JSON に 変換できる」かどうかが重要であって、「JSON から 変換できる」かどうかは重要ではありません。
例えば LTSV はネストした JSON のようなデータを表現することはできませんが、「JSON に 変換できる」ことに変わりはないので、ここでいう JSONable なデータ形式にあたります。
ログを JSONable にするわけ
一般的なログのフォーマットは、必ずしも JSON や LTSV ではありませんし、多分それら以外のフォーマットのものが多数派でしょう。
TSV や CSV のものもありますし、Apache の combined のような独自形式のものが多いことと思います。
それを JSONable にすると、以下のような利点があります。
- ログフォーマットごとにパーザを用意しなくてもよくなる
- 各フィールドに名前がついているので、データそれ自体から意味を読み取りやすい (自己記述的である)
- フィールドの追加が容易である
- jq や jr2 を活用することであらゆる UNIX コマンドと組み合わせることができる
改行区切りにこだわる理由
おもに、tail
コマンドでの扱いやすさを目的としています。
例えば (やる人はあまりいないと思いますが) YAML は改行区切りでレコードを表現するわけではないので、おもむろに tail -F
したときに、データの途中から出力が始まって、正しくデータを読み取れない可能性があります。
また、JSON は仕様上改行で区切ることは一切決まっていないと思いますが、改行区切りで 1 行ずつ記述することはできます。
JSON へのエンコードを行うライブラリによっては、インデントや改行を加えて prettify するものもあるので、その点は注意が必要です。
LTSV については仕様からして改行区切りであることになっているので、問題にはならないでしょう。
おまけ: あくまで一次出力の話です
いまどきは Fluentd にデータを飛ばして、MongoDB のようなドキュメント指向データベースに保存するなど、そもそもログファイル自体書き出していない、ということもあるでしょう。
もちろんそれ自体は全く問題ではなくて、あくまでもアプリケーションからの一次出力さえ JSONable であれば、あらゆるツールと連携が可能になる、ということが大事です。
(Fluentd にさえ飛ばせれば良い、と言うこともできそうですが)
JSONable なフォーマットが向かない領域
基本的にバイナリデータを扱う必要がある場合は向かないでしょう。
もちろん BASE64 エンコード等を利用してできなくもないですが。
まぁログにバイナリを書き出したい、という要求は私にはないので問題にならないのですが。
ログ以外の領域について
JSON を積極的に採用する流れは Web API や JSON Schema 等いくらでもあります。
とりあえず選ぶフォーマットが何故 JSON なのか、については以前に以下のような記事を書いているので、あわせてお読みいただけると幸いです。
-
拙作の JSON フィルタツールです。jq みたいなことが Ruby でできます。詳細は LTSV のログを jq でフィルタする を参照。 ↩