肩赤な話題ですが、
Log4jのバージョンが2.0になってしばらく経ちました。
公式ページを覗いてみると、
今までとはガラリと変わった仕様の数々を垣間見ることができます。
今まで自作していたあのアペンダが、
2.0では不要になる…かもしれません。
そろそろどこかが特集でも組むかと思いましたが、
ググった限りでは(日本語記事は)まだ無さそうです。
Java7の記事をさっさと終わらせて、
自習代わりにこいつの記事を書きたいものです。
いや、記事を書く気力がね?
次回の中身は半分くらいできてはいるのですが…
そんな早朝…
2012年10月29日月曜日
2012年7月12日木曜日
標準出力をJUnitでテストするには
久しぶりにソースを公開してみます。
標準出力に結果を出すプログラムをJUnit 4.1でテストする方法とかで解説されていますが、
それを汎用的にしてみました。
名付けて、StandardOutputSnatcherクラスです。
略してSOS!
ちなみにLog4jの出力テストにも使えることにお気づきでしょうか?
そうです、ConsoleAppenderで出力すれば、
Log4jで出力した内容をStringで取得できるのです。
適当にコピー&ペーストでお試しあれ。
…ちゃんと意味を理解したうえでね。
2012/07/08追記:微妙に修正
標準出力に結果を出すプログラムをJUnit 4.1でテストする方法とかで解説されていますが、
それを汎用的にしてみました。
名付けて、StandardOutputSnatcherクラスです。
略してSOS!
ちなみにLog4jの出力テストにも使えることにお気づきでしょうか?
そうです、ConsoleAppenderで出力すれば、
Log4jで出力した内容をStringで取得できるのです。
適当にコピー&ペーストでお試しあれ。
…ちゃんと意味を理解したうえでね。
2012/07/08追記:微妙に修正
2011年7月22日金曜日
強制ログローテート
t-katochinさんが開発したlog4jの拡張アペンダをさらに拡張してみました。
[log4j] いいとこどりAppender
名前は「org.mericle.log4j.ForcedDailyRollingFileAppender」です。
どんな拡張かというと、
ログローテートを*必ず*実行する機能です。
例えばバッチ処理でログに加工を行う場合、
バッチが動作するまでにログローテートが行われている必要があります。
ですが今までのアペンダには、
ログローテートのタイミングは*最初の*ログ出力時という問題があります。
日次でローテートを行い、
バッチ処理が0時05分だったとしましょう。
もしも0時丁度から0時05分までにログが出力されなかったとき、
その日のバッチ処理が行えないことになってしまいます。
今まではそうした要件がある場合、
ログローテートのためにログ出力を行うことで対応していました。
ただそのためだけに、
別のバッチ処理が発生することになってしまいます。
また、ローテート用のあまり意味のないログが出力されることにもなります。
要件次第ではこれが許されないことがあります。
同じことを要求される案件が3つ目を迎えたとき、
このアペンダの作成を決意しました。
このアペンダは日次なら0時丁度にログローテートされます。
分次、週次、月次、年次にも(理論上は)対応している憎いやつです。
スレッド処理があるので不安がありますが、
JMeterでの10万回試験では問題は見つかっていません。
…きっと大丈夫!
同じ悩みを抱えたマイノリティな仲間がいましたら、
その助けになることを祈ります。
○バイナリ
log4j-extention-1.21.jar
※JDK6でコンパイルしています。
○ソース
log4j-extention-1.21-sources.jar
※Seasarファウンデーションソフトウェアライセンスに従ってください。
※2011-07-26追記:ちょっとコメントを直しました。
※2011-11-30追記:ローリング→ローテートに変更。なぜかこう言ってしまう…あ、アペンダ名か!
[log4j] いいとこどりAppender
名前は「org.mericle.log4j.ForcedDailyRollingFileAppender」です。
どんな拡張かというと、
ログローテートを*必ず*実行する機能です。
例えばバッチ処理でログに加工を行う場合、
バッチが動作するまでにログローテートが行われている必要があります。
ですが今までのアペンダには、
ログローテートのタイミングは*最初の*ログ出力時という問題があります。
日次でローテートを行い、
バッチ処理が0時05分だったとしましょう。
もしも0時丁度から0時05分までにログが出力されなかったとき、
その日のバッチ処理が行えないことになってしまいます。
今まではそうした要件がある場合、
ログローテートのためにログ出力を行うことで対応していました。
ただそのためだけに、
別のバッチ処理が発生することになってしまいます。
また、ローテート用のあまり意味のないログが出力されることにもなります。
要件次第ではこれが許されないことがあります。
同じことを要求される案件が3つ目を迎えたとき、
このアペンダの作成を決意しました。
このアペンダは日次なら0時丁度にログローテートされます。
分次、週次、月次、年次にも(理論上は)対応している憎いやつです。
スレッド処理があるので不安がありますが、
JMeterでの10万回試験では問題は見つかっていません。
…きっと大丈夫!
同じ悩みを抱えたマイノリティな仲間がいましたら、
その助けになることを祈ります。
○バイナリ
log4j-extention-1.21.jar
※JDK6でコンパイルしています。
○ソース
log4j-extention-1.21-sources.jar
※Seasarファウンデーションソフトウェアライセンスに従ってください。
※2011-07-26追記:ちょっとコメントを直しました。
※2011-11-30追記:ローリング→ローテートに変更。なぜかこう言ってしまう…あ、アペンダ名か!
2011年7月12日火曜日
そんなにログが見たいのか!?
いや、何がいいたいのかって…
記事のランキングの話です。
「myBatisのログをLog4jに出力する」
が一位ってどういうこと!?
そんなに困っている人がいるってこと!?
う~ん、気が向いたらlog4jのおバカな解説書こうと思っていましたが、
先にmyBatisにした方がいいのかな?
確かにログが見れないと詰む要素はありますし。
(ソース読めばかなり分かりやすくログを出す方法が…いやよそう俺勝手皆混乱)
日本語のまとめサイトは少なそうだし、
需要があると信じて…まあ気が向いたら?
記事のランキングの話です。
「myBatisのログをLog4jに出力する」
が一位ってどういうこと!?
そんなに困っている人がいるってこと!?
う~ん、気が向いたらlog4jのおバカな解説書こうと思っていましたが、
先にmyBatisにした方がいいのかな?
確かにログが見れないと詰む要素はありますし。
(ソース読めばかなり分かりやすくログを出す方法が…いやよそう俺勝手皆混乱)
日本語のまとめサイトは少なそうだし、
需要があると信じて…まあ気が向いたら?
2011年4月11日月曜日
Log4jで環境変数を利用する
Log4jと環境変数をキーワードに訪れる方が見られるので、
ちょっとまとめてみることにしました。
まずLog4jの設定ファイルは、
環境変数の値を利用することが可能です。
利用する方法は、
${(環境変数の名前)} まちがいです。システムプロパティです。
とするだけです。
それだけで読み込んだときに環境変数の値に置換されます。
設定値となる場所ならどこでも使えるはずです。
例えばtomcatでLog4jを使う場合は、
${catalina.home}/logs/trace.log
なんて書き方ができます。
これでtomcatのlogsフォルダへログを出力できます。
アペンダの参照を環境変数で定義すれば、
起動方法によってログの出力先を変更するようなこともできます。
地味に応用範囲が広いので、
使い方を練習しておくと得するかも?
2012/08/30追記:
すいませんでしたぁ!!
環境変数ではなくシステムプロパティでした!
手っ取り早い話は、星野政利の日記を参照してください。
一言コメントをもらったら直したというのに…恥をさらしまくっていたよ~
ちなみに起動時のオプション以外でどうにかしたい場合は、
以下のコードとかで環境変数をシステムプロパティに注ぎ込むって手もあります。
え?邪道?
ですよね~
ちょっとまとめてみることにしました。
まずLog4jの設定ファイルは、
環境変数の値を利用することが可能です。
利用する方法は、
とするだけです。
それだけで読み込んだときに環境変数の値に置換されます。
設定値となる場所ならどこでも使えるはずです。
例えばtomcatでLog4jを使う場合は、
${catalina.home}/logs/trace.log
なんて書き方ができます。
これでtomcatのlogsフォルダへログを出力できます。
アペンダの参照を環境変数で定義すれば、
起動方法によってログの出力先を変更するようなこともできます。
地味に応用範囲が広いので、
使い方を練習しておくと得するかも?
2012/08/30追記:
すいませんでしたぁ!!
環境変数ではなくシステムプロパティでした!
手っ取り早い話は、星野政利の日記を参照してください。
一言コメントをもらったら直したというのに…恥をさらしまくっていたよ~
ちなみに起動時のオプション以外でどうにかしたい場合は、
以下のコードとかで環境変数をシステムプロパティに注ぎ込むって手もあります。
え?邪道?
ですよね~
2011年4月5日火曜日
myBatisのログをLog4jに出力する
そういえば分かりにくそうだったので記載しよう。
○前提条件
多分Apache commons loggingが必要な気がする。
○log4j.xmlの書き方
多分この2つで十分だと思われる。
ソースはソースコード読んだ結果。
他の場所への出力は…自分は使わないので気が向いたときにでも。
○前提条件
多分Apache commons loggingが必要な気がする。
○log4j.xmlの書き方
多分この2つで十分だと思われる。
ソースはソースコード読んだ結果。
他の場所への出力は…自分は使わないので気が向いたときにでも。
2011年3月9日水曜日
Log4jの書き込みから例外を出させる
だいぶ前からの続きです
とりあえず出来上がったソースを公開しておきます。
まずは色々取得できるように、
例外クラスを新規につくります。
注意していただきたいのは、
RuntimeExceptionを継承していることです。
後述するインターフェースの仕様で、
通常のExceptionだとスローさせることができません。
そしてエラーハンドラを作成します。
あとはlog4j.xmlのerrorHandlerタグのclass属性にて、
作成したエラーハンドラをパッケージ名も含めて記述しておけばOKです。
ログを出力する際には、
作成した例外クラスをキャッチするようにしてください。
(何の役に立つかはイミフですが、)
これでログのエラーキャッチができると思います。
2011年2月18日金曜日
Log4jのエラーハンドラ
Log4jでよく、
「ログ書き込みの成否を取得したい」
って依頼を受けます。
通知されないのがLog4jの魅力なのですが…
まあ仕方ありません。
(成否が分からないだって!?そんなことが本当にあるのか?)
Log4jのErrorHandlerを継承して適当なクラスを作り、
アペンダには<errorhandler>を使って使用を宣言します。
あとはそのまま使えば…とはなりません。
ErrorHandlerのインターフェースは例外を返す仕様とはなっていないからです。
(RuntimeException系の例外クラスなら…
いやよそう、自分の勝手な想像でみんなを混乱させたくない。)
エラーハンドラのインスタンスへ干渉するには、
ロガーからgetAppenderでアペンダを取得して、
さらにgetErrorHandlerすればインスタンスに到達できます。
ただこれどう考えても単一のインスタンスなので、
相当排他処理を頑張らないとまずいことになりそうです。
あまりに使いにくいので、
サンプルとして紹介する価値もありません。
あれ?なんか霧が出てきたような…
追記:RuntimeExceptionでどうにかしたのはこちら
「ログ書き込みの成否を取得したい」
って依頼を受けます。
通知されないのがLog4jの魅力なのですが…
まあ仕方ありません。
(成否が分からないだって!?そんなことが本当にあるのか?)
Log4jのErrorHandlerを継承して適当なクラスを作り、
アペンダには<errorhandler>を使って使用を宣言します。
あとはそのまま使えば…とはなりません。
ErrorHandlerのインターフェースは例外を返す仕様とはなっていないからです。
(RuntimeException系の例外クラスなら…
いやよそう、自分の勝手な想像でみんなを混乱させたくない。)
エラーハンドラのインスタンスへ干渉するには、
ロガーからgetAppenderでアペンダを取得して、
さらにgetErrorHandlerすればインスタンスに到達できます。
ただこれどう考えても単一のインスタンスなので、
相当排他処理を頑張らないとまずいことになりそうです。
あまりに使いにくいので、
サンプルとして紹介する価値もありません。
あれ?なんか霧が出てきたような…
追記:RuntimeExceptionでどうにかしたのはこちら
2011年1月19日水曜日
Log4jで環境変数以外のキーワードを追加したい場合(修正版)
前回からの続きです
ちゃんと上手いやり方があったじゃないか…
このクラスのconfigureメソッドを使えば、
任意のプロパティをキーとして設定できます。
副作用は…無いといいなぁ…
ちゃんと上手いやり方があったじゃないか…
このクラスのconfigureメソッドを使えば、
任意のプロパティをキーとして設定できます。
副作用は…無いといいなぁ…
public class Log4jDomConfigurator extends DOMConfigurator {
private Properties propertiesField = null;
public synchronized Properties getProperties() {
return propertiesField;
}
public synchronized void setProperties(final Properties properties) {
propertiesField = properties;
}
@Override
protected String subst(final String value) {
return super.subst(value, getProperties());
}
public static void configure(final String filename) {
new Log4jDomConfigurator().doConfigure(
filename,
LogManager.getLoggerRepository());
}
public static void configure(
final String filename,
final Properties properties) {
Log4jDomConfigurator configurator = new Log4jDomConfigurator();
configurator.setProperties(properties);
configurator.doConfigure(
filename,
LogManager.getLoggerRepository());
}
}
2011年1月17日月曜日
Log4jで環境変数以外のキーワードを追加したい場合
見事に三日坊主…は置いといて、
初めて技術的な話題に触れるとします。
Log4jの設定ファイルでは、
${キー名}みたいな書式で環境変数を参照できます。
ただ環境変数以外のキーを用意したい場合は、
ちょっと困ってしまいました…(遠い目)
1.3のJoranConfiguratorを使えばいいじゃない
というわけでハッキングです。
DOMConfiguratorを少々(?)いじることにします。
まずはDOMConfiguratorのソースを、
まるごと別のクラスへ移植します。
DOMConfiguratorCustomとかが良い感じでしょうかね?
その中にProperties propsというメンバ変数があるので、
とりあえずSetterメソッドを用意してやります。
setPropsとか、setPropertiesあたりが手頃でしょうか。
後はこんな感じで使います。
DOMConfiguratorCustom config = new DOMConfiguratorCustom();
config.setProps(追加するプロパティ);
config.doConfigure(設定ファイルのパス, LogManager.getLoggerRepository());
コンストラクタにしたり、
staticメソッドにするのはお好みでどうぞ~
ちなみにソースを全コピーしたのは、
クラスを継承してpropsに問い合わせたらIllegalAccessErrorが起こったからです。
多分コンパイラのバージョンクラスローダーが違うからかな~?
もっと簡単な抜け道があったら、
教えて!エライ人!
追記:どうにかしたのはこちら
初めて技術的な話題に触れるとします。
Log4jの設定ファイルでは、
${キー名}みたいな書式で環境変数を参照できます。
ただ環境変数以外のキーを用意したい場合は、
ちょっと困ってしまいました…(遠い目)
というわけでハッキングです。
DOMConfiguratorを少々(?)いじることにします。
まずはDOMConfiguratorのソースを、
まるごと別のクラスへ移植します。
DOMConfiguratorCustomとかが良い感じでしょうかね?
その中にProperties propsというメンバ変数があるので、
とりあえずSetterメソッドを用意してやります。
setPropsとか、setPropertiesあたりが手頃でしょうか。
後はこんな感じで使います。
DOMConfiguratorCustom config = new DOMConfiguratorCustom();
config.setProps(追加するプロパティ);
config.doConfigure(設定ファイルのパス, LogManager.getLoggerRepository());
コンストラクタにしたり、
staticメソッドにするのはお好みでどうぞ~
ちなみにソースを全コピーしたのは、
クラスを継承してpropsに問い合わせたらIllegalAccessErrorが起こったからです。
多分
もっと簡単な抜け道があったら、
教えて!エライ人!
追記:どうにかしたのはこちら
登録:
投稿 (Atom)