金曜日, 3月 29, 2013

Java ロギングのこと .. log4j-over-slf4j.jar slf4j-log4j12.jar

ロガー移行

Javaには優れたロガーが多い.slf4j, logback 等々.
現時点ではおそらくlogbackならびにslf4jの評価が高く,実際私のところでもアプリケーションデベロッパ達は徐々にlog4jからそれらに移行しつつある.

問題発生!

そんな中私が早晩おこるであろうと思っていたことが案の定(笑)発生した.
log4j-over-slf4jとslf4j-log4j12のクラスパス上での衝突である.

上記2ライブラリはブリッジデザインでのslf4j-api具現パッケージであり,双方をクラスパスに載せると相互参照永久ループが発生しアプリケーションはクラッシュする.

もし以下の点がたくさん思い当たるならば,より問題がおこる確率は高くなる.

  1. プロジェクトやmulti-module mavenプロジェクトがある程度以上の規模である
  2. 相互独立した開発チームが同一のmulti-module mavenプロジェクトを開発している
  3. 未熟にデザインされたライブラリの依存性を持っている
  4. slf4jフレームワークに習熟した人が少ない
  5. 各プロジェクトはロガーを好きに選ぶことができる
  6. library dependenciesの管理が徹底されていない

手前のケースだとまさに上に述べたとおりで,あるプロジェクトがlog4jからslf4jへの移行過渡期にlog4j-over-slf4jへのdependencyを,また別のプロジェクトがlog4j-slf4jを採用した結果あるアプリケーションがクラッシュする羽目に陥った.

解決策。。


この問題を解決するのは決して難しくはない.slf4j-log4j12またはlog4j-over-slf4jのどちらかをdependencyから外せばよい.そして残したほうのスコープをruntimeにする.どちらを外すか?パフォーマンスの理由からlog4j-over-slf4jを外すのがいいだろう.slf4jの公式ホームページからパフォーマンス分析結果を見ることができる.

以下引用
NOTE ON PERFORMANCE Contrary to other bridging modules, namely jcl-over-slf4j and log4j-over-slf4j, which reimplement JCL and respectively log4j, the jul-to-slf4j module does not reimplement the java.util.logging because packages under the java.* namespace cannot be replaced. Instead, jul-to-slf4j translates LogRecord objects into their SLF4J equivalent. Please note this translation process incurs the cost of constructing a LogRecordinstance regardless of whether the SLF4J logger is disabled for the given level or nor. Consequently, j.u.l. to SLF4J translation can seriously increase the cost of disabled logging statements (60 fold or 6000%) and measurably impact the performance of enabled log statements (20% overall increase). As of logback version 0.9.25, it is possible to completely eliminate the 60 fold translation overhead for disabled log statements with the help of LevelChangePropagator.

これはいけない!さっさとけしちゃいましょう  エイヤッ 

以上問題解決.あとはロガー使用を中央管理する体制を強化するなりデベロッパをトレーニングするなりして適宜問題の芽をつむいでおきましょう.



0 件のコメント: