Log4j完全教程

本文为转载学习

原文链接:http://hi.baidu.com/boyyf/item/cec95635dbd50e169dc65e26


认识Log4j

    在你开发项目的过程过,是否时常使用System.out.println()?考虑是否需要记录程序运行过程中出现的错误?是否需要记录用户的行为?Apache Log4j项目将帮助我们逃脱硬编码写输出的痛苦,独立的日志输出程序将使得程序员可以便利的分级输出日志信息。更为重要的是,Log4j灵活的配置功能使得我们完全不需要修改程序,而仅仅修改配置文件即可彻底改变日志输出的格式、目标等属性,并且Log4j还为我们提供了各种便利的日志目的地,如“一天一个日志文件”、套接字、数据库、电子邮箱,甚至Unix的守护进程和Nt的事件服务。

Log4j的三大组建

    Log4j有三个主要的组件:LoggersAppendersLayouts,这里可简单理解为日志记录器日志要输出的地方日志以何种形式输出

Loggers

    组件在此系统中被分为五个级别:DEBUG、INFO、WARN、ERROR和FATAL。这五个级别是有顺序的,DEBUG < INFO < WARN < ERROR < FATAL,明白这一点很重要,这里Log4j有一个规则:假设Loggers级别为P,如果在Loggers中发生了一个级别Q比P高的日志输出事件,则会输出,否则屏蔽掉。

Appenders

    禁用与使用日志请求只是Log4j其中的一个小小的地方,Log4j日志系统允许把日志输出到不同的地方,如控制台(Console)、文件(Files)、根据天数或者文件大小产生新的文件、以流的形式发送到其它地方等等。

常见的Appender有:

      org.apache.log4j.ConsoleAppender(控制台)

      org.apache.log4j.FileAppender(文件)

      org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),

      org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)

      org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

      org.apache.log4j.net.SMTPAppender(发送到邮箱)

      org.apache.log4j.jdbc.JDBCAppender(储存到数据库)

Layouts

    有时用户希望根据自己的喜好格式化自己的日志输出。Log4j可以在Appenders的后面附加Layouts来完成这个功能。Layouts提供了四种日志输出样式,如根据HTML样式、自由指定样式、包含日志级别与信息的样式和包含日志时间、线程、类别等信息的样式等等。

    常见的Layout有:

      org.apache.log4j.HTMLLayout(以HTML表格形式布局),

      org.apache.log4j.PatternLayout(可以灵活地指定布局模式),

      org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),

      org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

Layouts有以下各常用的占位符:

      %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL

      %r 输出自应用启动到输出该log信息耗费的毫秒数

      %c 输出所属的类目,通常就是所在类的全名

      %t 输出产生该日志事件的线程

      %n 输出一个回车换行符,Windows平台为"\r\n",Unix平台为"\n"

      %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921

      %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)

Log4j的配置文件

    就本人看来,Log4j的便利之处就在于他的配置非常灵活的依赖于配置文件,可以说在程序中只需要写出在哪里需要输出日志,日志的级别,以及日志的内容(这些通常都是固定不变的),而对于常需要改变的内容,比如日志的格式、输出到哪里、怎么储存,甚至需要那些记录器都只需要修改配置文件,而无需修改程序。但同时,这也决定了Log4j的使用核心就在配置文件的编写。

    Log4j的配置文件可以拥有两种形式,一是properties文件,另一种是xml文件,在此,只探讨properties文件形式。

    首先请看一段配置文件(由于properties并不支持中文,复制使用时请将中文注释删掉,或者下载源程序包中的配置文件):

#下面是Logger的定义

#定义根logger,其余所有的logger都是它的子logger

log4j.rootLogger=DEBUG

#logger的定义策略1:根据类名定义logger

#这里就定义了两个logger,一个名为"com.ins1000.log4j.servlets",另一个名

#为"com.ins1000.log4j.servlets"。#logger的命名是具有层次性和隶属性的,跟

#类的全名一样,可以说"com.ins1000.log4j.servlets.Test"这个logger是"com.

#ins1000.log4j.servlets"这个的子logger。

log4j.logger.com.ins1000.log4j.servlets=DEBUG,CONSOLE

log4j.logger.com.ins1000.log4j.servlets.Test=DEBUG,CONSOLE,DailyRollingFile


#logger的定义策略2:根据用途定义logger

#定义了一个名为sa(system action)的logger,用于记录程序的系统行为,如程

#序启动,初始化完成等

log4j.logger.sa=DEBUG,CONSOLE_SA

#定义了一个名为us(users action)的logger,用于记录用户的一般行为,如注册

#发布文章、发布作品等

log4j.logger.ua=DEBUG,DailyRollingFile_UA

#定义了一个名为e(Errors或Exceptions)的logger,用于记录程序运行中出现的

#错误和异常

log4j.logger.e=DEBUG,CONSOLE_E,ROLLING_FILE_E

#以上各个定义的等号右方DEBUG的表示该logger的日志输出起始级别,接着后面是

