torutkのブログ

ソフトウェア・エンジニアのブログ

ログとトレース

システムにおける「ログ」の扱いは、思ったより重要度が高いのですが、システム設計時点ではなかなか掘り下げて設計されずに積み残ってしまいがちな機能です。アプリケーション開発者の気まぐれなデバッグログではなく、システムに発生しえる様々な障害(機能停止だけでなく、パフォーマンス障害、セキュリティ、ほか)の発生と後での障害切り分けに必要な情報をログに残すのは大変な作業です。

ロギングライブラリを使用する場合、開発中に、ログ採取ポイントを特定し、かつログ出力カテゴリやレベル、出力内容を設計し実装している必要があります。もしこの作業が十分でないと、後付でアプリケーションのソースコードをログ出力のためだけに修正し再配布しなければならなくなります。

C/C++なんかでは、アプリケーション側でログ出力文を埋め込まなくても、関数の呼び出しなどをトレース情報として残す仕組みを入れることがありました。Javaでも同様にトレース的な仕組みを用意したいと思い、使えそうな技術を探してみると、

  • JVMTIでトレース用エージェントを作成する
  • Java Bytecode Instrumentation
  • アスペクト指向ツールでメソッドの呼び出し前後にログ出力コードを織り込む
  • BTrace

などがあります。

以下、それぞれのメモです。

JVMTIエージェント

昔簡単なサンプルを作ったことがありました。エージェントをネイティブ(C/C++)で作成するのが手間ですね。
http://www.02.246.ne.jp/~torutk/javahow2/jvmti.html

Java Bytecode Instrumentation

Javaでエージェントを記述できるのですが、バイトコードを操作するためのツール(javaassist等)が必要になります。以下参考になりそうな記事を挙げますが、これもちょっと手間がかかりそうです。

Java Bytecode Instrumentationを利用したログツールLimpidLog

LimpidLogの紹介記事

アスペクト指向ツール

事前にコンパイルするのは採用したくないので、実行時に(ロード時に)織り込みできるものが前提となります。

AspectJ

最新バージョンはAspectJ 1.6.8。大分前から(おそらく1.5以降)、コンパイル時ではなく、プログラムロード時に織り込み(ロードタイム・ウィービング)ができます。
簡単な例を以下ページに記載しています。

GluonJ

javassistを使ったAOPツールで、同じ東工大の千葉先生らが開発しています。ロードタイム・ウィービングが可能です。

BTrace

最初、Solaris 10のDTraceを利用して実現しているものと誤解しており、てっきりSolaris OS上のJava限定かと勘違いしていましたが、実はOS非依存の仕組みでした。
実行中のJavaプログラムに接続してメソッド呼び出しのトレースを非侵襲的に取得することができます。また、javaagentオプションを指定して実行するアプリケーションにBTraceスクリプトを組み込むこともできるようです。

ユーザーガイドです。