log4j打印日志

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中增加配置

	
		log4jConfigLocation
		classpath:log4j.xml
	

3web.xml中增加监听

	
	org.springframework.web.util.Log4jConfigListener
	

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

三、Log4j组件简介

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

1Loggers

Loggers组件默认有5个级别,即DEBUG,INFO,WARN,ERROR,FATAL,五个日志的级别是DEBUG用来指定日志的级别,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,im
log4j.additivity.org.apache=true
# 控制台(console)
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n

# 日志文件(logFile)
log4j.appender.logFile=org.apache.log4j.FileAppender
log4j.appender.logFile.Threshold=DEBUG
log4j.appender.logFile.ImmediateFlush=true
log4j.appender.logFile.Append=true
log4j.appender.logFile.File=D:/logs/log.log4j
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
log4j.appender.logFile.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# 回滚文件(rollingFile)
log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.Threshold=DEBUG
log4j.appender.rollingFile.ImmediateFlush=true
log4j.appender.rollingFile.Append=true
log4j.appender.rollingFile.File=D:/logs/log.log4j
log4j.appender.rollingFile.MaxFileSize=200KB
log4j.appender.rollingFile.MaxBackupIndex=50
log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout
log4j.appender.rollingFile.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# 定期回滚日志文件(dailyFile)
log4j.appender.dailyFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyFile.Threshold=DEBUG
log4j.appender.dailyFile.ImmediateFlush=true
log4j.appender.dailyFile.Append=true
log4j.appender.dailyFile.File=D:/logs/log.log4j
log4j.appender.dailyFile.DatePattern='.'yyyy-MM-dd
log4j.appender.dailyFile.layout=org.apache.log4j.PatternLayout
log4j.appender.dailyFile.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# 应用于socket
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 Factor 5
log4j.appender.socket.layout=org.apache.log4j.PatternLayout
log4j.appender.socket.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# Log Factor 5 Appender
log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000
# 发送日志到指定邮件
log4j.appender.mail=org.apache.log4j.net.SMTPAppender
log4j.appender.mail.Threshold=FATAL
log4j.appender.mail.BufferSize=10
log4j.appender.mail.From = [email protected]
log4j.appender.mail.SMTPHost=mail.com
log4j.appender.mail.Subject=Log4J Message
log4j.appender.mail.To= [email protected]
log4j.appender.mail.layout=org.apache.log4j.PatternLayout
log4j.appender.mail.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %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('=[%-5p] %d(%r) --> [%t] %l: %m %x %n')
log4j.appender.database.layout=org.apache.log4j.PatternLayout
log4j.appender.database.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n

# 自定义Appender
log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender
log4j.appender.im.host = mail.cybercorlin.net
log4j.appender.im.username = username
log4j.appender.im.password = password
log4j.appender.im.recipient = [email protected]
log4j.appender.im.layout=org.apache.log4j.PatternLayout
log4j.appender.im.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n

xml配置样例


    
      

   
  
  
  
   
  
   
 
 
  
  
  
  
  
   
  
  
   
   
   
  
   
 
 
  
  
  
  
  
   
  
  
   
   
   
  
   
 
 
  
  
  
  
  
   
  
  
   
   
   
  
   

 
   
  
  
  
  
 

自定义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;  
    }  

	@Override
	public int decide(LoggingEvent arg0) {
		// TODO Auto-generated method stub
		
		int 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等。一方面,生产系统要求安全性高,另一方面,生产环境吞吐量比较大时,日志会急剧增长,占用存储空间。

(完)

你可能感兴趣的:(Java)