CodeGym /Java 博客 /随机的 /Java 日志记录
John Squirrels
第 41 级
San Francisco

Java 日志记录

已在 随机的 群组中发布
你好!在编写课程时,我特别强调是否有一个特定的主题在实际工作中是绝对必要的。所以,听好了!从就业的第一天起,我们今天要讨论的主题肯定会在您的所有项目中派上用场。我们将讨论 Java 日志记录。这个话题一点也不复杂(我什至会说简单)。但是在您的第一份工作中您将有足够多明显的事情需要强调,因此最好现在就彻底理解它 :) 好吧,让我们开始吧。

Java 中的日志记录是什么?

日志记录是记录有关程序运行的数据的行为。我们记录这些数据的地方叫做“日志”。立即出现两个问题:写入什么数据以及写入何处?让我们从“哪里”开始。您可以在许多不同的地方编写有关程序工作的数据。例如,在你学习期间,你经常使用System.out.println()将数据输出到控制台。这确实是日志记录,尽管是最简单的形式。当然,这对用户或产品支持团队来说不是很方便:显然,他们不想安装 IDE 并监视控制台 :) 有一种更常用的信息记录格式:文本文件。人类阅读这种格式的数据要舒服得多,当然存储数据也方便得多!现在是第二个问题:应该记录哪些程序数据?这完全取决于你!Java 的日志系统非常灵活。您可以将其配置为记录您的程序所做的一切。一方面,这很好。但另一方面,想象一下,如果 Facebook 或 Twitter 的日志将所有内容都写入其中,那么它们的日志会有多大。这些大公司可能确实有能力存储那么多数据。但想象一下,在 500 GB 的文本日志中找到关于一个严重错误的信息会有多困难?这比大海捞针还糟糕。因此,Java 可以配置为仅记录错误数据。甚至只是严重错误!也就是说,谈论 Java 的本机日志系统并不完全准确。事实上,在将此功能添加到语言之前,程序员需要日志记录。当 Java 推出自己的日志库时,每个人都已经在使用 log4j 库。Java 中的日志记录历史实际上非常悠久且内容丰富。总之,Java有自己的日志库,但是几乎没有人用:)后来,当几个不同的日志库出现并开始被程序员使用时,兼容性问题就出现了。为了阻止人们在十几个具有不同接口的不同库中重新发明轮子,创建了抽象的 SLF4J 框架(“Service Logging Facade For Java”)。之所以称为抽象,是因为即使您使用和调用 SLF4J 类的方法,在幕后它们实际上使用了之前出现的所有日志记录框架:log4j、标准 java.util.logging 等。如果在某些时候您需要其他库缺少的 Log4j 的某些特定功能,但又不想将您的项目直接链接到该库,只需使用 SLF4J。然后让它调用 Log4j 方法。如果您改变主意并决定不再需要 Log4j 功能,则只需重新配置“此处,以及此处的Log4j 库。接下来,解压存档并使用 IntelliJ IDEA 将 JAR 文件添加到类路径中。菜单项:File -> Project Structure -> Libraries 选择需要的JAR文件并添加到项目中(我们下载的archives包含很多JAR文件——看图片就可以看到你需要的)注意这个指令是给那些同学 的谁不知道如何使用 Maven。如果您知道如何使用 Maven,通常最好(更容易)尝试从那里开始。 如果您使用Maven,请添加此依赖项: 为什么我们需要日志 - 2为什么我们需要日志记录 - 3

    	<dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.14.0</version>
    	</dependency>
伟大的!我们弄清楚了设置 :) 让我们看看 SLF4J 是如何工作的。我们如何确保程序的工作记录在某处?为此,我们需要两件事:记录器和追加器。让我们从第一个开始。记录器是提供对日志记录的完全控制的对象。创建记录器非常简单:我们使用静态LoggerFactory.getLogger()方法来完成此操作。方法参数是将记录其操作的类。让我们运行我们的代码:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyTestClass {

   public static final Logger LOGGER = LoggerFactory.getLogger(MyTestClass.class);

   public static void main(String[] args) {

       LOGGER.info("Test log entry!!!");
       LOGGER.error("An error occurred!");
   }
}
控制台输出:

