最近在项目开发管理过程中,我发现了很多测试打印信息,并且在源码中还搜索不到打印信息的地方,无法删除。平时在项目开发中,也跟项目组成员说明过打印的测试信息在功能开发完成后,需要删除打印信息,但是收效甚微,所以想通过普及强制使用Log4j进来改善当前的状况。
什么是Log4j
Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。(摘自百度百科)
Log4j的组成
Log4j由三个重要的组成构成:日志记录器(Loggers),输出端(Appenders)和日志格式化器(Layout)。
日志记录器Loggers
控制要启用或禁用哪些日志记录语句,并对日志信息进行级别限制
Logger对象的获得或创建
对象创建有2种方式
Logger logger = Logger.getLogger(LogTest.class);
Logger logger = Logger.getRootLogger();
一般使用第一种方式
日志级别
每个Logger都被设定了一个日志级别(log level),用来控制日志信息的输出。日志级别从高到低分为:
A:off 最高等级,用于关闭所有日志记录。
B:fatal 指出每个严重的错误事件将会导致应用程序的退出。
C:error 指出虽然发生错误事件,但仍然不影响系统的继续运行。
D:warm 表明会出现潜在的错误情形。
E:info 一般和在粗粒度级别上,强调应用程序的运行全程。
F:debug 一般用于细粒度级别上,对调试应用程序非常有帮助。
G:all 最低等级,用于打开所有日志记录。
上面这些级别是定义在org.apache.log4j.Level类中,Log4j只建议使用4个级别,优先级从高到低分别是:
1.error
2.warn
3.info
4.debug
通过使用日志级别,可以控制应用程序中相应级别日志信息的输出。例如,如果使用了info级别,则应用程序中所有低于info级别的日志信息(如debug)将不会被打印出来。
package com.wz.demo; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Level; import org.apache.log4j.Logger; public class LogTest { public static void main(String[] args) { // Logger logger = Logger.getLogger(LogTest.class); Logger logger = Logger.getRootLogger(); // 使用默认的配置信息,不需要写log4j.properties BasicConfigurator.configure(); // 设置日志输出级别为info,这将覆盖配置文件中设置的级别 logger.setLevel(Level.INFO); // 下面的消息将被输出 logger.debug("this is an debug"); logger.info("this is an info"); logger.warn("this is a warn"); logger.error("this is an error"); logger.fatal("this is a fatal"); } }
打印结果如下:
1 [main] INFO root - this is an info 2 [main] WARN root - this is a warn 2 [main] ERROR root - this is an error 2 [main] FATAL root - this is a fatal
输出端Appenders
Appender用来指定日志信息输出到哪个地方,可以同时指定多个输出目的地。Log4j允许将信息输出到许多不同的输出设备中,一个log信息输出目的地就叫做一个Appender。
每个Logger都可以拥有一个或多个Appender,每个Appender表示一个日志的输出目的地。可以使用Logger.addAppender(Appender app)为Logger增加一个Appender,也可以使用Logger.removeAppender(Appender app)为Logger删除一个Appender。
以下为Log4j几种常用的输出目的地。
a:org.apache.log4j.ConsoleAppender:将日志信息输出到控制台。
b:org.apache.log4j.FileAppender:将日志信息输出到一个文件。
c:org.apache.log4j.DailyRollingFileAppender:将日志信息输出到一个日志文件,并且每天输出到一个新的日志文件。
d:org.apache.log4j.RollingFileAppender:将日志信息输出到一个日志文件,并且指定文件的尺寸,当文件大小达到指定尺寸时,会自动把文件改名,同时产生一个新的文件。
e:org.apache.log4j.WriteAppender:将日志信息以流格式发送到任意指定地方。
f:org.apache.log4j.jdbc.JDBCAppender:通过JDBC把日志信息输出到数据库中。
package com.wz.demo; import java.io.IOException; import org.apache.log4j.FileAppender; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.SimpleLayout; public class LogTest { public static void main(String[] args) { Logger logger = Logger.getLogger(LogTest.class); try { logger.addAppender(new FileAppender(new SimpleLayout(), "E://out.txt", false)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }// 添加输出端 logger.setLevel((Level) Level.DEBUG);// 覆盖配置文件中的级别 logger.debug("debug"); logger.info("info"); logger.warn("warn"); logger.error("error"); logger.fatal("fatal"); } }
上述代码是把打印的日志信息输出到E盘out.txt文件中。
日志格式化器Layout
控制日志信息的显示格式
HTMLLayout
格式化日志输出为HTML表格形式
package com.wz.demo; import java.io.IOException; import org.apache.log4j.FileAppender; import org.apache.log4j.HTMLLayout; import org.apache.log4j.Level; import org.apache.log4j.Logger; public class LogTest { public static void main(String[] args) { Logger logger = Logger.getLogger(LogTest.class); try { logger.addAppender(new FileAppender(new HTMLLayout(), "out.html", false)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }// 添加输出端 logger.setLevel((Level) Level.DEBUG);// 覆盖配置文件中的级别 logger.debug("debug"); logger.info("info"); logger.warn("warn"); logger.error("error"); logger.fatal("fatal"); } }
SimpleLayout
以一种非常简单的方式格式化日志输出,它打印三项内容:级别-信息
package com.wz.demo; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.SimpleLayout; public class LogTest { public static void main(String[] args) { Logger logger = Logger.getLogger(LogTest.class); logger.addAppender(new ConsoleAppender(new SimpleLayout())); logger.setLevel((Level) Level.DEBUG);// 覆盖配置文件中的级别 logger.debug("debug"); logger.info("info"); logger.warn("warn"); logger.error("error"); logger.fatal("fatal"); } }
输出如下:
DEBUG - debug INFO - info WARN - warn ERROR - error FATAL - fatal
PatternLayout
根据指定的转换模式格式化日志输出,或者如果没有指定任何转换模式,就使用默认的转化模式格式,跟SimpleLayout输出一致。
package com.wz.demo; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; public class LogTest { public static void main(String[] args) { Logger logger = Logger.getLogger(LogTest.class); logger.addAppender(new ConsoleAppender(new PatternLayout("%d [%t] %-5p %-40.40c %X{traceId}-%m%n"))); logger.setLevel((Level) Level.DEBUG);// 覆盖配置文件中的级别 logger.debug("debug"); logger.info("info"); logger.warn("warn"); logger.error("error"); logger.fatal("fatal"); } }
输出如下:
2018-06-08 10:03:12,118 [main] DEBUG com.wz.demo.LogTest -debug 2018-06-08 10:03:12,121 [main] INFO com.wz.demo.LogTest -info 2018-06-08 10:03:12,121 [main] WARN com.wz.demo.LogTest -warn 2018-06-08 10:03:12,121 [main] ERROR com.wz.demo.LogTest -error 2018-06-08 10:03:12,122 [main] FATAL com.wz.demo.LogTest -fatal
TTCCLayout
包含日志产生的时间、线程、类别等等信息
package com.wz.demo; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.TTCCLayout; public class LogTest { public static void main(String[] args) { Logger logger = Logger.getLogger(LogTest.class); logger.addAppender(new ConsoleAppender(new TTCCLayout())); logger.setLevel((Level) Level.DEBUG);// 覆盖配置文件中的级别 logger.debug("debug"); logger.info("info"); logger.warn("warn"); logger.error("error"); logger.fatal("fatal"); } }
输出如下:
2 [main] DEBUG com.wz.demo.LogTest - debug 3 [main] INFO com.wz.demo.LogTest - info 3 [main] WARN com.wz.demo.LogTest - warn 3 [main] ERROR com.wz.demo.LogTest - error 3 [main] FATAL com.wz.demo.LogTest - fatal