log4j配置文件详解

1、log4j已经被移植到C, C++, C#, Perl, Python, Ruby, Eiffel 几种语言。
2、log4j有三种主要的组件记录器 ,存放器 ,布局
3、记录器(记录器可不关心log数据存放的事哟)
   log4j允许程序员定义多个记录器,每个记录器有自己的名字,记录器之间通过名字来表明隶属关系(或家族关系)。列如,记录器a.b,与记录器 a.b.c之间是父子关系,而记录器a与a.b.c之间是祖先与后代的关系,父子关系是祖先与后代关系的特例。通过这种关系,可以描述不同记录器之间的逻 辑关系。
  有一个记录器叫根记录器,它永远存在,且不能通过名字检索或引用,可以通过Logger.getRootLogger()方法取得它,而一般记录器通过Logger.getLogger(String name)方法。下面是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 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);
}


  记录器还有一个重要的属性,就是级别。(这好理解,就象一个家庭中,成员间存在辈份关系,但不同的成员的身高可能不一样,且身高与辈份 无关)程序员可以给不同的记录器赋以不同的级别,如果某个成员没有被明确值,就自动继承最近的一个有级别长辈的级别值。根记录器总有级别值。例如:

记录器名赋予的级别值继承的级别值
rootProotProot
X Px Px
X.Y none Px
X.Y.Znone Px


  程序员可以自由定义级别。级别值之间存在偏序关系,如上面几种级别就有关系DEBUG   每一条要输出的log信息,也有一个级别值。
   前面的Logger类中,就预定义了 DEBUG, INFO, WARN, ERROR ,FATAL几种级别,由于与方法绑定,让人易产生误解,其实这几个方法只不过表明了要记录的log信息的级别。当调用log()方法时,log信息的级 别就需要在通过参数明确指定。
  如果一条log信息的级别,大于等于记录器的级别值,那么记录器就会记录它。如果你觉得难以理解,可参考下例。

   // get a logger instance named "com.foo"
   Logger  logger = Logger.getLogger("com.foo");

 

   // Now set its level. Normally you do not need to set the
   // level of a logger programmatically. This is usually done
   // in configuration files.
   logger.setLevel(Level.INFO);

   Logger barlogger = Logger.getLogger("com.foo.Bar");

   // This request is enabled, because WARN >= INFO.
   logger.warn("Low fuel level.");

   // This request is disabled, because DEBUG < INFO.
   logger.debug("Starting search for nearest gas station.");

   // The logger instance barlogger, named "com.foo.Bar",
   // will inherit its level from the logger named
   // "com.foo" Thus, the following request is enabled
   // because INFO >= INFO.
   barlogger.info("Located nearest gas station.");

   // This request is disabled, because DEBUG < INFO.
   barlogger.debug("Exiting gas station search");


  有几个有趣的情况,一是当一个记录器实例化后,再一次用相同的名字调用getLogger()会返回对它的引用,这非常有利于用同一个 记录器在不同代码或类中记录log信息,另一个是与自然界中祖先先于后代出现不同,一个记录器的祖先可以比后代记录出现的晚,但会自动根据名字之间的关系 建立这种家族关系。

 

4、存放器
  在log4j中,log信息通过存放器输出到目的地。支持的存放器有console, files, GUI components, remote socket servers, JMS, NT Event Loggers, remote UNIX Syslog daemons。通过file存放器,log信息可以被输出到不同的文件中(即不同的目的地)。log信息可被异步存放。
  一个记录器可以有多个存放器,可以通过方法addAppender来增加存放器。一条blog信息如果可被这个记录器处理,则记录器会把这条信息送往每个它所拥有的存放器。
  每个记录器有一个继承开关 ,其开关决定记录器是/否继承其父记录器的存放器,注意,如果继承则只继承其父记录器,而不考虑更远的祖先的情况。参考下表:

记录器增加的存放器继承的存放器输出的目的地备注
rootA1not applicableA1The root logger is anonymous but can be accessed with the Logger.getRootLogger() method. There is no default appender attached to root.
xA-x1, A-x2TRUEA1, A-x1, A-x2Appenders of "x" and root.
x.ynoneTRUEA1, A-x1, A-x2Appenders of "x" and root.
x.y.zA-xyz1TRUEA1, A-x1, A-x2, A-xyz1Appenders in "x.y.z", "x" and root.
securityA-secFALSEA-secNo appender accumulation since the additivity flag is set to false.
security.accessnoneTRUEA-secOnly appenders of "security" because the additivity flag in "security" is set to false.

  
  
5、布局
  布局负责格式化输出的log信息。log4j的PatternLayout可以让程序以类似C语言printf的格式化模板来定义格式。

 

6、log4j可据程序员制定的标准自动提供一些log信息,这对那类需要频繁log的对象的情况很帮助。对象的自动log,具有继承性。

 

 

 

前面主要记了一些原理,今天是实务。

1、研究发现,一个系统中4%的代码是用来作logging的。
2、Log4J的配置文件(Configuration File)就是用来设置记录器的级别、存放器和布局的,它可接key=value格式的设置或xml格式的设置信息。通过配置,可以创建出Log4J的运行环境。
  Log4J运行时,不对环境做任何假定,尤其是没有默认的存放器。
3、有几种方式可以配置Log4J
1)在程序中调用BasicConfigurator.configure()方法;
2)配置放在文件里,通过命令行参数传递文件名字,通过PropertyConfigurator.configure(args[x])解析并配置;
3)配置放在文件里,通过环境变量传递文件名等信息,利用log4j默认的初始化过程解析并配置;
4)配置放在文件里,通过应用服务器配置传递文件名等信息,利用一个特殊的servlet来完成配置。
看下面的例子:

import com.foo.Bar;

 // Import log4j classes.

 import org.apache.log4j.Logger;

 import org.apache.log4j.BasicConfigurator;

 public class MyApp {

   // Define a static logger variable so that it references the

   // Logger instance named "MyApp".

   static Logger logger = Logger.getLogger(MyApp.class);


   public static void main(String[] args) {

     // Set up a simple configuration that logs on the console.

     BasicConfigurator.configure();


     logger.info("Entering application.");

     Bar bar = new Bar();

     bar.doIt();

     logger.info("Exiting application.");

   }

 }

 

 package com.foo;

 import org.apache.log4j.Logger;

 

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


  BasicConfigurator.configure给根记录器增加一个 ConsoleAppender,输出格式通过PatternLayout设为"%-4r [%t] %-5p %c %x - %m%n",还有根记录器的默认级别是Level.DEBUG.
  记录器之间的关系如下图:
  

log4jexample.gif


  输出结果如下:

0 [main] INFO MyApp - Entering application.
36 [main] DEBUG com.foo.Bar - Did it again!
51 [main] INFO MyApp - Exiting application.


  下面的代码结合配置信息,会得到与上述程序一样的结果。

import com.foo.Bar;

 import org.apache.log4j.Logger;

 import org.apache.log4j.PropertyConfigurator;


 public class MyApp {

   static Logger logger = Logger.getLogger(MyApp.class.getName());

   public static void main(String[] args) {

     // BasicConfigurator replaced with PropertyConfigurator.

     PropertyConfigurator.configure(args[0]);


     logger.info("Entering application.");

     Bar bar = new Bar();

     bar.doIt();

     logger.info("Exiting application.");

   }

 }


配置文件的内容如下:

# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1

 

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

利用配置文件,可以很方便地修改配置。如下例

log4j.rootLogger=debug, stdout, R

 

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

# Pattern to output the caller's file name and line number.
#log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
# Print the date in ISO 8601 format
log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=example.log

log4j.appender.R.MaxFileSize=100KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=1

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

# Print only messages of level WARN or above in the package com.foo.
log4j.logger.com.foo=WARN


对于tomcat4,利用环境变量传递参数的,可参见以下几个例子