ERROR StatusLogger No Log4j 2 configuration file found. Using default configuration (logging only errors to the console), or user programmatically provided configurations. Set system property 'log4j2.debug' to show Log4j 2 internal initialization logging. See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2 15:49:08.907 [main] ERROR MyTestClass - An error occurred!
我们在这里看到了什么?首先,我们看到一条错误消息。这是因为现在我们缺少必要的设置。因此,我们的记录器目前只能输出错误消息 (ERROR),并且只能输出到控制台。logger.info ()方法不起作用。但是logger.error()做到了!在控制台上,我们看到当前日期,错误发生的方法(main),单词“ERROR”,以及我们的信息!ERROR 是日志级别。一般来说,如果一个日志条目被标记为“ERROR”,那么程序在此时发生了错误。如果该条目标有单词“INFO”,则该消息仅表示有关程序正常运行的当前信息。SLF4J 库有很多不同的日志记录级别,可以让您灵活地配置日志记录。这一切都非常易于管理:所有必要的逻辑都已在 Java Logger类中。你只需要调用相关的方法。如果要记录常规消息,请调用 logger.info()方法。对于错误消息,请使用logger.error()。对于警告,请使用logger.warn()

现在让我们谈谈appender

appender 是你的数据去的地方。在某种程度上,数据源的对立面,即“B点”。默认情况下,数据输出到控制台。请注意,在前面的示例中,我们无需进行任何配置:文本出现在控制台中,Log4j 库的记录器只能向控制台输出 ERROR 级别的消息。很明显,人们在文本文件中读写日志更方便。要更改记录器的默认行为,我们需要配置文件附加程序。首先,您需要直接在 src 文件夹中创建一个 log4j.xml 文件。您已经熟悉 XML 格式:我们最近上了一堂关于它的:) 以下是文件的内容:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
   <Appenders>
       <File name="MyFileAppender" fileName="C:\Users\Username\Desktop\testlog.txt" immediateFlush="false" append="false">
           <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
       </File>
   </Appenders>
   <Loggers>
       <Root level="INFO">
           <AppenderRef ref="MyFileAppender"/>
       </Root>
   </Loggers>
</Configuration>
这里没有什么特别的或困难的:) 但是,让我们过一遍内容。
<Configuration status="INFO">
这就是所谓的 StatusLogger。它与我们的记录器无关,用于 Log4j 的内部进程。如果你设置 status="TRACE" 而不是 status="INFO",那么所有关于 Log4j 内部工作的信息都会显示在控制台上(StatusLogger 在控制台上显示数据,即使我们的 appender 是一个文件)。我们现在不需要它,所以让我们保持原样。

<Appenders>
   <File name="MyFileAppender" fileName="C:\Users\Evgeny\Desktop\testlog.txt" append="true">
       <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
   </File>
</Appenders>
在这里我们创建我们的 appender。<File>标签表明它将是一个文件追加器。 name="MyFileAppender"设置附加程序的名称。 fileName="C:\Users\Username\Desktop\testlog.txt"指示将写入所有数据的日志文件的路径。 append="true"表示数据是否应该写在文件的末尾。在我们的例子中,这正是我们要做的。如果将该值设置为 false,则每次启动程序时都会删除日志文件的旧内容。 <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>表示格式设置。在这里,我们可以使用正则表达式来自定义日志中文本的格式。

<Loggers>
       <Root level="INFO">
           <AppenderRef ref="MyFileAppender"/>
       </Root>
</Loggers>
此处我们指示根级别。我们设置了“INFO”级别,这意味着所有级别高于 INFO 的消息(根据我们上面查看的表格)将不会被记录。我们的程序将有 3 条消息:一条 INFO、一条 WARN 和一条 ERROR。使用当前配置,将记录所有 3 条消息。如果将根级别更改为 ERROR,则只有来自 LOGGER.error() 方法调用的最后一条消息才会出现在日志中。此外,此处还包含对 appender 的引用。要创建这样的引用,您需要在<Root>标记内创建一个<ApprenderRef>标记,并向其添加ref='your appender's name'属性。以防你忘记了,这是我们设置 appender 名称的地方:<. 这是我们的代码!

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyTestClass {

   public static final Logger LOGGER = LoggerFactory.getLogger(MyTestClass.class);

   public static void main(String[] args) {

       LOGGER.info("The program is starting!!!");

       try {
           LOGGER.warn("Attention! The program is trying to divide a number by another.
           System.out.println(12/0);
       } catch (ArithmeticException x) {

           LOGGER.error("Error! Division by zero!");
       }
   }
}
当然,它有点古怪(捕获 RuntimeException 是一个有问题的想法),但它非常适合我们的目的:) 让我们连续运行main()方法 4 次并查看我们的 testlog.txt 文件。您不需要提前创建它:库会自动执行此操作。一切正常!:) 现在你有一个配置好的记录器。您可以尝试一些旧程序,为每个方法添加记录器调用。然后查看生成的日志 :) 它深入考虑了日志记录的主题。一次阅读所有内容将是一项挑战。也就是说,它确实包含很多额外的有用信息。例如,您将学习如何配置记录器,以便在我们的 testlog.txt 文件达到特定大小时创建一个新的文本文件 :) 我们的课程到此结束!今天你熟悉了一个很重要的话题,这些知识一定会对你以后的工作有所帮助。直到下一次!:)
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION