循序渐进看Java web日志跟踪(3)-Log4J的使用和配置

循序渐进看Java web日志跟踪(3)-Log4J的使用和配置

  之前说过关于java日志跟踪的几大主要用的框架,也说到了,其实在其中,Log4J充当着一个相当重要的角色。目前,大部分框架也都是采用的是Log4J,虽然说它已经停止了更新,作者也重新起了LogBack的项目,但是,LogBack目前在国内的使用还是相当的少。目前大部分项目还是使用的是Log4J,所以记录一下Log4J的一些常见的使用方法和配置。
 
1、简单的Log4J使用实例
     Log4J作为一个较好的框架,它有着功能强大操作简单的特点,在日常开发过程中,其实需要开发人员做的,大部分是其配置文件的编写,而不是去过多的研究如何写代码。以下是使用Log4J的简单的使用实例,从中,便可以看出其简单易用。
     首先,需要导入Log4J 的jar包,在此就不再赘述了。然后就是在根目录下创建log4j.properties文件(该文件就是在开发过程中我们最常需要写到的文件),在文件中加入代码
#可以设置级别:debug>info>error
#debug:显示debug、info、error
#info:显示info、error
#error:只error
log4j.rootLogger=debug,appender1
#log4j.rootLogger=info,appender1
#log4j.rootLogger=error,appender1
#输出到控制台
log4j.appender.stdout.Threshold=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[Bash]:%d %5p (%c:%L) - %m%n
  最后,编辑简单的测试类:
 1 private static Logger logger = Logger.getLogger(Log.class);
 2 
 3 public static void main(String[] args) {
 4     // System.out.println("This is println message.");
 5 
 6     // 记录debug级别的信息
 7     logger.debug("This is debug message.");
 8     // 记录info级别的信息
 9     logger.info("This is info message.");
10     // 记录error级别的信息
11     logger.error("This is error message.");
12 }


  运行后,在控制台上的输出如下:

[Bash]:2016-01-18 23:10:11,089  INFO (com.sean.log.LogTest1:14) - This is info message
[Bash]:2016-01-18 23:10:11,093 ERROR (com.sean.log.LogTest1:15) - This is error message
  以上,就算是完成了Log4J的简单使用。
 
  2、输出什么?

  上面,我们实现了Log4J的控制台输出,这里面,需要用到的代码并不多,相对而言,需要说的是log4J的配置文件。在通用的开发环境中,Log4J的使用,重点就是在于其配置文件的配置中。Log4J的配置文件有两种,一种是采用properties文件,另一种是使用xml文件。常见的,也是使用properties的方式进行配置。


1. DEBUG (the least serious)
#   2. INFO
#   3. WARN
#   4. ERROR
#   5. FATAL (the most serious)

  其中debug级别最高,fatal级别为最低,定义的级别越高,则Log4J 会输出显示的级别越多,反之越少。
     接下来,需要配置之前说到的日志输出类,告诉log4J,要采用哪个工具类输出到哪里,常见的包括如同控制台,文本文件,html文件,数据库等。其配置大概如下
log4j.appender.appenderName = class#配置日志输出采用的类
log4j.appender.appenderName.key= value#配置相关日志输出的参数

   到这里,暂时不再说如何输出,先说下输出什么。在第一个实例中,能够发现,控制台的输出和在配置文件中配置的参数是有关的。

     第一个实例中,定义了一个appender为stdout,就是输出到控制台,其中有个参数为ConversionPattern,实例输出的信息其实是以该模板为参照了。在Log4J 中,所有Log4J 定义的appender,都需要定义一个格式化输出的方式,即layout,默认采用的是PatternLayout,而layout会有一个ConversionPattern 参数,主要是让开发者配置他们输出的信息的模板。具体可以如何配置呢?
