LOG4J2使用笔记

一、简介

Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX SYSlog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

Log4j 2 官网:https://logging.apache.org/log4j/2.x

二、背景

Log4j的1.x版本已经被广泛使用于很多应用程序中。然而,由于需要严格遵循很老的Java版本,使它变得越来越难以维护,终在2015年8月寿终正寝,最新版为1.2.17。它的替代品,SLF4J和Logback对框架做了很多必要的改进。那么为什么还要费心去做Log4j 2呢?几个原因如下:

  1. Log4j 2被设计为可以作为审计框架使用。Log4j 1.x和Logback都会在重新配置的时候失去事件,而Log4j2不会。在Logback中,Appender当中的异常对应用从来都是不可见的。但Log4j2的Appender可以设置为允许将异常渗透给应用程序。
  2. Log4j 2包含基于LMAX Disruptor库的下一代异步日志器。在多线程情况下,异步日志器具有比Log4j 1.x和Logback高出10倍的吞吐性能以及更低的延迟。
  3. Log4j 2在稳定记录状态下,对单机应用是无垃圾的,对Web应用是低垃圾的。这不仅降低了垃圾回收器的压力,还可以提供更好的响应性能。
  4. Log4j 2使用插件系统使得它非常容易通过新的Appender、Filter、Layout、Lookup和Pattern Converter来扩展框架,且不需要对Log4j做任何修改。
  5. 由于插件系统的配置更简单了,配置项不需要声明类名称。
  6. 支持自定义日志级别。自定义日志级别可以在代码或配置中定义。
  7. 支持Lambda表达式。运行在Java 8上的客户端代码可以使用Lambda表达式来实现仅在对应的日志级别启用时延迟构造日志消息。由于不需要明确地层层把关,这带来了更简洁的代码。
  8. 支持Message对象。Message允许支持感兴趣或复杂的结构体在日志系统中传输,且可以被高效地操作。用户可以自由地创建他们自己的Message类型,并编写自定义的Layout、Filter和Lookup来操作它们。
  9. Log4j 1.x支持Appender上的Filter。Logback引入了TurboFilter来在事件被Logger处理之前对它们进行过滤。Log4j 2支持的Filter可以设置为在被Logger接管之前即处理事件,如同它在Logger或Appender中被处理。
  10. 很多Logback的Appender不接受一个Layout,且只能发送固定格式的数据。而大多数Log4j 2的Appender接受Layout,允许数据以任意一种所需的格式传输。
  11. Log4j 1.x和Logback中的Layout返回一个String。这导致了在Logback Encoder中讨论的问题。Log4j 2用更简单的方法,Layout总是返回一个字节数组。优点是这意味着它们可以用于任何Appender,而不仅仅是写入到OutputStream中的那些。
  12. Syslog Appender既支持TCP也支持UDP,同样支持BSD系统日志以及RFC 5424格式。
  13. Log4j 2利用了Java 5的并发优势,并在尽可能最低的程度上进行锁定。Log4j 1.x中已知存在死锁问题。其中很多已经在Logback中修复,但很多Logback的class文件仍然需要在更高的编译级别中同步。
  14. 这是一个被所有ASF项目集体支持使用的Apache软件基金会项目。如果你想要贡献或修改,只要参照贡献中的方法。

三、配置

1.log4j2配置方法

  1. 通过一个XML或JSON格式的配置文件
  2. 以编程方式,通过创建一个ConfigurationFactory工厂和Configuration实现
  3. 以编程方式,通过调用API暴露在配置界面添加组件的默认配置
  4. 以编程方式,通过调用Logger内部类上的方法

2.配置文件及加载流程

log4j 2.x版本不再支持像1.x中的.properties后缀的文件配置方式,2.x版本配置文件后缀名只能为".xml",".json"或者".jsn".系统选择配置文件的优先级(从先到后)如下:

  1. .classpath下的名为log4j2-test.json 或者log4j2-test.jsn的文件.
  2. .classpath下的名为log4j2-test.xml的文件.
  3. .classpath下名为log4j2.json 或者log4j2.jsn的文件.
  4. .classpath下名为log4j2.xml的文件.

一般默认使用log4j2.xml进行命名。如果本地要测试,可以把log4j2-test.xml放到classpath,而正式环境使用log4j2.xml,则在打包部署的时候不要打包log4j2-test.xml即可。

3.默认配置


<?xml version="1.0" encoding="UTF-8"?>

<Configuration status="WARN">

    <Appenders>

       <Console name="Console" target="SYSTEM_OUT">

          <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>

       </Console>

    </Appenders>

    <Loggers>

       <Root level="error">

          <AppenderRef ref="Console"/>

       </Root>

    </Loggers>

</Configuration>

