Java日志记录:记录器

时间:2020-01-09 10:36:45  来源:igfitidea点击:

" java.util.Logger"类是Java日志记录API的主要访问点。这是创建记录器的方法:

Logger logger = Logger.getLogger("myLogger");

作为参数传递给getLogger()工厂方法的字符串是要创建的Logger的名称。我们可以自由选择名称,但是名称暗示了Logger在Logger层次结构中的位置。每一个 。名称中的(点)被解释为层次结构中的一个分支。看这些名字:

myApp
myApp.user
myApp.admin
myApp.admin.import.user

这些名称都是有效的。它们也暗示着等级制度。名称" myApp"位于层次结构的顶部。两个名称" myApp.user"和" myApp.admin"是" myApp"名称的子代。名称" myApp.admin.import.user"是名称" myApp.admin.import"的分支,又是" myApp.admin"名称的分支。

Logger层次结构在其自己的文本中有更详细的介绍。

如果需要,可以使用getName()方法获取Logger的名称。这是一个例子:

String name = logger.getName();

习惯上使用创建Logger的类的类名(包括包名)作为Logger的名。这是一个例子:

Logger logger = Logger.getLogger( MyClass.class.getName() );

记录讯息

要使用Logger记录消息,我们可以调用其许多记录方法之一。其中包括:

log  (Level level, String message);
log  (Level level, String message, Object param1);
log  (Level level, String message, Object[] params);

log  (Level level, String message, Throwable t);

log  (LogRecord record);

logp (Level level, String sourceClass, String sourceMethod, String msg);
logp (Level level, String sourceClass, String sourceMethod, String msg,
    Object param1);
logp (Level level, String sourceClass, String sourceMethod, String msg,
    Object[] params);
logp (Level level, String sourceClass, String sourceMethod, String msg,
    Throwable t);

logrb(Level level, String sourceClass, String sourceMethod,
    String bundle, String msg);
logrb(Level level, String sourceClass, String sourceMethod,
    String bundle, String msg, Object param1);
logrb(Level level, String sourceClass, String sourceMethod,
    String bundle, String msg, Object[] params);
logrb(Level level, String sourceClass, String sourceMethod,
    String bundle, String msg, Throwable t);

entering(String sourceClass, String sourceMethod);
entering(String sourceClass, String sourceMethod, Object param1);
entering(String sourceClass, String sourceMethod, Object[] params);

exiting (String sourceClass, String sourceMethod);
exiting (String sourceClass, String sourceMethod, Object result);

fine    (String message);
finer   (String message);
finest  (String message);

config  (String message);
info    (String message);
warning (String message);
severe  (String message);

throwing(String sourceClass, String sourceMethod, Throwable t);

我不会详细解释这些方法中的每一个。它们在JavaDoc for Java中进行了解释。但是,我将解释它们的目的。知道了它们的目的之后,我们很可能可以在JavaDoc的帮助下找出其余的内容。

log()方法

log()方法组将以特定的日志级别记录一条消息。日志级别作为参数传递。使用Level常量之一作为参数。日志级别在其自己的文本中进行了更详细的介绍。

一些log()方法可以使用对象参数。在记录日志消息之前,将这些对象参数插入到日志消息中。如果没有通过"过滤器"或者由于日志级别太低未过滤掉消息,则仅将对象参数合并到消息中。在邮件被过滤掉的情况下,这可以提高性能。

这是一个log()的例子:

Logger logger = Logger.getLogger("myLogger");

logger.log(Level.SEVERE, "Hello logging");

这是记录到控制台的内容(默认记录目标):

08-01-2012 14:10:43 logging.LoggingExamples main
SEVERE: Hello logging

这是在消息中插入参数的示例:

logger.log(Level.SEVERE, "Hello logging: {0} ", "P1");

这是正在记录的内容:

08-01-2012 14:45:12 logging.LoggingExamples main
SEVERE: Hello logging: P1

注意如何将对象参数值" P1"插入日志消息中" {0}"所在的位置。 " 0"是要插入的对象参数的索引。

下面是一个示例,该示例记录一条消息,该消息包含要插入到日志消息中的多个对象参数:

logger.log(Level.SEVERE, "Hello logging: {0}, {1}",
    new Object[] {"P1", "P2"});

这是正在记录的内容:

08-01-2012 14:45:12 logging.LoggingExamples main
SEVERE: Hello logging: P1, P2

再次注意,对象参数是如何插入日志消息中的,而不是{0}{1}标记中。如前所述,令牌内部的数字是指要传递给log()消息的对象参数数组中要插入的对象参数的索引。

这是一个记录Throwable的示例:

logger.log(Level.SEVERE, "Hello logging",
    new RuntimeException("Error"));

这是正在记录的内容(使用滚动条查看全部内容):

08-01-2012 14:54:29 logging.LoggingExamples main
SEVERE: Hello logging
java.lang.RuntimeException: Error
	at logging.LoggingExamples.main(LoggingExamples.java:18)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

