log4j打印日志

来源:互联网 发布:may it be是什么意思 编辑:程序博客网 时间:2024/06/11 22:41

log4j打印日志

日志在应用中发挥着作用,是应用的重要组成部分。日志用于记录应用的行为,记录应用的输入输出等,根据日志文件可以定位问题,挖掘数据,优化性能,统计应用各类指标,还原应用输入输出等重要功能,下面是一个Java应用使用log4j打印日志的简单例子。

 

一、日志根据内容的不同区分出不同的日志,需要根据应用需求而定。以下为根据需求,定义几个不同日志。如:

1. 记录应用的输入输出的access log,其中包含一次pv(请求)的详细信息,一次pv包含两行日志,一行请求,一行响应,请求中包括时间戳,pvid,请求URL,请求ip,请求参数等,响应中包括时间戳,pvid,响应结果等。

2. 记录应用行为的error log,包括时间,堆栈信息,线程信息,错误信息,应用代码打印信息等

3. 记录数据的service log,内容根据需要记录的数据而定。

4. 开发阶段、测试使用的console log,内容一般为最全的log,包含其他各种log

二、系统中引入log4j

1,引入依赖

2,应用web.xml中增加配置

<context-param><param-name>log4jConfigLocation</param-name><param-value>classpath:log4j.xml</param-value></context-param>

3web.xml中增加监听

<listener><listener-class>org.springframework.web.util.Log4jConfigListener</listener-class></listener>

4,增加log4j配置文件,通常为log4j.properties或者log4j.xml配置文件

三、Log4j组件简介

log4j有三个重要的组件:Loggers(记录器),Appenders(输出源)和Layouts(布局)。可以通俗的理解为,不同的日志,输出到什么地方,以什么样的格式输出,综合这三个组件就可以以不同的形式(Layouts)打印不同级别(Loggers)的日志到不同的地方(Appenders)。现就三个组件做简单介绍:

1Loggers

Loggers组件默认有5个级别,即DEBUG,INFO,WARN,ERROR,FATAL,五个日志的级别是DEBUG<INFO<WARN<ERROR<FATAL,用来指定日志的级别,Appenders可以设定日志的界别,设置之后只输出级别大于等于设定级别的日志,假如日志设置为ERRORERRORFATAL会输出,而比ERROR级别小的WARN,INFO,DEBUG则不会输出。log4j可以自定义日志级别

2Appenders

log4j提供了把日志输出道不同地方的功能,如控制台(console,文件(Files),可以根据时间或者文件大小产生新的日志文件,也可以以流的方式发送到其他地方(邮件,数据库,文件系统)等。

常用的Appenders类如下:

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

org.apache.log4j.FileAppender(文件)

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

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

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

 

Appender配置方法

log4j.appender.appenderName=className

log4j.appender.appenderName.O1=xxx1

... ...

log4j.appender.appenderName.ON=xxxN

 

3Layouts

Log4jAppenders中增加Layouts来定义日志格式,Layouts提供了四种日输出的样式

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

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

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

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

 

Layouts的配置方法

log4j.appender.appenderName.layout=className

log4j.appender.appenderName.layout.O1=xxx1

... ...

log4j.appender.appenderName.layout.ON=xxxN


四、log4j配置详解

应用中需要对LoggerAppenderLayout进行详细的设定,log4j支持xmlproperties形式的两种配置,下面是properties类型日志的详细配置。

1,配置root Logger

log4j.rootLogger=[level],appenderName1,appenderName2,... ...

Level为日志的最低级别,可设置OFFFATALERRORWARNINFODEBUGALL或者自定义的级别,一般是ERRORWARNINFODEBUGALL这几个级别,这里是总开关,如设置了INFODEBUG级别的日志不会打印。

appenderName则是指定日志输出到什么地方,可以配置多个,“,”号分割

定义各个包的日志级别可以

log4j.logger.org.springframework=error设置org.springframework包的日志级别为ERROR,表示org.springframework包下只打印大于等于ERROR级别的日志,没有设置的包按照root的定义打印

2,配置Appender

 

1)ConsoleAppender

Threshold:日志最低级别

encoding:编码