4.配置文件节点解析

  • 根节点Configuration有两个属性:status和monitorinterval,两个子节点:Appenders和Loggers
  1. status用来指定log4j本身的打印日志的级别
  2. monitorinterval用于指定log4j自动重新配置的监测间隔时间,单位是s,最小是5s

  • Appenders节点,常见的有三种子节点:Console、RollingFile、File

  • Console节点用来定义输出到控制台的Appender
  1. name:指定Appender的名字
  2. target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT
  3. PatternLayout:输出格式,不设置默认为:%m%n

  • File节点用来定义输出到指定位置的文件的Appender
  1. name:指定Appender的名字
  2. fileName:指定输出日志的目的文件带全路径的文件名
  3. PatternLayout:输出格式,不设置默认为:%m%n

  • RollingFile节点用来定义超过指定大小自动删除旧的创建新的的Appender
  1. name:指定Appender的名字
  2. fileName:指定输出日志的目的文件带全路径的文件名
  3. PatternLayout:输出格式,不设置默认为:%m%n
  4. filePattern:指定新建日志文件的名称格式
  5. Policies:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志
  6. 时间滚动策略:TimeBasedTriggeringPolicy,interval属性用来指定多久滚动一次,默认是1 hour,modulate=true用来调整时间,比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am...而不是7am
  7. 文件大小滚动策略:SizeBasedTriggeringPolicy,size属性用来定义每个日志文件的大小
  8. DefaultRolloverStrategy:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max属性)

  • Loggers节点,常见的子节点有两种:Root和Logger
  1. Root节点用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出
  2. Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等,name属性用来指定该Logger所适用的类或者类所在的包全路径
  3. AppenderRef节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root,如果指定了,那么会在指定的这个Appender和Root下的Appender中都输出,此时可以设置Logger的additivity="false",只在自定义的Appender中进行输出

5.日志level

共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF

  1. All:最低等级的,用于打开所有日志记录
  2. Trace:是追踪,程序推进跟踪,一般不用
  3. Debug:指出细粒度信息事件对调试应用程序是非常有帮助的
  4. Info:消息在粗粒度级别上突出强调应用程序的运行过程
  5. Warn:输出警告及warn以下级别的日志
  6. Error:输出错误信息日志
  7. Fatal:输出每个严重的错误事件将会导致应用程序的退出的日志
  8. OFF:最高等级的,用于关闭所有日志记录

6.比较完整的log4j2.xml配置模板

<?xml version="1.0" encoding="UTF-8"?>

<!-- 日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->

<!-- Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出 -->
<!-- monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数 -->
<Configuration status="WARN" monitorInterval="30">
	<Properties>
		<Property name="baseDir">${sys:user.dir}/logs</Property>
	</Properties>

	<!-- 先定义所有的appender -->
	<Appenders>
		<!-- 这个输出控制台的配置 -->
		<Console name="Console" target="SYSTEM_OUT">
			<!-- 输出日志的格式 -->
			<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"></PatternLayout>
		</Console>

		<!-- 打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用 -->
		<File name="log" fileName="${baseDir}/test.log" append="false">
			<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"></PatternLayout>
		</File>

		<!-- 打印出所有的info及以上级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档 -->
		<RollingFile name="RollingFileInfo" fileName="${baseDir}/info.log"
			filePattern="${baseDir}/%d{yyyyMMdd}/info-%i.log.zip">
			<!-- 控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
			<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"></ThresholdFilter>
			<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %l %-5p - %msg%xEx%n"></PatternLayout>
			<Policies>
				<!-- 设置每天切换日志一次 -->
				<TimeBasedTriggeringPolicy interval="1" modulate="true"></TimeBasedTriggeringPolicy>
				<!-- 设置日志文件满50MB后切换 -->
				<SizeBasedTriggeringPolicy size="50 MB"></SizeBasedTriggeringPolicy>
			</Policies>
			<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 -->
			<DefaultRolloverStrategy max="20">
				<!-- 配置说明:
					* 只处理位于${baseDir}文件夹下的文件 
					* 只处理以 .log.zip 结尾的文件 (name match) 
					* 只处理最后一次修改时间超过7天以内的文件
				-->
				<Delete basePath="${baseDir}" maxDepth="1">
					<IfFileName glob="*.log.zip" />
					<IfLastModified age="7d" />
				</Delete>
			</DefaultRolloverStrategy>
		</RollingFile>

		<RollingFile name="RollingFileError" fileName="${baseDir}/error.log"
			filePattern="${baseDir}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log">
			<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"></ThresholdFilter>
			<PatternLayout pattern="%d{HH:mm:ss.SSS} - %p - %l - %m%n"></PatternLayout>
			<Policies>
				<SizeBasedTriggeringPolicy size="50 MB"></SizeBasedTriggeringPolicy>
			</Policies>
		</RollingFile>
	</Appenders>

	<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效 -->
	<Loggers>
		<!--过滤掉Spring和MyBatis的一些无用的DEBUG信息 -->
		<logger name="org.springframework" level="INFO"></logger>
		<logger name="org.mybatis" level="INFO"></logger>

		<root level="all">
			<appender-ref ref="Console"></appender-ref>
			<appender-ref ref="RollingFileInfo"></appender-ref>
			<appender-ref ref="RollingFileError"></appender-ref>
		</root>
	</Loggers>
