Log4J徹底解説

ファイル保存系Appender

目次

FileAppdender

さて、超重要な FileAppender である。名前の通り、ファイルにログを吐き出すという一番使いでの大きな Appender だが、ちょっと待ってね。「ファイルをどう扱うか?」でこれから2つばかり派生クラスがあるんである。要するに「ログローテート」の問題で、ログファイルってものは、どんどんログが蓄積されてしまいには超巨大ファイルになって、馬鹿なエディタ(あるいはメモリ/スワップ領域不足)だと開けなくなる....かもしれない。というわけで、フツーは「ログローテーション」と呼ばれる機構があるのだ。これはファイルを「回転」させて、バックアップを保持しながら効果的に古いログを削除していく仕組みである。

たとえば、mylog.log にログを出すとする。ある条件(ファイルサイズが1Mを超えるとか、月が変わるとか)が成立すると、今までのファイルが mylog.log.1 とかいう名前に変わり、新しいログが新しいファイルである mylog.log に出される...という仕組みがログローテーションである。この時、古い mylog.log.1 がすでにあったら、それが削除されてリネームされる、とかいう風に動作するので、古い順にログが消えていく...ということだ。UNIX の場合、/usr/sbin/logrotate というコマンドがあって、/etc/logrotate.conf の設定を見てログローテーションをする、という root にとっては常識ツールが存在している。log4j ではこれをログライブラリレベルでやる仕様があるんである。

しかし、重要な哲学的問題がある。「ファイルをオープンするってどういうこと?」というのを、皆さんは悩んだことはないかな? つまり、「ファイルをオープンして、継続的に書き出しているケースで、そのファイルが外部から名前を変えられた場合、そのファイルが削除された場合には、どうすればイイの?」という問題である。勿論、書き出す毎にファイルを再オープンしてクローズすれば、こんな問題は気にしなくて良い。しかし、効率の問題を考えた時にはファイルハンドルを保持しっぱなしにして、プロセス終了でファイルハンドルを破棄する、というやり方をするケースが多いと思う。で、これがログローテーションで大きな問題になる。実際、継続的に書き出すためにオープンされているファイルが、名前の変更or削除された場合にどうなるかは、厳格にはOS依存(さらに正確にはファイルシステム依存)である。この問題が生じるログローテーションはややこしいんである。

/usr/sbin/logrotate では、大概ログを吐くデーモンにシグナルを送って、「さあ、ログローテーションするから、ファイルを閉じちゃって、その後で再オープンしてね」と伝える(大概 kill -HUP する)のがフツーだ。しかし、UNIXシグナルというものは、Sun は頑固にサポートしない(まあ、かなり強烈なOS依存があるし...)機構であるので、どうしてもこれはログライブラリの側で対処しなければいけない問題になる。が、FileAppender 自体は、この問題には一切関知していない。それをするのは、FileAppender 派生クラスたちだ。

というわけで、「ログローテーションをすべきならば、FileAppender を使っちゃいけないよ!」というのをまず最初にきっちり言っておこう。実際 Linux で実験をしてみると、FileAppender で吐くファイルの名前を変えても、FileAppender は気にせずにそのファイルに追加し続けるし、ファイルを削除しても FileAppender 自体はそれに気づかずにログ内容は宙に消えていく....要するに /usr/sbin/logrotate と log4j は相性が悪いんである。

まあ、「どうやってローテートするの?」は後の話として、まず FileAppender のオプションを見て行こう。これには次のオプションがある。

File
吐き出すファイル名を指定する。当然、実行ディレクトリからの相対表記が可能である。
Append
追加モードか否かを指定する boolean 値(trueかfalse)である。デフォルトは false であって、起動のたびごとにファイルが新たに作られることになる。まあ、運用だと true にして、サーバの起動とは無関係にログが累積していく風にするのがフツーだろう。
BufferedIO
これも boolean で、バッファリングをするか否かを指定する。デフォルトは false でバッファリングをしない。true にするとバッファリングのおかげで頻繁にログが取られる場合には効率が向上することもあろう。
BufferSize
バッファリングをする場合のバッファサイズである。
Threshold
(AppenderSkeltonから継承)
ImmediateFlush
(WriterAppenderから継承)
Encoding
(WriterAppenderから継承)