ImmediateFlushtrue或者falsetrue表示日志会立即输出,默认true

2)FileAppender

Threshold:日志最低级别

encoding:编码

ImmediateFlushtrue或者falsetrue表示日志会立即输出,默认true

File:日志文件路径

Appendtrue或者falsetrue日志追加到指定文件中,默认为truefalse时会覆盖

DatePattern

3)DailyRollingFileAppender

Threshold:日志最低级别

encoding:编码

ImmediateFlushtrue或者falsetrue表示日志会立即输出,默认true

File:日志文件路径

Appendtrue或者falsetrue日志追加到指定文件中,默认为truefalse时会覆盖

DatePattern’_yyyyMMdd.HH’每小时产生一个新文件,可以按照分,时,天,周,月来滚动日志文件

yyyyMM每月

yyyyww每周

yyyyMMdd每天

yyyyMMdda每天两次

yyyyMMddHH每小时

yyyyMMddHHmm每分钟

4)RollingFileAppender

Threshold:日志最低级别

encoding:编码

ImmediateFlushtrue或者falsetrue表示日志会立即输出,默认true

File:日志文件路径

Appendtrue或者falsetrue日志追加到指定文件中,默认为truefalse时会覆盖

MaxFileSize:日志文件大小,超过后产生新的文件,后缀可以使MBKBGB

MaxBackupIndex:设置产生滚动文件的最大数

Appender中也可以增加Filter,来过滤日志信息,符合条件的日志才会被打印。

3,配置Layout

主要看一下使用率比较高的ConversionPattern的格式化符号

%p:输出日志级别,即DEBUGINFOWARNERRORFATAL

%d:输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,如:%d{yyyy-MM-dd HH:mm:ss,SSS}

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

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

%l:输出日志事件的发生位置,相当于%c.%M(%F:%L)的组合,包括类全名、方法、文件名以及在代码中的行数。例如:test.TestLog4j.main(TestLog4j.java:10)

%c:输出日志信息所属的类目,通常就是所在类的全名。

%M:输出产生日志信息的方法名。

%F:输出日志消息产生时所在的文件名称。

%L::输出代码中的行号。

%m::输出代码中指定的具体日志信息。

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

%x:输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。

%%:输出一个"%"字符。

另外,还可以在%与格式字符之间加上修饰符来控制其最小长度、最大长度、和文本的对齐方式。如:

1) c:指定输出category的名称,最小的长度是20,如果category的名称长度小于20的话,默认的情况下右对齐。

2)%-20c"-"号表示左对齐。

3)%.30c:指定输出category的名称,最大的长度是30,如果category的名称长度大于30的话,就会将左边多出的字符截掉,但小于30的话也不会补空格。

 

properties配置样例:

