- PR -

Windows上でlog4jを使用した所UTF-8で出力されない

投稿者投稿内容
takamaro
大ベテラン
会議室デビュー日: 2004/10/12
投稿数: 100
投稿日時: 2004-11-28 11:11
またまた再投稿です・汗

別に継承なんぞはしなくても済みそうです。
空のコンストラクタがあるのを見逃していました。。。

コード:


RollingFileAppender rfa = null;
rfa = new RollingFileAppender();
rfa.setLayout(layout1);
rfa.setMaximumFileSize(m_maxFileSize);
rfa.setMaxBackupIndex(m_maxBackupCnt);
rfa.setEncoding("UTF-8");
rfa.setFile(logFileName,true,rfa.getBufferedIO(),rfa.getBufferSize());



必ずsetFile()の呼び出し前に各種設定を行わなければ上手くいかないと思います。

P.S これで駄目でしたら環境を整えてから回答しますので、今回はご容赦を。

[ メッセージ編集済み 編集者: takamaro 編集日時 2004-11-28 13:57 ]
マーサ
ベテラン
会議室デビュー日: 2004/11/26
投稿数: 87
投稿日時: 2004-11-28 20:06
いつも有難う御座いますm(__)m

引用:

もし、RollingFileAppenderを拡張したクラスの使用が可能ならば




はい、可能ですので実装してみました。
結果は・・・。

エンコーディング・・・OK
起動時のファイルサイズによるバックアップ・・・OK
実行時のファイルサイズによるバックアップ・・・NG?

ん〜、おしいです。。。

エンコーディングもされ、起動時のバックアップも大丈夫だったので、
さてと暫く動かしっぱなしにしてみたら、実行時のバックアップが不完全でした。

ファイルサイズを1000000と指定したところ、2,144KBでバックアップ。
100000と指定したところ、214KBでバックアップ。。。
指定サイズの約2倍でバックアップされる結果となりました。

と言う事で、rollOverするタイミングを調査中です・・・むむむ・・・。

PS
ちなみに、空のコンストラクタを使用した場合も同様でした。

[ メッセージ編集済み 編集者: マーサ 編集日時 2004-11-28 20:15 ]

[ メッセージ編集済み 編集者: マーサ 編集日時 2004-11-28 20:22 ]
マーサ
ベテラン
会議室デビュー日: 2004/11/26
投稿数: 87
投稿日時: 2004-11-28 21:46
申し訳有りません。
前の投稿で不備が有りました。

引用:


ファイルサイズを1000000と指定したところ、2,144KBでバックアップ。
100000と指定したところ、214KBでバックアップ。。。
指定サイズの約2倍でバックアップされる結果となりました。



ログを2種類出力していて、片方は正常に出力されているので別の問題みたいです。
※処理は一緒で、ファイルサイズやバックアップ数が異なる程度

と言う事で、解決となります。
有難う御座いました。
takamaro
大ベテラン
会議室デビュー日: 2004/10/12
投稿数: 100
投稿日時: 2004-11-29 00:49
解決済みなので蛇足になりますが

ファイルサイズが指定(setMaxFileSize() or setMaximumFileSize())と異なる
理由は org.apache.log4j.helper.CountionQuietWriter の実装に問題が在りそうです。
ここの write() メソッドが

コード:

public void write(String string) {
    try {
      out.write(string);
      count += string.length();
    }
    catch(IOException e) {
      errorHandler.error("Write failure.", e, ErrorCode.WRITE_FAILURE);
    }
}


と「文字列の長さ」を数え、それをファイルサイズに当てはめています。
本当でしたら指定文字コードでエンコードされたバイト数を数えなければ正確な
実装とは言いがたいのですが、そこが出来てません。
恐らく、指定文字コードによってファイルサイズに違いが出てしまうはずです。
対策は、このCountingQuietWriterを継承したクラスを新たに作り、そのwrite()
メソッドをオーバーライドしてcount変数をエンコード後のバイト数で増加するようにし、
加えて、RollingFileAppenderクラスを継承した新たなクラスを作り、setFile()
メソッドをオーバーライドして、先に作ったCountingQuiteWriter継承クラスを
ストリームに用いるようにするしかないと思われます。
作業自体はそれ程難しい事にならないとは思いますけど、どうするかはマーサさん
次第でしょう(必要なら助言は惜しみません、、環境整えたしw)

それにしても、今回Log4Jのソースを拝見していて感じたのですが、これほど有名で
色々な処で使われている(と思われる)オープンソースプロジェクトだと言うのに、
設計&実装、がかなり杜撰で「がっかり」というのが本音です。
こういう機会ですからJakartaにコミットするなりすべきでは、と思うのですが、
日本の方は翻訳主体のようですし殆ど活動しているようには見受けられない。
本家にしても(わたしの語学力を含め)敷居が高そうで接し辛い。。。
恐らく私のように感じて、せっかく改変・修正をしてもそれが本体の方に反映され
ないといったケースが多いのではないでしょうかね?(どうにかならんものかw)
まぁ、Java本体にログ機能が標準で付いちゃいましたし将来的には死に体なのかも
しれませんがね。。。
マーサ
ベテラン
会議室デビュー日: 2004/11/26
投稿数: 87
投稿日時: 2004-11-29 10:42
takamaroさん、有難う御座います。