まあ、指定の仕方は言うまでもなく、こんなところだ。

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=mylog.log
log4j.appender.file.Append=true
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %5p %c{1} - %m%n

log4j.rootLogger=debug, file

RollingFileAppdender(1.2)

で、今からは例の「ログローテート」関連の仕様が入った FileAppender 派生クラスの話である。このページは 1.2.8 くらいのバージョンの頃から書き出しているが、今(2006年3月)時点で 1.3 のリリースが間近に迫って来ている状況である。なので、このページではまず現行の 1.2 系について説明したあと、新しい 1.3 系の説明をしようと思うんだが、実はこのログローテート関連が一番大きな変更があるんである。なので、今からする org.apache.log4j.RollingFileAppender の説明は、1.2系のものであり、これは 1.3 では設計が全面的に見直され、org.apache.log4j.rolling.RollingFileAppender に変わる。一応旧バージョンのものも互換性のために存在するが、deprecated の扱いになる。

実は 1.3 での変更のポイントは、1.2系で「ファイルのサイズが指定サイズを超えたらローテート」か「日時ベースでローテート」の2つの Appender に分離しているのを、1つにまとめる、ということなのである....この旧版 RollingFileAppender は「ファイルサイズが指定サイズを超えたら」の方の実装である。

なので、次のオプションがある。

MaxFileSize
このサイズを超えたらローテートする閾値である。「1024」とか「10KB」とか「3MB」とか「1GB」という風に指定できる。ちゃんとSIに従っていて、1MB=1024×1024byteであり、フヌケたメーカー風の勘定ではない。デフォルト値は 10MB である。
MaxBackupIndex
で、古いバックアップファイルは mylog.log.1 とかいう風に「.1」がついて保存されていくことになるのだが、このファイルは更にローテートされると「mylog.log.2」になり、更に...という風で続いていく。しかしこれだと延々ログは破棄されないことになってしまうので、どこかでケジメが必要だ。MaxBackupIndex は古いログをどこまで保存するか、を指定する。これが「1」(デフォルト値)だと、ローテートされた時に mylog.log は mylog.log.1 に名前が変更され、すでにあった mylog.log.1 は削除される。まあ、こんな具合にして、古いログを管理していくのである。
File
(FileAppenderから継承)
Append
(FileAppenderから継承)
BufferdIO
(FileAppenderから継承)
BufferSize
(FileAppenderから継承)
Threshold
(AppenderSkeltonから継承)
ImmediateFlush
(WriterAppenderから継承)
Encoding
(WriterAppenderから継承)

設定例はこんなところ。

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=mylog.log
log4j.appender.file.Append=true
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=3  # mylog.log.3 まで保持
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %5p %c{1} - %m%n

log4j.rootLogger=debug, file

DailyRollingFileAppdender(1.2)

これは日時ベースのローテートを行う 1.2系Appender である。1.3系では「日時ベース」も「サイズベース」も同じ Appender が扱うが、1.2系では分離している。 けど、これクラス名が間違ってるな。名前は「Daily」なんだけど、時間ベースでログローテートする仕様がすべてこれでOKになっている。だから、「月毎ローテート」でも「毎時ローテート」でも、これで出来るようになっているので安心してくれ。

要するに、設定可能な「DatePattern」オプションのパターンで、「月毎」か「毎日」か「毎時」かとかが指定できるのである。こんな具合だ。Fileオプションが「mylog.log」だとすると...