log4j.rootLogger=DEBUG,console,dailyFile,imlog4j.additivity.org.apache=true# 控制台(console)log4j.appender.console=org.apache.log4j.ConsoleAppenderlog4j.appender.console.Threshold=DEBUGlog4j.appender.console.ImmediateFlush=truelog4j.appender.console.Target=System.errlog4j.appender.console.layout=org.apache.log4j.PatternLayoutlog4j.appender.console.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n# 日志文件(logFile)log4j.appender.logFile=org.apache.log4j.FileAppenderlog4j.appender.logFile.Threshold=DEBUGlog4j.appender.logFile.ImmediateFlush=truelog4j.appender.logFile.Append=truelog4j.appender.logFile.File=D:/logs/log.log4jlog4j.appender.logFile.layout=org.apache.log4j.PatternLayoutlog4j.appender.logFile.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n# 回滚文件(rollingFile)log4j.appender.rollingFile=org.apache.log4j.RollingFileAppenderlog4j.appender.rollingFile.Threshold=DEBUGlog4j.appender.rollingFile.ImmediateFlush=truelog4j.appender.rollingFile.Append=truelog4j.appender.rollingFile.File=D:/logs/log.log4jlog4j.appender.rollingFile.MaxFileSize=200KBlog4j.appender.rollingFile.MaxBackupIndex=50log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayoutlog4j.appender.rollingFile.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n# 定期回滚日志文件(dailyFile)log4j.appender.dailyFile=org.apache.log4j.DailyRollingFileAppenderlog4j.appender.dailyFile.Threshold=DEBUGlog4j.appender.dailyFile.ImmediateFlush=truelog4j.appender.dailyFile.Append=truelog4j.appender.dailyFile.File=D:/logs/log.log4jlog4j.appender.dailyFile.DatePattern='.'yyyy-MM-ddlog4j.appender.dailyFile.layout=org.apache.log4j.PatternLayoutlog4j.appender.dailyFile.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n# 应用于socketlog4j.appender.socket=org.apache.log4j.RollingFileAppenderlog4j.appender.socket.RemoteHost=localhostlog4j.appender.socket.Port=5001log4j.appender.socket.LocationInfo=true# Set up for Log Factor 5log4j.appender.socket.layout=org.apache.log4j.PatternLayoutlog4j.appender.socket.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n# Log Factor 5 Appenderlog4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appenderlog4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000# 发送日志到指定邮件log4j.appender.mail=org.apache.log4j.net.SMTPAppenderlog4j.appender.mail.Threshold=FATALlog4j.appender.mail.BufferSize=10log4j.appender.mail.From = xxx@mail.comlog4j.appender.mail.SMTPHost=mail.comlog4j.appender.mail.Subject=Log4J Messagelog4j.appender.mail.To= xxx@mail.comlog4j.appender.mail.layout=org.apache.log4j.PatternLayoutlog4j.appender.mail.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n# 应用于数据库log4j.appender.database=org.apache.log4j.jdbc.JDBCAppenderlog4j.appender.database.URL=jdbc:mysql://localhost:3306/testlog4j.appender.database.driver=com.mysql.jdbc.Driverlog4j.appender.database.user=rootlog4j.appender.database.password=log4j.appender.database.sql=INSERT INTO LOG4J (Message) VALUES('=[%-5p] %d(%r) --> [%t] %l: %m %x %n')log4j.appender.database.layout=org.apache.log4j.PatternLayoutlog4j.appender.database.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n# 自定义Appenderlog4j.appender.im = net.cybercorlin.util.logger.appender.IMAppenderlog4j.appender.im.host = mail.cybercorlin.netlog4j.appender.im.username = usernamelog4j.appender.im.password = passwordlog4j.appender.im.recipient = corlin@cybercorlin.netlog4j.appender.im.layout=org.apache.log4j.PatternLayoutlog4j.appender.im.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n

xml配置样例

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">    <log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/' >      <!-- Appenders --> <appender name="console" class="org.apache.log4j.ConsoleAppender">    <param name="Threshold" value="ALL"/>  <param name="encoding" value="UTF-8"/>  <layout class="org.apache.log4j.PatternLayout">   <param name="ConversionPattern" value="%-d{yyyy-MM-dd HH:mm:ss}\t[%p]\t%m%n" />  </layout> </appender>    <appender name="error" class="org.apache.log4j.DailyRollingFileAppender">  <param name="File" value="/home/work/logs/error_log" />  <param name="Append" value="true" />  <param name="encoding" value="UTF-8"/>  <param name="DatePattern" value="_yyyyMMdd.HH"/>  <layout class="org.apache.log4j.PatternLayout">   <param name="ConversionPattern" value="%-d{yyyy-MM-dd HH:mm:ss}\t[%p]\t%m%n" />  </layout>  <filter class="org.apache.log4j.varia.LevelRangeFilter">   <param name="levelMin" value="DEBUG" />   <param name="levelMax" value="ERROR" />   <param name="AcceptOnMatch" value="true" />  </filter> </appender>    <appender name="access" class="org.apache.log4j.DailyRollingFileAppender">  <param name="File" value="/home/work/logs/access_log" />  <param name="Append" value="true" />  <param name="encoding" value="UTF-8"/>  <param name="DatePattern" value="_yyyyMMdd.HH"/>  <layout class="org.apache.log4j.PatternLayout">   <param name="ConversionPattern" value="%m%n" />  </layout>  <filter class="com.ttt.logs.HJLogFilter">   <param name="levelMin" value="ACCESS" />   <param name="levelMax" value="ACCESS" />   <param name="AcceptOnMatch" value="true" />  </filter> </appender>    <appender name="service" class="org.apache.log4j.DailyRollingFileAppender">  <param name="File" value="/home/work/logs/service_log" />  <param name="Append" value="true" />  <param name="encoding" value="UTF-8"/>  <param name="DatePattern" value="_yyyyMMdd.HH"/>  <layout class="org.apache.log4j.PatternLayout">   <param name="ConversionPattern" value="%m%n" />  </layout>  <filter class="com.ttt.logs.HJLogFilter">   <param name="levelMin" value="SERVICE" />   <param name="levelMax" value="SERVICE" />   <param name="AcceptOnMatch" value="true" />  </filter> </appender>  <!-- Root Logger --> <root>  <priority value="ALL" />   <appender-ref ref="console"/>  <appender-ref ref="error"/>  <appender-ref ref="access"/>  <appender-ref ref="service"/> </root></log4j:configuration>

