protobuf によるログの保存てどうなのか予備調査
Apacheとかウェブサーバのログってなんでテキストで流しているのだろう、あんなものはprotocol bufferか何かにエンコードして保存してしまえばよいのではないか、sawzallもオープンソース化されたことだし、ログ解析もszlでやってしまえばいいのではないだろうか。
行単位でawkだのperlだのでワンライナーをちょこちょこ書くぐらいならはじめから構造化して保存しておけばいいし機械処理もしやすい。catできない欠点はあるけど、別にいいんじゃね?というUnix思想の大否定なわけだけど、そんなようなことを以前から少し思っていた。
今回まずログをprotobufにするとどういうことが起こるか、というのを試してみた。というかつまり、あくまでも副次作用ではあるが、ログの保存容量が減るんじゃねと思ったけど本当にそうなのかというのを見てみた。
適当なproto messageを定義して、適当なpythonスクリプトでjmuk.orgのログをprotobufに変換してみた。意外に変なリクエストが多くてちゃんとしたパーサは面倒そうだということがわかったのはひとつの収穫である気がするが、それはさておき、結果としては無圧縮状態では75%ぐらいのサイズになった。つまり4分の1ほどの容量が削減される計算になる。メッセージの構造などを考えるともっと小さくなる可能性もあるが、まあそんなものであろう。ただし、普通は最新のものをのぞけばbzipなどで圧縮をかけるものだろうし、そうなれば差はぐっと縮まる。となれば案外たいしたことないといえばたいしたことない。
圧縮についてもう少し考えると、ウェブサーバのログを保存する上でデカイのはパスとユーザエージェントだ。どちらも他のフィールドに比べれば長いし、全く共通することも多いから全部のログにいちいち保存するのは無駄っぽい。さらに言うと共通部分も多いだろうからfront codingも効きそうだ。実際、UAを別に保存してIDだけふる方式を予備的に試してみたところでは有望そうだが、これ以上のことは面倒なのでやっていない。まあアーカイブならともかく最新のログでは、ファイルの末尾に足していくだけのファイル形式の方が望ましいだろうから、そうやって特定のフィールドを特別扱いするのはうまいやり口なのかどうかはわからない。
—
さて、ちょっと脱線したのだが、このアプローチはうまくいくんだろうか? 実際のところ、apacheや世のウェブサーバがテキストフォーマット&1行1エントリなのは、syslog(とnewsyslogによるローテート)を使っているからであり、本気でやるにはまずprotobuf-syslogを作るところからはじめなければならない。それはいかにも面倒そうだし、そこまでするだけの利点が俺にあるかというとあんまりない。そんなに一生懸命がんばらないといけないようなほどのログの量じゃないし、大して解析してないし。
ただ、ウェブサーバのログは大抵の場合はhuman readableかつ行志向であり(Unix的であり)、必ずしもコンピュータでの処理を想定した構造になってないのは不思議な気がする。ワンライナーでちょこちょこ書くのもいい加減つかれた、てのもある。ま、誰かやってみるといいんじゃないかなあ。
—
もとの話とあまり関係はないが、railsのアクセスログはちょっとひどくて1エントリ複数行だったり適当だったような気がする(今はどうなっているのか知らないが)。こうしたアプリケーションサーブレットのログについては、syslogも使ってないし、protobufとかでいいのかもしれない。開発環境ではASCIIフォーマットで書きだして、プロダクションならバイナリで、とかさ。まあ、フォーマットを定めづらいかも知れないが……。