日志记录---log4j详解

时间:2024-01-10 18:38:26

Apache官方项目地址

通常的日志记录的缺点是会减慢程序的运行速度,如果用普通的System.out的话影响视觉效果,另外解耦度也不好,而log4j的设计则使得日志记录变得可靠快速和可拓展性好。

log4j是用文件来配置的,学习曲线低。

Log4j有三个组件: loggers(日志写出器,供程序员输出日志信息)appenders(日志输出地) layouts(展现方式)。这三个组件是一块工作的,使开发者通过日志类型和日志等级记录日志,同时使得这些日志格式化。

log4j类图

日志记录---log4j详解

  • Logger - 日志写出器,供程序员输出日志信息
  • Appender - 日志目的地,把格式化好的日志信息输出到指定的地方去
  • ConsoleAppender - 目的地为控制台的
  • AppenderFileAppender - 目的地为文件的
  • AppenderRollingFileAppender - 目的地为大小受限的文件的Appender
  • Layout - 日志格式化器,用来把程序员的logging request格式化成字符串
  • PatternLayout - 用指定的pattern格式化logging request的Layout
日志结构

java是java.util的父亲,是java.util.vector的祖先

root logger一般在log树的顶端,一般是不存在的,也不能通过名字来获取,但是可以调用 static Logger.getRootLogger来获取,通过调用public static Logger Logger.getLogger(String name)或者public static Logger Logger.getLogger(Class clazz)获得(或者创建)一个named logger。后者相当于调用Logger.getLogger(clazz.getName())。在某对象中,用该对象所属的类为参数,调用Logger.getLogger(Class clazz)以获得logger被认为是目前所知的最理智的命名logger的方法。

package org.apache.log4j;

  public class Logger {

    // Creation & retrieval methods:
public static Logger getRootLogger();
public static Logger getLogger(String name); // printing methods:
public void trace(Object message);
public void debug(Object message);
public void info(Object message);
public void warn(Object message);
public void error(Object message);
public void fatal(Object message); // generic printing method:
public void log(Level l, Object message);
}

level预定义了5个等级DEBUG,INFO,WARN,ERROR和FATAL

日志级别为:ALL<DEBUG<INFO<WARN<ERROR<FATAL<OFF。定义在org.apache.log4j.Level这个类中,如果一个给定的loger没有指定等级,会继承最近的一个祖先然后得到一个等级。

为了确保所有的logger可以继承一个等级,root logger一定有一个分配好的等级,如果一个logger没有设置最低等级,会继承直接父logger的最低等级。如果所有的logger都分配好了等级,那么就不需要等级继承了。

每条输出到logger的日志请求(logging request)也都有一个level,如果该request的level大于等于该logger的level,则该request将被处理(称为enabled);否则该request将被忽略。故可得知:

  • logger的level越低,表示该logger越详细
  • logging request的level越高,表示该logging request越优先输出
Appenders 和 Layouts

一个输出的目的地叫appender,当前而已,appender 主要存在于console, file等。一个logger里面可以添加多个appender。

对于Appender的继承:一个Logger除了配置给它的Appender之外,它会继承它所有父Logger的Appender,除非它的Additivity属性设为false。看表

Logger
Name
Added
Appenders
Additivity
Flag
Output Targets Comment
root A1 not applicable A1 The root logger is anonymous but can be accessed with the Logger.getRootLogger() method. There is no default appender attached to root.
x A-x1, A-x2 true A1, A-x1, A-x2 Appenders of "x" and root.
x.y none true A1, A-x1, A-x2 Appenders of "x" and root.
x.y.z A-xyz1 true A1, A-x1, A-x2, A-xyz1 Appenders in "x.y.z", "x" and root.
security A-sec false A-sec No appender accumulation since the additivity flag is set to false.
security.access none true A-sec Only appenders of "security" because the additivity flag in "security" is set to false.

ConsoleAppender可以使用ConsoleAppender对象把日志输出到控制台。

// Log4j APIs : class ConsoleAppender extends WriterAppender

// 构造方法,使用一个Layout对象构造一个ConsoleAppender对象
// 默认情况下,ConsoleAppender的target是System.out
public ConsoleAppender(Layout layout); // 构造方法,使用一个Layout对象和一个target字符串构造ConsoleAppender对象
// target的可能取值为ConsoleAppender.SYSTEM_OUT和ConsoleAppender.SYSTEM_ERR
public ConsoleAppender(Layout layout, String target);

  