unix设置
export CATALINA_OPTS ="-Dlog4j.configuration=foobar.txt"<===用PropertyConfigurator解析
export CATALINA_OPTS ="-Dlog4j.debug -Dlog4j.configuration=foobar.xml"<===用DOMConfigurator解析
以下是windows设置
set CATALINA_OPTS =-Dlog4j.configuration=foobar.lcf -Dlog4j.configuratorClass=com.foo.BarConfigurator<===用com.foo.BarConfigurator解析
set CATALINA_OPTS =-Dlog4j.configuration=file:/c:/foobar.lcf

配置文件位置如果没有明确指明,则要放在WEB-INF/classes目录下。
4、用servlet配置log4j
在Application目录下的web.xml文件加入以后代码

  <servlet>

    <servlet-name>log4j
log4j-init
</servlet-name>

    <servlet-class>com.apache.jakarta.log4j.Log4jInit</servlet-class>

    <init-param>

      <param-name>log4j</param-name>

      <param-value>/
WEB-INF/log4j.properties</param-value>

    </init-param>

    <load-on-startup>1</load-on-startup>

  </servlet>


这段代码的意思是说,在Tomcat启动时加载com.apache.jakarta.log4j.Log4jInit这个名叫Log4jInit.class这个类文件。
其中Log4jInit.class的源代码如下

 

package com.apache.jakarta.log4j;

import org.apache.log4j.PropertyConfigurator;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