自定义Filter

public class HJLogFilter extends Filter {boolean acceptOnMatch = false;      private String levelMin;          private String levelMax;      public static int getLevel(String level){  level = level.toUpperCase();  if(level.equals("ACCESS")){  return LevelType.ACCESS.getType();  }  if(level.equals("SERVICE")){  return LevelType.SERVICE.getType();  }  if(level.equals("OFF")){  return LevelType.OFF.getType();  }  if(level.equals("FATAL")){  return LevelType.FATAL.getType();  }  if(level.equals("ERROR")){  return LevelType.ERROR.getType();  }  if(level.equals("INFO")){  return LevelType.INFO.getType();  }  if(level.equals("WARN")){  return LevelType.WARN.getType();  }  if(level.equals("DEBUG")){  return LevelType.DEBUG.getType();  }  if(level.equals("ALL")){  return LevelType.ALL.getType();  }  return LevelType.OFF.getType();  }            public String getLevelMin() {          return levelMin;      }        public void setLevelMin(String levelMin) {          this.levelMin = levelMin;      }        public String getLevelMax() {          return levelMax;      }        public void setLevelMax(String levelMax) {          this.levelMax = levelMax;      }        public boolean isAcceptOnMatch() {          return acceptOnMatch;      }        public void setAcceptOnMatch(boolean acceptOnMatch) {          this.acceptOnMatch = acceptOnMatch;      }  @Overridepublic int decide(LoggingEvent arg0) {// TODO Auto-generated method stubint inputLevel = arg0.getLevel().toInt();  if(inputLevel >= getLevel(levelMin) && inputLevel <= getLevel(levelMax)){  return 0;  }         return -1;  }private static enum LevelType{  OFF(2147483647),  FATAL(50000),  ERROR(40000),  WARN(30000),  INFO(20000),  DEBUG(10000),  ALL(-2147483648),  ACCESS(1000),SERVICE(1001);  int type;  public int getType() {  return type;  }  private LevelType(int type) {  this.type = type;  }  } }

自定义日志级别

public class HJCustomLog {    private static class CustomerLogLevel extends Level{          public CustomerLogLevel(int level, String levelStr, int syslogEquivalent) {              super(level, levelStr, syslogEquivalent);          }                         static final long serialVersionUID = 3491141966387921974L;    }            private static final Level accessLevel = new CustomerLogLevel(    HJLogFilter.getLevel("ACCESS"),     "ACCESS",     SyslogAppender.LOG_LOCAL0);          private static final Level serviceLevel = new CustomerLogLevel(    HJLogFilter.getLevel("SERVICE"),     "SERVICE",     SyslogAppender.LOG_LOCAL0);            public static void accessLog(Logger logger,String objLogInfo){          logger.log(accessLevel, objLogInfo);      }          public static void serviceLog(Logger logger,String objLogInfo){          logger.log(serviceLevel, objLogInfo);      }  }


日志的记录也和应用场景有关,生产环境(pro)一般要比测试环境(test)和开发环境(dev)日志更加谨慎,生产环境要提高日志的级别,不打印调试信息,数据库信息,sql等。一方面,生产系统要求安全性高,另一方面,生产环境吞吐量比较大时,日志会急剧增长,占用存储空间。

(完)