#这个logger要输#出的Appender,可以有多个,用逗号隔开。

#其次,这里提到了两种logger的命名策略,虽然互联网上几乎所有的教程皆称以类

#的全名是最简单也最好的命名策略,因为其层次结构跟我们的项目完全一致,但是

#本人处于应用需要,还是提出了另一种根据用途命名的策略,即把所有需要记录的

#日志信息分为3中(系统行为、用户行为、异常),分别输出到不同的地方。


#下面定义各个层次是否继承父辈的属性(初始级别和Appenders)

log4j.additivity.com.ins1000.log4j=true

log4j.additivity.com.ins1000.log4j.Test=true

log4j.additivity.e=false

log4j.additivity.sa=false

log4j.additivity.ua=false

log4j.addivity.org.apache=true

#下面定义各个Appenders

###################################

# Console Appender

###################################

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender

log4j.appender.Threshold=DEBUG

log4j.appender.CONSOLE.Target=System.out

log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout

log4j.appender.CONSOLE.layout.ConversionPattern=[ins1000]%p: %m [%c]%n

###################################

# Console Appender For SystemAction

###################################

log4j.appender.CONSOLE_SA=org.apache.log4j.ConsoleAppender

log4j.appender.Threshold=DEBUG

log4j.appender.CONSOLE_SA.Target=System.out

log4j.appender.CONSOLE_SA.layout=org.apache.log4j.PatternLayout

log4j.appender.CONSOLE_SA.layout.ConversionPattern=[ins1000]\u7cfb\u7edf\u4fe1\u606f: %m%n

###################################

# Console Appender For Errors and Exceptions

###################################

log4j.appender.CONSOLE_E=org.apache.log4j.ConsoleAppender

log4j.appender.Threshold=DEBUG

log4j.appender.CONSOLE_E.Target=System.out

log4j.appender.CONSOLE_E.layout=org.apache.log4j.PatternLayout

log4j.appender.CONSOLE_E.layout.ConversionPattern=[ins1000]\u7cfb\u7edf\u5f02\u5e38: %m [%l]%n

#上面的Appender都是输出到控制台,多个项目的信息都可能被输出到控制台,所以

#一般都会加上项目名称,如[ins1000]

########################

# Rolling File For Errors and Exceptions

########################

log4j.appender.ROLLING_FILE_E=org.apache.log4j.RollingFileAppender

log4j.appender.ROLLING_FILE_E.Threshold=ERROR

log4j.appender.ROLLING_FILE_E.File=${webappHome}/WEB-INF/log/errors/ins1000.log

#日志文件的位置,其中${webappHome}代表环境变量中webappHome的值,Log4j会在

#初始化的死后自动期待,所以我们可以在Log4j初始化的时候将webapp的绝对路径存

#入系统环境标量中,从而解决要手动修改日志文件的问题

log4j.appender.ROLLING_FILE_E.Append=true

log4j.appender.ROLLING_FILE_E.MaxFileSize=5120KB

#一个文件的大小(当超过这个大小时,自动更换一个文件)

log4j.appender.ROLLING_FILE_E.MaxBackupIndex=1

log4j.appender.ROLLING_FILE_E.layout=org.apache.log4j.PatternLayout

log4j.appender.ROLLING_FILE_E.layout.ConversionPattern=%n%n[%d{yyyy-MM-dd HH:mm:ss}]%m [%l]%n

########################

# DailyRollingFile Appender

#######################

log4j.appender.DailyRollingFile=org.apache.log4j.DailyRollingFileAppender

log4j.appender.DailyRollingFile.DatePattern=yyyy-MM-dd'.log'

#日期戳后缀的格式

log4j.appender.DailyRollingFile.File=${webappHome}/WEB-INF/log/ins1000_

log4j.appender.DailyRollingFile.Append=true

log4j.appender.DailyRollingFile.layout=org.apache.log4j.PatternLayout

log4j.appender.DailyRollingFile.layout.ConversionPattern=[%-5p]%m [%c][%d{yyyy-MM-dd HH:mm:ss}]%n

#这个Appender的工作机理是先将日志写在/WEB-INF/log/ins1000_,待到了第二天,自动将其更名为

#ins1000_yyyy-MM-dd.log(其中yyyy-MM-dd是第一天的日期)。然后仍将第二天的日志先记录在在

#ins1000_中,第三天再改名,以此类推。

########################

# DailyRollingFile Appender For Users Action

#######################

log4j.appender.DailyRollingFile_UA=org.apache.log4j.DailyRollingFileAppender

log4j.appender.DailyRollingFile_UA.DatePattern=yyyy-MM-dd'.log'

log4j.appender.DailyRollingFile_UA.File=${webappHome}/WEB-INF/log/users_action/ins1000_

#${webappHome} is an enviorment variable which is setted in Log4jInit

#it refers to the absolute path of the webapp

log4j.appender.DailyRollingFile_UA.Append=true

log4j.appender.DailyRollingFile_UA.layout=org.apache.log4j.PatternLayout

