uehaj's blog

Grな日々 - GroovyとかGrailsとかElmとかRustとかHaskellとかReactとかFregeとかJavaとか -

超絶未来のprintfデバッグ

printfデバッグというものはなかなか滅びないものでございます。

詳細ログファイルを見ながらデバッグするということに形を変えている様にも思われます。

ならいっそ、それを発展させるとどうなるか?

ログ出力指向のデバッギング。ログビューワの超強力なものでデバッガと連動するようなものを使う。

まず、ログは単なる文字列ではない。文字列的にも見れるが、それを構成する要素は全て、どこのルーチンを経由して来たかが全部たどれるようになっている。

100: ABC 2000:

というログ表示の例えば100をクリックすると、

def func(b) {
int a = 100;
Log.info("$a: $b" + getData() + ": ");
}

のaの定義のところにジャンプ。
bであれば、func()の呼び出し元をたどっていく。

特定の出力データをバイト単位でトラッキングして、どこから来たのか、どういう処理を経てきたのか、どこで発生したのか、が分かる。
これで、以下のようなことができる。

  • 「最近修正したコードが関与して出力されているデータ」という条件でログをフィルタリングしたり、目立つ色で表示されたり、特定の入力(例えばwebからの入力)から来ているものに「危険」マーカーつけてトラッキングしたり。
  • ログデータには情報を紐付けられる。たとえば「メモ」を貼付けて、「後でチェックする」とか。「このパターンが後で生じたら知らせて」とか。アサーションがログに引っ付けられる。コードがアサーションで汚れなくなる。
  • 前回の実行とdiffがあるとこだけフィルタリングしたり、強調したりするとか。
  • ソースコード履歴システムと連動して、指定したコミットで出力が変化した部分をチェックするとか。CIとも連動する。
  • ユニットテストと連動して、ログ出力をテストしていく(任意のメソッドが常に豊富なログを吐くなら、ユニットテストはずいぶん簡単になりうる)とか。テスト出力のログからたどっていくとか。
  • ちなみにもちろん、出力時刻やどのメソッド,どのスレッドが出したかも特定的にたどれる。逆に言うと、それらは、平文のログの一部として明示的に出力したり、常に見たりする必要がない。あ、もちろん明示的なログ出力コードはコードには混入させません。aspectでもなんでもいいけど、それは言語の実行機構の根幹に組み込まれている。

いろいろできると思うんだ。

さかのぼるための情報記録の容量とか大変だろうけど、時をさかのぼるデバッガGDB拡張、この手のハードウェアデバッグ機器と比べると、ログ出力につながるデータをデータフロー分析していけば限定できるのではないか?

「平文ログをにらんでデバッグ」は、あと50年後には憐憫と嫌悪を持って振り返られるものとなるだろう。というより今でも嫌悪してます。