環境までそろえて頂いて、申し訳ありませんm(__)m

ふむ、予想通り文字数カウントだったわけですねw
一方は単なるログですが、もう一方がメッセージログで日本語が沢山出力されます。
そこで、文字数でカウントしているのかな?っと、当りを付けていたのですが、
ロジックをそこまで追えていませんでした。。。

ちょっと問題なので、対策はとろうと考えています。
まだ、自分でロジックを追えていないので実際にどうすれば良いかピンと来ません。
もう少しロジックを追ってみて、分からない事が有ったらHELP!すると思います

まだまだ、log4jには隠れている問題?が有りそうですね。
この際なので、出来れば今回の件について本家の方に問合せしてみようと思います。
(語学力が無いのできちんと伝わるかどうか・・・その前に本家のMLか・・・)
takamaro
大ベテラン
会議室デビュー日: 2004/10/12
投稿数: 100
投稿日時: 2004-11-29 14:42
引用:

この際なので、出来れば今回の件について本家の方に問合せしてみようと思います。



要点としては、


  • org.apache.log4j.WriterAppender#setEncoding()メソッドが意味を成していない。
  • 無意味なsetEncoding()メソッドは混乱の原因になるので廃止の方向へ向かうべき。
  • その代わりにコンストラクタ引数で文字コード、その他を指定できるよう改善を求む。

  • org.apache.log4j.RollingFileAppender使用時、最大ファイル容量値を越えてしまう。
  • org.apache.log4j.helpers.CountingQuietWriterのcountが1char=1byteと見なす為。
  • エンコード後のバイト数からカウントを数えるよう改善を求む。
  • 出力ストリームをWriter系からStream系へ変更する事で改善できるのではないか?

  • MaxFileSize,MaximumFileSizeとの命名がされているが、実際は指定容量に収まらない。
  • 原因はファイルサイズのチェックが出力後に行なわれる為、常に最大値以上になる。
  • ファイルサイズチェックは出力前の事前チェックに変更して頂けるよう改善を求む。


と、こんなところでしょうかね。。。私が見た範囲だけでも。
もし宜しければ、上記の内容も便乗でお願いできたら有りがたいです。
気が向いた時で結構ですので。。。ではでは。
マーサ
ベテラン
会議室デビュー日: 2004/11/26
投稿数: 87
投稿日時: 2004-11-29 16:08
むぐ・・・早くも行き詰まりました。。。
※もしかしたらtakamaroさんの考えとズレているのかも知れません。(多分ズレています><)

それと、以下の部分が良く分かりませんでした。

引用:

RollingFileAppenderクラスを継承した新たなクラスを作り、setFile()
メソッドをオーバーライドして、先に作ったCountingQuiteWriter継承クラスを
ストリームに用いるようにするしかないと思われます。




write()メソッドのオーバーロードを作成して、エンコーディング後のバイトレングスを
countしていく事は理解しました。
このwrite()メソッドを利用するには、CountingQuietWriterクラスが構築されてないと
いけない。
CountingQuietWriterクラスはRollingFileAppenderクラスのsetQWForFiles()メソッド
で構築される。
じゃぁ、setQWForFiles()メソッドをコールしているのは・・・?
・・・見つけられませんでした。。。
(訂正)FileAppenderクラスから呼ばれてますね^^;
    つまり、これも追加してしまえば良いのかなぁ・・・?

えっと、つまりCountingQuietWriterクラスを継承したクラスの作成方法(内容)が良く分かりませんでした。
もう少し、説明をお願いします。


PS
問合せの方は、直ぐに手をつけられそうに有りませんが。。。
少し落ち着いたら行おうと思います。


[ メッセージ編集済み 編集者: マーサ 編集日時 2004-11-29 17:08 ]
マーサ
ベテラン
会議室デビュー日: 2004/11/26
投稿数: 87
投稿日時: 2004-11-29 18:15
段々わかって来ました。
と言う事で、中間報告です。

以下のクラスを作成しました。

コード:
    if(bufferedIO) {
      setImmediateFlush(false);
    }

    reset();
    Writer fw = createWriter(new FileOutputStream(fileName, append));
    if(bufferedIO) {
      fw = new BufferedWriter(fw, bufferSize);
    }
    this.setQWForFiles(fw);
    this.fileName = fileName;
    this.fileAppend = append;
    this.bufferedIO = bufferedIO;
    this.bufferSize = bufferSize;
    writeHeader();



動作的には・・・起動時と動作中のバックアップがうまく動きません。
もう少しで出来そうな気もするのですが。
ただ、この様な作りで良いのかな?と、思ったりしています。。。

スキルアップ/キャリアアップ(JOB@IT)