“哦,你来了!你还记得我们今天还有一节课吗?”
“不是,我就是来找你的,差点……”
“太好了,那我们开始吧,今天我要给大家讲讲伐木。”
“日志是已发生事件的列表。几乎就像航海日志或日记。或者推特——也许你能更好地理解它。毫不奇怪,记录器是你用来记录日志的对象。”
“在编程中,习惯上记录几乎所有内容。而在 Java 中,我们记录所有内容,甚至更多。”
“事实是,Java 程序通常是没有 UI、控制台等的大型服务器应用程序。它们同时处理数以千计的用户请求,并且经常出现各种错误。尤其是当不同的线程开始相互干扰时。”
“事实上,在这些情况下搜索很少重现的错误和故障的唯一方法是记录每个线程上发生的一切。”
“大多数情况下,日志包含有关方法参数的信息、任何捕获的错误以及大量中间信息。”
“日志越完整,重现事件序列和跟踪故障或错误的原因就越容易。”
“有时日志每天达到几千兆字节。这是正常的。”
“几千兆字节?O_o”
“是的。大多数情况下,日志文件会自动存档,并注明相关日期。”
“哇哦。”
“嗯嗯,一开始Java是没有自己的logger的,结果写了几个独立的logger,其中最常见的就是log4j。”
“几年后,Java 有了自己的记录器,但它的功能远不如它,并没有被广泛使用。”
“Java 有官方记录器是事实,但整个 Java 程序员社区更喜欢使用其他记录器。 ”
“后来又基于log4j写了几个logger。”
“然后为所有这些编写了现在广泛使用的特殊通用记录器 slf4j。它与 log4j 非常相似,因此我将在解释日志记录时以它为例。”
“整个测井过程由三部分组成。”
“首先,收集情报。”
“第二,过滤收集到的信息。”
“第三,记录选择的信息。”
“让我们从收集开始。这是一个记录类的典型示例:”
class Manager
{
private static final Logger logger = LoggerFactory.getLogger(Manager.class);
public boolean processTask(Task task)
{
logger.debug("processTask id = " + task.getId());
try
{
task.start();
task.progress();
task.complete();
return true;
}
catch(Exception e)
{
logger.error("Unknown error", e);
return false;
}
}
}
“注意以红色突出显示的词。”
“第 3 行 ——创建记录器对象。几乎每个类都会创建这样一个静态对象!好吧,除了那些除了存储数据之外什么都不做的类。”
" LoggerFactory是一个用于创建记录器的特殊类,getLogger 是它的静态方法之一。通常传递当前对象,但也可以有多种选择。"
" Line 7 – 将方法调用的信息写入记录器。请注意,这是方法的第一行。一旦调用方法,我们立即将信息写入日志。"
“我们调用debug方法,就是说信息的重要性是DEBUG级别,这个是用来过滤的,过几分钟我会告诉你的。”
“第 17 行——我们捕获异常并……立即将其写入日志!这正是需要做的。”
“这次我们调用error方法,马上提示信息为ERROR级别”
“现在一切似乎都清楚了。好吧,就我们谈话的过程中可以清楚的而言。”
“很好,那我们继续进行消息过滤。”
“通常,每条日志消息都有自己的重要性级别,您可以使用它来丢弃一些消息。以下是我提到的重要性级别:”
重要性等级 | 描述 |
---|---|
全部 | 所有消息 |
痕迹 | 细粒度的调试消息 |
调试 | 重要的调试信息 |
信息 | 信息性消息 |
警告 | 警告 |
错误 | 错误 |
致命的 | 致命错误 |
离开 | 没有留言 |
过滤消息时也会使用这些级别。
假设您将日志记录级别设置为 WARN。然后所有不如 WARN 重要的消息将被丢弃:TRACE、DEBUG、INFO。
如果将过滤级别设置为 FATAL,那么即使是 ERROR 消息也会被丢弃。
“过滤时还有两个重要级别:OFF,丢弃所有消息;ALL,显示所有消息(不丢弃任何消息)。”
“如何以及在何处设置过滤?”
“我不多说了就告诉你。”
“通常,log4j 记录器设置在 log4j.properties 文件中指定。”
您可以在此文件中指定多个附加程序对象。数据被写入这些对象。有数据源,也有附加程序——目的相反的对象。数据像水一样流入的对象。
“这里有些例子:”
# Root logger option
log4j.rootLogger = INFO, stdout
# Direct log messages to stdout
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss}
第 1 行和第 4 行——这些是注释
第 2 行——我们指出我们想要的日志记录级别。所有不太重要的级别(DEBUG、TRACE)都将被丢弃。
在同一个地方,我们添加一个逗号,然后指示将写入日志的对象的名称(这是我们自己提出的)。第 5-9 行包含其设置。
第 5 行——我们指定附加程序的类型 ( ConsoleAppender )。
第 6 行——我们准确指出我们正在写入的位置(System.out.)。
第 7 行——我们设置将管理转换模式 (PatternLayout) 的类。
第 8 行——我们设置将用于写入的转换模式。在上面的示例中,它是日期和时间。
“这是写入文件的样子:”
# Root logger option
log4j.rootLogger = INFO, file
# Direct log messages to a log file
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File = C:\\loging.log
log4j.appender.file.MaxFileSize = 1MB
log4j.appender.file.MaxBackupIndex = 1
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = %-5p %c{1}:%L - %m%n
“第 2 行设置消息过滤级别和 appender 对象(sink)的名称。”
“第 5 行——我们指定文件附加程序类型 ( RollingFileAppender )。”
“第 6 行 – 我们指定将写入日志的文件的名称。”
“第 7 行 – 我们指定最大日志大小。当超过此大小限制时,将创建一个新文件。”
“第 8 行 – 我们指定要存储的旧日志文件的数量。”
“第 9-10 行——设置转换模式。”
“我不知道这里发生了什么,但我可以猜到。这令人鼓舞。”
“那太好了。下面是一个如何将日志写入文件和控制台的示例:”
# Root logger option
log4j.rootLogger = INFO, file, stdout
# Direct log messages to a log file
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File = C:\\loging.log
log4j.appender.file.MaxFileSize = 1MB
log4j.appender.file.MaxBackupIndex = 1
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = %-5p %c{1}:%L - %m%n
# Direct log messages to stdout
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss}
“啊,那你就可以了?太好了!”
“是的。您可以根据需要声明任意数量的附加程序并自定义每个附加程序。”
此外,每个附加程序都可以有非常灵活的消息过滤设置。我们不仅可以为每个附加程序分配一个单独的消息过滤级别,而且我们还可以按包过滤消息!这就是为什么您需要在创建记录器时指定一个类(我说的是LoggerFactory.getLogger)。
“例如:”
# Root logger option
log4j.rootLogger = INFO, file, stdout
# Direct log messages to a log file
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.threshold = DEBUG
log4j.appender.file.File = C:\\loging.log
log4j.appender.file.MaxFileSize = 1MB
log4j.appender.file.MaxBackupIndex = 1
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = %-5p %c{1}:%L - %m%n
# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.threshold = ERROR
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss}
log4j.logger.org.springframework = ERROR
log4j.logger.org.hibernate = ERROR
log4j.logger.com.codegym = DEBUG
log4j.logger.org.apache.cxf = ERROR
“第 6 行和第 15 行——我们为每个附加程序设置了自己的过滤级别。”
“第 20-23 行——我们为其消息指定包名称和过滤级别。Log4j.logger 是一个前缀:包名称以橙色突出显示。”
“真的吗?你甚至可以那样做。嗯,酷!”
“顺便说一句,log4j 和 slf4j 都不包含在 JDK 中。您需要单独下载它们。您可以在此处下载。但还有另一种方法:”
“第 1 步。将导入添加到类中:”
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
“第 2 步。将光标放在这些行上,然后在 IntelliJ IDEA 中按 Alt+Enter”
"第 3 步。选择“Web 上的文件 jar» 菜单项。
“第 4 步。选择‘slf4j-log4j13.jar’”
“第 5 步。指定下载库 (jar) 的位置”
“第 6 步。使用您需要的课程。”
“哇!今天过得真好。有那么多新鲜事,还有那么多酷事!”
“这是另一篇关于日志记录的好文章:https://docs.oracle.com/javase/10/core/java-logging-overview.htm#JSCOR-GUID-48004124-2C00-49F7-A640-0C0DDA271DBC ”
“好了,够了,放松点吧,程序员。”
GO TO FULL VERSION