• 1. Log4j分享 Log4j知识分享 钟主华 2012-2-24
  • 2. Log4j分享log4j简介 log4j的构成 Logger组件介绍 Appender组件介绍 Layout组件介绍 Log4j使用经验 Log4j的扩展
  • 3. Log4j介绍 1、Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。 2、log4j提供分级方法在程序中嵌入日志记录语句,并且日志信息具有多种输出格式和多个输出级别。
  • 4. log4j的构成log4jLoggersAppendersLayoutsERROR WARN INFO DEBUGConsole File DailyRolling RollingFile WriteHTMLLayout PatternLayout SimpleLayout TTCCLayout
  • 5. Log4j的组件Logger - 在执行应用程序时,接收日志语句生成的日志请求。它是一种重要的日志处理组件, 可以通过 log4j API 的 logger 类对其进行访问。它的方法有:debug、info、warn、error、fatal 和 log。这些方法用于记录消息。还有一种很不常用的trace方法。这个级别比debug的级别还低。 Appender - 管理日志语句的输出结果。执行日志事件时,Logger 对象将接收来自日志事件的记录请求。此请求是通过 logger 发送至 appender 的。然后,Appender 将输出结果写入到用户选择的目的地。对于不同的日志目的地,提供不同的 appender 类型。这些 appender 包括:用于文件的 file appender、用于数据库的 JDBC appender 和用于 SMTP 服务器的 SMTP appender。 Layout - 用于指定 appender 将日志语句写入日志目的地所采用的格式。appender 可以用来格式化输出结果的各种布局包括:简单布局、模式布局和 HTML 布局。
  • 6. Logger组件日志记录器(Logger)是日志处理的核心组件。 log4j具有5种正常级别(Level): static Level DEBUG 指出对调试应用程序是有帮助的细粒度信息事件 static Level INFO 表明消息在粗粒度级别上强调应用程序的运行过程 static Level WARN 表明会出现潜在错误的情形 static Level ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。 static Level FATAL 指出每个严重的错误事件将会导致应用程序的退出。 Log4j所有的日志级别应该是有8个级别分别如下:ALL
  • 7. Logger组件创建一个日志记录器(Logger)的方式有多种: 下面方法可以取到root日志记录器: Logger log = Logger.getRootLogger(); 注释:以.properties类型配置文件为例,这种方式获取的是log4j.rootLogger对应的Logger。 还可以如下创建一个新的日志记录器: Logger log = Logger.getLogger("MyLogger"); 注释:以.xml类型的配置文件为例,这种方式获取的是对应的Logger。 比较常用的做法,就是根据类名实例化一个静态的全局日志记录器: static Logger log = Logger.getLogger(test.class); 注释:这种方式获取的logger会新建一个Logger实例,但是logger实例的日志级别会根据class所在的包逐渐向上查找,如果有针对该class所在包的Logger配置如( log4j.logger.com.test )会继承配置的这个logger的日志级别,如果不存在针对该类所在包的配置Logger,则会继承rootLogger的日志级别
  • 8. Appender组件
  • 9. Appender组件下面列出一些可用的Appender: JDBCAppender,通过jdbc的方式把日志保存在数据库中。 ConsoleAppender, 使用用户指定的布局(layout) 输出日志事件到System.out或者 System.err。默认的目标是System.out。 FileAppender,把日志事件写入一个文件 DailyRollingFileAppender 扩展FileAppender,可以实现多个日志文件,并以用户选定的频率进行循环日志记录 RollingFileAppender 扩展FileAppender,备份容量达到一定大小的日志文件 WriterAppender 根据用户的选择把日志事件写入到Writer或者OutputStream SMTPAppender 当特定的日志事件发生时,一般是指发生错误或者重大错误时,发送一封邮件 SocketAppender 给远程日志服务器(通常是网络套接字节点)发送日志事件(LoggingEvent)对象 注:所有的appender都有一些公有的设置属性如additivity、threshold
  • 10. ConsoleAppender配置如果使用ConsoleAppender,那么log信息将写到Console。效果等同于直接把信息打印到System.out上了。 #指定日志消息的输出类型 log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender #输出到控制台最低层次 log4j.appender.CONSOLE.Threshold=DEBUG #默认情况下是:System.out,指定输出控制台 log4j.appender.CONSOLE.Target=System.out #指定日志消息的输出编码 log4j.appender.CONSOLE.Encoding=GBK #指定日志消息的输出样式 log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout #配置日志消息的输出样式 log4j.appender.CONSOLE.layout.ConversionPattern=%d - %c -%-4r [%t] %-5p %c %x - %m%n
  • 11. FileAppender配置使用FileAppender,那么log信息将写到指定的文件中。相应地,在配置文件中应该指定log输出的文件名。 #指定日志消息的输出类型 log4j.appender.FILE=org.apache.log4j.FileAppender #指定日志消息的输出名输出目录 log4j.appender.FILE.File=C:/log4j/file.log #默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容 log4j.appender.FILE.Append=true #指定日志消息的输出最低层次(此出层次受rootLogger的限制) log4j.appender.FILE.Threshold=DEBUG #指定日志消息的输出编码 log4j.appender.FILE.Encoding=GBK #指定日志消息的输出样式 log4j.appender.FILE.layout=org.apache.log4j.PatternLayout #配置日志消息的输出样式 log4j.appender.FILE.layout.ConversionPattern= %d - %c -%-4r [%t] %-5p %c %x %n method:%l %n- %m%n
  • 12. DailyRollingFileAppender配置使用FileAppender可以将log信息输出到文件中,但是如果文件太大了读起来就不方便了。这时就可以使用DailyRollingAppender。DailyRollingAppender可以把Log信息输出到按照日期来区分的文件中。配置文件就会每天产生一个log文件,每个log文件只记录当天的log信息: #指定日志输出类型 log4j.appender.XXX=org.apache.log4j.DailyRollingFileAppender #指定日志消息的输入文件名称地址 log4j.appender.XXX.File=C:/log4j/logMin #指定日志消息的编码 log4j.appender.XXX.Encoding=GBK #指定日志消息的输出最低层次 log4j.appender.XXX.Threshold=DEBUG #指定日志消息的时间间隔 log4j.appender.XXX.DatePattern='.'yyyy-MM-dd #指定日志消息的样式 log4j.appender.XXX.layout=org.apache.log4j.PatternLayout #配置日志消息的样式 log4j.appender.XXX.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L : %m%nDailyRollingFileAppender输出频率 '.'yyyy-MM,对应monthly(每月) '.'yyyy-ww,对应weekly(每周) '.'yyyy-MM-dd,对应daily(每天) '.'yyyy-MM-dd-a,对应half-daily(每半天) '.'yyyy-MM-dd-HH,对应hourly(每小时) '.'yyyy-MM-dd-HH-mm,对应minutely(每分钟)
  • 13. RollingFileAppender配置 文件大小到达指定尺寸的时候产生一个新的文件。#指定日志输出类型 log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender #指定日志消息的输出最低层次 log4j.appender.ROLLING_FILE.Threshold=DEBUG #指定日志消息的输出文件位置 log4j.appender.ROLLING_FILE.File=C:/log4j/rolling.log #默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容 log4j.appender.ROLLING_FILE.Append=true #指定日志消息的编码 log4j.appender.CONSOLE_FILE.Encoding=GBK # 后缀可以是KB, MB 或者是 GB. 在日志文件到达该大小时自动滚动,即将原来的内容移到 mylog.log.1文件 log4j.appender.ROLLING_FILE.MaxFileSize=10KB #指定可以产生的滚动文件的最大数 log4j.appender.ROLLING_FILE.MaxBackupIndex=1 #指定日志消息的输出最低层次 log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout log4j.appender.ROLLING_FILE.layout.ConversionPattern=%d - %c -%-4r [%t] %-5p %c %x - %m%n
  • 14. SocketAppender配置SocketAppender是给远程日志服务器(通常是网络套接字节点)发送日志事件(LoggingEvent)对象,然后由日志服务器根据日志事件记录日志行为 log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender log4j.appender.SOCKET.RemoteHost=localhost //远程日志服务器地址 log4j.appender.SOCKET.Port=5001 //远程日志服务器的端口 log4j.appender.SOCKET.LocationInfo=true Server端: Server端使用SocketServer类。这个类提供了main函数,直接运行就可以了,不过需要注意参数的使用: 以下是一个运行的例子: java -cp log4j-1.2.16.jar org.apache.log4j.net.SocketServer 4560 /data/log4j/log4jserver.properties /data/log4j/lcf/ 4560是监听的端口,貌似SocketAppender默认也是这个端口。/data/log4j/log4jserver.properties是配置文件的地址,这个可以随便改。/data/log4j/lcf/依然是配置文件的地址,不过是以文件夹的形式。操蛋的是,这个文件夹下面随便写个配置文件它是不会读的!现在只知道generic.lcf会读,其它类似1.lcf之类的文件都会被跳过去。
  • 15. SMTPAppender配置SMTPAppender的主要功能是当日志事件发生之后可以通过邮件的形式给配置好的邮箱发送日志信息,具体配置如下: log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender log4j.appender.MAIL.Threshold=ERROR //日志的错误级别 log4j.appender.MAIL.BufferSize=512 //缓存文件大小,日志达到512K时发送Email log4j.appender.MAIL.SMTPHost=smtp.163.com //发送邮件的服务器 log4j.appender.MAIL.Subject=Log4J ErrorMessage //邮件的标题 log4j.appender.MAIL.SMTPUsername=邮箱用户名 //用户名 log4j.appender.MAIL.SMTPPassword=邮箱密码 log4j.appender.MAIL.From=test@163.com //发件人地址 log4j.appender.MAIL.To=test@163.com //日志邮件的接收者 log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout //日志PatternLayout log4j.appender.MAIL.layout.ConversionPattern=[ErrorMessage] %d - %c -%-4r [%t] %-5p %c %x - %m%n //日志的格式
  • 16. JDBCAppender配置JDBCAppender是通过jdbc的方式,把日志信息插入到配置好的数据库中。具体配置如下: log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test //数据库地址 log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver //数据库驱动 log4j.appender.DATABASE.user=root //数据库用户名 log4j.appender.DATABASE.password= password //数据库密码 log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES (‘[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n’) //插入时执行的sql语句 log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
  • 17. Layout组件结构Layout关系图:
  • 18. Layout组件 Appender必须使用一个与之相关联的Layout,这样它才能知道怎样格式化它的输出。目前,log4j常用有三种类型的Layout: 1. HTMLLayout 格式化日志输出为HTML表格。 2. PatternLayout 根据指定的转换模式格式化日志输出,或者如果没有指定任何转换模式,就使用默认的转换模式。 3. SimpleLayout 以一种非常简单的方式格式化日志输出,它打印级别 Level,然后跟着一个破折号“-“ ,最后是日志消息。
  • 19. Layout参数说明(1)参数说明例子%c 列出logger名字空间的全称,如果加上{<层数>}表示列出从最内层算起的指定层数的名字空间假设当前logger名字空间是“a.b.c”%ca.b.c%c{2}b.c%20c若名字空间长度小于20,则左边用空格填充%-20c若名字空间长度小于20,则右边用空格填充%.30c若名字空间长度超过30,截去多余字符%20.30c若名字空间长度小于20,则左边用空格填充;若名字空间长度超过30,截去多余字符%-20.30c若名字空间长度小于20,则右边用空格填充;若名字空间长度超过30,截去多余字符
  • 20. Layout参数说明(2)参数说明例子%C列出调用logger的类的全名(包含包路径假设当前类是“org.apache.xyz.SomeClass”%Corg.apache.xyz.SomeClass%C{1}SomeClass%d显示日志记录时间,{<日期格式>}使用ISO8601定义的日期格式%d{yyyy/MM/dd HH:mm:ss,SSS}2012/2/24 17:53:30,117%d{ABSOLUTE}22:23:30,117%d{DATE}12 Oct 2012 22:23:30,117%d{ISO8601}2005-10-12 22:23:30,117%F显示调用logger的源文件名%FMyClass.java%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数%lMyClass.main(MyClass.java:129)%L 显示调用logger的代码行%L129
  • 21. Layout参数说明(3)参数说明例子%m 显示输出消息%mThis is a message for debug%M显示调用logger的方法名%Mmain%n当前平台下的换行符%nWindows平台下表示rn UNIX平台下表示n%p 显示该条日志的优先级%pINFO%r显示从程序启动时到记录该条日志时已经经过的毫秒数%r1215%t输出产生该日志事件的线程名%tMyClass%x 按NDC(Nested Diagnostic Context,线程堆栈)顺序输出日志%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的客户端的日志%%显示一个百分号%%%
  • 22. Layout参数说明(4)org.apache.log4j.NDC。NDC是Nested Diagnostic Context的简写,意为嵌套诊断环境,使用时提供一个堆栈对象来保存信息。堆栈的特点是数据后进先出、先进后出,即清理堆栈时,后保存的数据会被先清掉,而先保存的数据则被后清掉。示例代码: PatternLayout layout = new PatternLayout(“%m %x”); ConsoleAppender appender = new ConsoleAppender(layout); Logger log = Logger.getLogger(Test.class); log.addAppender(appender);      String tmp = “zhongzh”; //模拟从客户端获取的信息 log.debug(“Start”); NDC.push(tmp); //添加信息到堆栈中 log.debug(“Before”); NDC.pop(); //将信息从堆栈中移除 log.debug(“After”); NDC.remove(); //将当前线程移除,退出NDC环境 log.debug(“End”); 这里使用了PatternLayout来格式化信息,其模式字符%x就是用来输出NDC信息的。程序运行后会输出如下内容: Start Before zhongzh After End 注:NDC实现机制是基于线程实例为key的hashtable
  • 23. Layout参数说明(5)org.apache.log4j.MDC。MDC是Mapped Diagnostic Context的简写,意为映射诊断环境,提供了一个Map对象来保存信息。Map对象使用Key、Value的形式保存值。 示例代码: PatternLayout layout = new PatternLayout(“%m %X{name} %X{ip}”); ConsoleAppender appender = new ConsoleAppender(layout); Logger log = Logger.getLogger(Test.class); log.addAppender(appender);      log.debug(“Start”); //添加信息到Map中 MDC.put(“name”, “zhongzh”); MDC.put(“ip”, “192.168.1.1”); log.debug("Test1"); 程序运行后输出内容: Test1 zhongzh 192.168.1.1      //添加信息到Map中,若Key重复,则覆盖之前的值 注:MDC是通过InheritableThreadLocal实现的多线程并发     
  • 24. Log4j启动方式 从LogManager的static{}代码块开始执行。首先在classPath范围内查找log4j.xml文件,如果不存在log4j.xml文件会接着查找log4j.properties文件(xml类型的配置文件优先于properties类型的配置文件)。然后根据配置文件的格式选择PropertyConfigurator或DOMConfigurator对配置信息进行加载。当然如果以上两种类型的配置文件同时不存在,那么可以使用PropertyConfigurator或DOMConfigurator类以动态的方式设置log4j。例如: 配置参数:   Properties pro=new Properties();  pro.put("log4j.rootLogger", "info,A");  pro.put("log4j.appender.A", "org.apache.log4j.DailyRollingFileAppender");  pro.put("log4j.appender.A.File", "D:/logs/sys.log");  pro.put("log4j.appender.A.DatePattern", "'.'yyyy-MM-dd-HH");  pro.put("log4j.appender.A.layout", "org.apache.log4j.PatternLayout");  pro.put("log4j.appender.A.layout.ConversionPattern", "%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m -(:%L)%n");   使配置生效 PropertyConfigurator.configure(pro);
  • 25. Log4j中过滤器的使用(1)在我们日常的log4j使用中我们一般是将不同级别的日志统一打印到日志文件中,这样容易造成日志的混乱,不便于我们观察日志。其实我们可以使用log4j提供的过滤器来对不同级别的日志进行区分,把不同级别的日志分别打印到不同的文件中。例如:
  • 26. Log4j过滤器的使用(2)上文中提到的是通过xml形式的文件配置过滤器,下面我们来看一看通过.properties文件配置的方式: log4j.appender.test1.filter.two=org.apache.log4j.varia.LevelMatchFilter log4j.appender.test1.filter.two.levelToMatch= levelToMatch log4j.appender.test1.filter.two.acceptOnMatch=false log4j.appender.test1.filter.two=org.apache.log4j.varia.LevelRangeFilter log4j.appender.test1.filter.two.levelMin=WARN log4j.appender.test1.filter.two.levelMax=WARN
  • 27. AOP+Log4j有的时候我们的业务逻辑需要统一记录访问日志的时候我们可以采用spring aop + log4j的形式统一为接口添加日志。例如:  
  • 28. Log4j设置注意事项1、在J2EE开发的环境下,我们希望默认的配置文件尽量都统一放在WEB-INF下。这时我们需要改变SPRING和LOG4J的配置文件位置。在配置web.xml的时候,一定要把加载log4j配置文件路径的类设置在前,spring的设置在后。因为spring启动的时候需要使用到log4j,这样spring初始化信息才能通过log4j输出。 2、 Log4j下的appender嵌套,在所有的appdender中只有AsyncAppender才具有appender嵌套功能,并且如果要使用异步的方式打印日志就必须使用AsyncAppender,但是AsyncAppender只允许在xml格式的配置文件中才能使用。 3、为了提高log4j的性能,我们设置配置文件的时候应该注意:在.properties文件中应该通过设置log4j.additivity.logName=false,在.xml文件中应该设置禁止去递归查找父类Logger来接收日志事件。
  • 29. Log4j使用经验在使用logger.debug(“message”),打印日志的时候,如果message信息是通过String的字符串相加组成如:String message = “test” + “some message”+ object.toString () + …… 那么在进行字符串相加之前有必要进行if(logger.isDebugEnabled())判断,如果当前日志级别允许Level.DEBUG才进行输出字符串的加法操作,否则不进行处理。同理在使用logger.info(“message”)的时候应该也一样需要进行判断。
  • 30. 什么是Perf4jPerf4j是一个用于计算和显示性能相关的统计信息(例如最大值、最小值、算数平均均值、标准方差和TPS等)的工具集。除了将统计信息输出到标准错误流或者日志中之外,Perf4j也支持输出为图表(使用Google Chart API),以及通过JMX公开。其主要的功能如下: 1、以StopWatch这种简洁的方式进行计时。 2、提供了一个命令行工具,用于分析日志以及生成统计信息或图表。 3、易于集成到大部分已有的日志工具中,例如log4j, java.util.logging, Apache Commons Logging and SLF4J。 4、提供了定制的log4j appenders用于实时地生成统计信息。 5、支持以JMX的方式公开统计信息,在特定的统计信息超过指定阀值时可以发送通知。 6、提供了一个servlet,用于在web应用中以图表的形式显示统计信息。 7、支持以AOP的方式进行计时。
  • 31. Perf4j——StopWatchorg.perf4j.LoggingStopWatch类用于在代码中添加计时语句并打印到标准输出或者日志文件中: StopWatch stopWatch = new LoggingStopWatch(); //... execute code here to be timed stopWatch.stop("example1", "custom message text"); 对stop()方法的调用记录了执行时间并打印日志信息。默认情况下,基类LoggingStopWatch将输出打印到System.err流中。但是大多数情况下,你需要使用一个集成到现有Java日志框架(如Log4JStopWatch、CommonsLogStopWatch或者Slf4JStopWatch)的子类。下面是一些stop watch的输出示例: start[1233364397765] time[499] tag[example1] message[custom message text] start[1233364398264] time[556] tag[example1] message[custom message text] start[1233364398820] time[698] tag[example1] message[custom message text]
  • 32. Log4j和perf4j整合Perf4J的扩展功能大部分通过一套定制的log4j appender提供。这样开发人员就能在部署阶段通过非常熟悉的日志框架来零零散散的添加分析和监控功能。例如:
  • 33. Perf4j其他应用Per4j一个重要的功能是允许Perf4J作为JMX MBeans的属性展示性能数据,同时在性能低于可接受的阈值时发送JMX通知。当然除了JMX插件,Perf4J也支持生成性能图表的画图appender,使用前端的Perf4J画图Servlet等。
  • 34. 完毕 谢 谢!