- - PR -
Log4jをラップしたクラスの作成
1
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2004-09-27 21:50
次の環境でアプリケーションを開発しております。
JDK 1.4 log4j 1.2.8 commons-logging このアプリケーションでは commons-loggingを使いlog4jからログ出力を行っているのですが、 ログをデータベースにも出力するという要件が発生した為 2つの出力を両方行うログクラスを自分で作成しました。 作成したログクラス Logger.java public class Logger { /** commons-logging */ private Log log = null; private static Logger instance = null; /** constructor */ private Logger(Class clazz) { log = LogFactory.getLog(clazz); } public static Logger getLogger(Class clazz) { if (instance == null) { instance = new Logger(clazz); } return instance; } public fatal( String message ){ log.fatal(message); //ログをデータベースに出力 ・・・ } ・・・ } Log4j設定ファイル log4j.properties log4j.rootCategory=info,A1 log4j.appender.A1=org.apache.log4j.RollingFileAppender log4j.appender.A1.File=D:\\test.log log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=%5p %d{yyyy/MM/dd-HH:mm:ss} [%F:%L] - %m %n ログを出力したいクラス Test.java public class Test { private final Logger log = Logger.getLogger(Test.class); public static void main(){ log.fatal("this is log message!!!") ・・・ } } このクラスを使うことによりログは出力されるのですが、 Log4jに出力されたログは以下のようになります。 FATAL 2004/09/27-18:55:03 [Logger.java:35] - this is log message!!! ログを出力しているTest.javaが出力元としてログに出力して欲しいのですが、 (当然ですが)実際にcommons-loggingを使用しているLogger.javaがログ出力元なっています。 これをどうにかして Test.java をログ出力元として出力したいのですが。。。 ご存知の方がおられましたら、アドバイスよろしくお願いします。 | ||||
|
投稿日時: 2004-09-27 22:17
commons-logging はあまり使ったことないのですが、
log4jをラップした場合のログ出力元はどうしてもorg.apache.log4j.Loggerの メソッドを呼んだクラスになってしまいます。 これを解決するには、 1.org.apache.log4j.spi.LocationInfoというクラスを修正 2.自前のLocationInfoを作成し[Logger.java:35] の部分を自作し、 出力レイアウトには[%F:%L] を指定しない。 のいずれかになると思います。 私は2の方法で対処しました。 org.apache.log4j.spi.LocationInfoが何を行っているかはソースを 参照してください。 [ メッセージ編集済み 編集者: javan 編集日時 2004-09-27 22:18 ] [ メッセージ編集済み 編集者: javan 編集日時 2004-09-27 22:25 ] | ||||
|
投稿日時: 2004-09-28 18:21
tottmoさん
データベースがjdbc接続可能ならば、ラッピングクラスを作成しなくとも org.apache.log4j.RollingFileAppender org.apache.log4j.jdbc.JDBCAppender の2つのAppenderを設定し、出力先として指定すれば済む気がするのですが、 jdbc接続がサポートされていないデータベースへ出力するということでしょうか? なお、log4jの設定については http://www.okisoft.co.jp/esc/log4j/ に丁寧な説明があります。 | ||||
|
投稿日時: 2004-09-28 22:39
javanさん、leさん 返信ありがとうございます。
>javanさん 私も2.でやってみようと思います。 org.apache.log4j.spi.LocationInfo を一見しましたがなかなか敷居が高い感じがしました。(^_^; がんばってみます。 >leさん 確かにおっしゃるとおりです。 はじめの文ではデータベースにただ書き込みたいがためのように書きましたが、(すみません) 実はベータベースへの出力は メッセージ以外に実行ユーザーや実行対象要素名などその他の属性も出力する必要があり、Log4JのJDBC出力をそのまま使う方法は採用しませんでした。 メッセージ以外の文字列をメッセージとは別のカラムに出力できればよいのですが… | ||||
|
投稿日時: 2004-09-29 01:01
なるほどそういうことですか。
因みに私は、似たような用件があったときにはメッセージの先頭の固定長部分を、 ユーザー名や、その他必要な情報の編集部分として、 log.debug(util.str.StringUtil.FixedStr("user1" , "element") + "debugログ出力"); (ここで、util.str.StringUtil.FixedStr(String str1 , String str2)は固定長の レイアウトを編集するクラスメソッドです。) といった具合に編集して、 lox4j.xml 側で、 <param name="ConversionPattern" value="INSERT INTO JBOSS_LOG_TABLE (LOG_DATE, LOG_TIME, PRIORITY, CLASS,METHOD, LINE, USER1, element1, MESSAGE) VALUES ('%d{yyyy-MM-dd}', '%d{HH:mm:ss,SSS}', '%p', '%C', '%M', '%L', trim(substr('%m',1,10)), trim(substr('%m',11,50)), substr('%m',61));" /> といった具合に分解してやることで逃げておりました。 (SQLはpostgreSQLの場合の例です) | ||||
|
投稿日時: 2004-09-29 01:02
Log4JにはMDCという便利なヤツがあります。ひょっとしたら役に立つかもしれません。 ぜひ一度ご検討あれ。 | ||||
|
投稿日時: 2004-09-29 10:53
私も以前似たようなことを考えました。
そのときにパフォーマンスとか設計とか関係なしに こうすればイメージした動きだなぁって思ったことがあります。
| ||||
|
投稿日時: 2004-09-29 20:48
leさん、佐々木さん、わたびんさん 返信ありがとうございます。
MDCで実現できました。 ありがございます。しかも案外簡単にでした。 code:---------------- MDC.put("user","tottmo"); と書けば、%X{user}で"tottmo"がデータベースに出力されました。 commons-loggingを使用しているなかでMDCの部分だけLog4Jによった実装をすることに違和感がありますが、そこはプロジェクトの中で調整しきたいと思います。 leさん ConversionPatternにtrimやsubstrが書けるんですね。勉強になりました。 わたびんさん ちょっと良く分からないのですが、Loggerをstaticにすると[%F:%L]などで ラッピングクラスではなく、ログを出力するクラスの情報が得られるということでしょうか? Loggerはもともとインスタンスがひとつの気がしますが… |
1