</Configuration>

四.使用LOG4J

	/**
	 * 加载log4j2.xml配置文件
	 * @throws Exception
	 */
	public static void load() throws Exception {
		
		System.out.println("加载log4j配置开始...");
		
		ConfigurationSource source = null;
		FileInputStream fis = null;
		try {
			String logConfPath = System.getProperty("user.dir") + File.separatorChar + "configs" + File.separatorChar + "log4j2.xml";
			fis = new FileInputStream(logConfPath);
			source = new ConfigurationSource(fis);
			Configurator.initialize(null, source);
			System.out.println("加载log4j配置完成!");
		}catch (Exception e) {
			e.printStackTrace();
			System.err.println("加载log4j配置失败!");
		} finally {
			if (fis != null) {
				fis.close();
			}
		}
	}

	public static void main(String[] args) {
		try {
			// 加载log4j2配置文件
			Log4j2Conf.load();	
			Logger log = LoggerFactory.getLogger(RootLogger.ROOT);
			
			log.debug("hello,woshizjc!");
			log.error("报错拉!");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

五.自定义输出格式

%c{参数} 或 %logger{参数}输出日志名称;如果加上{<层数>}表示列出从最内层算起的指定层数的名字空间,下同假设当前logger名字空间是"a.b.c"
%c{2}列出从最内层算起的2层名字空间,输出结果"b.c"
%20c若名字空间长度小于20,则左边用空格填充
%.30c若名字空间长度超过30,截去多余字符
%-20.30c若名字空间长度小于20,则右边用空格填充;若名字空间长度超过30,截去多余字符
%C{参数} 或 %class{参数}列出调用logger的类的全名(包含包路径)假设当前类是"org.apache.xyz.SomeClass"
%Corg.apache.xyz.SomeClass
%C{1}SomeClass
%F 或 %file显示调用logger的源文件名
%m 或 %msg 或 %message输出日志信息
%M 或 %method 显示调用logger的方法名
%r显示从程序启动时到记录该条日志时已经经过的毫秒数
%d{参数}显示日志记录时间%d{yyyy/MM/dd HH:mm:ss,SSS}2005/10/12 22:23:30,117
%d{ABSOLUTE}22:23:30,117
%d{DATE}12 Oct 2005 22:23:30,117
%d{ISO8601}2005-10-12 22:23:30,117
%t输出产生该日志事件的线程名
%l输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数
%L显示调用logger的代码行号
%p 或 %level显示该条日志的日志等级
%x按NDC(Nested Diagnostic Context,线程堆栈)顺序输出日志假设某程序调用顺序是MyApp调用com.foo.Bar
%c %x - %m%nMyApp - Call com.foo.Bar.
com.foo.Bar - Log in Bar
MyApp - Return to MyApp.
%X按MDC(Mapped Diagnostic Context,线程映射表)输出日志。通常用于多个客户端连接同一台服务器,方便服务器区分是那个客户端访问留下来的日志%X{5}记录代号为5的客户端的日志
%%显示一个百分号
%n当前操作系统下的换行符
highlight{pattern}{style}高亮显示
特殊符号有些特殊符号不能直接打印,需要使用实体名称或者编号&&amp; 或者 &#38;
<&lt; 或者 &#60;
>&gt; 或者 &#62;
&quot; 或者 &#34;
&apos; 或者 &#39;
pattern对齐修饰编写格式为在任何pattern和%之间加入一个小数,可以是正数,也可以是负数。 整数表示右对齐,负数表示左对齐;整数位表示输出信息的最小n个字符,如果输出信息不够n个字符,将用空格补齐;小数位表示输出信息的最大字符数,如果超过n个字符,则只保留最后n个字符的信息(注意:保留的是后20个字符,而不是前20个字符)示例如下
%20右对齐,不足20个字符则在信息前面用空格补足,超过20个字符则保留原信息 
%-20左对齐,不足20个字符则在信息后面用空格补足,超过20个字符则保留原信息
%.30如果信息超过30个字符,则只保留最后30个字符
%20.30右对齐,不足20个字符则在信息前面用空格补足,超过30个字符则只保留最后30个字符
%-20.30左对齐,不足20个字符则在信息后面用空格补足,超过30个字符则只保留最后30个字符

 

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值