log4j.appender.DailyRollingFile_UA.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}] %m%n

 


本人在网上处处寻觅,都没有发现有对Log4j配置文件详细介绍的文档,如果大家English不错的话,建议大家需要的时候可以看看Log4j的API,应该有比较详细的介绍。在此,本人只再介绍几个常用的Appender的配置:

#####################

# File Appender

#####################

log4j.appender.FILE=org.apache.log4j.FileAppender

log4j.appender.FILE.File=file.log

log4j.appender.FILE.Append=false

log4j.appender.FILE.layout=org.apache.log4j.PatternLayout

log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

# Use this layout for LogFactor 5 analysis

########################

# Rolling File

########################

log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender

log4j.appender.ROLLING_FILE.Threshold=ERROR

log4j.appender.ROLLING_FILE.File=rolling.log

log4j.appender.ROLLING_FILE.Append=true

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=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

####################

# Socket Appender

####################

log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender

log4j.appender.SOCKET.RemoteHost=localhost

log4j.appender.SOCKET.Port=5001

log4j.appender.SOCKET.LocationInfo=true

# Set up for Log Facter 5

log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout

log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n

########################

# Log Factor 5 Appender

########################

log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender

log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000

########################

# SMTP Appender

#######################

log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender

log4j.appender.MAIL.Threshold=FATAL

log4j.appender.MAIL.BufferSize=10

log4j.appender.MAIL.SMTPHost=mail.hollycrm.com

log4j.appender.MAIL.Subject=Log4J Message

log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout

log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

########################

# JDBC Appender

#######################

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=

log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES (’[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n’)

log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout

log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender

log4j.appender.A1.File=SampleMessages.log4j

log4j.appender.A1.DatePattern=yyyyMMdd-HH’.log4j’

log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout  

 


自动初始化Log4j的Servlet

package com.ins1000.log4j.servlets;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import org.apache.log4j.PropertyConfigurator;
public class Log4jInit extends HttpServlet {
    public void init(ServletConfig config) throws ServletException {
       //获取本webapp所在的绝对路径
       String prefix = config.getServletContext().getRealPath("/");
       //从web.xml读取配置文件名
       String file = config.getInitParameter("Log4j-init-file");
       //对绝对路径进行修饰
       String editedPrefix = prefix.substring(0,prefix.length()-1).replace("\\", "/");
       //将修饰后的绝对路径存入系统环境变量
       System.setProperty("webappHome", editedPrefix);
       //执行Log4j的初始化
       PropertyConfigurator.configure(prefix + file);
    }
}

    为了让这个Servlet在Web服务器启动时自动运行,还需要在项目的web.xml写入:

<servlet>
    <description>Log4jInit</description>
    <display-name>Log4jInit</display-name>
    <servlet-name>Log4jInit</servlet-name>
    <servlet-class>com.ins1000.log4j.servlets.Log4jInit</servlet-class>
    <init-param> 
        <param-name>Log4j-init-file</param-name> 
        <param-value>WEB-INF/config/Log4j.properties</param-value> 
    </init-param> 
<load-on-startup>1</load-on-startup> 
</servlet>

在程序中使用Log4j

    在程序中使用Log4j,也就是要输出日志信息,一般分为两个步骤:首先获得一个Logger实例,然后调用此实例的debug()、info()、warn()、error()、fatal()等进行日志的输出。

    在上面的配置文件中,讲到了两种命名策略,一种是直接根据类的全名命名,另一种是根据用途命名,那么在实例化和使用的时候,就会稍微有些不同。

    根据类全命命名:

Logger logger = Logger.getLogger(this.getClass());

    //实例化一个logger,这里this.getClass()将返回这个类的全名,如果这个名字在配置文件中定义了,则这个logger有其相关定义了的属性,如果没有,则看是否定义了其父类和时候设置了继承。如果都没有,则拥有rootLogger的属性。

    //当然,logger的实例化可以任意取名,比如Logger logger = Logger.getLogger("myLogger"),但一句相关的策略,将会更加便于管理。

    logger.debug("按类取名测试:DEBUG");
    logger.info("按类取名测试:INFO");
    logger.warn("按类取名测试:WARN");
    logger.error("按类取名测试:ERROR");
    logger.error("按类取名测试:ERROR", Exception e);
    logger.fatal("按类取名测试:FATAL");

    //这就是条用logger的各种方法输出日志信息。其中logger.error("按类取名测试:ERROR", Exception e)也会将异常堆栈e的相关信息也输出到相应的Appender

    根据用途命名:

    Logger logger_sa = Logger.getLogger("sa");
    logger_sa.info("Log4j演示程序启动成功");
    Logger logger_ua = Logger.getLogger("ua");
    logger_ua.info("用户boyyf注册成功");
    Logger logger_e = Logger.getLogger("e");
    try {
        Integer.parseInt("a");
    } catch (Exception e) {
        logger_e.error("出现数值转换异常",e);
        //这样会在日志中记录异常堆栈
    }

你可能感兴趣的:(log4j)