corejava11(7.5 日志)

7.5 日志

每一个Java程序员都熟悉将System.out.println调用添加到麻烦代码中以了解程序行为的过程。当然,一旦找出了问题的原因,就可以删除打印语句,只在下一个问题出现时将它们放回原处。日志API旨在解决这个问题。API的主要优点如下:

  • 很容易抑制所有日志记录或低于某个级别的日志记录,也很容易将其重新打开。
  • 抑制日志非常便宜,因此将日志代码留在应用程序中只会受到最小的惩罚。
  • 日志记录可以定向到不同的处理程序,以便在控制台中显示、写入文件等。
  • 日志记录器和处理程序都可以过滤记录。过滤器可以使用过滤器实现者提供的任何条件来丢弃烦人的日志条目。
  • 日志记录可以采用不同的格式,例如纯文本或XML。
  • 应用程序可以使用多个日志记录器,其分层名称如com.mycompany.myapp,与包名称类似。
  • 日志配置由配置文件控制。

注意

许多应用程序使用其他日志记录框架,例如Log4J 2(https://logging.apache.org/log4j/2.x)和Logback(https://logback.qos.ch),它们提供了比标准Java日志记录框架更高的性能。这些框架有稍微不同的API。记录诸如slf4j(https://www.slf4j.org)和commons logging(https://commons.apache.org/proper/commonslogging)提供了一个统一的API,这样您就可以在不重写应用程序的情况下替换日志框架。为了使问题更加混乱,Log4J 2也可以使用SLF4J的组件。在这本书中,我们覆盖了标准的Java日志记录框架。对于许多用途来说,它已经足够好了,学习它的API将为您了解替代方案做好准备。

注意

至于Java 9,Java平台有一个独立的轻量级日志记录系统,它不依赖于java.logging模块(包含标准Java日志记录框架)。该系统仅用于Java API中。如果存在java.logging模块,日志消息将自动转发给它。第三方日志框架可以提供适配器来接收平台日志消息。我们不讨论平台日志,因为它不打算被应用程序程序员使用。

7.5.1 基本日志

对于简单的日志记录,使用全局日志记录程序并调用其info方法:

Logger.getGlobal().info("File->Open menu item selected");

默认情况下,记录的打印方式如下:

May 10, 2013 10:12:15 PM LoggingImageViewer fileOpen
INFO: File->Open menu item selected

但是如果你调用

Logger.getGlobal().setLevel(Level.OFF);

在适当的位置(如main的开头),所有日志记录都将被抑制。

7.5.2 高级日志

既然你已经看到了“傻瓜式日志”,那么我们继续进行工业强度的日志。在专业应用程序中,您不希望将所有记录都记录到单个全局记录器中。相反,您可以定义自己的记录器。

调用getLogger方法以创建或检索日志:

private static final Logger myLogger = Logger.getLogger("com.mycompany.myapp");

提示

不被任何变量引用的日志可以被回收。要防止这种情况发生,请使用静态变量保存对日志的引用,如上面的示例所示。

与包名称类似,日志名称是分层的。实际上,它们比包更具有层次性。包与其父级之间没有语义关系,但日志父级和子级共享某些属性。例如,如果在日志“com.mycompany”上设置日志级别,则子记录器继承该级别。

有下面七个日志级别:

  • SEVERE
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST

默认情况下,实际记录前三个级别。您可以设置不同的级别,例如,

logger.setLevel(Level.FINE);

现在FINE和上面的所有级别都会被记录下来。

您还可以使用Level.ALL打开所有级别的日志记录,或使用Level.OFF关闭所有日志记录。

所有级别都有日志记录方法,例如

logger.warning(message);
logger.fine(message);

等等。或者,可以使用log方法并提供级别,例如

logger.log(Level.FINE, message);

提示

默认的日志记录配置记录INFO级别或更高级别的所有记录。因此,您应该使用CONFIGFINEFINERFINEST级别来调试对诊断有用但对用户毫无意义的消息。

小心

如果将日志级别设置为比INFO更精细的值,则还需要更改日志处理程序配置。默认的日志处理程序禁止显示INFO以下信息。有关详细信息,请参阅下一节。

默认日志记录显示包含日志记录调用的类和方法的名称,如从调用堆栈推断的那样。但是,如果虚拟机优化了执行,则可能无法获得准确的调用信息。您可以使用logp方法给出调用类和方法的精确位置。方法签名是

void logp(Level l, String className, String methodName, String message)

跟踪执行流有一些方便的方法:

void entering(String className, String methodName)
void entering(String className, String methodName, Object param)
void entering(String className, String methodName, Object[] params)
void exiting(String className, String methodName)
void exiting(String className, String methodName, Object result)

例如

int read(String file, String pattern)
{
    logger.entering("com.mycompany.mylib.Reader", "read",
    new Object[] { file, pattern });
    . . .
    logger.exiting("com.mycompany.mylib.Reader", "read", count);
    return count;
}

这些调用生成以字符串条目ENTRYRETURN开始的FINER级别的日志记录。

注意

在将来的某个时候,将重写带有Object[]参数的日志记录方法,以支持变量参数列表(“varargs”)。然后,您就可以调用logger.entering("com.mycompany.mylib.reader", "read", file, pattern)

日志记录的一个常见用途是记录意外的异常。两种方便的方法包括在日志记录中描述异常。

void throwing(String className, String methodName, Throwable t)
void log(Level l, String message, Throwable t)

典型的用法是

if (. . .)
{
    var e = new IOException(". . .");
    logger.throwing("com.mycompany.mylib.Reader", "read", e);
    throw e;
}

以及

try
{
    . . .
}
catch (IOException e)
{
    Logger.getLogger("com.mycompany.myapp").log(Level.WARNING, "Rea");
}

throwing调用记录一个级别FINER的记录和一条以THROW开头的消息。

7.5.3 更改日志管理器配置

您可以通过编辑配置文件来更改日志记录系统的各种属性。默认配置文件位于

conf/logging.properties

(或者在Java 9以前是jar/lib/logging.properties)。

要使用另一个文件,请通过启动应用程序,将java.util.logging.config.file属性设置为文件位置。

java -Djava.util.logging.config.file=configFile MainClass

要更改默认日志记录级别,请编辑配置文件并修改行

.level=INFO

您可以通过添加诸如

com.mycompany.myapp.level=FINE

也就是说,将.level后缀附加到记录器名称中。

正如您将在本节后面看到的,记录器实际上不会将消息发送到作为处理程序工作的控制台。处理程序也有级别。要在控制台上看到FINE消息,还需要设置

java.util.logging.ConsoleHandler.level=FINE

小心

日志管理器配置中的设置不是系统属性。使用-Dcom.mycompany.myapp.level=FINE启动程序对记录器没有任何影响。

The log manager is initialized during VM startup, before main executes. If
you want to customize the logging properties but didn’t start your application
with the -Djava.util.logging.config.file command-line option,
call System.setProperty(
“java.util.logging.config.file”, file) in your program.
But then you must also call

LogManager.getLogManager().readConfiguration() to
reinitialize the log manager.

日志管理器在VM启动期间(在main执行之前)初始化。如果您想自定义日志记录属性,但没有使用-Djava.util.logging.config.file命令行选项启动应用程序,请在程序中调用System.setProperty("java.util.logging.config.file", file)。但是,还必须调用LogManager.getLogManager().readConfiguration()以重新初始化日志管理器。

至于Java 9,您可以通过调用以下代码来更新日志记录配置。

LogManager.getLogManager().updateConfiguration(mapper);

java.util.logging.config.file系统属性指定的位置读取新配置。然后应用映射器解析旧配置或新配置中所有键的值。映射器是一个Function<String, BiFunction<String, String, String>>。它将现有配置中的键映射到替换函数。每个替换函数接收与键关联的新旧值(如果没有关联的值,则为null),并生成替换,如果在更新中应删除键,则为null

这听起来相当复杂,所以让我们来举几个例子。一个有用的映射方案是合并旧的和新的配置,当新的和旧的配置中都存在一个键时,优先选择新的值。然后mapper

key -> ((oldValue, newValue) -> newValue == null ? oldValue : newValue)

或者您可能只想更新以com.mycompany开头的密钥,而不更改其他密钥:

key -> key.startsWith("com.mycompany")
    ? ((oldValue, newValue) -> newValue)
    : ((oldValue, newValue) -> oldValue)

也可以使用jconsole程序更改正在运行的程序中的日志记录级别。有关信息,请参阅www.oracle.com/technetwork/articles/java/jconsole- 1564139.html#LoggingControl

注意

日志属性文件由java.util.logging.LogManager类处理。可以通过将java.util.logging.manager系统属性设置为子类的名称来指定不同的日志管理器。或者,您可以保留标准日志管理器,并且仍然可以从日志属性文件中绕过初始化。将java.util.logging.config.class系统属性设置为以其他方式设置日志管理器属性的类的名称。有关详细信息,请参阅LogManager类的API文档。

7.5.4 本地化

您可能希望将日志消息本地化,以便国际用户能够阅读它们。应用程序国际化是第二卷第7章的主题。简而言之,在本地化日志消息时需要记住以下几点。

本地化应用程序在resource bundles中包含特定于区域设置的信息。资源包由一组不同地区(如美国或德国)的映射组成。例如,资源包可以将字符串“readingFile”映射为英文字符串“Reading file”或者德文“Achtung! Datei wird eingelesen”。

一个程序可以包含多个资源包,例如,一个用于菜单,另一个用于日志消息。每个资源包都有一个名称(例如“com.mycompany.logmessages”)。要添加到资源束的映射,请为每个区域设置提供一个文件。英语消息映射位于文件com/mycompany/logmessages_en.properties中,德语消息映射位于文件com/mycompany/logmessages_de.properties中。(ende是语言代码。)您将文件与应用程序的类文件放在一起,这样ResourceBundle类将自动定位它们。这些文件是纯文本文件,由诸如

readingFile=Achtung! Datei wird eingelesen
renamingFile=Datei wird umbenannt
. . .

请求记录器时,可以指定资源束:

Logger logger = Logger.getLogger(loggerName, "com.mycompany.logmessages");

然后为日志消息指定资源绑定键,而不是实际的消息字符串:

logger.info("readingFile");

通常需要在本地化消息中包含参数。消息可能包含占位符:{0}{1},依此类推。例如,要将文件名包含在日志消息中,请使用如下占位符:

Reading file {0}.
Achtung! Datei {0} wird eingelesen.

然后,要将值传递给占位符,请调用以下方法之一:

logger.log(Level.INFO, "readingFile", fileName);
logger.log(Level.INFO, "renamingFile", new Object[] { oldName, newName });

或者,如Java 9所示,可以在logrb方法中指定资源束对象(而不是名称):

logger.logrb(Level.INFO, bundle, "renamingFile", oldName, newName);

注意

这是唯一使用变量参数作为消息参数的日志记录方法。

7.5.5 处理程序

默认情况下,记录器将记录发送到ConsoleHandler,该处理程序将记录打印到System.err流。具体来说,记录器将记录发送到父处理程序,最终祖先(名为“”)具有一个ConsoleHandler

和记录器一样,处理程序也有一个日志级别。对于要记录的记录,其记录级别必须高于记录器和处理程序的阈值。日志管理器配置文件将默认控制台处理程序的日志级别设置为

java.util.logging.ConsoleHandler.level=INFO

要用FINE级别记录,请更改配置中的默认记录器级别和处理程序级别。或者,您可以完全绕过配置文件并安装自己的处理程序。

Logger logger = Logger.getLogger("com.mycompany.myapp");
logger.setLevel(Level.FINE);
logger.setUseParentHandlers(false);
var handler = new ConsoleHandler();
handler.setLevel(Level.FINE);
logger.addHandler(handler);

默认情况下,记录器将记录发送到自己的处理程序和父处理程序。我们的日志程序是原始日志程序(名为“”)的一个子程序,它将所有级别INFO及以上的记录发送到控制台。但是,我们不希望看到这些记录两次,因此我们将useParentHandlers属性设置为false

若要将日志记录发送到其他位置,请添加其他处理程序。日志API为此提供了两个有用的处理程序:FileHandlerSocketHandlerSocketHandler将记录发送到指定的主机和端口。更感兴趣的是在文件中收集记录的FileHandler

您只需将记录发送到默认的文件处理程序,如下所示:

var handler = new FileHandler();
logger.addHandler(handler);

记录被发送到用户主目录中的javan.log文件,其中n是使文件唯一的数字。如果系统没有用户主目录的概念(例如,在Windows 95/98/Me中),则文件存储在默认位置,如C:\Windows。默认情况下,记录的格式为XML。典型的日志记录具有以下形式

<record>
    <date>2002-02-04T07:45:15</date>
    <millis>1012837515710</millis>
    <sequence>1</sequence>
    <logger>com.mycompany.myapp</logger>
    <level>INFO</level>
    <class>com.mycompany.mylib.Reader</class>
    <method>read</method>
    <thread>10</thread>
    <message>Reading file corejava.gif</message>
</record>

您可以通过在日志管理器配置中设置各种参数(参见表7.1)或使用其他构造函数(参见本节末尾的API注释)来修改文件处理程序的默认行为。

表7.1 文件处理程序配置参数

配置属性 描述 默认值
java.util.logging.FileHandler.level 处理程序级别 Level.ALL
java.util.logging.FileHandler.append 控制处理程序是应附加到现有文件,还是应为每个运行的程序打开一个新文件 false

| java.util.logging.FileHandler.limit | 打开另一个文件之前要写入文件的最大字节数(0=无限制) | 0 (no limit) in the 50000
configuration |
| java.util.logging.FileHandler.pattern | 日志文件名的模式。模式变量见表7.2。 | %h/java%u.log |
| java.util.logging.FileHandler.count | 旋转序列中的日志数 | 1 (不旋转) |
| java.util.logging.FileHandler.filter | 要使用的筛选器类 | 无过滤 |
| java.util.logging.FileHandler.encoding | 要使用的字符编码 | 平台编码 |
| java.util.logging.FileHandler.formatter | 记录格式化程序 | java |

您可能不想使用默认的日志文件名。因此,您应该使用另一个模式,例如%h/myapp.log。(有关模式变量的说明,请参见表7.2。)

表7.2 日志文件模式变量

变量 描述
%h user.home系统属性的值
%t 系统临时目录
%u 用于解决冲突的唯一数字
%g 旋转日志的生成号(如果指定了旋转,并且模式不包含%g,则使用一个%g后缀)
%% %字符

如果多个应用程序(或同一应用程序的多个副本)使用同一个日志文件,则应打开append标志。或者,在文件名模式中使用%u,以便每个应用程序创建日志的唯一副本。

打开文件旋转也是一个好主意。日志文件以旋转顺序保存,如myapp.log.0myapp.log.1myapp.log.2等。每当文件超过大小限制时,将删除最旧的日志,重命名其他文件,并创建一个生成号为0的新文件。

提示

许多程序员使用日志作为技术支持人员的帮助。如果程序在字段中出现错误行为,用户可以将日志文件发回进行检查。在这种情况下,您应该打开附加标志,使用旋转日志,或者两者都使用。

您还可以通过扩展HandlerStreamHandler类来定义自己的处理程序。我们在本节末尾的示例程序中定义这样的处理程序。这个处理程序在一个窗口中显示记录(参见图7.2)。

图7.2 在窗口中显示记录的日志处理程序

处理程序扩展StreamHandler类并安装一个流,其write方法在文本区域中显示流输出。

class WindowHandler extends StreamHandler
{
    public WindowHandler()
    {
        . . .
        var output = new JTextArea();
        setOutputStream(new OutputStream()
            {
                public void write(int b) {} // not called
                public void write(byte[] b, int off, int len)
                {
                    output.append(new String(b, off, len));
                }
            });
    }
    . . .
}

这种方法只有一个问题:处理程序缓冲记录,并且只在缓冲区满时将它们写入流。因此,我们重写publish方法以在每条记录之后刷新缓冲区:

class WindowHandler extends StreamHandler
{
    . . .
    public void publish(LogRecord record)
    {
        super.publish(record);
        flush();
    }
}

如果要编写更多的异域流处理程序,请扩展该Handler类并定义publishflushclose方法。

7.5.6 过滤器

默认情况下,根据记录级别筛选记录。每个记录器和处理程序都可以有一个可选的过滤器来执行额外的过滤。要定义过滤器,请实现Filter接口并定义方法

boolean isLoggable(LogRecord record)

使用所需的任何条件分析日志记录,并为应包含在日志中的记录返回true。例如,特定的过滤器可能只对enteringexiting方法生成的消息感兴趣。然后,过滤器应该调用record.getMessage()并检查它是以ENTRY开头还是以RETURN开头。

要将过滤器安装到记录器或处理程序中,只需调用setFilter方法。请注意,一次最多只能有一个过滤器。

7.5.7 格式器

ConsoleHandlerFileHandler类以文本和XML格式发出日志记录。但是,您也可以定义自己的格式。您需要扩展Formatter类并重写该方法

String format(LogRecord record)

该方法格式化记录的消息部分,替换参数并应用本地化。

许多文件格式(如XML)需要一个环绕格式化记录的头和尾部分。要实现这一点,请重写方法

String getHead(Handler h)
String getTail(Handler h)

最后,调用setFormatter方法将格式化程序安装到处理程序中。

7.5.8 日志配方

由于有如此多的日志记录选项,很容易失去对基本原理的跟踪。以下配方总结了最常见的操作。

  1. 对于一个简单的应用程序,选择一个记录器。最好将日志程序命名为与主应用程序包相同的名称,例如·com.mycompany.myprog·。您可以通过调用

    Logger logger = Logger.getLogger("com.mycompany.myprog");
    
    

    为了方便起见,您可能需要添加静态字段

    private static final Logger logger =
    Logger.getLogger("com.mycompany.myprog");
    
    

    到具有大量日志记录活动的类。

  2. 默认日志配置将级别INFO或更高级别的所有消息记录到控制台。用户可以覆盖默认配置,但是正如您所看到的,这个过程有点复杂。因此,最好在应用程序中安装更合理的默认值。
    以下代码确保所有消息都记录到特定于应用程序的文件中。将代码放入应用程序的main方法中。

    if (System.getProperty("java.util.logging.config.class") == null
    	&& System.getProperty("java.util.logging.config.file") == n
    {
        try
        {
            Logger.getLogger("").setLevel(Level.ALL);
            final int LOG_ROTATION_COUNT = 10;
            var handler = new FileHandler("%h/myapp.log", 0, LOG_ROTATION_COUNT);
            Logger.getLogger("").addHandler(handler);
        }
        catch (IOException e)
        {
        	logger.log(Level.SEVERE, "Can't create log file handler",
        }
    }
    
    
  3. 现在,你已经准备好记录你核心的内容了。请记住,所有具有级别INFOWARNINGSEVERE的消息都会显示在控制台上。因此,请为对程序用户有意义的消息保留这些级别。对于记录面向程序员的消息,FINE级别是一个很好的选择。
    每当您试图调用System.out.println时,请发出一条日志消息:

    logger.fine("File open dialog canceled");
    
    

    记录意外的异常也是一个好主意。例如:

    try
    {
    	. . .
    }
    catch (SomeException e)
    {
    	logger.log(Level.FINE, "explanation", e);
    }
    
    

    清单7.2将这个方法与一个附加的扭曲一起使用:日志消息也显示在一个日志窗口中。

清单7.2 logging/LoggingImageViewer.java

package logging;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.logging.*;
import javax.swing.*;

/**
 * A modification of the image viewer program that logs various events.
 * @version 1.03 2015-08-20
 * @author Cay Horstmann
 */
public class LoggingImageViewer
{
   public static void main(String[] args)
   {
      if (System.getProperty("java.util.logging.config.class") == null
            && System.getProperty("java.util.logging.config.file") == null)
      {
         try
         {
            Logger.getLogger("com.horstmann.corejava").setLevel(Level.ALL);
            final int LOG_ROTATION_COUNT = 10;
            var handler = new FileHandler("%h/LoggingImageViewer.log", 0, LOG_ROTATION_COUNT);
            Logger.getLogger("com.horstmann.corejava").addHandler(handler);
         }
         catch (IOException e)
         {
            Logger.getLogger("com.horstmann.corejava").log(Level.SEVERE,
               "Can't create log file handler", e);
         }
      }

      EventQueue.invokeLater(() ->
            {
               var windowHandler = new WindowHandler();
               windowHandler.setLevel(Level.ALL);
               Logger.getLogger("com.horstmann.corejava").addHandler(windowHandler);

               var frame = new ImageViewerFrame();
               frame.setTitle("LoggingImageViewer");
               frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

               Logger.getLogger("com.horstmann.corejava").fine("Showing frame");
               frame.setVisible(true);
            });
   }
}

/**
 * The frame that shows the image.
 */
class ImageViewerFrame extends JFrame
{
   private static final int DEFAULT_WIDTH = 300;
   private static final int DEFAULT_HEIGHT = 400;   

   private JLabel label;
   private static Logger logger = Logger.getLogger("com.horstmann.corejava");

   public ImageViewerFrame()
   {
      logger.entering("ImageViewerFrame", "<init>");      
      setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);

      // set up menu bar
      var menuBar = new JMenuBar();
      setJMenuBar(menuBar);

      var menu = new JMenu("File");
      menuBar.add(menu);

      var openItem = new JMenuItem("Open");
      menu.add(openItem);
      openItem.addActionListener(new FileOpenListener());

      var exitItem = new JMenuItem("Exit");
      menu.add(exitItem);
      exitItem.addActionListener(new ActionListener()
         {
            public void actionPerformed(ActionEvent event)
            {
               logger.fine("Exiting.");
               System.exit(0);
            }
         });

      // use a label to display the images
      label = new JLabel();
      add(label);
      logger.exiting("ImageViewerFrame", "<init>");
   }

   private class FileOpenListener implements ActionListener
   {
      public void actionPerformed(ActionEvent event)
      {
         logger.entering("ImageViewerFrame.FileOpenListener", "actionPerformed", event);

         // set up file chooser
         var chooser = new JFileChooser();
         chooser.setCurrentDirectory(new File("."));

         // accept all files ending with .gif
         chooser.setFileFilter(new javax.swing.filechooser.FileFilter()
            {
               public boolean accept(File f)
               {
                  return f.getName().toLowerCase().endsWith(".gif") || f.isDirectory();
               }

               public String getDescription()
               {
                  return "GIF Images";
               }
            });

         // show file chooser dialog
         int r = chooser.showOpenDialog(ImageViewerFrame.this);

         // if image file accepted, set it as icon of the label
         if (r == JFileChooser.APPROVE_OPTION)
         {
            String name = chooser.getSelectedFile().getPath();
            logger.log(Level.FINE, "Reading file {0}", name);
            label.setIcon(new ImageIcon(name));
         }
         else logger.fine("File open dialog canceled.");
         logger.exiting("ImageViewerFrame.FileOpenListener", "actionPerformed");
      }
   }
}

/**
 * A handler for displaying log records in a window.
 */
class WindowHandler extends StreamHandler
{
   private JFrame frame;

   public WindowHandler()
   {
      frame = new JFrame();
      var output = new JTextArea();
      output.setEditable(false);
      frame.setSize(200, 200);
      frame.add(new JScrollPane(output));
      frame.setFocusableWindowState(false);
      frame.setVisible(true);
      setOutputStream(new OutputStream()
         {
            public void write(int b)
            {
            } // not called

            public void write(byte[] b, int off, int len)
            {
               output.append(new String(b, off, len));
            }
         });
   }

   public void publish(LogRecord record)
   {
      if (!frame.isVisible()) return;
      super.publish(record);
      flush();
   }
}

java.util.logging.Logger 1.4

  • Logger getLogger(String loggerName)
  • Logger getLogger(String loggerName, String bundleName)
    获取具有给定名称的记录器。如果记录器不存在,则会创建它。本地化消息位于名为bundleName的资源包中。
  • void severe(String message)
  • void warning(String message)
  • void info(String message)
  • void config(String message)
  • void fine(String message)
  • void finer(String message)
  • void finest(String message)
    用方法名和给定消息指示的级别记录记录。
  • void entering(String className, String methodName)
  • void entering(String className, String methodName, Object param)
  • void entering(String className, String methodName, Object[] param)
  • void exiting(String className, String methodName)
  • void exiting(String className, String methodName, Object result)
    记录描述使用给定参数或返回值进入或退出方法的记录。
  • void throwing(String className, String methodName, Throwable t)
    记录描述给定异常对象的抛出的记录。
  • void log(Level level, String message)
  • void log(Level level, String message, Object obj)
  • void log(Level level, String message, Object[] objs)
  • void log(Level level, String message, Throwable t)
    记录具有给定级别和消息的记录,可以选择包括对象或可丢弃的记录。若要包含对象,消息必须包含格式占位符({0}{1}等)。
  • void logp(Level level, String className, String methodName, String message)
  • void logp(Level level, String className, String methodName, String message, Object obj)
  • void logp(Level level, String className, String methodName, String message, Object[] objs)
  • void logp(Level level, String className, String methodName, String message, Throwable t)
    使用给定的级别、精确的调用者信息和消息(可选包括对象或可丢弃项)记录记录。
  • void logrb(Level level, String className, String methodName, ResourceBundle bundle, String message, Object... params) 9
  • void logrb(Level level, String className, String methodName, ResourceBundle bundle, String message, Throwable thrown) 9
    用给定的级别、精确的调用者信息、资源束和消息记录一个记录,后跟对象或可丢弃的对象。
  • Level getLevel()
  • void setLevel(Level l)
    获取并设置此记录器的级别。
  • Logger getParent()
  • void setParent(Logger l)
    获取和设置此记录器的父记录器。
  • Handler[] getHandlers()
    获取此记录器的所有处理程序。
  • void addHandler(Handler h)
  • void removeHandler(Handler h)
    添加或删除此记录器的处理程序。
  • boolean getUseParentHandlers()
  • void setUseParentHandlers(boolean b)
    获取并设置“使用父处理程序”属性。如果此属性为true,则记录器将所有记录转发给其父级的处理程序。
  • Filter getFilter()
  • void setFilter(Filter f)
    获取并设置此记录器的筛选器。

java.util.logging.Handler 1.4

  • abstract void publish(LogRecord record)
    将记录发送到目标。
  • abstract void flush()
    刷新任何缓冲数据。
  • abstract void close()
    刷新任何缓冲数据并释放所有相关资源。
  • Filter getFilter()
  • void setFilter(Filter f)
    获取并设置此处理程序的筛选器。
  • Formatter getFormatter()
  • void setFormatter(Formatter f)
    获取并设置此处理程序的格式化程序。
  • Level getLevel()
  • void setLevel(Level l)
    获取并设置此处理程序的级别。

java.util.logging.ConsoleHandler 1.4

  • ConsoleHandler()
    构造新的控制台处理程序。

java.util.logging.FileHandler 1.4

  • FileHandler(String pattern)
  • FileHandler(String pattern, boolean append)
  • FileHandler(String pattern, int limit, int count)
  • FileHandler(String pattern, int limit, int count, boolean append)
  • FileHandler(String pattern, long limit, int count, boolean append) 9
    构造文件处理程序。模式格式见表7.2。limit是打开新日志文件之前的最大字节数。count是旋转序列中的文件数。如果appendtrue,则应将记录追加到现有日志文件。

java.util.logging.LogRecord 1.4

  • Level getLevel()
    获取此记录的日志记录级别。
  • String getLoggerName()
    获取正在记录此记录的记录器的名称。
  • ResourceBundle getResourceBundle()
  • String getResourceBundleName()
    获取用于本地化消息的资源束或其名称,如果未提供,则为null
  • String getMessage()
    获取本地化或格式化前的“原始”消息。
  • Object[] getParameters()
    获取参数对象,如果未提供,则为null
  • Throwable getThrown()
    获取引发的对象,如果未提供,则为null
  • String getSourceClassName()
  • String getSourceMethodName()
    获取记录此记录的代码的位置。这些信息可以由日志代码提供,也可以从运行时堆栈自动推断。如果日志代码提供了错误的值,或者正在运行的代码经过了优化,从而无法推断出确切的位置,则可能不准确。
  • long getMillis()
    获取自1970年以来的创建时间(毫秒)。
  • Instant getInstant() 9
    获取java.time.Instant形式的创建时间(见第二卷第6章)。
  • long getSequenceNumber()
    获取此记录的唯一序列号。
  • int getThreadID()
    获取在其中创建此记录的线程的唯一ID。这些ID由LogRecord类分配,与其他线程ID没有关系。

java.util.logging.LogManager 1.4

  • static LogManager getLogManager()
    获取全局LogManager实例。
  • void readConfiguration()
  • void readConfiguration(InputStream in)
    从系统属性java.util.logging.config.file或给定输入流指定的文件读取日志配置。
  • void updateConfiguration(InputStream in, Function<String,BiFunction<String,String,String>> mapper) 9
  • void updateConfiguration(Function<String,BiFunction<String,Str mapper) 9
    将日志配置与系统属性java.util.logging.config.file或给定输入流指定的文件合并。有关mapper参数的描述,请参见第407页的第7.5.3节“更改日志管理器配置”。

java.util.logging.filter 1.4

  • boolean isLoggable(LogRecord record)
    如果应记录给定的日志记录,则返回true

java.util.logging.Formatter 1.4

  • abstract String format(LogRecord record)
    返回格式化给定日志记录所产生的字符串。
  • String getHead(Handler h)
  • String getTail(Handler h)
    返回应出现在包含日志记录的文档的头和尾的字符串。`Formatter超类定义这些方法以返回空字符串;必要时重写它们。
  • String formatMessage(LogRecord record)
    返回日志记录的本地化和格式化消息部分。

猜你喜欢

转载自blog.csdn.net/nbda1121440/article/details/91496878