'.'yyyy-MM
月が変わった時に、ローテートする。バックアップされるファイル名は、mylog.log.2004-09 という風になる。
'.'yyyy-ww
週変わりでローテートする。コンピュータの常識だと「日曜==0」なので、土曜の深夜にローテートが行われ、ファイル名の「ww」はその年の通算週数になる。
'.'yyyy-MM-dd
毎日ローテートする。JBoss なんかはこれでやってるな。毎日深夜にローテートが実行され、ファイル名は mylog.log.2004-09-20 という風になる。
'.'yyyy-MM-dd-a
毎日深夜と正午にローテートする。ファイル名は mylog.log.2004-09-20-AM という風に午前/午後の区別が入る。
'.'yyyy-MM-dd-HH
毎時でローテートする。ファイル名は mylog.log.2004-09-20-12 という風になる。
'.'yyyy-MM-dd-HH-mm
毎分ローテートする(凄いな!)。ファイル名は mylog.log.2004-09-20-12-38 という風になる。けどこれだと、テキトーに削除してくのが難しいようにも思うけど...

というわけでオプションは、

DatePattern
説明済。デフォルトは「'.'yyyy-MM-dd」で毎日ローテート。
File
(FileAppenderから継承)
Append
(FileAppenderから継承)
BufferdIO
(FileAppenderから継承)
BufferSize
(FileAppenderから継承)
Threshold
(AppenderSkeltonから継承)
ImmediateFlush
(WriterAppenderから継承)
Encoding
(WriterAppenderから継承)

になるが、こいつは「どれだけバックアップを保持するの?」が指定できないので、ディスクがログで埋まって窒息しないように気をつけなきゃな。まあ、この問題を回避するのは、次の奴を使うと良い。

ExternallyRolledFileAppdender(1.2)

こいつは面白い! よくこんなん考えて Appender に入れてくれたものである! 筆者的には金星である。これは RollingFileAppender を継承しているから、ファイルサイズでローテーションする他に、ポートを監視してポートから「RollOver」を受信すると、ローテートするんである。

とこれを筆者は称賛したのだが、1.3系ではローテート仕様の見直しのトバッチリを受けて、実はこの Appender は Deprecated になってしまう...これ凄く惜しい。何とかならないの???

で、「ローテートしろよ!」のメッセージを送るのは、org.apache.log4j.Roller である。これはこれでアプリとして動作するもので、次のように起動する。

% java org.apache.log4j.varia.Roller host port

まあ、hostは多分 localhost だろう。勿論ネット透過性はあるのだが、特に認証などはないので、外部からローテートを起動するのは悪趣味だ。ファイアウォールなどで外部からはブロックすべきだな。crontab に仕掛けて、

0 0 1 * * java org.apache.log4j.varia.Roller localhost 1143 2>/dev/null >/dev/null

という風にしてやると、月ごとのローテートが可能になる。これは当然、RollingFileAppender の派生クラスなので、月毎に mylog.log.1, mylog.log.2 という風な名前でバックアップファイルが作られることになり、MaxBackupIndex オプションの指定に従って、古いものから破棄されていくのである。ただし、RollingFileAppender の派生クラスということは、逆にファイルサイズによるローテートも同時に有効なので、「ファイルサイズでローテートしたの? Roller でローテートしたの?」と悩みたくなければ、MaxFileSize の値をかなり大きめに取っておく必要がある。

勿論オプションは次の通り。

Port
Roller によるトリガを待ち受けるポート番号。デフォルト値はない(=0)ので、適当に使っていないポート番号を指定する。
MaxFileSize
(RollingFileAppenderから継承)
MaxBackupIndex
(RollingFileAppenderから継承)
File
(FileAppenderから継承)
Append
(FileAppenderから継承)
BufferdIO
(FileAppenderから継承)
BufferSize
(FileAppenderから継承)
Threshold
(AppenderSkeltonから継承)
ImmediateFlush
(WriterAppenderから継承)
Encoding
(WriterAppenderから継承)

まあ、設定ファイルはこんなところか。

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.varia.ExternallyRolledFileAppender
log4j.appender.file.Port=8938
log4j.appender.file.File=mylog.log
log4j.appender.file.Append=true
log4j.appender.file.MaxFileSize=1GB
log4j.appender.file.MaxBackupIndex=6  # mylog.log.6 まで保持
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %5p %c{1} - %m%n

log4j.rootLogger=debug, file

