log4j与log4j不同:log4j是通过Logger的静态方法getLogger()获取Logger对象,而log4j2是通过LogManager的静态方法getLogger()获取Logger对象。
log4j2配置系列之1
1. log4j2原理
使用log4j 2 api的应用程序将从LogManager请求具有特定名称的记录器。LogManager将找到适当的LoggerContext,然后从中获取记录器。如果必须创建记录器,它将与LoggerConfig关联,loggerconfig包含a)与记录器相同的名称,b)父包的名称,或c)根LoggerConfig。LoggerConfig对象是从配置中的记录器声明创建的。LoggerConfig与实际传递logevents的appender相关联。
2.logger等级制度
在log4j 1.x中,记录器层次结构是通过记录器之间的关系来维护的。在log4j 2中,这种关系不再存在。相反,层次结构是在loggerconfig对象之间的关系中维护的。
loggers和loggerconfigs是命名实体。记录器名称区分大小写,并遵循分层命名规则:
Nameed HierchaHierarchy
A LoggerConfig is said to be an ancestor of another LoggerConfig if its name followed by a dot is a prefix of the descendant logger name.
A LoggerConfig is said to be a parent of a child LoggerConfig if there are no ancestors between itself and the descendant LoggerConfig.
For example, the LoggerConfig named "com.foo" is a parent of the LoggerConfig named"com.foo.Bar".
Root LoggerConfig位于LoggerConfig层次结构的顶部。它是例外,因为它总是存在的,它是每一个层次的一部分。直接链接到root LoggerConfig的记录器可以按如下方式获取:
Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
还有更简单的一种获取方式:
Logger logger = LogManager.getRootLogger();
对于所有其他类型的记录器,可以通过LogManager的静态方法getLogger获取。具体用法请查阅log4j2 API。
3.LoggerContext
loggercontext充当日志系统的定位点。但是,根据具体情况,应用程序中可能有多个活动loggercontext。有关loggercontext的更多详细信息,请参阅日志分离部分。
4.Configuration
每个loggercontext都有一个活动配置。配置包含所有的appender、上下文范围的Filters、loggerconfigs和对strsubstitutor的引用。在重新配置期间,将存在两个配置对象。一旦所有的记录器被重定向到新配置,旧配置将被停止并丢弃。
5.Logger
如前所述,通过调用logmanager.getlogger创建记录器。记录器本身不执行任何直接操作。它只是有一个名称,并且与loggerconfig相关联。它扩展了AbstractLogger并实现了所需的方法。当配置被修改时,记录器可能与不同的loggerconfig相关联,从而导致其行为被修改。
例如:x和y引用确切的指向相同的Logger对象。
Logger x = LogManager.getLogger("wombat");
Logger y = LogManager.getLogger("wombat");
log4j环境的配置通常在应用程序初始化时完成。首选方法是读取配置文件。
log4j使按软件组件命名记录器变得很容易。这可以通过在每个类中实例化记录器来实现,记录器名称等于类的完全限定名。这是定义记录器的一种有用而直接的方法。由于日志输出带有生成日志的名称,此命名策略使识别日志消息的来源变得容易。然而,这只是一种可能的(尽管很常见)命名记录器的策略。log4j不限制可能的记录器集。开发人员可以根据需要自由命名记录器。由于以拥有的类命名日志记录器是一种常见的习惯用法,因此提供了方便的方法LogManager.getLogger()来自动使用调用类的完全限定类名作为日志记录器名称。不过,以日志记录器所在的类命名日志记录器似乎是目前已知的最佳策略。
6.LoggerConfig
loggerconfig对象是在日志配置中声明日志记录器时创建的。loggerconfig包含一组筛选器,这些筛选器必须允许logevent在传递给任何附加程序之前进行传递。它包含对应用于处理事件的附加程序集的引用。
6.1 log levels
loggerConfigs将被分配一个日志级别。内置级别集包括trace、debug、info、warn、error和fatal。log4j 2还支持自定义日志级别。另一种获得更多粒度的机制是使用标记。
log4j 1.x和logback都有“级别继承”的概念。在log4j 2中,loggers和loggerconfigs是两个不同的对象,所以这个概念的实现方式不同。每个记录器都引用适当的loggerconfig。
7.Filter
除了如前一节所述进行的自动日志级筛选之外,log4j还提供了可以在控件传递给任何LoggerConfig之前、控件传递给LoggerConfig之后、调用任何appender之前、控件传递给l之后应用的筛选器。但在调用特定的appender之前,以及在每个appender上。以一种与防火墙过滤器非常相似的方式,每个过滤器可以返回三个结果之一,接受、拒绝或中立。accept的响应表示不应调用其他筛选器,事件应继续。拒绝响应意味着应该立即忽略该事件,并将控制权返回给调用方。中性响应表示该事件应传递给其他筛选器。如果没有其他筛选器,则将处理事件。
虽然筛选器可以接受事件,但仍可能不记录该事件。当事件被预loggerconfig筛选器接受,但随后被loggerconfig筛选器拒绝或被所有附加程序拒绝时,可能会发生这种情况。
8.appender
基于日志记录程序有选择地启用或禁用日志记录请求的能力只是图片的一部分。log4j允许将日志记录请求打印到多个目的地。在log4j speak中,输出目的地称为appender。目前,控制台、文件、远程套接字服务器、apache flume、jms、远程unix syslog守护进程和各种数据库api都有附加程序。有关可用的各种类型的详细信息,请参阅附录部分。一个记录器可以连接多个附加程序。
可以通过调用当前配置的addLoggerAppender方法将追加程序添加到记录器。如果与记录器名称匹配的loggerconfig不存在,将创建一个loggerconfig,附加程序将附加到它,然后通知所有记录器更新其loggerconfig引用。
为给定记录器启用的每个日志记录请求都将转发给该记录器的loggerconfig中的所有附加程序以及loggerconfig父级的附加程序。换句话说,appender是从loggerconfig层次结构中附加继承的。例如,如果将控制台附加程序添加到根日志记录器,则所有启用的日志记录请求将至少在控制台上打印。如果另外在loggerconfig(比如c)中添加了一个文件追加器,那么对c和c的子级启用的日志记录请求将在文件和控制台中打印。可以重写此默认行为,以便通过在配置文件中的记录器声明上设置additivity=“false”,不再对appender累加。
关于appender可加性的规则总结如下。
8.log4j 1.x Migration
1.Using the Log4j 1.x bridge
也许最简单的转换为使用log4j 2的方法是用log4j2的log4j-1.2-api.jar替换log4j 1.xjar文件。但是,要成功使用此应用程序,必须满足以下要求:
1.它们不能访问log4j 1.x实现内部的方法和类,如Appenders、LoggerRepository或Category的callAppenders方法。
2.它们不能以编程方式配置log4j。
3.它们不能通过调用类DomConfigurator或PropertyConfigurator进行配置。
2.Converting to the Log4j 2 API
在大多数情况下,从log4j 1.x api到log4j 2的转换应该相当简单。许多日志语句不需要修改。但是,如有必要,必须进行以下更改:
1.版本1中的主包是org.apache.log4j,版本2中的主包是org.apache.logging.log4j
2.对org.apache.log4j.Logger.getLogger()的调用必须修改为org.apache.logging.log4j.LogManager.getLogger()。
3.对org.apache.log4j.Logger.getRootLogger()或org.apache.log4j.LogManager.getRootLogger()的调用必须替换为org.apache.logging.log4j.LogManager.getRootLogger()。
4.调用org.apache.log4j.Logger.getLogger接受LoggerFactory必须删除org.apache.log4j.spi.LoggerFactory并使用log4j 2的其他扩展机制之一。
5.将对org.apache.log4j.Logger.getEffectiveLevel()的调用替换为org.apache.logging.log4j.Logger.getLevel()。
6.删除对org.apache.log4j.LogManager.shutdown()的调用,在版本2中不需要它们,因为log4j核心现在会在启动时自动添加一个jvm关闭挂钩来执行任何核心清理。
从log4j 2.1开始,您可以指定一个自定义的shutdownCallbackRegistry来覆盖默认的jvm shutdown hook策略。
从log4j 2.6开始,现在可以使用org.apache.logging.log4j.LogManager.shutdown()手动启动关闭。
7.API不支持对org.apache.log4j.Logger.setLevel()或类似方法的调用。应用程序应该删除这些。log4j 2实现类中提供了等效的功能,请参见org.apache.logging.log4j.core.config.Configurator.setLevel(),但可能会使应用程序易受log4j2内部更改的影响。
8.在适当的情况下,应用程序应该转换为使用参数化消息,而不是字符串连接。
9.org.apache.log4j.MDC和org.apache.log4j.NDC已被线程上下文替换。
3.configuring Log4j2
尽管log4j 2配置语法不同于log4j 1.x,但大多数(如果不是全部)相同的功能都是可用的。
注意,通过${foo}语法进行的系统属性插值已经扩展,允许从许多不同的源进行属性查找。有关详细信息,请参阅查找文档。例如,在log4j 1.x中使用名为catalina.base的系统属性查找,语法将是${catalina.base}。在log4j 2中,语法是${sys:catalina.base}。
log4j 1.x有一个与log4j 2中的xmlayout不同的xmlayout,log4j-1.2-api模块包含一个log4j1xmlayout,它以log4j 1.x中的格式生成输出。log4j 1.x simplelayout可以用patternlayout%level-%m%n进行模拟。log4j 1.x ttcclayout可以用patternlayout“%r[%t]%p%c%notempty{%ndc}-%m%n”模拟。
log4j 1.x中的patternLayout和enhancedPatternLayout都可以替换为log4j 2中的patternLayout。log4j-1.2-api模块包含两个模式转换“%ndc”和“%properties”,可用于模拟log4j 1.x patternlayout中的“%x”和“%x”(log4j 2中的%x和%x的格式略有不同)。
下面是log4j 1.x及其在log4j 2中的对应配置示例:
Sample 1 - Simple configuration using a Console Appender
Log4j 1.x XML configuration
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</layout>
</appender>
<category name="org.apache.log4j.xml">
<priority value="info" />
</category>
<Root>
<priority value ="debug" />
<appender-ref ref="STDOUT" />
</Root>
</log4j:configuration>
Log4j 2 XML configuration
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="org.apache.log4j.xml" level="info"/>
<Root level="debug">
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
Sample 2 - Simple configuration using a File Appender, XMLLayout and SimpleLayout
Log4j 1.x XML configuration
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="A1" class="org.apache.log4j.FileAppender">
<param name="File" value="A1.log" />
<param name="Append" value="false" />
<layout class="org.apache.log4j.xml.XMLLayout" />
</appender>
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.SimpleLayout" />
</appender>
<category name="org.apache.log4j.xml">
<priority value="debug" />
<appender-ref ref="A1" />
</category>
<root>
<priority value ="debug" />
<appender-ref ref="STDOUT" />
</Root>
</log4j:configuration>
Log4j 2 XML configuration
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name="A1" fileName="A1.log" append="false">
<Log4j1XmlLayout />
</File>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%level - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="org.apache.log4j.xml" level="debug">
<AppenderRef ref="A1"/>
</Logger>
<Root level="debug">
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
Sample 3 - SocketAppender
Log4j 1.x XML configuration. This example from Log4j 1.x is misleading. The SocketAppender does not actually use a Layout. Configuring one will have no effect.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="A1" class="org.apache.log4j.net.SocketAppender">
<param name="RemoteHost" value="localhost"/>
<param name="Port" value="5000"/>
<param name="LocationInfo" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%t %-5p %c{2} - %m%n"/>
</layout>
</appender>
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</layout>
</appender>
<category name="org.apache.log4j.xml">
<priority value="debug"/>
<appender-ref ref="A1"/>
</category>
<root>
<priority value="debug"/>
<appender-ref ref="STDOUT"/>
</Root>
</log4j:configuration>
Log4j 2 XML configuration
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Socket name="A1" host="localHost" port="5000">
<PatternLayout pattern="%t %-5p %c{2} - %m%n"/>
</Socket>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="org.apache.log4j.xml" level="debug">
<AppenderRef ref="A1"/>
</Logger>
<Root level="debug">
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
Sample 4 - AsyncAppender and TTCCLayout
Log4j 1.x XML configuration using the AsyncAppender.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" configDebug="true">
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="TEMP"/>
</appender>
<appender name="TEMP" class="org.apache.log4j.FileAppender">
<param name="File" value="temp"/>
<layout class="org.apache.log4j.TTCCLayout">
<param name="ThreadPrinting" value="true"/>
<param name="CategoryPrefixing" value="true"/>
<param name="ContextPrinting" value="true"/>
</layout>
</appender>
<root>
<priority value="debug"/>
<appender-ref ref="ASYNC"/>
</Root>
</log4j:configuration>
Log4j 2 XML configuration.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug">
<Appenders>
<File name="TEMP" fileName="temp">
<PatternLayout pattern="%r [%t] %p %c %notEmpty{%ndc }- %m%n"/>
</File>
<Async name="ASYNC">
<AppenderRef ref="TEMP"/>
</Async>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="ASYNC"/>
</Root>
</Loggers>
</Configuration>
Sample 5 - AsyncAppender with Console and File
Log4j 1.x XML configuration using the AsyncAppender.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" configDebug="true">
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="TEMP"/>
<appender-ref ref="CONSOLE"/>
</appender>
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</layout>
</appender>
<appender name="TEMP" class="org.apache.log4j.FileAppender">
<param name="File" value="temp"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</layout>
</appender>
<root>
<priority value="debug"/>
<appender-ref ref="ASYNC"/>
</Root>
</log4j:configuration>
Log4j 2 XML configuration. Note that the Async Appender should be configured after the appenders it references. This will allow it to shutdown properly.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug">
<Appenders>
<Console name="CONSOLE" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</Console>
<File name="TEMP" fileName="temp">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</File>
<Async name="ASYNC">
<AppenderRef ref="TEMP"/>
<AppenderRef ref="CONSOLE"/>
</Async>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="ASYNC"/>
</Root>
</Loggers>
</Configuration>