目录[-]
- 1 系列目录
- 2 默认配置
- 3 第一个配置例子
- 4 复杂一点的配置
- 4.1 Appender之Syslog配置
- 4.2 Syslog及Syslog-ng相关配置(Fedora)
- 5 Log4j2与Spring集成
1 系列目录
- 2种日志接口框架,4种日志实现框架
- Apache Log4j
- Apache Commons Logging
- JDK Logging
- Logback
- Apache Log4j2
2 默认配置
本来以为Log4J2应该有一个默认的配置文件的,不过好像没有找到(通过DefaultConfiguration,初始化一个最小化配置),下面这个配置文件等同于缺省配置:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <configuration status="OFF"> 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 <appender-ref ref="Console"/> 11 </root> 12 </loggers> 13 </configuration>
3 第一个配置例子
配置Log4j 2可以有四种方法(其中任何一种都可以):
- 通过一个格式为
XML或JSON的配置文件。 - 以编程方式,通过创建一个
ConfigurationFactory工厂和Configuration实现。 - 以编程方式,通过调用
api暴露在配置界面添加组件的默认配置。 - 以编程方式,通过调用
Logger内部类上的方法。
注意,与Log4j 1.x不一样的地方,公开的Log4j 2 API没有提供任何添加、修改或删除 appender和过滤器或者操作配置文件的方法。
Log4j能够自动配置本身在初始化期间。当Log4j启动它将定位所有的ConfigurationFactory插件和安排然后在加权从最高到最低。Log4j包含两个ConfigurationFactory实现,一个用于JSON和XML。加载配置文件流程如下:
-
Log4j将检查“Log4j的配置文件“系统属性,如果设置,将
尝试加载配置使用 ConfigurationFactory 匹配的文件扩展。 -
如果
没有系统属性设置JSON ConfigurationFactory log4j2-test将寻找。 json或 log4j2-test。json在类路径中。 -
如果
没有这样的文件发现XML ConfigurationFactory log4j2-test将寻找。 xml在 类路径。 -
如果
一个测试文件无法找到JSON ConfigurationFactory log4j2将寻找。 log4j2.jsn json或 在类路径中。 -
如果
一个JSON文件无法找到XML ConfigurationFactory将试图定位 log4j2。 xml在类路径中。 -
如果
没有配置文件可以找到了 DefaultConfiguration 将被使用。 这将导致日志输出到控制台。1<?xml version="1.0" encoding="UTF-8"?> 2<configuration status="OFF"> 3 <appenders> 4 <Console name="Console" target="SYSTEM_OUT"> 5 <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> 6 </Console> 7 </appenders> 8 <loggers> 9 <!--我们只让这个logger输出trace信息,其他的都是error级别--> 10 <!-- 11 additivity开启的话,由于这个logger也是满足root的,所以会被打印两遍。 12 不过root logger 的level是error,为什么Bar 里面的trace信息也被打印两遍呢 13 --> 14 <logger name="cn.lsw.base.log4j2.Hello" level="trace" additivity="false"> 15 <appender-ref ref="Console"/> 16 </logger> 17 <root level="error"> 18 <appender-ref ref="Console"/> 19 </root> 20 </loggers> 21</configuration>
我们这里看到了配置文件里面是name很重要,没错,这个name可不能随便起(其实可以随便起)。这个机制意思很简单。就是类似于java package一样,比如我们的一个包:cn.lsw.base.log4j2。而且,可以发现我们前面生成Logger对象的时候,命名都是通过 Hello.class.getName(); 这样的方法,为什么要这样呢? 很简单,因为有所谓的Logger 继承的问题。比如 如果你给cn.lsw.base定义了一个logger,那么他也适用于cn.lsw.base.lgo4j2这个logger。名称的继承是通过点(.)分隔的。然后你可以猜测上面loggers里面有一个子节点不是logger而是root,而且这个root没有name属性。这个root相当于根节点。你所有的logger都适用与这个logger,所以,即使你在很多类里面通过类名.class.getName() 得到很多的logger,而且没有在配置文件的loggers下面做配置,他们也都能够输出,因为他们都继承了root的log配置。
我们上面的这个配置文件里面还定义了一个logger,他的名称是 cn.lsw.base.log4j2.Hello ,这个名称其实就是通过前面的Hello.class.getName(); 得到的,我们为了给他单独做配置,这里就生成对于这个类的logger,上面的配置基本的意思是只有cn.lsw.base.log4j2.Hello 这个logger输出trace信息,也就是他的日志级别是trace,其他的logger则继承root的日志配置,日志级别是error,只能打印出ERROR及以上级别的日志。如果这里logger 的name属性改成cn.lsw.base,则这个包下面的所有logger都会继承这个log配置(这里的包是log4j的logger name的“包”的含义,不是java的包,你非要给Hello生成一个名称为“myhello”的logger,他也就没法继承cn.lsw.base这个配置了。
那有人就要问了,他不是也应该继承了root的配置了么,那么会不会输出两遍呢?我们在配置文件中给了解释,如果你设置了additivity="false",就不会输出两遍。
4 复杂一点的配置
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!-- 3 Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出。 4 --> 5 <!-- 6 monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数。 7 --> 8 <configuration status="error" monitorInterval=”30″> 9 <!--先定义所有的appender--> 10 <appenders> 11 <!--这个输出控制台的配置--> 12 <Console name="Console" target="SYSTEM_OUT"> 13 <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> 14 <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/> 15 <!--这个都知道是输出日志的格式--> 16 <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/> 17 </Console> 18 <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用--> 19 <File name="log" fileName="log/test.log" append="false"> 20 <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/> 21 </File> 22 <!-- 这个会打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--> 23 <RollingFile name="RollingFile" fileName="logs/app.log" 24 filePattern="log/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> 25 <PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/> 26 <SizeBasedTriggeringPolicy size="50MB"/> 27 <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 --> 28 <DefaultRolloverStrategy max="20"/> 29 </RollingFile> 30 </appenders> 31 <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效--> 32 <loggers> 33 <!--建立一个默认的root的logger--> 34 <root level="trace"> 35 <appender-ref ref="RollingFile"/> 36 <appender-ref ref="Console"/> 37 </root> 38 </loggers> 39 </configuration>
-
扩展组件
- ConsoleAppender:输出结果到System.out或是System.err。
- FileAppender:输出结果到指定文件,同时可以指定输出数据的格式。append=“false”指定不追加到文件末尾
- RollingFileAppender:自动追加日志信息到文件中,直至文件达到预定的大小,然后自动重新生成另外一个文件来记录之后的日志。
-
过滤标签
- ThresholdFilter:用来过滤指定优先级的事件。
- TimeFilter:设置start和end,来指定接收日志信息的时间区间。
4.1 Appender之Syslog配置
log4j2中对syslog的简单配置,这里就不重复展示log4j2.xml了:
<Syslog name="SYSLOG" host="localhost" port="514" protocol="UDP" facility="LOCAL3"/>
host是指你将要把日志写到的目标机器,可以是ip(本地ip或远程ip,远程ip在实际项目中很常见,有专门的日志服务器来存储日志),也可以使用主机名,如果是本地,还可以使用localhost或127.0.0.1。
Port指定端口,默认514,参见/etc/rsyslog.conf(以Fedora系统为例,下同)。protocol指定传输协议,这里是UDP,facility是可选项,后面可以看到用法。
4.2 Syslog及Syslog-ng相关配置(Fedora)
在运行程序之前,需要修改:/etc/rsyslog.conf。
把这两行前的#去掉,即取消注释:
1#$ModLoad imudp 2#$UDPServerRun 514
这里启用udp监听,514是默认监听端口,重启syslog:
service syslog restart
大部分日志会默认写到/var/log/messages中,如果不想写到这个文件里,可以按下面修改,这样local3的日志就会写到app.log中。这里的local3即 log4j2.xml中facility的配置。
*.info;mail.none;authpriv.none;cron.none;local3.none /var/log/messages
新增一行:
local3.* /var/log/app.log
除了使用自带的syslog,我们也可以使用syslog的替代品,比如syslog-ng,这对于log4j2.xml配置没有影响。 安装:
yum install syslog-ng
启动:
service syslog-ng start
其配置文件为:
/etc/syslog-ng/syslog-ng.conf
启动前把source一节中这一行取消注释即可:
#udp(ip(0.0.0.0) port(514));
这个端口会和syslog冲突,可以使用别的端口比如50014,同时修改log4j2.xml中的port属性。另外提一下,使用非默认端口,要求log4j版本在1.2.15或以上。
syslog-ng本身也可以设置把日志送到远程机器上,在源机器上的syslog-ng.conf中添加:
destination d_remote1 {udp(153.65.171.73 port(514));};
这表示源机器上的syslog-ng会把接收到的日志送到远程主机153.65.171.73的514端口上,只要保证153.65.171.73上的syslog-ng正常运行并监听对应的端口即可。
5 Log4j2与Spring集成
web.xml配置:

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app\_3\_1.xsd" id="WebApp_ID" version="3.1"> <context-param> <param-name>contextConfigLocation</param-name> <!-- 读取classpath 以 applicationContext 开头的文件作为spring 的配置文件 \--> <param-value>classpath*:applicationContext-*.xml</param-value> </context-param> <!-- 解决中文乱码问题,将参数编码为utf-8 \--> <filter> <filter-name>encodingFilter</filter-name> <filter-class> org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
1<filter\> 2 <filter-name\>shiroFilter</filter-name\> 3 <filter-class\>org.springframework.web.filter.DelegatingFilterProxy</filter-class\> 4 <init-param\> 5 <param-name\>targetFilterLifecycle</param-name\> 6 <param-value\>true</param-value\> 7 </init-param\> 8</filter\> 9 10<!-- Make sure any request you want accessible to Shiro is filtered. /\* catches all \--> 11<!-- requests. Usually this filter mapping is defined first (before all others) to \--> 12<!-- ensure that Shiro works in subsequent filters in the filter chain: \--> 13 14<filter-mapping\> 15 <filter-name\>shiroFilter</filter-name\> 16 <url-pattern\>/\*</url-pattern\> 17</filter-mapping\> 18 19<!-- log4j2-begin for servlet 2.5 20 <listener> 21 <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class> 22 </listener> 23 <filter> 24 <filter-name>log4jServletFilter</filter-name> 25 <filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class> 26 </filter> 27 <filter-mapping> 28 <filter-name>log4jServletFilter</filter-name> 29 <url-pattern>/\*</url-pattern> 30 <dispatcher>REQUEST</dispatcher> 31 <dispatcher>FORWARD</dispatcher> 32 <dispatcher>INCLUDE</dispatcher> 33 <dispatcher>ERROR</dispatcher> 34 </filter-mapping> 35 log4j2-end \--> 36 37<!-- log4j2-begin for servlet version >3.0\--> 38<context-param\> 39 <param-name\>log4jConfigLocation</param-name\> 40 <param-value\>/WEB-INF/classes/log4j2.xml</param-value\> 41</context-param\> 42 43<listener\> 44 <listener-class\>org.springframework.web.context.ContextLoaderListener</listener-class\> 45</listener\> 46<servlet\> 47 <servlet-name\>dispatcher</servlet-name\> 48 <servlet-class\>org.springframework.web.servlet.DispatcherServlet</servlet-class\> 49 <init-param\> 50 <param-name\>contextConfigLocation</param-name\> 51 <param-value\>classpath\*:spring-mvc.xml</param-value\> 52 </init-param\> 53 <load-on-startup\>1</load-on-startup\> 54 <async-supported\>true</async-supported\> 55</servlet\> 56<servlet-mapping\> 57 <servlet-name\>dispatcher</servlet-name\> 58 <url-pattern\>/</url-pattern\> 59</servlet-mapping\> 60 61<display-name\>IotSupport</display-name\>
</web-app>