大した影響はないが、Roller はちょっとお馬鹿な動作をするみたいである。それはカレントディレクトリに log4j の設定ファイルがあると、これ自体 log4j のアプリとして設定ファイルを読んじゃうのである(苦笑)。読まなくてもイイのにな....だから、「java.net.BindException: Address already in use」みたいな例外を投げる時には、きっとカレントディレクトリに log4j.properties なんかがあって、その中で ExternallyRolledFileAppender の設定でポートがダブっているんだろうと思う。

RollingFileAppdender(1.3)

さて、今からが1.3で登場する新しい「ログローテーション付きファイル出力Appender」である。で、これの最大の特徴は、

triggeringPolicy
「いつ」ログローテートを行うか、そのきっかけを指定するクラス
rollingPolicy
「どのように」ログローテートを行うか、やり方を指定するクラス

に設計を分け、いわゆる「Strategyパターン」を採用したわけである。で、org.apache.log4j.rolling.RollingFileAppender には、形式的にはこの2つのオプションだけが追加されることになる。で、具体的な「いつ」「どのように」の指定は、これらのオプションのサブ要素として指定されることになるのだが...要するに「子持ちオプション」ということになるので、プロパティ形式では指定(log4j.properties)ができず、XML形式(log4j.xml)での指定しかできない。

具体的に triggeringPolicy として用意されているのは次の3つだ。これらは org.apache.log4j.rolling.TriggeringPolicy interface を implements している。

(org.apache.log4j.rolling.TimeBasedRollingPolicy)
時間ベースでローテートするトリガ指定は、本来 rollingPolicy であるべき TimeBasedRollingPolicy が兼用することになる。rollingPolicy で指定されるファイル名パターンからローテートすべきタイミングを拾い出して時間ベースのトリガ・タイミングを得る。
org.apache.log4j.rolling.SizeBasedTriggeringPolicy
ログファイルのサイズベースでローテートする。サブオプションでそのサイズを指定する。
MaxFileSize
ローテートすべきファイルのサイズ指定
org.apache.log4j.rolling.FilterBasedTriggeringPolicy
これはログイベントの内容から「ローテートすべきか否か」を判定するフィルターを与えて、ローテートを決めるストラテジである。これについては、とりあえずフィルタ機能の理解が必要なので、「フィルタ機能」の方で説明する。そっちを見てくれ。これを使うと、たとえばサーバログの場合、「サーバログの開始バナー」に反応して新しいログファイルにする、なんてことが可能になる。

で、rollingPolicy として用意されているのは次の2つだ。これらは org.apache.log4j.rolling.RollingPolicy interface を implements している。

org.apache.log4j.rolling.FixedWindowRollingPolicy
これは旧 RollingFileAppender のような「インデックス・ベースのバックアップファイル」を使うものである。だから、次のサブオプションを持つ。
ActiveFileName
現行のログファイルの指定名(Deprecated!)。
FileNamePattern
バックアップファイルのパターン。
     <param name="FileNamePattern" value="rolling.%i.zip" />
のように、「%i」でインデックスが入る領域を指定する。
MinIndex
インデックスに使う最小の数値
MaxIndex
インデックスの最大の数値
org.apache.log4j.rolling.TimeBasedRollingPolicy
これを使うと、デフォルトでは時間ベースのトリガ指定をすることになる。要するに旧 DailyRollingFileAppender と同様に、日時ベースの保存ファイル名から、ローテートのタイミングとファイル名を得てローテートする。サブオプションは以下の通り。
ActiveFileName
現行のログファイルの指定名(Deprecated!)。
FileNamePattern
バックアップファイルのパターン。
     <param name="FileNamePattern" value="rolling.%d{yyyy-MM-dd}.log" />
のように、「%d{yyyy-MM-dd}」の書き方で日時指定の入る領域を指定する。ここの書式は java.text.SimpleDateFormat で定義された書き方(旧DailyRollingFileAppenderとほぼ同様)で指定できる。

ふう、ややこしいな...で、更にややこしい(が、有益な新機能)面として、「圧縮ファイル対応」が付け加わっている。でこの「圧縮ファイル対応」は FileNamePattern のファイル名末尾が「.gz」なら「gzip」で圧縮し、「.zip」なら「zip」で圧縮するというやり方である。

