zoukankan      html  css  js  c++  java
  • Log4j的使用


    OK,现在我们开始研究Log4j。Log4j是目前应用最广泛的日志空间,它分如下几个日志级别,日志级别依次升高。级别高的level会屏蔽级别低的信息。

    TRACE→DEBUG→INFO→WARNING→ERROR→FATAL→OFF。

    比如设置INFO级别,TRACE,DEBUG就不会输出,如果设置WARNING级别,则TRACE,DEBUG,INFO都不会输出。


    • Log4j初体验
    现在我们编码尝试下Log4j。代码如下:
    package org.linkinpark.commons.logtest;
    
    import org.apache.log4j.Logger;
    
    public class Log4jTest
    {
    
    	public static Logger log = Logger.getLogger(Log4jTest.class);
    
    	/**
    	 * @创建时间: 2016年2月22日
    	 * @相关参数:
    	 * @功能描述: 定义一个输出日志的方法
    	 * <p>
    	 * trace→debug→info→warn→error→fatal→off
    	 * 级别依次升高,级别高的level会屏蔽级别低的level。
    	 * </p>
    	 */
    	public static void logTest()
    	{
    		log.trace("trace级别的日志输出");
    		log.info("info级别的日志输出");
    		log.debug("debug级别的日志输出");
    		log.warn("warn级别的日志输出");
    		log.error("error级别的日志输出");
    		log.fatal("fatal级别的日志输出");
    		try
    		{
    			System.out.println(9 / 0);
    		}
    		catch (RuntimeException e)
    		{
    			log.error(e.getMessage());
    		}
    	}
    
    	public static void main(String[] args)
    	{
    		logTest();
    	}
    
    }
    
    这里我们用maven来管理我们该测试项目,需要添加log4j的pom依赖。

    <dependency>
    			<groupId>log4j</groupId>
    			<artifactId>log4j</artifactId>
    			<version>1.2.17</version>
    		</dependency>
    日志的配置例如输出级别,输出到哪里,输出什么附加信息,输出格式等,一般都要写在配置文件log4j.properties中。
    #	可设置级别:TRACE→DEBUG→INFO→WARNING→ERROR→FATAL→OFF
    #	高级别level会屏蔽低级别level。
    #	debug:显示debug、info、error   
    #	info:显示info、error   
    
    #log4j.rootLogger=DEBUG,console,file
    log4j.rootLogger=INFO,console
      
      
    #输出到控制台   
    log4j.appender.console=org.apache.log4j.ConsoleAppender  
    #设置输出样式   
    log4j.appender.console.layout=org.apache.log4j.PatternLayout 
    #日志输出信息格式为
    log4j.appender.console.layout.ConversionPattern=[%-d{yyyy-MM-dd HH:mm:ss}]-[%t-%5p]-[%C-%M(%L)]: %m%n 
    
    #输出到文件(这里默认为追加方式)   
    #log4j.appender.file=org.apache.log4j.FileAppender 
    #log4j.appender.file.File=F:/LinkinPark/logs/Log4J.log 
    #样式为TTCCLayout   
    #log4j.appender.file.layout=org.apache.log4j.TTCCLayout  
    
    #自定义样式   
    #%c	输出所属的类目,通常就是所在类的全名 
    #%C	输出Logger所在类的名称,通常就是所在类的全名 
    #%d	输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss , SSS},%d{ABSOLUTE},%d{DATE}
    #%F	输出所在类的类名称,只有类名。
    #%l	输出语句所在的行数,包括类名+方法名+文件名+行数
    #%L	输出语句所在的行数,只输出数字
    #%m	输出代码中指定的讯息,如log(message)中的message
    #%M	输出方法名
    #%p	输出日志级别,即DEBUG,INFO,WARN,ERROR,FATAL
    #%r	输出自应用启动到输出该log信息耗费的毫秒数
    #%t	输出产生该日志事件的线程名
    #%n	输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n”
    #%%	用来输出百分号“%”
    #log4j.appender.Linkin.layout.ConversionPattern=%n[%l%d{yy/MM/dd HH:mm:ss:SSS}][%C-%M] %m  
    #log4j.appender.Linkin.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss}[%C]-[%p] %m%n   
    #log4j.appender.Linkin.layout.ConversionPattern = %d{ABSOLUTE} %5p %t %c{2}:%L - %m%n
    


    OK,现在让我们来看看控制台输出的日志情况。

    [2016-02-22 22:33:35]-[main- INFO]-[org.linkinpark.commons.logtest.Log4jTest-logTest(22)]: info级别的日志输出
     [2016-02-22 22:33:35]-[main- WARN]-[org.linkinpark.commons.logtest.Log4jTest-logTest(24)]: warn级别的日志输出
     [2016-02-22 22:33:35]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest-logTest(25)]: error级别的日志输出
     [2016-02-22 22:33:35]-[main-FATAL]-[org.linkinpark.commons.logtest.Log4jTest-logTest(26)]: fatal级别的日志输出
     [2016-02-22 22:33:35]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest-logTest(33)]: / by zero
     


    Log4j的使用十分灵活,功能也很强大。可以在配置文件中配置输出样式,可以把日志输出到屏幕,控制台,各种样式的文件,数据库,FTP服务器,HTTP服务器,远程实时监控程序,发送邮件到指定的邮箱,甚至是发送短信等。

    • Log4J的应用
    Log4J是Apache的一个开源项目,通过使用Log4J,我们可以控制日志信息输送的目的地,输出格式,通过设置日志信息的级别还可以细致地控制日志的生成过程。

    • 1,Log4j的执行效率
    Log4j内部做了大量的优化,缓存工作,是输出时对服务器的压力,消耗时间,资源等都达到最小,比如下面2行代码:
    log.debug("debug级别的日志输出");
    log.info("info级别的日志输出");
    这两句日志可能被记录到日志文件中,但是写的过程不同于常规的打开文件,写文件,关闭文件等流程,频繁的打开文件,关闭文件需要消耗大量的资源。Log4j只在初始化的时候打开文件,并保持对文件的写控制,知道在系统结束的时候才会关闭文件。这样就使I/O次数达到最小,提高了运行效率。

    当输出级别设置为ERROR时,debug,info等低级别方法会因为输出级别小于error而直接返回,所以不会消耗太多的资源。这里我们来看下debug()方法内部的实现代码:
    public void debug(Object message)
    	{
    		if (repository.isDisabled(Level.DEBUG_INT))
    			return;
    		if (Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel()))
    		{
    			forcedLog(FQCN, Level.DEBUG, message, null);
    		}
    	}
    
    


    • 2,优化日志代码

    虽然设为ERROR时debug()会直接返回,但是下面的代码仍然会消耗额外的时间,原因是在执行debug()前,需要先将字符串进行连接。

    log.debug("debug级别的日志输出"+i+"*"+j); // 有字符串拼接

    如果想要避免这种消耗,最好使用isDebugEnabled()或者isEnabledFor()判断一下,比如下面代码:

    if (log.isDebugEnabled())
    		{
    			log.debug("debug级别的日志输出");
    		}
    		if (log.isEnabledFor(Level.DEBUG))
    		{
    			log.debug("debug级别的日志输出");
    		}
    

    • 3,log4j配置文件
    Log4j默认的配置文件为log4j.properties。启动时,会加载classpath下的log4j.properties初始化Log4j。如果文件不存在,Log4j会在控制台打印如下信息,提示说没有找到Log4j配置。比如我们现在只保留Java代码,然后删除掉log4j.properties配置文件,看控制台报错。
    log4j:WARN No appenders could be found for logger (org.linkinpark.commons.logtest.Log4jTest).
    log4j:WARN Please initialize the log4j system properly.
    log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

    OK,现在重新将log4j.properties配置文件加入到我们的项目classpath中,然后控制台输出日志正常。这里一定要注意要加载项目的Classpath中,在这里我们随便写写测试类,所以直接丢项目src下面就好了,编译过后配置文件自动就放到了class的根目录下了。


    当然我们也可以使用其他的方式,只不过不推荐罢了。如果不使用默认的文件名log4j.properties,可以用PropertyConfigurator指定配置文件的路径。比如下面的代码,经过测试可行。当然还可以使用log4j.xml,只不过要在xml里面加入log4j的secma,不推荐。这里贴出使用Java类加载指定配置文件的代码:
    public static void logTest()
    	{
    		PropertyConfigurator.configure("/Users/LinkinPark/WorkSpace/linkin-log-test/src/main/java/org/linkinpark/commons/logtest/log4j.properties");
    		if (log.isDebugEnabled())
    		{
    			log.debug("debug级别的日志输出");
    		}
    	}

    这里也贴出PropertyConfigurator类configure()方法源码:
    static public void configure(String configFilename)
    	{
    		new PropertyConfigurator().doConfigure(configFilename, LogManager.getLoggerRepository());
    	}
    
    
    	public void doConfigure(String configFileName, LoggerRepository hierarchy)
    	{
    		Properties props = new Properties();
    		FileInputStream istream = null;
    		try
    		{
    			istream = new FileInputStream(configFileName);
    			props.load(istream);
    			istream.close();
    		}
    		catch (Exception e)
    		{
    			if (e instanceof InterruptedIOException || e instanceof InterruptedException)
    			{
    				Thread.currentThread().interrupt();
    			}
    			LogLog.error("Could not read configuration file [" + configFileName + "].", e);
    			LogLog.error("Ignoring configuration file [" + configFileName + "].");
    			return;
    		}
    		finally
    		{
    			if (istream != null)
    			{
    				try
    				{
    					istream.close();
    				}
    				catch (InterruptedIOException ignore)
    				{
    					Thread.currentThread().interrupt();
    				}
    				catch (Throwable ignore)
    				{
    				}
    
    
    			}
    		}
    		// If we reach here, then the config file is alright。嫁入到log4j中去了。
    		doConfigure(props, hierarchy);
    	}

    OK,log4j的配置文件内容还是比较多的,我们下一篇来详细的整理。这篇先这样。

  • 相关阅读:
    网络流24题
    Preliminaries for Benelux Algorithm Programming Contest 2019
    2019 ICPC Asia Xuzhou Regional
    2019 ICPC Asia Nanjing Regional
    后缀自动机学习
    2018 ACM-ICPC 焦作区域赛 E Resistors in Parallel
    2019 ICPC 上海区域赛总结
    LA 3641 Leonardo的笔记本 & UVA 11077 排列统计
    UVA 10294 项链与手镯 (置换)
    CF 1288 E. Messenger Simulator
  • 原文地址:https://www.cnblogs.com/LinkinPark/p/5232852.html
Copyright © 2011-2022 走看看