该参数的包括如下内容:
                  -X: X信息输出时左对齐;
                   %p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL,
                   %d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
                   %r: 输出自应用启动到输出该log信息耗费的毫秒数
                   %c: 输出日志信息所属的类目,通常就是所在类的全名
                   %t: 输出产生该日志事件的线程名
                   %l: 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)
                   %x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
                   %%: 输出一个"%"字符
                   %F: 输出日志消息产生时所在的文件名称
                   %L: 输出代码中的行号
                   %m: 输出代码中指定的消息,产生的日志具体信息
                   %n: 输出一个回车换行符,Windows平台为" ",Unix平台为" "输出日志信息换行
                   在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度
 
通过上述参数的组合,开发者可以定义出自己想要输出的内容,有Log4J 输出,如: %r %5p %d{yyyy-MM-dd HH:mm:ssS} %c %m%n
 
3、如何输出
 
之前说到了,log4J可以实现多种方式的输出,包括控制台,文件,socket,html,数据库,当然也允许自定义输出方式。其中,有一些配置,是仅需要在配置文件中配置,Log4J 即可帮我们完成输出的,而想socket和数据库这样的输出,则是需要其余的一些条件的配合才能进行。

以下是比较完整的log4J的配置文件如下
log4j.rootLogger=DEBUG,CONSOLE,A1,im 
log4j.addivity.org.apache=true
 # 应用于控制台
 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=[bash] %d - %c -%-4r [%t] %-5p %c %x - %m%n #格式化标准
 #应用于文件(单个文件)
 log4j.appender.FILE=org.apache.log4j.FileAppender
 log4j.appender.FILE .Threshold=ERROR   
 log4j.appender.FILE.File=file.log #文件名
 log4j.appender.FILE.Append=true #是否累加,是为增量输出,否未覆盖输出
 log4j.appender.FILE.layout=org.apache.log4j.PatternLayout #格式化方式
 log4j.appender.FILE.layout.ConversionPattern=[bash ] %d - %c -%-4r [%t] %-5p %c %x - %m%n #格式化标准
 # Use this layout for LogFactor 5 analysis
 # 应用于文件增量添加,按照大小
 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


 # 应用于文件增量添加,按照日期
 log4j.appender.Daily_ROLLING_FILE=org.apache.log4j. DailyRollingFileAppender#输出类
 log4j.appender.Daily_ROLLING_FILE .Threshold=ERROR #输出级别
 log4j.appender.Daily_ROLLING_FILE .File=rolling.log  #文件位置,可以动态配置
 log4j.appender.Daily_ROLLING_FILE .Append=true       #是否累加,是为增量输出,否未覆盖输出
 log4j.appender.info.DatePattern=-yyyy-MM-dd'.log'
 log4j.appender.Daily_ROLLING_FILE .layout=org.apache.log4j.PatternLayout  #格式化方式
 log4j.appender.Daily_ROLLING_FILE .layout.ConversionPattern=[bash ] %d - %c -%-4r [%t] %-5p %c %x - %m%n


 #应用于socket 
 log4j.appender.SOCKET=org.apache.log4j.net.SocketAppender
 log4j.appender.SOCKET.RemoteHost=localhost
 log4j.appender.SOCKET.Port=5001 
 log4j.appender.SOCKET.LocationInfo=true 
 log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout 
 log4j.appender.SOCKET.layout.ConversionPattern=[bash ] %d - %c -%-4r [%t] %-5p %c %x - %m%n


 # 发送日志给邮件(这种方式用公用邮箱时常会被拦截)
log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
log4j.appender.MAIL.Threshold=FATAL
log4j.appender.MAIL.BufferSize=10
log4j.appender.MAIL.From= @126.com
log4j.appender.MAIL.SMTPHost=smtp.126.com
log4j.appender.MAIL.SMTPUsername= @126.com
log4j.appender.MAIL.SMTPPassword= 
log4j.appender.MAIL.Subject=Log4J Message
log4j.appender.MAIL.To= @qq.com
log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
log4j.appender.MAIL.layout.ConversionPattern=[bash ] %d - %c -%-4r [%t] %-5p %c %x - %m%n


