2016-02-01 10 views
6

私は次の問題があります:java.util.logging.Loggerを使用します。いいえ、異なるリソースが見つかりました123、どのようにロガーの動作を変更することができます。ロガーを正しく初期化する方法は?

特に、2(私の意見では)クラスター名に従ってロガーを初期化するための良い構造が与えられています。これにより、必要に応じてデバッグ用のパッケージベースのレベルで冗長性を変更することもできます。

問題を掘り起こした後、グローバルロガーと「空の」ロガー(名前は"")が同じではないことが分かりました。以下の例も参照してください。 ロガーfoo.Barを作成しましたが、これはfooというロガーの代わりに空のロガーに固定されています。 初めてロガーbarを作成した場合、ロガーbar.Bazが正しくアンカーされます。

これは、以前に作成される親ロガーを想定することができないので、this questionのアプローチを主に役に立たない。私が見る限り、クラス名を解析し、必要に応じてロガーを作成する必要があります。

static {...}コードを追加して、独自のロガーを初期化する前に再帰的にロガーを初期化する必要があります。 複数のクラスがパッケージロガーのLogger.getLogger(String)メソッドを呼び出した場合(つまり、bar.Bazbar.FooBazの両方ともロガーbar)、複数の呼び出しが全体的に発生する場合、これは悪影響を及ぼしますか?

import java.util.Enumeration; 
import java.util.logging.LogManager; 
import java.util.logging.Logger; 
public class TestLogger 
{ 
    public static void main(String[] args) 
    { 
     // Create the logger directly 
     Logger.getLogger("foo.Bar"); 
     // Create the logger objects step-by-step 
     Logger.getLogger("bar"); 
     Logger.getLogger("bar.Baz"); 
     // Put the available loggers to output 
     Enumeration<String> e = LogManager.getLogManager().getLoggerNames(); 
     while(e.hasMoreElements()) 
     { 
      String s = e.nextElement(); 
      Logger l = Logger.getLogger(s); 
      String p = (l.getParent() == null ? "none" : "'" + l.getParent().getName() + "'"); 
      System.out.println("'" + s + "': " + p); 
     } 
    } 
} 

プログラムの出力は、すべてのクラスでLogger.getLogger(String)を持つ

'bar': '' 
'global': '' 
'foo.bar': '' 
'bar.baz': 'bar' 
'': none 
+0

'java.utils.Logger'sは扱いにくいことがあります。実際の質問が何であるか完全に理解していませんが、(おそらく)重要な副作用があります。ロガーはガベージコレクションされる可能性があります。あなたの 'main'メソッドで' Logger.getLogger( "foo")。setLevel(x) 'を書いた後に' Logger.getLogger( "foo") 'でロガーを取得すると、** ** may **別のインスタンスになる! 'main'で取得したロガーはすでにガベージコレクトされている可能性があり、2回目の' getLogger( "foo")コールは新しいインスタンスを作成します。 – Marco13

答えて

1

つの負の効果は、あなたがそれをモック(または特別なロガーを渡す)テストのためにすることはできませんということです。

例:あなたは次のクラスCをテストする必要があるとしましょう:

package a.b; 
class C { 
    private Logger logger; 
    private int capacity; 
    private int size; 
    C(int capacity) { 
    this.logger = Logger.getLogger("a.b.C"); 
    this.capacity = capacity; 
    size = 0; 
    } 
    void add(int item) { 
    if (size >= capacity) { 
     logger.log("You already reached the capacity: " + capacity); 
    } 
    //... 
    } 
} 

それは容量に達した場合は、ログを追加要件です。今度はそれをテストする必要があります。これは、これを試験する試験を行うことは非常に難しいとハックです:

public void testCapacityReachedLogs() { 
    C c = new C(2); 
    c.add(1); 
    c.add(2); 
    // verify that c logged the exact string: "You already reached the capacity: 2" 
} 

しかし、あなたが持っている場合:

package a.b; 
class D { 
    private Logger logger; 
    private int capacity; 
    private int size; 
    D(Logger logger, int capacity) { 
    this.logger = logger; 
    this.capacity = capacity; 
    size = 0; 
    } 
    void add(int item) { 
    if (size >= capacity) { 
     logger.log("You already reached the capacity: " + capacity); 
    } 
    //... 
    } 
} 

今、あなたはロガー模擬することができます

public void testCapacityReachedLogs() { 
    Logger logger = getMock(Logger.class); 
    D d = new D(logger, 2); 
    d.add(1); 
    d.add(2); 
    verify(logger).log("You already reached the capacity: 2"); 
} 

注意「モックを"関連するコードは必ずしもフレームワークの構文に従うものではなく、単なる例です。

+0

「模倣する」とはどういう意味ですか?少し説明していただけますか? –

+0

@ChristianWolf私は "モック"の例を追加しました – Gavriel

+0

ああ、そうです。説明してくれてありがとう。 –

関連する問題