FileAppender可以使用FileAppender对象把日志输出到一个指定的日志文件中去。

/ Log4j APIs : class FileAppender extends WriterAppender

// 构造方法,使用一个Layout对象和日志文件名构造一个FileAppender对象
public FileAppender(Layout layout, String filename)
throws IOException;
public FileAppender(Layout layout, String filename, boolean append)
throws IOException;

RollingFileAppender可以使用FileAppender的子类RollingFileAppender对象,把日志输出到一个指定的日志文件中。不同的是该日志文件的大 小受到限制,当日志内容超出最大的尺寸时,该文件将向上滚动(最老的日志被擦除)。还可以在该类对象中指定为日志文件做多少个备份。

// Log4j APIs : class RollingFileAppender extends FileAppender

// 构造方法,使用一个Layout对象和日志文件名构造一个RollingFileAppender对象
public RollingFileAppender(Layout layout, String filename)
throws IOException;
public RollingFileAppender(Layout layout, String filename, boolean append)
throws IOException; // 获得和设置日志备份文件的个数
public int getMaxBackupIndex();
public void setMaxBackupIndex(int index); // 获得和设置滚动日志文件的最大尺寸
public long getMaximumFileSize();
public void setMaximumFileSize(long size);

  

  


org.apache.log4j.PatternLayout主要是设置输出的格式。设置详细地址为:http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html

参数 说明 例子
%c 列出logger名字空间的全称,如果加上{<层数>}表示列出从最内层算起的指定层数的名字空间 log4j配置文件参数举例 输出显示媒介
假设当前logger名字空间是"a.b.c"
%c a.b.c
%c{2} b.c
%20c (若名字空间长度小于20,则左边用空格填充)
%-20c (若名字空间长度小于20,则右边用空格填充)
%.30c (若名字空间长度超过30,截去多余字符)
%20.30c (若名字空间长度小于20,则左边用空格填充;若名字空间长度超过30,截去多余字符)
%-20.30c (若名字空间长度小于20,则右边用空格填充;若名字空间长度超过30,截去多余字符)
%C 列出调用logger的类的全名(包含包路径) 假设当前类是"org.apache.xyz.SomeClass"
%C org.apache.xyz.SomeClass
%C{1} SomeClass
%d 显示日志记录时间,{<日期格式>}使用ISO8601定义的日期格式 %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
%F 显示调用logger的源文件名 %F MyClass.java
%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数 %l MyClass.main(MyClass.java:129)
%L 显示调用logger的代码行 %L 129
%m 显示输出消息 %m This is a message for debug.
%M 显示调用logger的方法名 %M main
%n 当前平台下的换行符 %n Windows平台下表示rn
UNIX平台下表示n
%p 显示该条日志的优先级 %p INFO
%r 显示从程序启动时到记录该条日志时已经经过的毫秒数 %r 1215
%t 输出产生该日志事件的线程名 %t MyClass
%x 按NDC(Nested Diagnostic Context,线程堆栈)顺序输出日志 假设某程序调用顺序是MyApp调用com.foo.Bar
%c %x - %m%n MyApp - Call com.foo.Bar.
com.foo.Bar - Log in Bar
MyApp - Return to MyApp.
%X 按MDC(Mapped Diagnostic Context,线程映射表)输出日志。通常用于多个客户端连接同一台服务器,方便服务器区分是那个客户端访问留下来的日志。 %X{5} (记录代号为5的客户端的日志)
%% 显示一个百分号 %% %

 PatternLayout是Layout的一个子类,用来使用类似C语言的printf函数中使用的格式控制字符串来控制日志的输出格式。

// Log4j APIs : class PatternLayout extends Layout

// 无参数构造方法,使用DEFAULT_CONVERSION_PATTERN构造一个PatternLayout
// 注意:DEFAULT_CONVERSION_PATTERN为"%m%n",只打印消息信息
public PatternLayout(); // 构造方法,使用自定义的pattern构造一个PatternLayout
public PatternLayout(String pattern); // 获得和设置PatternLayout对象的日志pattern
public String getConversionPattern();
public void setConversionPattern(String pattern);

  

举个例子

#log4j config
log4j.rootLogger=DEBUG,OUTPUT log4j.appender.OUTPUT.layout=org.apache.log4j.PatternLayout
log4j.appender.OUTPUT.layout.ConversionPattern=%d{DATE} %-4r [%t] %-5p %c %x - %m%n

 则输出的可能是