筆者に言わせるとこれ少し混乱しているようだ...少し実例ベースで話を進めよう。ごく簡単に「日時ベースのログローテートをする」のならば、log4j.xml の書き方は次のようになる。

(conf/log4j.xml.rolling1)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  <appender name="rolling" class="org.apache.log4j.rolling.RollingFileAppender">
     <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
        <param name="FileNamePattern" value="rolling.%d{yyyy-MM-dd}.log" />
     </rollingPolicy>
     <param name="Append" value="true" />
     <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d %5p %c{1} - %m%n" />
     </layout>
  </appender>

  <logger name="jp.or.nurs.sug.log4j.test">
    <level value ="debug" />
    <appender-ref ref="rolling"/>
  </logger>

</log4j:configuration>

要するにこれは「日時ベースのローテーション」なので、特に TriggeringPolicy はなくてOK(TimeBasedRollingPolicy が兼用)のわけである。これは判りやすいものと思う。この時、ログファイルは「rolling.2006-3-28.log」という名前で作られて、翌日の出力分は「rolling.2006-3-29.log」という名前で保存される。

じゃあ、サイズベースのローテーションはどうなるか?というと、次のようになる。

(conf/log4j.xml.rolling2)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  <appender name="rolling" class="org.apache.log4j.rolling.RollingFileAppender">
     <triggeringPolicy class="org.apache.log4j.rolling.SizeBasedTriggeringPolicy">
        <param name="MaxFileSize" value="3000" />
     </triggeringPolicy>

     <rollingPolicy class="org.apache.log4j.rolling.FixedWindowRollingPolicy">
        <param name="FileNamePattern" value="rolling.%i" />
        <param name="MinIndex" value="0" />
        <param name="MaxIndex" value="3" />
     </rollingPolicy>

     <param name="Append" value="true" />
     <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d %5p %c{1} - %m%n" />
     </layout>
  </appender>

  <logger name="jp.or.nurs.sug.log4j.test">
    <level value ="debug" />
    <appender-ref ref="rolling"/>
  </logger>
</log4j:configuration>

これはまず「rolling.0」が最新のログファイルとして作られ、そのサイズが 3000 byte を越えたら、「rolling.0」がバックアップされて「rolling.1」になり、空の「rolling.0」に新しいログが追加されていくことになる。バックアップファイルは「rolling.3」が最終で、古い「rolling.3」がバックアップされると消滅することになるわけだ。これは TriggeringPolicy と RollingPolicy の2本立てになっただけで、別に難しいわけではない。

あるいは、「サイズベースでローテートするけど、ファイル名は日時ベース」という上記2パターンの交雑のようなやり方もできる。

(conf/log4j.xml.rolling3)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  <appender name="rolling" class="org.apache.log4j.rolling.RollingFileAppender">
     <triggeringPolicy class="org.apache.log4j.rolling.SizeBasedTriggeringPolicy">
        <param name="MaxFileSize" value="1000" />
     </triggeringPolicy>

     <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
        <param name="FileNamePattern" value="rolling.%d{yyyy-MM-dd-HH-mm-ss}.log" />
     </rollingPolicy>
     <param name="Append" value="true" />
     <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d %5p %c{1} - %m%n" />
     </layout>
  </appender>

  <logger name="jp.or.nurs.sug.log4j.test">
    <level value ="debug" />
    <appender-ref ref="rolling"/>
  </logger>
</log4j:configuration>

まあこれは実験なので、「秒単位のファイル名」にしてあるので、良く判ると思うが、とりあえず出すファイル名は「そのログイベントがあった時の時間から」作り、サイズが 1000byte(小さい!)を越えたら、その「新しい時間」からファイル名を作りなおす、という形でローテーションがなされていく。このやり方の実用性はともかく、こういうことも可能である。

で、これが「圧縮ファイル対応」と共に使うと、「あれ?」という意外な動作をすることになる。たとえば、