public class Log4jInit extends HttpServlet {

 

public void init() { String prefix = getServletContext().getRealPath("/"); String file = getInitParameter("log4j"); // if the log4j-init-file is not set, then no point in trying System.out.println("................log4j start"); if(file != null) { PropertyConfigurator.configure(prefix+file); } } public void doGet(HttpServletRequest req, HttpServletResponse res) { } }


在加载的过程中,程序会读取/WEB-INF/log4j.properties这个文件。
配置文件讲解如下:

# Set root logger level to DEBUG and its only appender to A1
#log4j中有五级logger
#FATAL 0
#ERROR 3
#WARN 4
#INFO 6
#DEBUG 7
#配置根Logger,其语法为:
#log4j.rootLogger = [ level ] , appenderName, appenderName, …
log4j.rootLogger=INFO, A1 ,R
#这一句设置以为着所有的log都输出
#如果为log4j.rootLogger=WARN, 则意味着只有WARN,ERROR,FATAL
#被输出,DEBUG,INFO将被屏蔽掉.
# A1 is set to be a ConsoleAppender.
#log4j中Appender有几层如控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等
#ConsoleAppender输出到控制台
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 使用的输出布局,其中log4j提供4种布局. org.apache.log4j.HTMLLayout(以HTML表格形式布局)
#org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
#org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
#org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

 

log4j.appender.A1.layout=org.apache.log4j.PatternLayout
#灵活定义输出格式 具体查看log4j javadoc org.apache.log4j.PatternLayout
#d 时间 ....
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n
#R 输出到文件 RollingFileAppender的扩展,可以提供一种日志的备份功能。
log4j.appender.R=org.apache.log4j.RollingFileAppender
#日志文件的名称
log4j.appender.R.File=log4j.log
#日志文件的大小
log4j.appender.R.MaxFileSize=100KB
# 保存一个备份文件
log4j.appender.R.MaxBackupIndex=1

log4j.appender.R.layout=org.apache.log4j.TTCCLayout
#log4j.appender.R.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n


配置根Logger,其语法为:

log4j.rootLogger = [ level ] , appenderName, appenderName, ...


level 是日志记录的优先级
appenderName就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。

 

配置日志信息输出目的地Appender,其语法为

log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1
...
log4j.appender.appenderName.option = valueN


Log4j提供的appender有以下几种:
org.apache.log4j.ConsoleAppender(控制台),
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

 

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

log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1
....
log4j.appender.appenderName.layout.option = valueN


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

 

 

 

我这儿有两个程序,一个是普通的java程序,实现了一个“九九表”;另一个是servlet。我这儿用的tomcat是4.1.12,J2SE是1.3.1,log4j的版本是1.2.8.

一、九九表。
环境设置:需要将log4j-1.2.8.jar放入CLASSPATH变量中。
Hello.java文件的内容如下:

import org.apache.log4j.*;
public class Hello{
	static Logger logger = Logger.getLogger(Hello.class);
	public static void main(String[] args) {
	int i,j;
//	  BasicConfigurator.configure();
	  PropertyConfigurator.configure(args[0]);

      logger.info("Entering application.");
      for(i=1;i<10;i++){
	    logger.debug(""+i);
      	for (j=1;j<=i;j++){
      		logger.warn(""+j);
      		System.out.print(i*j);
      		System.out.print("\t");
      	}
      	System.out.println("");
    	}
      logger.info("Exiting application.");	  
}


log4j的配置文件log4j.inf的内容如下:

log4j.rootLogger=WARN, stdout, R

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

# Pattern to output the caller's file name and line number.
#log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
# Print the date in ISO 8601 format
log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=example.log

log4j.appender.R.MaxFileSize=100KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=1

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

# Print only messages of level WARN or above in the package com.foo.
log4j.logger.com.foo=WARN


运行:

javac Hello.java
java Hello log4j.inf


结果会在屏幕上显示,并在example.log文件中记录。

 

二、servlet
环境设置:将log4j-1.2.8.jar及servlet.jar放入环境变量CLASSPATH中,并且要将log4j-1.2.8复制到$TOMCAT_HOME/common/lib目录下。
假定,有一个布署到tomcat的应用叫myweb。
servlet程序Log4jInit.java的位置在$TOMCAT_HOME/webapps/myweb/WEB-INF/classes/com/hedong/learning/log4j/目录下,内容如下:

package com.hedong.learning.log4j;
import org.apache.log4j.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Log4jInit extends HttpServlet {
  public void init() {
        String prefix =  getServletContext().getRealPath("/");
        String file = getInitParameter("log4j");
        // if the log4j-init-file is not set, then no point in trying
        System.out.println("................log4j start");
        if(file != null) {
          PropertyConfigurator.configure(prefix+file);
        }
  }
public void doGet(HttpServletRequest req, HttpServletResponse res) {
  }
}


在Log4jInit.java所在目录下编译它:

javac Log4jInit.java


myweb的设置文件web.xml在$TOMCAT_HOME/webapps/myweb/WEB-INF/目录下,增加如下红色部分。

</web-app>
  ...........
  <servlet>
    <servlet-name>log4j-init</servlet-name>
    <servlet-class>com.hedong.learning.log4j.Log4jInit</servlet-class>
    <init-param>
      <param-name>log4j</param-name>
      <param-value>WEB-INF/log4j.properties</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

</web-app>


同时,在这个目录下建一个文件名叫log4j.properties,内容如下:

log4j.rootLogger=INFO, A1 , R
log4j.appender.A1=org.apache.log4j.ConsoleAppender 
log4j.appender.A1.layout=org.apache.log4j.PatternLayout 
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n 
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=$TOMCAT_HOME/webapps/dbweb/logs/log4j.log<----将$TOMCAT_HOME换成tomcat的安装目录

log4j.appender.R.MaxFileSize=100KB
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n


记住,别忘了创建目录$TOMCAT_HOME/webapps/dbweb/logs/,如果它不存在的话。
创建目录$TOMCAT_HOME/webapps/dbweb/test/,然后在这个目录下新建一个文件test.jsp,内容如下:

<%@ page contentType="text/html; charset=GB2312" %>
<%@ page import="org.apache.log4j.*" %>
<%
       Logger logger = Logger.getLogger("test.jsp");
       logger.info("befor say hi");
%>
<h1> Hi</h1>
<%
        logger.info("after say hi");
%>


然后,重新启动tomcat,通过浏览器访问这个jsp页面,如 http://yourdomain.com:8080/myweb/test/test.jsp,如果一切正常,会看到一个大大的HI。然后,在服务器 上的$TOMCAT_HOME/webapps/dbweb/logs/log4j.log文件中看到如下的信息:

INFO HttpProcessor[8080][4] test.jsp - befor say hi
INFO HttpProcessor[8080][4] test.jsp - after say hi

。在默认的情况下,tomcat的屏幕输出被重定向到$TOMCAT_HOME/logs/catalina.out文件中,在文件的最后也应看到上述的输出。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值