logp()方法

logp()方法的工作方式与log()方法类似,只是每个方法都需要额外的两个参数:sourceClass和sourceMethod参数。

这两个参数旨在告诉我们日志消息来自什么类和方法。换句话说,哪个类和方法是日志消息的"源"。

logrb()方法

logrb()方法的工作方式也与log()方法类似,只是它们可以从资源束中获取日志消息。资源束是一组包含键,值对的文本,例如属性文件。每个文件包含相同的键集,并具有不同的语言值。资源包是一项国际化函数,在这里我不会对其进行详细介绍。

这是一个logrb()的例子:

logger.logrb(Level.SEVERE, "logging.LoggingExamples", "main",
        "resources.myresources", "key1");

本示例通过键" key1"在名为" resources.myresources"的资源包中查找一条消息。如果资源包不包含具有该名称的键(key1),则该值本身将作为消息记录。在此示例中,如果资源束中不存在名为" key1"的键,则值" key1"将被记录为消息。

这是已记录的内容:

08-01-2012 17:14:39 logging.LoggingExamples main
SEVERE: This is message 1

这是资源束(属性文件)的样子:

key1 : This is message 1
key2 : this is message 2

Java Doc没有说明如何使用Locale本地化消息。换句话说,如何选择" ResourceBundle"的语言。

最后的日志方法

Logger还具有以下记录方法:

entering(String sourceClass, String sourceMethod);
entering(String sourceClass, String sourceMethod, Object param1);
entering(String sourceClass, String sourceMethod, Object[] params);

exiting (String sourceClass, String sourceMethod);
exiting (String sourceClass, String sourceMethod, Object result);

fine    (String message);
finer   (String message);
finest  (String message);

config  (String message);
info    (String message);
warning (String message);
severe  (String message);

这些方法中的每一个都对应一个日志级别。例如,finest(),finer(),fine(),info(),warning()和severe()分别对应于一个日志级别。使用这些方法之一记录消息对应于调用log()方法

添加和删除处理程序

我们可以使用addHandler()方法将Handler添加到Logger。这是一个例子:

Logger logger = Logger.getLogger("myLogger");

logger.addHandler(new ConsoleHandler());

logger.logrb(Level.SEVERE, "logging.LoggingExamples", "main",
        "resources.myresources", "key1");

一个"记录器"可以有多个"处理程序"。记录时,消息被转发到所有的"处理程序"。

我们可以使用getHandlers()方法获取Logger的所有Handler,如下所示:

Handler[] handlers = logger.getHandlers();

我们可以使用removeHandler()方法删除Handler。这是一个例子:

Logger logger = Logger.getLogger("myLogger");

Handler handler = new ConsoleHandler();

logger.addHandler(handler);

logger.remove(handler)

设置日志过滤器

我们可以在Logger上设置过滤器,以过滤出转发到Logger的Handler的LogRecords。我们可以使用setFilter()方法在Logger上设置Filter,如下所示:

Filter filter = new MyFilterImpl();

logger.setFilter(filter);

类MyFilterImpl应该是我们自己的Filter接口实现。请参阅过滤器上的文字,以了解有关实现自己的"过滤器"的更多信息。

我们可以通过调用getFilter()方法来获得使用中的Filter,如下所示:

Filter filter = logger.getFilter();

设置日志级别

我们可以设置要转发到Handler的消息的最低日志级别。这是一个代码示例:

Logger logger = Logger.getLogger("myLogger");

logger.setLevel(Level.INFO);

本示例将要转发的消息的最低日志级别设置为" Level.INFO"。要查看日志级别的层次结构,请阅读"日志级别"上的文本。

我们可以使用getLevel()方法获取Logger的日志级别:

logger.getLevel();

如果我们尝试使用该日志级别记录消息,则还可以检查是否将记录给定的日志级别。我们可以使用isLoggable()方法执行此操作,如下所示:

boolean isInfoLoggable = logger.isLoggable(Level.INFO);

父记录器

如本教程中其他地方所述,Logger被组织成一个层次结构。这意味着,Logger可以在层次结构中具有父Logger。我们可以使用getParent()方法获取给定Logger的父Logger。这是一个例子:

Logger parent = logger.getParent();

我们还可以告诉Logger在记录时使用或者不使用Parent记录器。我们可以使用setUseParentHandlers()来做到这一点,就像这样:

logger.setUseParentHandlers(false);

该示例关闭了将日志消息转发到父Logger的Handler的函数。

我们可以使用getUseParentHandlers()方法检查Logger是否将日志消息转发到其父Logger。这是一个例子:

boolean useParentLogger = logger.getUseParentHandlers();

添加方法

Logger类还有其他一些方法,我在这里没有介绍。这些是次要的函数,例如获得Logger等使用的ResourceBundle等。我们应该查看JavaDoc以获得实用程序方法的完整列表。