Java 一些记录日志系统
2016-11-05 14:56
169 查看
在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息。
在Java世界中,有很多的日志工具库来实现日志功能,避免我们重复造轮子,下面我们就来逐一了解日志工具。
1. 最常用的 在本地测试用的 System.out.println();
这种方式使用起来非常简单,但是缺点却是非常多的:
- 输出内容不可控
- 可读性差
- 大量的IO操作使程序变慢
从JDK1.4开始,JDK自带了一套日至系统,其最大的优点是不需要任何其他类库的支持,只要有JDK就可以运行,但是其易用性、功能和扩展性很差,因此在商业上很少使用。
JDK Logging把日志分为9个级别,分别为:ALL、FINEST、FINER、FINE、CONFIG、INFO、WARNING、SERVER、OFF,等级依次升高,较高等级屏蔽较低等级。
其中的Logger是:java.util.logging.Logger
1. 对于JDK自带的Logging,会有一个对应的配置文件
创建一个LogManager
默认是java.util.logging.LogManager,但是也可以自定义,修改系统属性"java.util.logging.manager"即可,源码如下(manager就是LogManager):
加载配置文件
默认是jre目录下的lib/logging.properties文件,也可以自定义修改系统属性"java.util.logging.config.file”,源码如下:
创建Logger,并缓存起来,放置到一个Hashtable中,并把LogManager设置进新创建的logger中
Log4j是目前应用最广泛的日志控件,它把日志分为ALL、TRACE、DEBUG、INFO、WARNING、ERROR、FITAL、OFF等几个等级,等级依次升高,依然是高等级屏蔽低等级。使用Log4j需要下载相应的jar包。
log4j
maven依赖如下:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
使用方式:
第一步:编写log4j.properties配置文件,放到类路径下
log4j.rootLogger = debug, console
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} %m%n
第二步:代码中如下使用
public class Log4jTest {
private static final Logger logger=Logger.getLogger(Log4jTest.class);
public static void main(String[] args){
if(logger.isTraceEnabled()){
logger.debug("log4j trace message");
}
if(logger.isDebugEnabled()){
logger.debug("log4j debug message");
}
if(logger.isInfoEnabled()){
logger.debug("log4j info message");
}
}
}
补充:
1 上述方式默认到类路径下加载log4j.properties配置文件,如果log4j.properties配置文件不在类路径下,则可以选择如下方式之一来加载配置文件
使用classLoader来加载资源PropertyConfigurator.configure(Log4jTest.class.getClassLoader().getResource(“properties/log4j.properties”));
使用log4j自带的Loader来加载资源PropertyConfigurator.configure(Loader.getResource(“properties/log4j.properties”));
第一种情况:没有指定配置文件路径
1 第一步: 引发LogManager的类初始化
Logger.getLogger(Log4jTest.class)的源码如下:
2 第二步:初始化一个logger仓库Hierarchy
Hierarchy的源码如下:
LoggerFactory defaultFactory: 就是创建Logger的工厂
Hashtable ht:用来存放上述工厂创建的Logger
Logger root:作为根Logger
LogManager在类初始化的时候如下方式来实例化Hierarchy:
new RootLogger作为root logger,默认是debug级别
最后把Hierarchy绑定到LogManager上,可以在任何地方来获取这个logger仓库Hierarchy
3 第三步:在LogManager的类初始化的过程中默认寻找类路径下的配置文件
通过org.apache.log4j.helpers.Loader类来加载类路径下的配置文件:
优先选择xml配置文件
4 第四步:解析上述配置文件
如果是xml文件则org.apache.log4j.xml.DOMConfigurator类来解析
如果是properties文件,则使用org.apache.log4j.PropertyConfigurator来解析
不再详细说明解析过程,看下解析后的结果:
设置RootLogger的级别
对RootLogger添加一系列我们配置的appender(我们通过logger来输出日志,通过logger中的appender指明了日志的输出目的地)
5 第五步:当一切都准备妥当后,就该获取Logger了
使用logger仓库Hierarchy中内置的LoggerFactory工厂来创建Logger了,并缓存起来,同时将logger仓库Hierarchy设置进新创建的Logger中
第二种情况,手动来加载不在类路径下的配置文件
PropertyConfigurator.configure 执行时会去进行上述的配置文件解析,源码如下:
仍然先会引发LogManager的类加载,创建出logger仓库Hierarchy,同时尝试加载类路径下的配置文件,此时没有则不进行解析,此时logger仓库Hierarchy中的RootLogger默认采用debug级别,没有appender而已。
然后解析配置文件,对上述logger仓库Hierarchy的RootLogger进行级别的设置,添加appender
此时再去调用Logger.getLogger,不会导致LogManager的类初始化(因为已经加载过了)
第三种情况,配置文件在类路径下,而我们又手动使用PropertyConfigurator去加载
也就会造成2次加载解析配置文件,仅仅会造成覆盖而已(对于RootLogger进行从新设置级别,删除原有的appender,重新加载新的appender),所以多次加载解析配置文件以最后一次为准。
LogManager: 它的类加载会创建logger仓库Hierarchy,并尝试寻找类路径下的配置文件,如果有则解析
Hierarchy : 包含三个重要属性:
LoggerFactory logger的创建工厂
Hashtable 用于存放上述工厂创建的logger
Logger root logger,用于承载解析文件的结果,设置级别,同时存放appender
PropertyConfigurator: 用于解析log4j.properties文件
Logger : 我们用来输出日志的对象
在Java世界中,有很多的日志工具库来实现日志功能,避免我们重复造轮子,下面我们就来逐一了解日志工具。
1. 最常用的 在本地测试用的 System.out.println();
这种方式使用起来非常简单,但是缺点却是非常多的:
- 输出内容不可控
- 可读性差
- 大量的IO操作使程序变慢
public class TestLogger { public static boolean debug = false; public static void main(String[] args) { for (int count = 0; count < 4; count++) { if (count % 2 == 0) debug = true; else debug = false; if (debug) System.out.println("系统消息: 第 " + count + "次打印。"); } } }
2. JDK的Logging
从JDK1.4开始,JDK自带了一套日至系统,其最大的优点是不需要任何其他类库的支持,只要有JDK就可以运行,但是其易用性、功能和扩展性很差,因此在商业上很少使用。 JDK Logging把日志分为9个级别,分别为:ALL、FINEST、FINER、FINE、CONFIG、INFO、WARNING、SERVER、OFF,等级依次升高,较高等级屏蔽较低等级。
public class TestJDKLogger { public static final Logger logger = Logger.getLogger(TestJDKLogger.class.toString()); public static void main(String[] args) { logger.info("jdk loggin info : a msg."); } }
其中的Logger是:java.util.logging.Logger
1. 对于JDK自带的Logging,会有一个对应的配置文件
logging.properties,位置在
$JAVA_HOME/jre/lib/logging.properties,我们首先看一个原始的配置文件。可以看到里面设置了默认的等级为
INFO,因此
INFO等级以下的信息就不会输出,要想输出其他等级的信息需要修改这里的level信息。
创建一个LogManager
默认是java.util.logging.LogManager,但是也可以自定义,修改系统属性"java.util.logging.manager"即可,源码如下(manager就是LogManager):
try { cname = System.getProperty("java.util.logging.manager"); if (cname != null) { try { Class clz = ClassLoader.getSystemClassLoader().loadClass(cname); manager = (LogManager) clz.newInstance(); } catch (ClassNotFoundException ex) { Class clz = Thread.currentThread().getContextClassLoader().loadClass(cname); manager = (LogManager) clz.newInstance(); } } } catch (Exception ex) { System.err.println("Could not load Logmanager \"" + cname + "\""); ex.printStackTrace(); } if (manager == null) { manager = new LogManager(); }
加载配置文件
默认是jre目录下的lib/logging.properties文件,也可以自定义修改系统属性"java.util.logging.config.file”,源码如下:
String fname = System.getProperty("java.util.logging.config.file"); if (fname == null) { fname = System.getProperty("java.home"); if (fname == null) { throw new Error("Can't find java.home ??"); } File f = new File(fname, "lib"); f = new File(f, "logging.properties"); fname = f.getCanonicalPath(); } InputStream in = new FileInputStream(fname); BufferedInputStream bin = new BufferedInputStream(in); try { readConfiguration(bin); } finally { if (in != null) { in.close(); } }
创建Logger,并缓存起来,放置到一个Hashtable中,并把LogManager设置进新创建的logger中
3. Log4j
Log4j是目前应用最广泛的日志控件,它把日志分为ALL、TRACE、DEBUG、INFO、WARNING、ERROR、FITAL、OFF等几个等级,等级依次升高,依然是高等级屏蔽低等级。使用Log4j需要下载相应的jar包。log4j
maven依赖如下:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
使用方式:
第一步:编写log4j.properties配置文件,放到类路径下
log4j.rootLogger = debug, console
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} %m%n
第二步:代码中如下使用
public class Log4jTest {
private static final Logger logger=Logger.getLogger(Log4jTest.class);
public static void main(String[] args){
if(logger.isTraceEnabled()){
logger.debug("log4j trace message");
}
if(logger.isDebugEnabled()){
logger.debug("log4j debug message");
}
if(logger.isInfoEnabled()){
logger.debug("log4j info message");
}
}
}
补充:
1 上述方式默认到类路径下加载log4j.properties配置文件,如果log4j.properties配置文件不在类路径下,则可以选择如下方式之一来加载配置文件
使用classLoader来加载资源PropertyConfigurator.configure(Log4jTest.class.getClassLoader().getResource(“properties/log4j.properties”));
使用log4j自带的Loader来加载资源PropertyConfigurator.configure(Loader.getResource(“properties/log4j.properties”));
第一种情况:没有指定配置文件路径
1 第一步: 引发LogManager的类初始化
Logger.getLogger(Log4jTest.class)的源码如下:
static public Logger getLogger(Class clazz) { return LogManager.getLogger(clazz.getName()); }
2 第二步:初始化一个logger仓库Hierarchy
Hierarchy的源码如下:
public class Hierarchy implements LoggerRepository, RendererSupport, ThrowableRendererSupport { private LoggerFactory defaultFactory; Hashtable ht; Logger root; //其他略 }
LoggerFactory defaultFactory: 就是创建Logger的工厂
Hashtable ht:用来存放上述工厂创建的Logger
Logger root:作为根Logger
LogManager在类初始化的时候如下方式来实例化Hierarchy:
static { Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG)); //略 }
new RootLogger作为root logger,默认是debug级别
最后把Hierarchy绑定到LogManager上,可以在任何地方来获取这个logger仓库Hierarchy
3 第三步:在LogManager的类初始化的过程中默认寻找类路径下的配置文件
通过org.apache.log4j.helpers.Loader类来加载类路径下的配置文件:
Loader.getResource("log4j.xml"); Loader.getResource("log4j.properties")
优先选择xml配置文件
4 第四步:解析上述配置文件
如果是xml文件则org.apache.log4j.xml.DOMConfigurator类来解析
如果是properties文件,则使用org.apache.log4j.PropertyConfigurator来解析
不再详细说明解析过程,看下解析后的结果:
设置RootLogger的级别
对RootLogger添加一系列我们配置的appender(我们通过logger来输出日志,通过logger中的appender指明了日志的输出目的地)
5 第五步:当一切都准备妥当后,就该获取Logger了
使用logger仓库Hierarchy中内置的LoggerFactory工厂来创建Logger了,并缓存起来,同时将logger仓库Hierarchy设置进新创建的Logger中
第二种情况,手动来加载不在类路径下的配置文件
PropertyConfigurator.configure 执行时会去进行上述的配置文件解析,源码如下:
public static void configure(java.net.URL configURL) { new PropertyConfigurator().doConfigure(configURL, LogManager.getLoggerRepository()); }
仍然先会引发LogManager的类加载,创建出logger仓库Hierarchy,同时尝试加载类路径下的配置文件,此时没有则不进行解析,此时logger仓库Hierarchy中的RootLogger默认采用debug级别,没有appender而已。
然后解析配置文件,对上述logger仓库Hierarchy的RootLogger进行级别的设置,添加appender
此时再去调用Logger.getLogger,不会导致LogManager的类初始化(因为已经加载过了)
第三种情况,配置文件在类路径下,而我们又手动使用PropertyConfigurator去加载
也就会造成2次加载解析配置文件,仅仅会造成覆盖而已(对于RootLogger进行从新设置级别,删除原有的appender,重新加载新的appender),所以多次加载解析配置文件以最后一次为准。
3.3 主要对象总结
LogManager: 它的类加载会创建logger仓库Hierarchy,并尝试寻找类路径下的配置文件,如果有则解析Hierarchy : 包含三个重要属性:
LoggerFactory logger的创建工厂
Hashtable 用于存放上述工厂创建的logger
Logger root logger,用于承载解析文件的结果,设置级别,同时存放appender
PropertyConfigurator: 用于解析log4j.properties文件
Logger : 我们用来输出日志的对象
相关文章推荐
- 两步实现Log4j记录java控制台输出的系统所有异常信息和自定义记录日志---->非常实用,强烈推荐阅读
- Java项目中使用log记录日志的一些总结
- 请教.Net平台大型业务系统中“日志记录” 的较好解决办法,类似Java下用AOP方式实现的最好
- Java自定义注解 和 springMVC拦截器 配合使用记录系统操作日志的案例
- java多线程模拟有会话的访问web系统,并记录访问日志
- Java项目中使用log记录日志的一些总结
- Java项目中使用log记录日志的一些细节
- 在Java中处理日志记录-Java基础-Java-编程开发
- 做物流系统(Struts)时的一些记录
- java程序获得windows系统的一些参数(cmd指令运行返回结果)
- JAVA日志记录,LOG4J
- 一个比较好用的日志记录系统
- 使用Log4j记录系统日志(转载)
- java 在文件中记录异常日志
- 系统架构设计之:异步日志记录篇
- 关于fedora10、ORACLE11、JAVA的一些记录
- 如何使用Dude管理器记录系统日志
- 系统架构设计之--异步日志记录篇
- 在PB中记录系统出错日志