欢迎来到Apache Log4j2 示例教程. 如果你问专家开发人员关于应用程序中最烦人的事情,答案可能与日志相关。如果应用程序中没有合适的日志,维修将是一场噩梦。大多数应用程序都会通过开发测试,单元测试,集成测试。但当涉及到生产时,你总是会面临独特的场景和例外。因此,唯一的方法来弄清楚在特定情况下发生了什么是通过日志进行调试。许多框架提供某种默认日志的方式,但总是最好使用行业标准的日志机制。
Log4j 例子教程
在本 Log4j2 示例教程中,您将学习如何开始使用 Apache Log4j2. 我们还将探索 Log4j2 架构,log4j2 配置,log4j2 日志级别,附件,过滤器和更多。
- Log4j2 概述
- [Log4j2 架构](#log4j2 架构)
- [Log4j2 配置](#log4j2 配置)
- [Log4j2 层次](#log4j2 层次)
- [Log4j2 架构](#log4j2 架构)
- [Log4j2 附件](#log4j2 附件))
- [Log4j2 过滤器](#log4j2 层次)(#log4j2 过滤器
Log4j2 全景
在应用程序中使用 Logging API 不是奢侈品,它是必不可少的。 Log4j是一个开源库,在 Apache 软件下发布和授权。
Category / Operation (Debugging, Logging) | Debugging | Logging |
---|---|---|
Human Intervention | There's a need for human intervention | No need for human intervention |
Persistent Medium | Can't be integrated with persistent storage | Can be integrated with persistent storage (Files, Database, NoSQL database, etc.) |
May used for Auditing | Can't be used for achieving auditing | Can be used for achieving auditing if it's used efficiently |
Sufficient for complicated structure and flow | Not sufficient; you may get lost with flow. | Sufficient |
Productivity | Less productive | More productive |
正如您上面所看到的,使用日志机制将更高效,维护成本更低. Apache Log4j 是用于 Java 应用程序日志的前台运行工具,所以您应该使用它。
Log4j2 架构
Before we proceed for Log4j Example tutorial, it's good to look into Log4j2 architecture. Below image shows the important classes in Log4j2 API. Here's the detailed explanation for the architecture shown above:
- 应用程序将要求
Logmanager
提供具有特定名称的Logger
。 (- )Logmanager
将找到适当的LoggerContext
,然后从中获取Logger
。 (- ) 如果 Logger 尚未被创建, 它将会被创建并与 ** LoggerConfig ** 关联, 根据以下三个选择 :
- 将创建Logger实例并与同名的LoggerConfig相关联。 例如
getLogger( App. class)
中的 App. class 将评价为 String `com.journaldev。 App'. LoggerConfig 名称与完全合格的类名(软件组件)相同. (_) - Logger 实例将会被创建并与 ** LoggerConfig ** 关联,后者具有相同的 Loggers 父包. 例如,
GetLogger ("com. journaldev")中的
com.journaldev' ' () ) 3. Logger 实例将被创建并与 Root ** LoggerConfig**相联. root LoggerConfig 将在没有配置文件时使用,或者当您正在获得一个在日志声明中没有定义的名称的日志时使用. () ( )* 配置文件中的LoggerConfig
对象由Logger声明创建。 LoggerConfig也用于处理LogEvents
并委托它们处理定义的Log4j2 Appenders.(_ ( )* 就存在而言,Rootloger是一个特例。 它始终存在,并处于任何日志等级的顶端。 (_) ( )* 您可以使用以下语句获取根日志 :( _) __ Logger logger = LogManager.get Logger (LogManager.ROOT_LOGGGER_NAME); Logger logger = LogManager.get RootLogger (); _
- log4j2 日志的名称对大小写敏感
- 除rootlogger外,所有logger都可以通过将其名称传入
LogManager.getLogger ()
( - LoggerContext是日志系统的发声点,因为应用程序中可能有多个 LoggerContext 。 每个 LoggerContext 应设置一个活动配置 。
- Log4j2 配置包含所有日志系统资产; LoggerConfig(s), Appender(s), Filter(s) 和许多其他配置 。 () ) * 呼叫 LogManager.getLogger () 通过传递同名将总是返回完全相同的日志实例的引用. () ( )* 日志系统的配置一般在应用程序初始化时完成. 这可以采取不同的形式;在程序上或通过读取log4j2配置文件. (_) (英语)
Every logger is associated with a LoggerConfig object, set of LoggerConfig objects made up a Hierarchy of loggers. This concept is known as Logger Hierarchy. Logger Hierarchy is made up of set of LoggerConfig objects with a parent-child relationship. The topmost element in every Logger Hierarchy is the Root Logger. If Log4j2 doesn't find the configuration file, only Root Logger will be used for logging with logging level as ERROR. Below image shows the warning message you will get in this case. Error StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console. The table below shows the parent-child relationship in the Logger Hierarchy.
LoggerConfig (Is A) | Root | com | com.journaldev | com.journaldev.logging |
---|---|---|---|---|
Root | X | Child | descendant | descendant |
com | Parent | X | Child | descendant |
com.journaldev | Ancestor | Parent | X | Child |
com.journaldev.logging | Ancestor | Ancestor | Parent | X |
为了澄清父母与子女的关系,上面的表格会如下:
- 根是com
- 根是com.journaldev的祖先
- 根是com.journaldev.logging的祖先
- com是Root的子女
- com是com.journaldev的祖先
- com是com.journaldev.logging的祖先
- com.journaldev.logging是com.journaldev的子女等等
一个LoggerConfig实例被认为是另一个LoggerConfig的祖先;如果其名称跟随一个点是后代名称的前缀,则LoggerConfig实例被称为另一个LoggerConfig的祖先;如果两者之间没有相连的名称。
Log4j2 配置
在您的应用程序中使用 Log4j2 配置的方法有很多。
- 使用以 XML、JSON、YAML 或属性文件编写的配置文件
- 通过编程,创建一个配置工厂和配置实施
- 通过编程,通过调用在配置接口中暴露的 API
- 通过编程,通过调用内部日志器类的方法
我们将主要专注于配置文件,但是,如果您想为某个特定的 Logger 配置特定日志策略,也应该了解编程方法,首先,让我们考虑在您没有提供配置文件的情况下。
1package com.journaldev;
2import org.apache.logging.log4j.LogManager;
3import org.apache.logging.log4j.Logger;
4public class App
5{
6 public static void main( String[] args ) {
7 Logger logger = LogManager.getRootLogger();
8 logger.trace("Configuration File Defined To Be :: "+System.getProperty("log4j.configurationFile"));
9 }
10}
一个简单的log4j2配置文件将看起来如下。 configuration.xml:
1<?xml version="1.0" encoding="UTF-8"?>
2<Configuration>
3 <Appenders>
4 <Console name="Console">
5 <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
6 </Console>
7 </Appenders>
8 <Loggers>
9 <Root level="trace">
10 <AppenderRef ref="Console"/>
11 </Root>
12 </Loggers>
13</Configuration>
以下是上面列出的代码的详细解释:
- 应用程序已通过调用 LogManager 的
getRootLogger
方法引用了 Root logger - 从 LogManager 引用了 Log4j 系统
- Log4j 将检查 log4j.configurationFile 系统属性以确定 log4j2 配置文件。Log4j 配置可以用 JSON、YAML 和 XML 编写
- 我们可以通过
System.setProperties
(log4j.configurationFile
,FILE_PATH
)设置 log4j.configurationFile 系统属性,或者通过将其作为 JVM 参数,如下图所示。
- 联合国 如果** 没有定义系统属性**,配置顺序在下方优先:
- 属性配置 Factory将在类路径中查找
log4j2-test.properties
。 (_) ) - YAML 配置 工厂将寻找log4j2-test.yaml 或log4j2-test.yml 在阶级路径。 - JSON 配置 工厂将寻找log4j2-test.jsn 或log4j2-test.json 在分类路径。
- XML 配置 工厂将在分类点寻找log4j2-test.xml。
- 属性配置 Factory 将在类路径上查找
log4j2. 属性
(_) ) - YAML 配置 工厂将寻找log4j2.yml 或log4j2.yaml 在阶级中。 - JSON 配置 工厂将寻找log4j2.jsn或log4j2.json 在阶级中。
- XML 配置 工厂将在阶级街道寻找log4j2.xml。
- 如果没有提供配置文件,则将使用 ** 默认配置** ,从而引导您进行一系列默认行为:
- Root logger 。 (_) ) + Root日志级别将被设置为ERROR.
- Root日志将日志信息传播到控制台. (_) ) + PattleLayout 设定为"%d{HH:mm:s.SS} [%t] %-5级 %logger{36} - %msg%n'
使用log4j2配置文件使log4j2配置如此简单,但让我们看看如何编程配置。
1package com.journaldev;
2import java.io.File;
3import java.io.FileInputStream;
4import java.io.FileNotFoundException;
5import java.io.IOException;
6import org.apache.logging.log4j.Level;
7import org.apache.logging.log4j.core.Logger;
8import org.apache.logging.log4j.core.LoggerContext;
9import org.apache.logging.log4j.core.appender.ConsoleAppender;
10import org.apache.logging.log4j.core.config.Configuration;
11import org.apache.logging.log4j.core.config.ConfigurationFactory;
12import org.apache.logging.log4j.core.config.ConfigurationSource;
13import org.apache.logging.log4j.core.config.LoggerConfig;
14import org.apache.logging.log4j.core.config.xml.XmlConfigurationFactory;
15import org.apache.logging.log4j.core.layout.PatternLayout;
16public class App
17{
18 public static void main( String[] args ) throws FileNotFoundException, IOException {
19
20 // Get instance of configuration factory; your options are default ConfigurationFactory, XMLConfigurationFactory,
21 // YamlConfigurationFactory & JsonConfigurationFactory
22 ConfigurationFactory factory = XmlConfigurationFactory.getInstance();
23
24 // Locate the source of this configuration, this located file is dummy file contains just an empty configuration Tag
25 ConfigurationSource configurationSource = new ConfigurationSource(new FileInputStream(new File("C:/dummyConfiguration.xml")));
26
27 // Get a reference from configuration
28 Configuration configuration = factory.getConfiguration(configurationSource);
29
30 // Create default console appender
31 ConsoleAppender appender = ConsoleAppender.createDefaultAppenderForLayout(PatternLayout.createDefaultLayout());
32
33 // Add console appender into configuration
34 configuration.addAppender(appender);
35
36 // Create loggerConfig
37 LoggerConfig loggerConfig = new LoggerConfig("com",Level.FATAL,false);
38
39 // Add appender
40 loggerConfig.addAppender(appender,null,null);
41
42 // Add logger and associate it with loggerConfig instance
43 configuration.addLogger("com", loggerConfig);
44
45 // Get context instance
46 LoggerContext context = new LoggerContext("JournalDevLoggerContext");
47
48 // Start logging system
49 context.start(configuration);
50
51 // Get a reference for logger
52 Logger logger = context.getLogger("com");
53
54 // LogEvent of DEBUG message
55 logger.log(Level.FATAL, "Logger Name :: "+logger.getName()+" :: Passed Message ::");
56
57 // LogEvent of Error message for Logger configured as FATAL
58 logger.log(Level.ERROR, "Logger Name :: "+logger.getName()+" :: Not Passed Message ::");
59
60 // LogEvent of ERROR message that would be handled by Root
61 logger.getParent().log(Level.ERROR, "Root Logger :: Passed Message As Root Is Configured For ERROR Level messages");
62 }
63}
- 联合国 您可以使用 Log4j2 提供的配置事实, 或者使用默认事实 。 我们使用 QML 配置 Factory 来获取配置 Factory 的实例 。 ( ) ( )* Factory 将通过通过相应的配置文件来给您一个所需的配置引用实例 。 () ( )* 配置实例将与 LoggerContext 一起用于启动日志系统。 () ( )* 一个控制台 Appender 已被配置并添加到默认布局的配置实例中 。 这个 Appener 会打印消息到您的控制台 。 () ( )* LoggerConfig 实例已经创建,提供了名称、 LEVEL 并且没有使用过滤器。 Created Appender 将为 LoggerConfig 指定此实例( ) ( )* LoggerConfig 实例添加到配置实例中 。 () ( )* 使用定义的名称创建 LoggerContext 的新实例 。 () ( )* 配置实例已被传递给 LoggerContext 实例, 并从后者开始引用 。 () ( )* 从 LoggerContext 获取了日志实例 。 此日志实例将被用于点燃一系列日志事件 。 (_) ( )* Logger 实例启动了三个事件, 将在 Log4j2 Levels 一节中加以解释 。
- com logger 配置以打印级别为 FATAL 的信件 。 () (
)* 默认情况下, Root 日志被配置为打印级别为 ERROR. () 的信件 。 (
)* 错误信件不会被
com
日志器登录, 因为它的关卡是 FATAL. (_) (英语)
相同的配置可以通过使用YAML、JSON或属性文件来完成,但是log4j2属性文件配置与log4j属性文件不同,所以请确保您不尝试使用log4j属性文件配置与log4j2一起使用。
1ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
在处理上面的代码时,会给你下面的输出:
1Logger Name :: com :: Passed Message ::
200:01:27.705 [main] ERROR - Root Logger:: Passed Message As Root Is Configured For ERROR Level messages
第一行日志来自 com 日志,第二行来自 Root Logger. com 日志的错误消息不会打印,因为其级别是致命的。
Log4j2 级别
You can see in above code examples that every time we define a LoggerConfig, we also provide logging level. By default log4j2 logging is additive. It means that all the parent loggers will also be used when a specific logger is used. Below image clarifies this situation. And herein points of clarification for it:
- 联合国 正如我们先前所说 每个伐木工都和LoggerConfig案有关 此loggerConfig 已被定义在配置范围 。 () (
)* 伐木水平可在LoggerConfig范围确定。 () (
)* 您可以通过登录器的名称、 父包或指向 Root Logger 本身来获取日志 。 () (
)* Root Logger是每个 LoggerConfig 等级的顶级节点. () (
)* 一旦获得
com.journaldev
日志并启动用于伐木的日志Event,日志GorgerConfig(net.journaldev)将登录信息,并在不尊重父母伐木水平的情况下,将信息传播到等级层。 因此日志事件会被传播到com和Rootloggers,他们也会根据定义的级别分别登录消息. - 一旦您获得 com 日志并启动用于日志的日志Event , 日志Config( com) 将会登录信件, 并在不尊重父母的日志级别的情况下, 将信件在等级层中同样传播 。 也就是说, Root 日志会被推广日志事件,它也会登录消息. () ( )* net.journaldev 等级体系的相同情况( ( )* 下几节将就添加剂概念作更多的澄清。 () ( )* 家长有机会通过使用"过滤"概念或设置添加剂指标来忽略消息,因此日志事件不会被传播给家长. ( ( )* 如果相应的logger Config 级别是 GreatER than log 事件级别, 日志者有机会忽略消息 。 (_) (英语)
现在,让我们看看与上面解释的添加性概念相关的例子:
1import net.NetApp;
2import net.journaldev.NetJournalDevApp;
3import com.ComApp;
4import com.journaldev.ComJournalDevApp;
5public class Main {
6 public static void main(String [] args){
7 new ComApp();
8 new ComJournalDevApp();
9 new NetApp();
10 new NetJournalDevApp();
11 }
12}
1package com.journaldev;
2import org.apache.logging.log4j.LogManager;
3import org.apache.logging.log4j.Logger;
4public class ComJournalDevApp {
5 public ComJournalDevApp(){
6 Logger logger = LogManager.getLogger(ComJournalDevApp.class);
7 logger.trace("COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::");
8 }
9}
1package net;
2import org.apache.logging.log4j.LogManager;
3import org.apache.logging.log4j.Logger;
4public class NetApp {
5 public NetApp(){
6 Logger logger = LogManager.getLogger(NetApp.class);
7 logger.error("NET :: LEVEL :: NetApp ERROR Message ::");
8 }
9}
1package net.journaldev;
2import org.apache.logging.log4j.LogManager;
3import org.apache.logging.log4j.Logger;
4public class NetJournalDevApp {
5 public NetJournalDevApp(){
6 Logger logger = LogManager.getLogger(NetJournalDevApp.class);
7 logger.error("NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::");
8 }
9}
虽然log4j2配置文件看起来如下:
1<?xml version="1.0" encoding="UTF-8"?>
2<Configuration>
3 <Appenders>
4 <Console name="Console">
5 <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
6 </Console>
7 </Appenders>
8 <Loggers>
9 <Root level="ERROR">
10 <AppenderRef ref="Console"/>
11 </Root>
12 <logger name="com" level="TRACE">
13 <AppenderRef ref="Console"/>
14 </logger>
15 <logger name="com.journaldev" level="TRACE">
16 <AppenderRef ref="Console"/>
17 </logger>
18 <logger name="net" level="ERROR">
19 <AppenderRef ref="Console"/>
20 </logger>
21 <logger name="net.journaldev" level="ERROR">
22 <AppenderRef ref="Console"/>
23 </logger>
24 </Loggers>
25</Configuration>
如果你得到主类执行,你会发现下面的结果:
110:34:47.168 [main] TRACE com.ComApp - COM :: LEVEL :: ComApp TRACE Message ::
210:34:47.168 [main] TRACE com.ComApp - COM :: LEVEL :: ComApp TRACE Message ::
310:34:47.170 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
410:34:47.170 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
510:34:47.170 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
610:34:47.171 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
710:34:47.171 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
810:34:47.171 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
910:34:47.171 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
1010:34:47.171 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
下面是上面列出的代码的详细解释:
- 配置文件包含五个 loggerConfig 实例定义,它们是 Root, com, com.journaldev, net & net.journaldev. 就像上面的 Logger 等级一样.
- 根级别配置为 ERROR,这实际上是默认值
- com & com.journaldev 级别配置为 TRACE
- net & net.journaldev 级别配置为 ERROR.
- 您可能注意到ComAPP 和 ComJournalDevApp loggers 邮件分别显示两次和三次。 这些邮件根据 ComApp 和 ComJournalDevApp 的 Logger 等级设置为 TRACE
- net & com.
Logging Space 考虑了 log 事件的级别和 loggerConfig 的级别,以及 Logger 等级。
那么,如果我们将 LoggerConfig for com 更改为 INFO,然后将整个程序留下:
1<?xml version="1.0" encoding="UTF-8"?>
2<Configuration>
3 <Appenders>
4 <Console name="Console">
5 <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
6 </Console>
7 </Appenders>
8 <Loggers>
9 <Root level="ERROR">
10 <AppenderRef ref="Console"/>
11 </Root>
12 <logger name="com" level="INFO">
13 <AppenderRef ref="Console"/>
14 </logger>
15 <logger name="com.journaldev" level="TRACE">
16 <AppenderRef ref="Console"/>
17 </logger>
18 <logger name="net" level="ERROR">
19 <AppenderRef ref="Console"/>
20 </logger>
21 <logger name="net.journaldev" level="ERROR">
22 <AppenderRef ref="Console"/>
23 </logger>
24 </Loggers>
25</Configuration>
然后结果将是如下:
111:08:10.305 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
211:08:10.305 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
311:08:10.305 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
411:08:10.307 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
511:08:10.307 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
611:08:10.308 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
711:08:10.308 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
811:08:10.308 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
- 當然,您可能會注意到ComAPP日志事件被忽略,這是因為loggerConfig for com的定義水平。INFO(400)水平低於日志事件的水平,這裡是TRACE(600)。
要确保显示了日志事件,LoggerConfig 的级别应大于或等于日志事件的级别。
下表显示了 log4j2 级别和每个级别的重量:
LEVEL | Weight |
---|---|
OFF | 0 |
FATAL | 100 |
ERROR | 200 |
WARN | 300 |
INFO | 400 |
DEBUG | 500 |
TRACE | 600 |
ALL | Integer.MAX_VALUE |
毫无疑问,上面的表比单词更清楚,它为您提供了主要原因,即记录事件 TRACE 未显示,而 LoggerConfig 的级别是 INFO。
请注意,日志事件的传播在日志登记器等级是超出这个计算,它忽略了水平。
但是如果我们从配置中删除 com.journaldev 的 LoggerConfig,并为 com.journaldev.logging 添加一个新的配置文件,使配置文件看起来如下:
1<?xml version="1.0" encoding="UTF-8"?>
2<Configuration>
3 <Appenders>
4 <Console name="Console">
5 <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
6 </Console>
7 </Appenders>
8 <Loggers>
9 <Root level="ERROR">
10 <AppenderRef ref="Console"/>
11 </Root>
12 <logger name="com" level="TRACE">
13 <AppenderRef ref="Console"/>
14 </logger>
15 <logger name="com.journaldev.logging" level="TRACE">
16 <AppenderRef ref="Console"/>
17 </logger>
18 <logger name="net" level="ERROR">
19 <AppenderRef ref="Console"/>
20 </logger>
21 <logger name="net.journaldev" level="ERROR">
22 <AppenderRef ref="Console"/>
23 </logger>
24 </Loggers>
25</Configuration>
You may find the figure below more convenient for you to understand what's happened in the above log4j2 configuration. Here's some clarification for the figure shown above and how it may affect the behavior of logging events:
- 当日志事件被名为 com.journaldev.logging 的 Logger 丢弃时,与该名称相关联的 LoggerConfig (即 com.journaldev.logging) 已被用来处理并打印消息
- Being com.journaldev.logging LoggerConfig 的附加属性默认设置为 true,日志事件已被传递给在这种情况下是指 com.journaldev.
- Being com.journaldev LoggerConfig 在配置中没有定义,没有任何操作发生,而日志事件将传递到 com,然后Rootger LogfigCon 实例( *) & 根将接收日志事件并打印它,而不论它是发送的级别(_MBRK
作为上述点的结果,您将看到以下输出:
114:08:37.634 [main] TRACE com.ComApp - COM :: LEVEL :: ComApp TRACE Message ::
214:08:37.634 [main] TRACE com.ComApp - COM :: LEVEL :: ComApp TRACE Message ::
314:08:37.636 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
414:08:37.636 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
514:08:37.637 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
614:08:37.637 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
714:08:37.637 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
814:08:37.638 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
914:08:37.638 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
1014:08:37.640 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
1114:08:37.640 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
1214:08:37.640 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
你可能会注意到以下几点:
- Log event at com package 已显示两次. One for com while second for Root.
- Log event at com.journaldev 已显示两次. One for com 和 second for Root. 虽然它以前是三次,但目前 com.journaldev 的 LoggerConfig 没有,所以在 com.journaldev 包中可能没有发生logging,并且该事件将被传播给 com 和 Root.
- 在 com.journaldev.logging 上显示了三次,一个是 com.journaldev.logging 包,另一个是 com 和第三个是 Root。 根据 Logger Hierarchy 传播,它应该显示一次,但由于没有 com.jounraldev LogConfig,它会显示三次.
如果您已定义一个 com.journaldev LoggerConfig 实例没有指定水平,它将继承其母级。
但是,如果你在配置文件中定义了 com.journaldev LoggerConfig 并错过了指定 LoggerConfig 的级别,幸运的是, Logger 层次结构的概念会让你在这里存储,而 com.journaldev 将从其母级值继承。
1<?xml version="1.0" encoding="UTF-8"?>
2<Configuration>
3 <Appenders>
4 <Console name="Console">
5 <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
6 </Console>
7 </Appenders>
8 <Loggers>
9 <Root level="ERROR">
10 <AppenderRef ref="Console"/>
11 </Root>
12 <logger name="com" level="TRACE">
13 <AppenderRef ref="Console"/>
14 </logger>
15 <logger name="com.journaldev">
16 <AppenderRef ref="Console"/>
17 </logger>
18 <logger name="com.journaldev.logging" level="TRACE">
19 <AppenderRef ref="Console"/>
20 </logger>
21 <logger name="net" level="ERROR">
22 <AppenderRef ref="Console"/>
23 </logger>
24 <logger name="net.journaldev" level="ERROR">
25 <AppenderRef ref="Console"/>
26 </logger>
27 </Loggers>
28</Configuration>
Logger Name | Assigned LoggerConfig | LoggerConfig Level | Logger Level |
---|---|---|---|
Root | Root | ERROR | ERROR |
com | com | TRACE | TRACE |
com.journaldev | com | TRACE | TRACE |
com.journaldev.logging | com.journaldev.logging | TRACE | TRACE |
- com.journaldev.logging 套件已经与 LogConfig 与 Log 级 TRACE 相关联。 com.journaldev 套件已经与没有指定 Log 级的 LoggerConfig 相关联,因此它将继承其家长日志级,并且肯定值将为 com 套件 TRACE
- com 套件已经与 Loggerconfig 与 Log 级 TRACE 相关联。
下面是执行结果,而 com.journaldev 继承 com 日志级别:
114:41:37.419 [main] TRACE com.ComApp - COM :: LEVEL :: ComApp TRACE Message ::
214:41:37.419 [main] TRACE com.ComApp - COM :: LEVEL :: ComApp TRACE Message ::
314:41:37.421 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
414:41:37.421 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
514:41:37.421 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
614:41:37.422 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
714:41:37.422 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
814:41:37.422 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
914:41:37.422 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
1014:41:37.423 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
1114:41:37.423 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
1214:41:37.423 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
1314:41:37.423 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
1414:41:37.423 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
下面的结果将是,如果你删除声明 LoggerConfig for com 包:
114:43:28.809 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
214:43:28.809 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
314:43:28.809 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
414:43:28.811 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
514:43:28.811 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
614:43:28.812 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
714:43:28.812 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
814:43:28.812 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
您可能会注意到没有邮件已登录 com 和 com.journaldev,以下是原因。
- 删除与 com 套件相关联的 LoggerConfig 会导致在该套件中提到的所有 Log 事件被忽略
- 由于配置中对 com 套件没有 LoggerConfig 定义,所以与 com.journaldev 相关的 LoggerConfig 将继承其母级 Log 级别。 Com 没有定义,而 Logger 层次达到顶部,现在是指 Root。 根级 Log 是 ERROR(200) 并且 com.journaldev 中的 Log 事件级别是 TRACE(600) - 参见 ComJournalDevApp - 根据以前的方程式定义, LogConfig 级别应该大于或等于 Log 事件,这就是错误的,所以在 com.journaldev 中不会显示任何消息。
最后但不是最重要的,下面的表显示了您在使用日志系统时可能遇到的所有可能的日志场景:
X (N/A) | LoggerConfig Level | OFF(0) | FATAL(100) | ERROR(200) | WARN(300) | INFO(400) | DEBUG(500) | TRACE(600) | ALL(MAX) |
---|---|---|---|---|---|---|---|---|---|
Event Level | X | X | X | X | X | X | X | X | X |
OFF(0) | X | YES | NO | NO | NO | NO | NO | NO | NO |
FATAL(100) | X | NO | YES | YES | YES | YES | YES | YES | YES |
ERROR(200) | X | NO | NO | YES | YES | YES | YES | YES | YES |
WARN(300) | X | NO | NO | NO | YES | YES | YES | YES | YES |
INFO(400) | X | NO | NO | NO | NO | YES | YES | YES | YES |
DEBUG(500) | X | NO | NO | NO | NO | NO | YES | YES | YES |
TRACE(600) | X | NO | NO | NO | NO | NO | NO | YES | YES |
ALL(MAX) | X | NO | NO | NO | NO | NO | NO | NO | YES |
- 没有直接方法可以用于投放 OFF/ALL 日志事件
- 主要用于投放 OFF/ALL 日志事件,您可以使用 logger.log(Level.OFF, "Msg")或 logger.log(LEVEL.ALL,"Msg"),分别
- 日志方法负责根据上述方程处理日志事件
处理方程式表示:如果 LoggerConfig 级别大于或等于 Log 事件级别,则该事件将被接受进行进一步处理。
日志事件将被接受进行进一步处理 - 这非常重要,因为你有能力防止某些事件被处理,即使它通过使用Log4j2过滤器被接受。你可以将 additive属性设置为假,以避免日志事件传播到家长日志记录者。
1<?xml version="1.0" encoding="UTF-8"?>
2<Configuration>
3 <Appenders>
4 <Console name="Console" target="SYSTEM_OUT">
5 <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
6 </Console>
7 </Appenders>
8 <Loggers>
9 <Root level="ERROR">
10 <AppenderRef ref="Console"/>
11 </Root>
12 <logger name="com" level="TRACE" additivity="false">
13 <AppenderRef ref="Console"/>
14 </logger>
15 <logger name="com.journaldev" additivity="false">
16 <AppenderRef ref="Console"/>
17 </logger>
18 <logger name="com.journaldev.logging" level="TRACE" additivity="false">
19 <AppenderRef ref="Console"/>
20 </logger>
21 <logger name="net" level="ERROR" additivity="false">
22 <AppenderRef ref="Console"/>
23 </logger>
24 <logger name="net.journaldev" level="ERROR" additivity="false">
25 <AppenderRef ref="Console"/>
26 </logger>
27 </Loggers>
28</Configuration>
执行结果将如下:
117:55:30.558 [main] TRACE com.ComApp - COM :: LEVEL :: ComApp TRACE Message ::
217:55:30.560 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
317:55:30.561 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
417:55:30.561 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
517:55:30.562 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
您可能会注意到,没有日志事件传播到其父母日志。
Log4j2 搜索
理想情况下,您可以将搜索定义为您可以传输Logging配置文件的值的方式。Log4j2为您提供了不同的搜索集,可以独立使用来设置来自不同背景的值:
- 背景地图搜索
- 数据搜索
- 环境搜索
- Java搜索
- JNDI搜索
- JVM输入参数搜索(JMX)
- 主要参数搜索
- 地图搜索
- 结构化数据搜索
- 系统属性搜索
- 网络搜索
您可以参阅Log4j2 文档以获取有关每个类型的搜索的详细信息,但让我们来看看这里的一些示例来涵盖Log4j2搜索的基本知识。 环境搜索代表了您可以传递环境值的方式(通过Linux等/个人资料,Windows系统环境或应用程序的启动脚本。
- 使用 Windows 环境变量功能来定义环境变量:
- 右键单击您计算机图标并选择属性。 控制面板首页应显示
- 单击高级系统设置,然后打开环境变量窗口
- 在 系统变量部分中,用 JournalDevVar 定义变量
- 更新 log4j2.xml 内部的模式布局以包含您新添加的变量
使用启动脚本功能来定义您的环境变量
- 使用正常的默认脚本,您可以使用Eclipse IDE Running Script功能,点击您的运行菜单并选择运行配置
- 导航到环境卡并定义您的变量
Look now at the modified log4j2.xml file and notice the use of environment variables.
1<Console name="Console" target="SYSTEM_OUT">
2 <PatternLayout pattern="%d{HH:mm:ss.SSS} $${env:JournalDevVar} $${env:JournalDevSecondVar} [%t] %-5level %logger{36} - %msg%n"/>
3</Console>
执行结果将如下所示:
123:57:02.511 JournalDev www.journaldev.com [main] TRACE com.ComApp - COM :: LEVEL :: ComApp TRACE Message ::
223:57:02.517 JournalDev www.journaldev.com [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
323:57:02.520 JournalDev www.journaldev.com [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
423:57:02.523 JournalDev www.journaldev.com [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
523:57:02.527 JournalDev www.journaldev.com [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
But you may face a little issue here and especially when you're defining an OS's environment variables and it's the Eclipse Cache. Ideally, Eclipse has cached all system variables when it gets running and you may find all of them under Run - Run Configuration - Environment Tab - Click Select button. So, you may be confusing when you have defined it but the Application doesn't recognize it. Even if you restart your Eclipse, you won't get the solution and to solve it you must execute eclipse.exe -clean upon your Eclipse installation. To make sure your environment variables are defined properly and your system is going to find them willingly, you may use the correspondence plugin type that's provided by Log4j2 API. Make an instance of EnvironmentLookup and ask it for looking up certain variable and if it's defined, so you would find them easily.
1EnvironmentLookup lookup = new EnvironmentLookup();
2LogManager.getRootLogger().error(lookup.lookup("JournalDevSecondVar"));
Log4j2 附件
您以前曾看到如何使用 Lookups 将变量注入配置文件中。 但是,您可能想要修改您的消息通过的媒介。 而不是直接使用控制台,您可能需要这样的文件或数据库存储库来确保您的消息永久保留。 Log4j2 提供了许多附件,您可以参阅 log4j2 文档以获取附件的更多细节。 简而言之,以下是所有 Log4j2 附件的列表。
- ConsoleAppender
- AsyncAppender
- FailoverAppender
- FileAppender
- FlumeAppender
- JDBCAppender
- JMSAppender
- JPAAppender
- MemoryMappedFileAppender
- NoSQLAppender
- OutputStreamAppender
- RandomAccessFileAppender
- RewriteAppender
- RollingFileAppender
- RollingRandomAccessFileAppender
- RoutingAppender
- SMTPAppender
- SocketAppender
- SyslogAppender
用于记录事件的最著名的媒体是控制台,文件和数据库. 由于该文件会保存您的消息,数据库可能会被用来审核它们。
JDBC应用程序
JDBCAppender的主要目标是通过JDBC连接将日志事件写入关系表中。我们不会花费太多时间解释如何优化您的连接池,因为本教程不是为此目的而设计的。但是,您肯定会得到一个完整的功能示例,可以帮助您将日志事件写入数据库。在我们开始之前,让我们看看所有必要的参数和每个参数的描述,以便正确配置JDBCAppender。
*______________________________________________________________________________________________________________________________________________________ 名称 QQ 字符串 需要, Appender 的名称 QQ QQ 忽略 Exceptions QQ布尔 QQ 默认值设定为真实值, 使所抛出的例外也被记录, 然后被忽略 。 假值表示例外会被宣传给呼叫者. QQ QQ 过滤器 QQ 过滤器 用于决定日志事件是否由这个 Appender 处理 。 __ ____ 缓冲 QQQ 英寸 默认值为0,表示日志事件没有进行缓冲. 大于0的值将引导 Appender 缓冲日志事件,然后在缓冲到达指定限度后冲出. QQ QQ 连接源 QQ 连接源 需要, 数据库连接应当从中检索的连接源 。 & _ _ ________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________ | (_ _) | column column column Column Column Column Column Column Column Column | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | columns | columns columns columns columns columns columns columns columns columns columns columns columns columns columns columns columns | columns | columns columns columns columns columns columns | | columns columns columns columns columns columns | columns columns 这可以用多个"Column"元素处理. |
参数 名称 列表 列表 列表 列表 列表 列表 列表 列表 列表 列表 列表
参数 名
参数 名称:
由于您被迫使用 JNDI,我们的示例将为 Oracle 数据库和 Apache Tomcat 7 配置连接数据源。
如果你对Oracle不太了解,我建议你安装它的Express Edition(https://www.oracle.com/database/technologies/appdev/xe.html)。 *在你的环境中安装Apache(Tomcat 7](https://tomcat.apache.org/download-70.cgi) *在你的Eclipse中创建一个Maven WebApp项目
- 确保您的项目成功创建,如果您在pom中发现任何错误,请确保您修复它们
- 添加Log4j2依赖
1<dependency>
2 <groupId>org.apache.logging.log4j</groupId>
3 <artifactId>log4j-api</artifactId>
4 <version>2.2</version>
5</dependency>
6<dependency>
7 <groupId>org.apache.logging.log4j</groupId>
8 <artifactId>log4j-core</artifactId>
9 <version>2.2</version>
10</dependency>
- 配置您的背景以包含 MySQL 数据源声明. 根据 Apache 文档,该文件应该位于您的 Web Application META-INF 文件夹中。
1<Context path="/JournalDevWebLogging"
2 privileged="true" antiResourceLocking="false" antiJARLocking="false">
3 <Resource name="jdbc/JournalDevDB" auth="Container"
4 factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
5 type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000"
6 username="root" password="root" driverClassName="com.mysql.jdbc.Driver"
7 url="jdbc:mysql://localhost:3306/journaldev" />
8</Context>
- 配置您的数据库并创建您的日志表,
1CREATE TABLE `logging` (
2 `EVENT_ID` int(11) NOT NULL AUTO_INCREMENT,
3 `EVENT_DATE` datetime DEFAULT NULL,
4 `LEVEL` varchar(45) DEFAULT NULL,
5 `LOGGER` varchar(45) DEFAULT NULL,
6 `MSG` varchar(45) DEFAULT NULL,
7 `THROWABLE` varchar(45) DEFAULT NULL,
8 PRIMARY KEY (`EVENT_ID`)
9) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
- 設定您的 log4j2.xml 看起來如下:
1<?xml version="1.0" encoding="UTF-8"?>
2<Configuration>
3 <Appenders>
4 <Console name="Console" target="SYSTEM_OUT">
5 <PatternLayout
6 pattern="%d{HH:mm:ss.SSS} $${env:JournalDevVar} $${env:JournalDevSecondVar} [%t] %-5level %logger{36} - %msg%n" />
7 </Console>
8 <JDBC name="databaseAppender" tableName="journaldev.logging">
9 <DataSource jndiName="java:/comp/env/jdbc/JournalDevDB" />
10 <Column name="EVENT_DATE" isEventTimestamp="true" />
11 <Column name="LEVEL" pattern="%level" />
12 <Column name="LOGGER" pattern="%logger" />
13 <Column name="MSG" pattern="%message" />
14 <Column name="THROWABLE" pattern="%ex{full}" />
15 </JDBC>
16 </Appenders>
17 <Loggers>
18 <Root level="ERROR">
19 <AppenderRef ref="Console" />
20 </Root>
21 <logger name="com" level="TRACE" additivity="false">
22 <AppenderRef ref="databaseAppender" />
23 </logger>
24 <logger name="com.journaldev" additivity="false">
25 <AppenderRef ref="databaseAppender" />
26 </logger>
27 </Loggers>
28</Configuration>
- 创建任何 Web 资源,允许您获取日志器的参考,然后记录事件
1package com.journaldev;
2import java.io.IOException;
3import javax.servlet.ServletException;
4import javax.servlet.http.HttpServlet;
5import javax.servlet.http.HttpServletRequest;
6import javax.servlet.http.HttpServletResponse;
7import org.apache.logging.log4j.LogManager;
8import org.apache.logging.log4j.Logger;
9public class JournalDevServlet extends HttpServlet{
10 private static final long serialVersionUID = 1L;
11 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
12 Logger logger = LogManager.getLogger(JournalDevServlet.class);
13 logger.trace("JournalDev Database Logging Message !");
14 }
15}
- 您可以任意配置 ServletContextListener,以确保数据源的初始化完成
1package com.journaldev;
2import javax.naming.Context;
3import javax.naming.InitialContext;
4import javax.naming.NamingException;
5import javax.servlet.ServletContextEvent;
6import javax.servlet.ServletContextListener;
7import org.apache.logging.log4j.LogManager;
8public class JournalDevServletContextListener implements ServletContextListener{
9 private InitialContext context = null;
10 public void contextDestroyed(ServletContextEvent event) {
11 }
12 public void contextInitialized(ServletContextEvent event) {
13 try {
14 // Get initial context
15 context = new InitialContext();
16 // Get a reference for sub context env
17 Context envContext = (Context)context.lookup("java:comp/env");
18 // Get a reference for sub context jdbc and then locating the data source defined
19 LogManager.getRootLogger().error(((Context)envContext.lookup("jdbc")).lookup("JournalDevDB"));
20 } catch (NamingException e) {
21 LogManager.getRootLogger().error(e);
22 }
23 }
24}
- 定义您的 Servlet 在您的 web.xml 文件中.
- 运行应用程序并访问上述定义的 Servlet. 您将看到下面的日志.
1Mar 15, 2015 2:31:41 PM org.apache.catalina.core.AprLifecycleListener init
2INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: C:\Program Files\Java\jdk1.6.0_26\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:\Program Files\Java\jdk1.6.0_26\jre\bin;C:/Program Files/Java/jdk1.6.0_26/bin/../jre/bin/server;C:/Program Files/Java/jdk1.6.0_26/bin/../jre/bin;C:/Program Files/Java/jdk1.6.0_26/bin/../jre/lib/amd64;D:\OracleWebCenter\OracleWC\Oracle11g\app\oracle\product\11.2.0\server\bin;;C:\Program Files\Common Files\Microsoft Shared\Windows Live;C:\Program Files (x86)\Common Files\Microsoft Shared\Windows Live;D:\OracleDB\app\product\11.2.0\dbhome_1\bin;org.C:\Program Files (x86)\Common Files\NetSarang;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x64;D:\SpringRoo\spring-roo-1.2.5.RELEASE\bin;D:\Ant\apache-ant-1.9.2\bin;C:\Python27;C:\Program Files\Java\jdk1.6.0_26\bin;D:\Maven\apache-maven-3.2.1/bin;D:\bower-master\bin;C:\Program Files (x86)\Git\cmd;C:\Program Files\nodejs\;C:\Program Files\Microsoft Windows Performance Toolkit\;D:\Grails\grails-2.4.0\bin;D:\Gradle\gradle-2.0\bin;C:\Program Files (x86)\Windows Live\Shared;C:\Program Files\TortoiseSVN\bin;D:\Strawberry\perl\bin;D:\Strawberry\perl\site\bin;D:\Strawberry\c\bin;C:\Users\mohammad.amr\AppData\Roaming\npm;D:\JournalDev\eclipse;;.
3Mar 15, 2015 2:31:41 PM org.apache.tomcat.util.digester.SetPropertiesRule begin
4WARNING: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.j2ee.server:JournalDevWebLogging' did not find a matching property.
5Mar 15, 2015 2:31:41 PM org.apache.coyote.AbstractProtocol init
6INFO: Initializing ProtocolHandler ["http-bio-8080"]
7Mar 15, 2015 2:31:41 PM org.apache.coyote.AbstractProtocol init
8INFO: Initializing ProtocolHandler ["ajp-bio-8009"]
9Mar 15, 2015 2:31:41 PM org.apache.catalina.startup.Catalina load
10INFO: Initialization processed in 1020 ms
11Mar 15, 2015 2:31:41 PM org.apache.catalina.core.StandardService startInternal
12INFO: Starting service Catalina
13Mar 15, 2015 2:31:41 PM org.apache.catalina.core.StandardEngine startInternal
14INFO: Starting Servlet Engine: Apache Tomcat/7.0.35
1514:31:43.847 [localhost-startStop-1] ERROR - org.apache.tomcat.jdbc.pool.DataSource@10fd0a62{ConnectionPool[defaultAutoCommit=null; defaultReadOnly=null; defaultTransactionIsolation=-1; defaultCatalog=null; driverClassName=com.mysql.jdbc.Driver; maxActive=100; maxIdle=30; minIdle=10; initialSize=10; maxWait=10000; testOnBorrow=false; testOnReturn=false; timeBetweenEvictionRunsMillis=5000; numTestsPerEvictionRun=0; minEvictableIdleTimeMillis=60000; testWhileIdle=false; testOnConnect=false; password=root; url=jdbc:mysql://localhost:3306/journaldev; username=root; validationQuery=null; validatorClassName=null; validationInterval=30000; accessToUnderlyingConnectionAllowed=true; removeAbandoned=false; removeAbandonedTimeout=60; logAbandoned=false; connectionProperties=null; initSQL=null; jdbcInterceptors=null; jmxEnabled=true; fairQueue=true; useEquals=true; abandonWhenPercentageFull=0; maxAge=0; useLock=false; dataSource=null; dataSourceJNDI=null; suspectTimeout=0; alternateUsernameAllowed=false; commitOnReturn=false; rollbackOnReturn=false; useDisposableConnectionFacade=true; logValidationErrors=false; propagateInterruptState=false; }
16Mar 15, 2015 2:31:43 PM org.apache.coyote.AbstractProtocol start
17INFO: Starting ProtocolHandler ["http-bio-8080"]
18Mar 15, 2015 2:31:43 PM org.apache.coyote.AbstractProtocol start
19INFO: Starting ProtocolHandler ["ajp-bio-8009"]
20Mar 15, 2015 2:31:43 PM org.apache.catalina.startup.Catalina start
21INFO: Server startup in 1909 ms
Log4j2 过滤器
即使有一个LoggerConfig候选人来处理Log事件,你也可以将其配置为拒绝将Log事件传输到后端附件中。这可以通过log4j2过滤器完成。本节不是为了为你提供一个侵入性的、大规模的和大量的教程,关于在Log4j2中使用过滤器,因为他们需要大量的文章,涵盖每一个。但是在这里,你会看到如何使用最简单的过滤器来学习这个概念。你可能使用的最简单的过滤器之一是BurstFilter,它为你提供了一个机制来控制LogEvents在达到最大限度后默默默地抛弃事件的速度。
Parameter Name | Type | Description |
---|---|---|
level | String | Level of messages to be filtered |
rate | float | The average number of events per second to allow |
maxBurst | integer | The maximum number of events that can occur before events are filtered for exceeding the average rate. The default is 10 times the rate. |
onMatch | String | Action to take when filter matches. May be Accept, DENY or NEUTRAL. The default is NEUTRAL |
onMismatch | String | Action to tale when filter doesn't match. May be Accept, DENY or NEUTRAL. The default is NEUTRAL |
现在,看看BurstFilter在您的数据库附件中的位置。
1<?xml version="1.0" encoding="UTF-8"?>
2<Configuration>
3 <Appenders>
4 <Console name="Console" target="SYSTEM_OUT">
5 <PatternLayout
6 pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
7 </Console>
8 <JDBC name="databaseAppender" tableName="journaldev.logging">
9 <DataSource jndiName="java:/comp/env/jdbc/JournalDevDB" />
10 <BurstFilter level="TRACE" rate="20" maxBurst="2"/>
11 <Column name="EVENT_DATE" isEventTimestamp="true" />
12 <Column name="LEVEL" pattern="%level" />
13 <Column name="LOGGER" pattern="%logger" />
14 <Column name="MSG" pattern="%message" />
15 <Column name="THROWABLE" pattern="%ex{full}" />
16 </JDBC>
17 </Appenders>
18 <Loggers>
19 <Root level="ERROR">
20 <AppenderRef ref="Console" />
21 </Root>
22 <logger name="com" level="TRACE" additivity="false">
23 <AppenderRef ref="databaseAppender" />
24 </logger>
25 <logger name="com.journaldev" additivity="false">
26 <AppenderRef ref="databaseAppender" />
27 </logger>
28 </Loggers>
29</Configuration>
- 数据库附件会考虑 BurstFilter,而控制台附件不会
- 虽然使用控制台日志器会导致您记录完整的日志事件,但数据库附件不会这样做,因为BurstFilter会阻止其中一些程序
- 即使使用的日志器是处理日志事件的候选人,也可以实现此 LogEvents 拒绝 。
1package com.journaldev;
2import java.io.IOException;
3import javax.servlet.ServletException;
4import javax.servlet.http.HttpServlet;
5import javax.servlet.http.HttpServletRequest;
6import javax.servlet.http.HttpServletResponse;
7import org.apache.logging.log4j.LogManager;
8import org.apache.logging.log4j.Logger;
9public class JournalDevServlet extends HttpServlet{
10 private static final long serialVersionUID = 1L;
11 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
12 Logger logger = LogManager.getLogger(JournalDevServlet.class);
13 for(int i = 0 ; i < 1000 ; i++){
14 logger.trace("Index :: "+i+" :: JournalDev Database Logging Message !");
15 LogManager.getRootLogger().error("Index :: "+i+" :: JournalDev Database Logging Message !");
16 }
17 }
18}
即使这些 LoggerConfigs 是处理投放到那里的日志事件的候选人,但过滤器已经阻止了其中一些被处理,然后登录。
Log4j2 配置
由于不同附件消耗日志事件和每个附件的性质,布局是以满足日志事件消耗者需求的格式形成日志事件的,在Log4j 1.x和Logback API中,日志事件的布局转换为字符串,而Log4j2布局已经考虑了不同的转换方式;这就是通过将日志事件转换为字节的范围。这种新型转换将迫使您配置 Charset以确保日志事件的布局包含正确的值。
Log4j2 模式布局
Pattern layout is a configurable, flexible String pattern aimed to format the LogEvent. This kind of formatting is dependent on the conversion pattern concept. This section will depict you the most important features pattern layout provides. Conversion pattern is related to the conversion pattern that printf in language C provides. Generally, the conversion pattern is composed of literal text and format control Expressions called conversion specifiers. Figure below depicts you what parts the conversion pattern composed from: This figure above is a trial to simplify the Conversion Pattern, but for sure it's better for you to refer Apache Log4j2 documentation for further details about Layouts and Pattern Layout specifically. Also, you may refer above for log events and see at every time what's Conversion Pattern it is used for format the messages.
您应该使用哪个Log4j2级
你可能问自己最大的问题是,何时应该使用特定的日志事件级别。在开发领域,使用DEBUG日志事件是正常的,而在生产中,我们应该使用INFO或WARN级别。
Log Event Level | When It Should Be Used |
---|---|
OFF | When no events will be logged |
FATAL | When a severe error will prevent the application from continuing |
ERROR | When an error in the application, possibly recoverable |
WARN | When an event that might possible lead to an error |
INFO | When an event for informational purposes |
DEBUG | When a general debugging event required |
TRACE | When a fine grained debug message, typically capturing the flow through the application |
ALL | When all events should be logged |
Log4j2 教程摘要
Log4j2 是 Apache Logging 框架的改进版本。Log4j2 提供了从 Log4j1.x 的一系列新功能和性能改进。这个 log4j2 教程旨在帮助您在一个地方获得所有内容。由于这些概念中的一些并不容易同时覆盖,我们决定将我们的努力纳入解释这个概念并使用一些样本以获得进一步的澄清。附件、过滤器、布局和搜索都受此规则的约束。 ** 一些重要点** 为了确保您能够运行下面的应用程序并避免任何障碍,请检查下面的内容:
- 您的 Eclipse IDE 已启用
- 您的 Apache Tomcat 在您的 Apache Home lib 文件夹中具有 MySQL 连接器 JAR。
[下载Apache Log4j 2示例项目]
这就是log4j2教程的全部,我希望大多数重要的点都被涵盖,以便您在应用程序中开始使用Log4j2。