logbackで日次ログローテーションする
logbackで日次ローテーションをする時のサンプル。
<configuration> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logFile.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- daily rollover --> <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- keep 30 days worth of history --> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="FILE" /> </root> </configuration>
実はlogbackダウンロードした中に入っている。
logback-0.9.29/logback-examples/src/main/java/chapters/appenders/conf/logback-RollingTimeBased.xml
他にもサイズローテなどのサンプルが入っているので開いてみると幸せになれる。
いくつか設定方法を紹介。(公式にも掲載されている)
%d{}のフォーマットを書き換えることで、ローテーションタイミングが決まる。
フォーマットはjava.text.SimpleDateFormat参照。
- 日次ローテ
%dは"2006-11-24"形式。
- 月次ローテ
例えば、"%d{yyyy/MM}/logFile.log"とすると、月次ディレクトリが作られる。
# 2011/08/logFile.log
- 週次ローテ
localeに依存する。
- 毎時ローテ
- 毎分ローテ!
また、ログファイルをアーカイブする際にzipさせることも可能。
※ただし注意事項があるようなので公式説明をよく読まれたし。
- GZIPで圧縮する
ファイル名の最後に ".gz" もしくは ".zip"をつけるだけ。
logbackを使う
今まではJavaでログ出力といえば、log4jだったが、最近ではlogbackも使いやすくなっている。
[追記]
logbackはintra-martで採用されたりしているので既にかなりメジャーであると言える。
http://www.intra-mart.jp/apilist/v70/doclet/im_commons/jp/co/intra_mart/common/platform/log/rolling/ExtendedTimeBasedRollingPolicy.html
[追記-終]
logbackでログをファイル出力する場合は下記のAppenderクラスを使う。
- FileAppender - ファイルへ出力する。
- RollingFileAppender - FileAppenderを継承し、ログローテーションを提供する。
詳細はリンクを参照。
logbackではログローテーションを実現する際に、RollingPolicyクラスとTriggeringPolicyクラスというものを使うことになる。
簡単にいうと、RollingPolicyはローテ時のバックアップファイル名についての規定を提供。
TriggeringPolicyはログローテーションのローテタイミングについての規定と機能を提供、という感じ。
ローテーションを実現するにはRollingPolicyとTriggeringPolicyの2つを定義する必要がありそう、とここでイメージできる。
主なRollingPolicyクラスは以下
日次ローテ、毎時ローテなどを提供する。
TimeBasedRollingPolicyはTriggeringPolicyとRollingPolicyが同居する。(つまり定義一つでOK)
バックアップファイル名をlog.1,log.2の形で作成できる。
別にSizeBasedTriggeringPolicyを定義する必要がある。
日時ローテとサイズローテを組み合わせたい場合に使う。
使いたい場合は、TimeBasedRollingPolicyの中に組み込む形で定義するようだ。
詳細はリンクを参照。(サンプル有り)
主なTriggeringPolicyクラスは以下
言わずもがなサイズローテーション用TriggeringPolicy。
FixedWindowRollingPolicyと併用。
logbackがlog4jより良い点として、"複数のJVMによる同じログファイルへの書き込みをサポートしている"というところだろう。
FileAppenderに"prudent"(boolean)という設定項目がある。
デフォルトではfalseだが、trueにすることで、複数プロセスで同じログファイルへの出力を保証するモードを利用できる。
log4jでは複数プロセス(マルチJVM)で同じログファイルへ出力するとログが消えるなどしてしまう。
ちなみにprudent=trueの場合は通常ログ書き出しメソッド(OutputStreamAppender#writeOut)でなく、
独自のFileAppender#safeWriteメソッドを使う。
safeWriteはこれだ。
final private void safeWrite(E event) throws IOException { ResilientFileOutputStream resilientFOS = (ResilientFileOutputStream) getOutputStream(); FileChannel fileChannel = resilientFOS.getChannel(); if (fileChannel == null) { return; } FileLock fileLock = null; try { fileLock = fileChannel.lock(); long position = fileChannel.position(); long size = fileChannel.size(); if (size != position) { fileChannel.position(size); } super.writeOut(event); } finally { if (fileLock != null) { fileLock.release(); } } }
つまりFileChannelで排他ロックを取りながらログ出力をする。
処理速度にいちゃもんが付きそうだが、正確にログが取りたい場合は使いたいところだ。
また、logbackはslf4jというライブラリとセットで利用する。
ほとんどslf4jを使うことを意識する必要はないが、introductionを参照して理解しておくと良い。
また日本語サイトでは、ここもslf4jのロガー実装切替アルゴリズムが理解できる。
オレオレJUnit フレームワーク
JUnitでオレオレフレームワーク(というほどのものじゃないが)を書きました。
こうしておくとちょっとだけ楽になります。
public class MyTestFrame extends TestCase{ private long start; private long end; protected static int count = 0; @Override public void setUp(){ System.out.println(); start = System.currentTimeMillis(); } @Override public void tearDown(){ end = System.currentTimeMillis(); System.out.println(getMethodName(count++)+": "+(end-start)+"ms."); } private static String methodNames[] = null; private String getMethodName(int num){ if(methodNames == null || methodNames.length == 0){ List<String> tmpNames = new ArrayList<String>(); Method ms[] = this.getClass().getMethods(); String mn = null; for(Method m : ms){ mn = m.getName(); if(mn.startsWith("test")) tmpNames.add(mn); } methodNames = new String[tmpNames.size()]; methodNames = tmpNames.toArray(methodNames); } return methodNames.length <= num ? "null" : methodNames[num]; } }
こんな感じで標準出力されるのでコマンドベースで実行したりする場合などには役に立ちます。
.
testSimple: 769ms.
.
testBuffered: 206ms.
.
testStream: 307ms.
.
testBufferedStream: 236ms.
.
testApacheIO: 282ms.
ファイル入出力 Nullの挿入
基本的にNULLを処理しようとするとNullPointerExceptionが発生してしまいます。
そのためNULLにならないように常に考慮しなければなりません。
今まで紹介したファイル入出力でNULLデータを書きこむとどうなるか、テストを行ってみました。
public void testNullWrite(){ String data = null; try{ SimpleFileInOut.write(makeOutFileName(),data); count++; }catch(NullPointerException e){ System.out.println("nullpo SimpleFileInOut"); } try{ BufferedFileInOut.write(makeOutFileName(),data); count++; }catch(NullPointerException e){ System.out.println("nullpo BufferedFileInOut"); } try{ StreamFileInOut.write(makeOutFileName(),data); count++; }catch(NullPointerException e){ System.out.println("nullpo StreamFileInOut"); } try{ BufferedStreamFileInOut.write(makeOutFileName(),data); count++; }catch(NullPointerException e){ System.out.println("nullpo BufferedStreamFileInOut"); } try{ FileUtils.write(new File(makeOutFileName()), data); }catch(NullPointerException e){ System.out.println("nullpo FileUtils"); }catch (IOException e) { e.printStackTrace(); } }
処理結果
nullpo SimpleFileInOut
nullpo BufferedFileInOut
nullpo StreamFileInOut
nullpo BufferedStreamFileInOut
testNullWrite: 3ms.
つまり、ApacheIOのFileUtilsでのみNULLデータを書きこんでもぬるぽが起きない。
ちなみに0Byteのファイルが作成されます。
ファイル入出力 ApacheCommons IOの例
Apache CommonsのIOライブラリを利用したファイル入出力を紹介します。
簡単です。
private String inFileName = "resources/file/dummy.dat"; private String outFileName = "tmp/dummy.dat"; public void testApacheIO() throws IOException{ String data = FileUtils.readFileToString(new File(inFileName)); FileUtils.write(new File(outFileName), data); }
ファイル入出力 処理速度比較_1
今まで記事にしたファイル入出力メソッドの処理速度の比較表。
ファイル入出力 シンプルな例 - clash_m45の開発日記
ファイル入出力 Bufferedな例 - clash_m45の開発日記
ファイル入出力 Streamクラスでの例 - clash_m45の開発日記
ファイル入出力速度計測
クラス | 処理時間(ms) | 順位 |
---|---|---|
FileReader,FileWriter | 235 | 3*1 |
BufferedReader,BufferedWriter | 205 | 1 |
FileInputStream,FileOutputStream | 299 | 4 |
BufferedInputStream,BufferedOutputStream | 235 | 2 |
このことから標準Java APIでファイル入出力最速は、
BufferedReader,BufferedWriterとなります。
個人的にはBufferedInputStream,BufferedOutputStreamと
BufferedReader,BufferedWriterで差が出たことが発見でした。
今度はApache Commonsの IOライブラリを使った例を紹介します。
早くなるのかな?遅くなるのかな?
乞うご期待!(なんつって)
*1:ほぼ2位同等速度ですが、たまに遅いことがあるため3位としました。
ファイル入出力 Streamクラスでの例
今回はInputStream,OutputStreamクラスのサブクラスでのファイル入出力を紹介します。
続きを読む