12 Oct 2005 22:23:30,117 0 [main] INFO MyApp - Entering application 

 

配置

对log4j环境的配置就是对root logger的配置,包括把root logger设置为哪个级别(level);为它增加哪些appender,等等。这些可以通过设置系统属性的方法来隐式地完成,也可以在程序里调用 XXXConfigurator.configure()方法来显式地完成。

默认的log4j初始化过程

Logger类的静态初始化块(static initialization block)中对log4j的环境做默认的初始化。注意:如果程序员已经通过设置系统属性的方法来配置了log4j环境,则不需要再显式地调用XXXConfigurator.configure()方法来配置log4j环境了。

Logger的静态初始化块在完成初始化过程时将检查一系列log4j定义的系统属性。它所做的事情如下:

  • 检查系统属性log4j.defaultInitOverride,如果该属性被设置为false,则执行初始化;否则(只要不是false,无论是什么值,甚至没有值,都是否)跳过初始化。
  • 把系统属性log4j.configuration的值赋给变量resource。如果该系统变量没有被定义,则把resource赋值为"log4j.properties"。注意:在apache的log4j文档中建议使用定义log4j.configuration系统属性的方法来设置默认的初始化文件是一个好方法。
  • 试图把resource变量转化成为一个URL对象url。如果一般的转化方法行不通,就调用org.apache.log4j.helpers.Loader.getResource(resource, Logger.class)方法来完成转化。
  • 如果url以".xml"结尾,则调用方法DOMConfigurator.configure(url)来完成初始化;否则,则调用方法 PropertyConfigurator.configure(url)来完成初始化。如果url指定的资源不能被获得,则跳出初始化过程。
  • BasicConfigurator.configure()

    BasicConfigurator.configure()方法使用最简的方法配置log4j环境。注:所谓配置log4j环境,就是指配置root logger,因为所有其它的logger都是root logger的后代,所以它们(默认情况下)都将继承root logger的性质。

    BasicConfigurator.configure()完成的任务是:

    • 用默认pattern创建PatternLayout对象p:
      PatternLayout p = new PatternLayout("%-4r[%t]%-5p%c%x - %m%n");
    • 用p创建ConsoleAppender对象a,目标是system.out,标准输出设备:
      ConsoleAppender a = new ConsoleAppender(p,ConsoleAppender.SYSTEM_OUT);
    • 为root logger增加一个ConsoleAppender p:
      rootLogger.addAppender(p);

举个例子,两个类

package log.bar;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger; public class MyApp {
static Logger log=Logger.getLogger(MyApp.class);
public static void main(String[] args) {
BasicConfigurator.configure();
log.info("Entering application.");
Bar bar = new Bar();
bar.doIt();
log.info("Exiting application.");
} }

 

package log;

import org.apache.log4j.Logger;

public class Bar {
static Logger log = Logger.getLogger(Bar.class); public void doIt() {
log.debug("Did it again!");
} }

输出结果为

0 [main] INFO log.MyApp  - Entering application.
2 [main] DEBUG log.Bar - Did it again!
2 [main] INFO log.MyApp - Exiting application.

  

配置根Logger,其语法为:

log4j.rootLogger = [ level ] , appenderName, appenderName, …
appenderName就是指日志信息输出到哪个地方。您可以同时指定多个输出目的地。

输出到appender语句为:

log4j.appender.stdout(这个是自定义的AppenderName)=org.apache.log4j.ConsoleAppender

其中,Log4j提供的appender有

org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

布局语句为

log4j.appender.stdout(这个是自定义的appenderName).layout=org.apache.log4j.PatternLayout(布局中的一个)  

配置日志信息的格式(布局),其语法为:

org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

格式化语句为

log4j.appender.stdout(自定义appenderName).layout.ConversionPattern=%d %p [%c:%L] - <%m>%n  

设置为日志文件存储地址语句为

log4j.appender.logfile(自定义appenderName).File=/home/ismp/log/ismpweb.log(自定义地址)

例: 

