サーチ…


デフォルトロガーの使用

次の例は、デフォルトのlogging apiを使用する方法を示しています。

import java.util.logging.Level;
import java.util.logging.Logger;

public class MyClass {
    
    // retrieve the logger for the current class
    private static final Logger LOG = Logger.getLogger(MyClass.class.getName());
    
    public void foo() {
        LOG.info("A log message");
        LOG.log(Level.INFO, "Another log message");

        LOG.fine("A fine message");
    
        // logging an exception
        try {
            // code might throw an exception
        } catch (SomeException ex) {
            // log a warning printing "Something went wrong"
            // together with the exception message and stacktrace
            LOG.log(Level.WARNING, "Something went wrong", ex);
        }

        String s = "Hello World!";

        // logging an object
        LOG.log(Level.FINER, "String s: {0}", s);

        // logging several objects
        LOG.log(Level.FINEST, "String s: {0} has length {1}", new Object[]{s, s.length()});
    }

}

ロギングレベル

JavaロギングApiには7 つのレベルがあります 。降順のレベルは次のとおりです。

  • SEVERE (最高値)
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST (最低値)

デフォルトのレベルはINFO (ただし、これはシステムによって異なり、仮想マシンを使用します)。

注意 :レベルOFF (ロギングをオフにするために使用できる)とALLOFFのoposite)もあります。

このコード例:

import java.util.logging.Logger;

public class Levels {
    private static final Logger logger = Logger.getLogger(Levels.class.getName());

    public static void main(String[] args) {

        logger.severe("Message logged by SEVERE");
        logger.warning("Message logged by WARNING");
        logger.info("Message logged by INFO");
        logger.config("Message logged by CONFIG");
        logger.fine("Message logged by FINE");
        logger.finer("Message logged by FINER");
        logger.finest("Message logged by FINEST");

        // All of above methods are really just shortcut for
        // public void log(Level level, String msg):
        logger.log(Level.FINEST, "Message logged by FINEST");
    }
}

デフォルトでは、このクラスを実行すると、レベルがCONFIGより高いメッセージのみが出力されます。

Jul 23, 2016 9:16:11 PM LevelsExample main
SEVERE: Message logged by SEVERE
Jul 23, 2016 9:16:11 PM LevelsExample main
WARNING: Message logged by WARNING
Jul 23, 2016 9:16:11 PM LevelsExample main
INFO: Message logged by INFO

複雑なメッセージのロギング(効率的)

多くのプログラムで見られるログのサンプルを見てみましょう。

public class LoggingComplex {
    
    private static final Logger logger = 
        Logger.getLogger(LoggingComplex.class.getName());

    private int total = 50, orders = 20;
    private String username = "Bob";

    public void takeOrder() {
        // (...) making some stuff
        logger.fine(String.format("User %s ordered %d things (%d in total)", 
                                  username, orders, total));
        // (...) some other stuff
    }

    // some other methods and calculations
}

上の例は完璧に見えますが、多くのプログラマーはJava VMがスタックマシンであることを忘れています。つまり、メソッドを実行する前に 、すべてのメソッドのパラメータが計算されます。

この事実は、特にFINEFINERFINESTようなデフォルトでは無効になっているような低レベルのログを記録するために、Javaのログインには不可欠です。 takeOrder()メソッドのJavaバイトコードを見てみましょう。

javap -c LoggingComplex.classの結果は次のようになります。

public void takeOrder();
    Code:
       0: getstatic     #27 // Field logger:Ljava/util/logging/Logger;
       3: ldc           #45 // String User %s ordered %d things (%d in total)
       5: iconst_3
       6: anewarray     #3  // class java/lang/Object
       9: dup
      10: iconst_0
      11: aload_0
      12: getfield      #40 // Field username:Ljava/lang/String;
      15: aastore
      16: dup
      17: iconst_1
      18: aload_0
      19: getfield      #36 // Field orders:I
      22: invokestatic  #47 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      25: aastore
      26: dup
      27: iconst_2
      28: aload_0
      29: getfield      #34 // Field total:I
      32: invokestatic  #47 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      35: aastore
      36: invokestatic  #53 // Method java/lang/String.format:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
      39: invokevirtual #59 // Method java/util/logging/Logger.fine:(Ljava/lang/String;)V
      42: return

39行目は実際のロギングを実行します。ロギングレベルがFINEよりも高く(デフォルトでは)設定されていれば、以前のすべての作業(変数のロード、新しいオブジェクトの作成、文字列をformatメソッドで連結)は何もできません。このようなロギングは、非常に非効率的であり、不必要なメモリとプロセッサリソースを消費します。

そのため、使用するレベルが有効になっているかどうかを確認する必要があります。

適切な方法は次のとおりです。

public void takeOrder() {
    // making some stuff
    if (logger.isLoggable(Level.FINE)) {
        // no action taken when there's no need for it
        logger.fine(String.format("User %s ordered %d things (%d in total)",
                                  username, orders, total));
    }
    // some other stuff
}

Java 8以降:

Loggerクラスには、 Supplier<String> asパラメータを取る追加のメソッドがあります。これは単にラムダによって提供されます。

public void takeOrder() {
    // making some stuff
    logger.fine(() -> String.format("User %s ordered %d things (%d in total)",
            username, orders, total));
    // some other stuff
}

Suppliers get()メソッドget()この場合はラムダ)は、対応するレベルが有効になったときにのみ呼び出され、 if構造はもう必要ありません。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow