May 24, 2007
[Library] Log4j を使用してログを syslog に出力する
Debian Etch の syslog にリモートから Log4j を使用してログを出力する方法をメモ。
syslogd の設定
Debian Etch では、デフォルト状態の syslogd はリモートからのログを受け付けない設定になっている。 そのため、syslogd の設定を変更して syslogd をリブートする必要がある。 設定は /etc/default/syslogd で行う。
設定が正常に反映されたか確認するために、syslog のポートが開いているかチェックする。# diff /etc/default/syslogd.original /etc/default/syslogd 13c13 < SYSLOGD="" --- > SYSLOGD="-r" # /etc/init.d/sysklogd restart #
UDP の 514 が開いていたら設定は成功。# netstat -an | grep -i udp | grep 514 udp 0 0 0.0.0.0:514 0.0.0.0:* #
Log4j の設定
Log4j にはデフォルトで syslog にログを出力してくれる org.apache.log4j.net.SyslogAppender が用意されている。 しかし、残念なことに org.apache.log4j.PatternLayout が文字エンコーディングの変換機能を持っていないので、マルチバイト文字をメッセージに使用するとログが文字化けしてしまう。 そのため、PatternLayout を拡張して文字エンコーディングを変換する機能を持った Layout クラスを自作する必要がある。 Debian Etch の場合は(インストール時の設定にもよるけれど)、通常デフォルトの文字エンコーディングは EUC-JP になっていると思うので、EUC-JP に変換できればマルチバイト文字をログに出力できる。
文字エンコーディング変換機能付き PatternLayout
PatternLayout の拡張は非常に簡単。 単純に文字エンコーディングを設定内容からインジェクションしてもらい、PatternLayout でメッセージをフォーマットした後に変換処理をするだけ。
package jp.in_vitro.samplecode;
import java.io.UnsupportedEncodingException;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.spi.LoggingEvent;
/**
* メッセージのフォーマット後に文字エンコーディング変換を行う {@link PatternLayout}。
*/
public class CharsetSupportPatternLayout extends PatternLayout {
/** メッセージをフォーマット後に変換する文字エンコーディング。 */
private String charset;
public CharsetSupportPatternLayout() {
super();
}
public CharsetSupportPatternLayout(final String pattern) {
super(pattern);
}
public void setCharset(final String charset) {
this.charset = charset;
}
@Override
public String format(final LoggingEvent event) {
String message = super.format(event);
if (this.charset != null) {
try {
message = new String(message.getBytes(this.charset));
} catch (UnsupportedEncodingException e) {
}
}
return message;
}
}
Log4j の設定
log4j.properties に下記の様な感じで設定する。log4j.xml にする場合はこの内容に準じて XML に書き直せば良い。 Facility は syslog のカテゴリに相当するもので、デフォルトでは user、uucp などが規定されている。 システムにもよるけれど、専用の Facility を用意した方が分かり易いと個人的には思う。 前述の通り、Debian Etch の場合、charset は EUC-JP を指定する(と大抵は上手くいくと思う)。 ConversionPattern は通常と少し違い、時刻と改行コードを省略している。 時刻は syslogd が自動的に付加してくれるのと、改行コードはプラットフォーム毎に異なるのでメッセージには付加しないようにしている。 メッセージに改行コードが付いていなくても、syslogd が付加してくれる様なので特に問題はない(はず)。
log4j.appender.syslog=org.apache.log4j.net.SyslogAppender
log4j.appender.syslog.Facility=[facility]
log4j.appender.syslog.SyslogHost=[syslog server]
log4j.appender.syslog.layout=jp.in_vitro.samplecode.CharsetSupportPatternLayout
log4j.appender.syslog.layout.charset=[syslog server default character encoding]
log4j.appender.syslog.layout.ConversionPattern=%5p %c{1} - %m
実験
下記の様なテストコードを Windows XP 上で実行してみた。 面倒なので facility は uucp を間借りした。
Logger log = Logger.getLogger(CharsetSupportPatternLayoutTest.class);
log.fatal("Oh, my god!!");
log.error("緊急事態");
log.warn("気をつけて");
log.info("お知らせ");
log.debug("デバッグ");
リモートの Debian Etch では以下の様なログが出力された。
というわけで、実験成功。 但し、何故か変な化け方をする文字が結構ある。 メッセージの 'る' が 'た' に変わってしまうといった感じ。 後で原因を調査しないと・・・。# tail -f /var/log/uucp.log May 26 16:14:03 192.168.1.101 FATAL Hoge - Oh, my god!! May 26 16:14:03 192.168.1.101 ERROR Hoge - 緊急事態 May 26 16:14:03 192.168.1.101 WARN Hoge - 気をつけて May 26 16:14:03 192.168.1.101 INFO Hoge - お知らせ May 26 16:14:04 192.168.1.101 DEBUG Hoge - デバッグ



