log4j学习
log4j学习
2017年7月10日
1:45
一.Log4J三大组件
1.Logger(记录器):只负责(根据日志级别)记录日志,不负责日志存储位置
2.Appender(存放器):将Logger记录的日志,存放到配置文件中所指向的地方,只处理日志的存放过程.
3.Layout(布局):将日志格式化后输出
一个Logger可配置多个Appender,可同时输出到多个设备上
每个Appender都有一个Layout来格式化输出内容
二.Log4J配置
参考
http://blog.csdn.net/azheng270/article/details/2173430/
配置文件,.分别设置输出到控制台的logger,和输出到文件的logger
### 设置根Logger ###
#log4j.rootLogger=[level],appendName1,appendName2,...
#level为debug,appendName1为1,appendName2为D,...
#根记录器的默认级别是Level.DEBUG
#指定三个rootLogger,stdout,D,E
log4j.rootLogger = debug,stdout,D,E
##############################################################
### 输出信息到控制台 ###
#Log4j提供的appender包括:ConsoleAppender(控制台),FileAppender(文件),DailyRollingFileAppender(每天产生一个日志文件)
#RollingFileAppender(文件大小到达指定尺寸的时候产生一个新文件),WriterAppender(将日志信息以流格式发送到任意指定地方)
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
#layout包括:HTMLLayout(以HTML表格形式布局),PatternLayout(灵活指定布局模式),SimpleLayout(包含日志信息的级别和信息字符串),TTCCLayout(包含日志产生的时间,线程,类别等信息)
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
#格式化日志信息
#-x x信息输出时左对齐
#%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
#%d 输出日志时间点的日期,如%d{yyyy-MM-dd HH:mm:ss,SSS},输出类似:2002-10-18 22:10:28,921
#%l 输出日志事件的发生位置,包括类目名,发生的线程,以及在代码中的行数,输出类似:TestLog.main(TestLog.java:10)
#%n 输出一个回车换行符,windows中"\r\n",unix中"\n"
#%m 输出代码中指定的消息
#%r 输出自应用启动 至 输出该log信息 所耗费的毫秒数
#%c 输出类的全名
#%t 输出产生该日志事件的线程名
#以下配置输出类似于
#[WARN ] 2017-07-09 21:43:28,765 method:com.zc.zlog.TestLog2.<init>(TestLog2.java:12)
#yes ~~~
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
##############################################################
### 输出到日志文件 ###
#一.输出DEBUG 级别以上的日志到E://logs/log.log中
#名为D的Logger对象的appender为DailyRollingFileAppender类型(每天产生一个日志文件)
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
#名为D的Logger对象的输出文件,也可使用相对路径
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
#输出DEBUG级别及以上的日志,Threshold指定日志消息的输出最低层次
log4j.appender.D.Threshold = DEBUG
#名为D的Logger对象的layout
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
###二.输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
三.程序运行期 动态修改这些日志级别
从api猜 或者 看他的代码 来得出办法。
1.
本地库:G:\MyMavenRepository\log4j\log4j\1.2.16
源码:D:\workspace-e2\log4j-1.2.16-sources
demo:D:\workspace-e2\MyLog4j
doc:G:\MyMavenRepository\log4j\log4j\1.2.16\log4j-1.2.16-javadoc.jar
2.参照javadoc以及源码大致了解每个包的作用,大致锁定最需要关心的几个包,如下
org.apache.log4j:核心包
3.以
PropertyConfigurator.configure("src\\main\\resources\\log4j.properties");
为入口,大致阅读解析配置的过程
|
PropertyConfigurator.doConfigure()中
|
4.获取logger实例的过程
|
5.logger按不同日志级别打日志的大致流程
|
......
子主题 1
|
......
子主题 1
|
6.查看org.apache.log4j包,发信Level类和日志等级直接相关
父类Priority中定义的部分属性
public final static int OFF_INT = Integer.MAX_VALUE;
|
Level类中定义的Level实例属性
|
发现可修改日志等级的toLevel方法
|
然而以上发现并不能解决问题
直到使用logger点出它的所有方法
|
没错,我发现
程序运行期 动态修改这些日志级别
从api猜 或者 看他的代码 来得出办法。
实际上就一行代码!
不管了
|
但是修改不了文件中的日志级别,所以当然不可能这么简单.
7.重新整理思路,我现在需要根据不同的Appender设置不同的日志级别,而且应该能够根据配置文件中不同logger名配置不同的日志级别.
那么去Appender类中看看有没有相关方法吧,没有.但是在其子类AppenderSkeleton中存在
/**
Set the threshold level. All log events with lower level
than the threshold level are ignored by the appender.
<p>In configuration files this option is specified by setting the
value of the <b>Threshold</b> option to a level
string, such as "DEBUG", "INFO" and so on.
@since 0.8.3 */
public
void setThreshold(Priority threshold) {
this.threshold = threshold;
}
}
至于传入的Priority参数,正好可以传入之前已经发现的Level实例.
下一个问题就是如何获取到Appender
联系配置文件中log4j.rootLogger = debug,stdout,D,E和
log4j.appender.stdout = org.apache.log4j.ConsoleAppender等等
rootLogger和appender之间一定存在某种联系.
最终通过rootLogger获取appender,遍历并调用setThreshold()修改即可.
package com.zc.zlog;
import java.util.Enumeration;
import org.apache.log4j.Appender;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.jdbc.JDBCAppender;
public class TestLog3
{
private static Logger logger = Logger.getLogger(TestLog3.class);
public static void main(String[] args)
{
PropertyConfigurator.configure("src\\main\\resources\\log4j.properties");
logger.debug("这是改级别前的debug日志");
logger.info("这是改级别前的info日志");
logger.warn("这是改级别前的warn日志");
logger.error("这是改级别前的error日志");
logger.fatal("这是改级别前的fatal日志");
Logger rootLogger = Logger.getRootLogger();
@SuppressWarnings("rawtypes")
Enumeration allCurrAppenders = rootLogger.getAllAppenders();
while (allCurrAppenders.hasMoreElements())
{
Appender currAppender = (Appender) allCurrAppenders.nextElement();
//可以获取到配置的appender的name,则可以根据不同的name动态修改不同的日志级别
System.out.println(currAppender.getName());
if (currAppender instanceof AppenderSkeleton)
{
((AppenderSkeleton) currAppender).setThreshold(Level.ERROR);
}
else if (currAppender instanceof JDBCAppender)
{
((JDBCAppender) currAppender).setThreshold(Level.ERROR);
}
}
//可修改日志级别,但是修改不了文件中的日志级别
logger.setLevel(Level.ERROR);
logger.debug("这是改级别后的debug日志");
logger.info("这是改级别后的info日志");
logger.warn("这是改级别后的warn日志");
logger.error("这是改级别后的error日志");
logger.fatal("这是改级别后的fatal日志");
}
}
运行后无论是输出到控制台,或者文件的日志级别都都能够得到更改.