# html输出
log4j.appender.HTML=org.apache.log4j.FileAppender
log4j.appender.HTML.File=D://htmlLayout.html
log4j.appender.HTML.layout=org.apache.log4j.HTMLLayout
log4j.appender.HTML.layout.Title=HTML Layout Example
log4j.appender.HTML.layout.LocationInfo=true
log4j.appender.HTML.layout.ConversionPattern=[bash ] %d - %c -%-4r [%t] %-5p %c %x - %m%n

 # 用于数据库 
 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=[bash ] %d - %c -%-4r [%t] %-5p %c %x - %m%n
以上配置文件中,控制台输出,文本输出,html输出都是只需要在配置文件中进行配置,log4j就会根据配置文件中的格式进行输出的。
 
关于使用socket输出,则需要有一台对应的服务器,同时,服务器上还需要有个服务器程序,进行socket监听,来处理日志。
 
比如,当配置文件配置如下时:
#应用于socket
 log4j.appender.SOCKET=org.apache.log4j.net.SocketAppender
 log4j.appender.SOCKET.RemoteHost=localhost
 log4j.appender.SOCKET.Port=9090
 log4j.appender.SOCKET.LocationInfo=true
 log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
 log4j.appender.SOCET.layout.ConversionPattern=[Bash]:%d %5p (%c:%L) - %m%n


默认情况下log4j采用的是tcp协议进行访问,所以,在服务器端需要有个程序,监听9090端口,来实现日志的接收

public static void main(String arg[]) throws IOException {

    ServerSocket serverSocket=new ServerSocket(9090);
    while (true){
        Socket s= serverSocket.accept();
        String line;

        BufferedReader is=new BufferedReader(new InputStreamReader(s.getInputStream(),"utf-8"));
        System.out.println(is.readLine());
    }


}
关于通过邮件的方式输出,首先确定classpath下有mail.jar包,供Log4J 发送使用,接下来需要配置发送邮箱,和邮件服务器地址,还有用户名密码。需要注意的是,如果采用的是邮件服务提供商的例如网易这样子的邮箱,很有可能会导致发送不出或者被拦截的可能,同时邮件也有可能会存在乱码的问题。
 
关于通过数据库的方式输出,首先,要在对应的数据库服务器下创建一个数据库与表,作为输出的对象。接着,需要导入对应数据库驱动的jar包,然后再配置文件中配置好用户名和密码。最后是配置需要输出的数据库语句。Log4J 并不能知道你需要输出什么,所以需要开发者自己定义好要输出的字段,组成数据库语句,有Log4J 去执行,才能实现数据的输出。如:insert into log(message) values('%m')
 
除了Log4J 定义好的appender以外,开发者还可以通过自定义的方式来实现appender,自定义的方式需要继承基类 AppenderSkeleton ,具体如何实现,建议参考源码,此处主要讲应用,就不再赘述了
 
最后简易的说一下Log4J 的几种输出方式的使用情况,文件输出应该是最常用的一种,因为其配置较为简单,而且能够进行按日期增量备份,如果是不是要求非常高,该方式已经能够达到日志输出的目的了。相较之下,采用socket,mail的方式相对更少用,首先,采用socket的话,需要有个socket的服务端程序来接收日志,这样子意味着要添加工作量,除非是已经有了对应的程序,否则在开发过程中,个人不会选择用socket。至于mail,功能非常强大,可是有一点,在于如果采用常用的邮件提供商,会有被拦截的可能。同时,如果只有当日志输出把握的非常好的情况下,才会出现mail的情况,比如,需要严格定义好输出error的标准,然后设置mail输出等级为error,如果设置的不好,可能会导致不断发送垃圾文件的可能
 
关于使用数据库和html的方式收集数据,两者各有各的好处。Html对日志的展示比较直观,可是,如果单独采用这种方式的话,可能就无法日志进行进一步的处理了。采用数据库的方式最大的好处,可以对日志进行进一步的处理,如索引,筛选等,可是需要的资源也比较多。好刀用到刀刃上,具体该怎么使用,还需要根据具体的需求来进行设计。
 
参考:http://www.blogjava.net/hwpok/archive/2008/08/23/223891.html