(conf/log4j.xml.rolling4)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  <appender name="rolling" class="org.apache.log4j.rolling.RollingFileAppender">
     <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
        <param name="FileNamePattern" value="rolling.%d{yyyy-MM-dd-HH-mm-ss}.log.gz" />
     </rollingPolicy>
     <param name="Append" value="true" />
     <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d %5p %c{1} - %m%n" />
     </layout>
  </appender>

  <logger name="jp.or.nurs.sug.log4j.test">
    <level value ="debug" />
    <appender-ref ref="rolling"/>
  </logger>
</log4j:configuration>

まあ、秒単位でローテートして...という非実用的なやり方なので、何なのだが、これだと「rolling.2006-03-28-20-01-10.log」というようなログファイルが出来て、10秒以降の新しいログイベントが発生すると「rolling.2006-03-28-20-01-10.log.gz」のかたちで圧縮されて「バックアップ」になっていくわけだ。要するに「現行ログは圧縮されていると追加できないのでまずい..」ということで、現行ログに限っては圧縮指定を無視しているわけである。ここも少し問題があって、Log4j を使うアプリを再起動すると、「今自分が扱わない古いログファイル」については圧縮をサボる。まあ、これは仕方のないことだが....

(conf/log4j.xml.rolling5)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  <appender name="rolling" class="org.apache.log4j.rolling.RollingFileAppender">
     <triggeringPolicy class="org.apache.log4j.rolling.SizeBasedTriggeringPolicy">
        <param name="MaxFileSize" value="1000" />
     </triggeringPolicy>

     <rollingPolicy class="org.apache.log4j.rolling.FixedWindowRollingPolicy">
        <param name="FileNamePattern" value="rolling.%i.gz" />
        <param name="MinIndex" value="0" />
        <param name="MaxIndex" value="3" />
     </rollingPolicy>

     <param name="Append" value="true" />
     <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d %5p %c{1} - %m%n" />
     </layout>
  </appender>

  <logger name="jp.or.nurs.sug.log4j.test">
    <level value ="debug" />
    <appender-ref ref="rolling"/>
  </logger>
</log4j:configuration>

で問題はこれだ。一応 FixedWindowRollingPolicy の場合も圧縮指定が効くのだが、現行ログのファイル名は「rolling.0.gz」であるクセに、これは圧縮されていない。勿論「rolling.1.gz」以降のバックアップファイルは圧縮されるわけで、ちょっとバグのようだ。まあ、現行ログファイル名が「rolling.0」になれば OK のわけである。

これを気持ち悪い...と感じるなら、ちょっと別なオプションを使うことも可能なようだ。そのオプションは「ActiveFileName」だが....これはJavaDoc では Deprecated の扱いになっているので、どうなることやら。それでも一応現状では次の設定で「.gz」の付かない非圧縮形式のファイルに現行ログが出ることになる(がアテにしないように!)。

     <rollingPolicy class="org.apache.log4j.rolling.FixedWindowRollingPolicy">
        <param name="ActiveFileName" value="rolling" />
        <param name="FileNamePattern" value="rolling.%i.gz" />
        <param name="MinIndex" value="0" />
        <param name="MaxIndex" value="3" />
     </rollingPolicy>

可能オプションを最後にまとめておく。

triggeringPolicy
「いつ」ログローテートを行うか、そのきっかけを指定するクラス
rollingPolicy
「どのように」ログローテートを行うか、やり方を指定するクラス
File
(FileAppenderから継承)。ただし、これは設定しても無視される。
Append
(FileAppenderから継承)
BufferdIO
(FileAppenderから継承)
BufferSize
(FileAppenderから継承)
Threshold
(AppenderSkeltonから継承)
ImmediateFlush
(WriterAppenderから継承)
Encoding
(WriterAppenderから継承)

ふう、筆者お気に入りの ExternallyRolledFileAppdender は、この新しい設計では入る余地がなさそうだ...とっても残念である。まあ、1.3 での以降はちょっと過激なんだよな....たとえば、JDBCAppender がどうやらなくなりそうだけど、「旧DBスキームをそのまま生かして移行したい!」というニーズをこれは無視している。過去互換性にコダワリすぎるのは問題だが、Appender みたいなものは過去互換性を維持しても良いように思うんだけどね。皆さんいかが?



copyright by K.Sugiura, 1996-2006