#log4j.rootCategory=DEBUG, stdout,logfile
#log4j.category.org.springframework=WARN,stdout,logfile
#log4j.category.net.sf.cindy=WARN,stdout,logfile
log4j.rootCategory=DEBUG, stdout log4j.logger.httpclient=error
log4j.logger.org.apache=error
log4j.category.org.springframework=error
log4j.category.net.sf.cindy=WARN,stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c:%L] - <%m>%n log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.logfile.File=/home/ismp/log/ismpweb.log
log4j.appender.logfile.DatePattern=.yyyy-MM-dd
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c:%L] - <%m>%n

  

  上面category已经废弃了,logger是category的子类,但废弃了也是可以用的。

  

  

 

log4j是专门用于打印日志信息的组件,通过配置可以把特定的日志信息通过指定的格式输出到指定的地方。

日志记录---log4j详解 总结一下:

  • Logger类:完成日志记录,设置日志信息级别
  • Appender类:决定日志去向,终端、DB、硬盘
  • Layout类:决定日志输出的样式,例如包含当前线程、行号、时间

日志记录---log4j详解 log4j.rootLogger=日志级别,appender1, appender2, ….

  • 日志级别:ALL<DEBUG<INFO<WARN<ERROR<FATAL<OFF,不区分大小写
  • 注意,需在控制台输入,只需将其中一个appender定义为stdout即可
  • 注意,rootLogger默认是对整个工程生效
  • 注意,如果只想对某些包操作,那么:log4j.logger.com.hutu=info, stdout,表示该日志对package com.hutu生效
  • 注意,这样做可以区分dev/线上,也可以减小性能影响:if(log.isDebugEnabled()){log.debug();}

日志记录---log4j详解 log4j.appender.appender1=org.apache.log4j.日志输出到哪儿

  • ConsoleAppender(控制台)
  • FileAppender(文件)
  • DailyRollingFileAppender(每天产生一个日志文件)
  • RollingFileAppender(文件大小到达指定尺寸时产生一个新的文件)
  • WriteAppender(将日志信息以流格式发送到任意指定的地方)
  • JDBCAppender(将日志信息保存到数据库中)

日志记录---log4j详解 log4j.appender.appender1.File=文件目录及文件

${user.home}/logs/...

日志记录---log4j详解 log4j.appender.appender1.MaxFileSize=最大文件大小

日志记录---log4j详解 log4j.appender.appender1.MaxBackupIndex=备份文件个数

  • 其中,appender1是在第一行定义过的;
  • 文件目录及文件,例如,/home/admin/logs/hutudan.log
  • 最大文件大小,例如,100KB
  • 备份文件个数,例如,1

日志记录---log4j详解 log4j.appender.ServerDailyRollingFile.DatePattern=日志后缀格式

  • 例如,'.'yyyy-MM-dd

日志记录---log4j详解 log4j.appender.appender1.layout=org.apache.log4j.日志布局格式

  • HTMLLayout(以HTML表格形式布局)
  • SimpleLayout(包含日志信息的级别和信息字符串)
  • TTCCLayout(包含日志产生的时间,执行绪,类别等信息)
  • PatternLayout(可以灵活的指定布局格式,常用)

日志记录---log4j详解 log4j.appender.appender1.layout.ConversionPattern=日志输出格式

  1. 例如,%d - %m%n或%d{yyyy-MM-dd HH:mm:ss} %p [%c] %m%n
  2. %c 输出日志信息所属的类的全名
  3. %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy-M-dd HH:mm:ss },输出类似:2002-10-18- 22:10:28
  4. %f 输出日志信息所属的类的类名
  5. %l 输出日志事件的发生位置,即输出日志信息的语句处于它所在的类的第几行
  6. %m 输出代码中指定的信息,如log(message)中的message
  7. %n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”
  8. %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL。如果是调用debug()输出的,则为DEBUG,依此类推
  9. %r 输出自应用启动到输出该日志信息所耗费的毫秒数
  10. %t 输出产生该日志事件的线程名
  11. 可参考:http://blog.sina.com.cn/s/blog_4e4dd5570100qowy.html

日志记录---log4j详解 log4j.appender.ServerDailyRollingFile.Append=true

例子:

log4j.rootLogger=debug, stdout
log4j.category.org.apache.zookeeper=error
log4j.category.org.springframework=error
log4j.category.org.hibernate=error
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c:%L] - %m%n

  

作者: lostblog

出处: http://www.cnblogs.com/jayit/>

关于作者:专注java服务器端开发,请多多赐教!

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出, 原文链接 如有问题, 可邮件(1073019917@qq.com)咨询.