1、日志的级别:

我们现在要调用logger的方法,不过在这个Logger对象中,有很多方法,所以要先了解log4j的日志级别,log4j规定了默认的几个级别:trace<debug<info<warn<error<fatal等。这里要说明一下:

1)级别之间是包含的关系,意思是如果你设置日志级别是trace,则大于等于这个级别的日志都会输出。

2)基本上默认的级别没多大区别,就是一个默认的设定。你可以通过它的API自己定义级别。你也可以随意调用这些方法,不过你要在配置文件里面好好处理了,否则就起不到日志的作用了,而且也不易读,相当于一个规范,你要完全定义一套也可以,不用没多大必要。

3)这不同的级别的含义大家都很容易理解,这里就简单介绍一下:

trace: 是追踪,就是程序推进以下,你就可以写个trace输出,所以trace应该会特别多,不过没关系,我们可以设置最低日志级别不让他输出。

debug: 调试么,我一般就只用这个作为最低级别,trace压根不用。是在没办法就用eclipse或者idea的debug功能就好了么。

info: 输出一下你感兴趣的或者重要的信息,这个用的最多了。

warn: 有些信息不是错误信息,但是也要给程序员的一些提示,类似于eclipse中代码的验证不是有error 和warn(不算错误但是也请注意,比如以下depressed的方法)。

error: 错误信息。用的也比较多。

fatal: 级别比较高了。重大错误,这种级别你可以直接停止程序了,是不应该出现的错误么!不用那么紧张,其实就是一个程度的问题。

2、日志调用:

这里随便写个类,调用就是这么简单,log4j的核心在配置文件上。

 
  1. import org.apache.logging.log4j.Level;

  2. import org.apache.logging.log4j.LogManager;

  3. import org.apache.logging.log4j.Logger;

  4. public class Hello {

  5. static Logger logger = LogManager.getLogger(Hello.class.getName());

  6. public boolean hello() {

  7. logger.entry(); //trace级别的信息,单独列出来是希望你在某个方法或者程序逻辑开始的时候调用,和logger.trace("entry")基本一个意思

  8. logger.error("Did it again!"); //error级别的信息,参数就是你输出的信息

  9. logger.info("我是info信息"); //info级别的信息

  10. logger.debug("我是debug信息");

  11. logger.warn("我是warn信息");

  12. logger.fatal("我是fatal信息");

  13. logger.log(Level.DEBUG, "我是debug信息"); //这个就是制定Level类型的调用:谁闲着没事调用这个,也不一定哦!

  14. logger.exit(); //和entry()对应的结束方法,和logger.trace("exit");一个意思

  15. return false;

  16. }

  17. }

如果没有自定义配置文件,上面这个类在写一个main方法,控制台会输入下面的样子:

 
  1. 19:09:40.256 [main] ERROR cn.lsw.base.log4j2.Hello - Did it again!

  2. 19:09:40.260 [main] FATAL cn.lsw.base.log4j2.Hello - 我是fatal信息

看到没,只有>=ERROR的日志输出来了(这是因为Log4j有一个默认的配置,它的日志级别是ERROR,输出只有控制台)。如果我已经定义好了日志,我把日志级别改成了TRACE,输出会变成下面这样:

 
  1. 19:11:36.941 TRACE cn.lsw.base.log4j2.Hello 12 hello - entry

  2. 19:11:36.951 ERROR cn.lsw.base.log4j2.Hello 13 hello - Did it again!

  3. 19:11:36.951 INFO cn.lsw.base.log4j2.Hello 14 hello - 我是info信息

  4. 19:11:36.951 DEBUG cn.lsw.base.log4j2.Hello 15 hello - 我是debug信息

  5. 19:11:36.951 WARN cn.lsw.base.log4j2.Hello 16 hello - 我是warn信息

  6. 19:11:36.952 FATAL cn.lsw.base.log4j2.Hello 17 hello - 我是fatal信息

  7. 19:11:36.952 DEBUG cn.lsw.base.log4j2.Hello 18 hello - 我是debug信息

  8. 19:11:36.952 TRACE cn.lsw.base.log4j2.Hello 19 hello - exit

所有的日志都打印出来了,大家可以对照上面的代码看一看。

3. 配置文件:

现在开始正题了。

本来以为Log4J 2应该有一个默认的配置文件的,不过好像没有找到,下面这个配置文件等同于缺省配置:

 
  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <configuration status="OFF">

  3. <appenders>

  4. <Console name="Console" target="SYSTEM_OUT">

  5. <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>

  6. </Console>

  7. </appenders>

  8. <loggers>

  9. <root level="error">

  10. <appender-ref ref="Console"/>

  11. </root>

  12. </loggers>

  13. </configuration>

而我们只要把configuration>loggers>root的level属性改为trace,就可以输出刚才写的所有信息了。相信用过Log4j的人对这个配置文件也不算陌生,Log4J传统的配置一直是.properties文件,键值对的形式,那种配置方式很不好看,但是基本上我们从这个配置文件也能看到Log4J 1的影子,无非是appender了,layout之类的,含义也基本一样的。

这里不准备仔细的讲配置文件,没什么必要,大家只要知道一些基本的配置就可以了。我这里写几个配置文件,并且给了一定的注释和讲解,基本上可以用了。

 第一个例子:

 
  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <configuration status="OFF">

  3. <appenders>

  4. <Console name="Console" target="SYSTEM_OUT">

  5. <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>

  6. </Console>

  7. </appenders>

  8. <loggers>

  9. <!--我们只让这个logger输出trace信息,其他的都是error级别-->

  10. <!--

  11. additivity开启的话,由于这个logger也是满足root的,所以会被打印两遍。

  12. 不过root logger 的level是error,为什么Bar 里面的trace信息也被打印两遍呢

  13. -->

  14. <logger name="cn.lsw.base.log4j2.Hello" level="trace" additivity="false">

  15. <appender-ref ref="Console"/>

  16. </logger>

  17. <root level="error">

  18. <appender-ref ref="Console"/>

  19. </root>

  20. </loggers>

  21. </configuration>

先简单介绍一下下面这个配置文件。

1)根节点configuration,然后有两个子节点:appenders和loggers(都是复数,意思就是可以定义很多个appender和logger了)(如果想详细的看一下这个xml的结构,可以去jar包下面去找xsd文件和dtd文件)

2)appenders:这个下面定义的是各个appender,就是输出了,有好多类别,这里也不多说(容易造成理解和解释上的压力,一开始也未必能听懂,等于白讲),先看这个例子,只有一个Console,这些节点可不是随便命名的,Console就是输出控制台的意思。然后就针对这个输出设置一些属性,这里设置了PatternLayout就是输出格式了,基本上是前面时间,线程,级别,logger名称,log信息等,差不多,可以自己去查他们的语法规则。

3)loggers下面会定义许多个logger,这些logger通过name进行区分,来对不同的logger配置不同的输出,方法是通过引用上面定义的logger,注意,appender-ref引用的值是上面每个appender的name,而不是节点名称。

这个例子为了说明什么呢?我们要说说这个logger的name(名称)了(前面有提到)。

4、 name的机制:

 我们这里看到了配置文件里面是name很重要,没错,这个name可不能随便起(其实可以随便起)。这个机制意思很简单。就是类似于java package一样,比如我们的一个包:cn.lsw.base.log4j2。而且,可以发现我们前面生成Logger对象的时候,命名都是通过 Hello.class.getName(); 这样的方法,为什么要这样呢? 很简单,因为有所谓的Logger 继承的问题。比如 如果你给cn.lsw.base定义了一个logger,那么他也适用于cn.lsw.base.lgo4j2这个logger。名称的继承是通过点(.)分隔的。然后你可以猜测上面loggers里面有一个子节点不是logger而是root,而且这个root没有name属性。这个root相当于根节点。你所有的logger都适用与这个logger,所以,即使你在很多类里面通过  类名.class.getName()  得到很多的logger,而且没有在配置文件的loggers下面做配置,他们也都能够输出,因为他们都继承了root的log配置。

我们上面的这个配置文件里面还定义了一个logger,他的名称是 cn.lsw.base.log4j2.Hello ,这个名称其实就是通过前面的Hello.class.getName(); 得到的,我们为了给他单独做配置,这里就生成对于这个类的logger,上面的配置基本的意思是只有cn.lsw.base.log4j2.Hello 这个logger输出trace信息,也就是他的日志级别是trace,其他的logger则继承root的日志配置,日志级别是error,只能打印出ERROR及以上级别的日志。如果这里logger 的name属性改成cn.lsw.base,则这个包下面的所有logger都会继承这个log配置(这里的包是log4j的logger name的“包”的含义,不是java的包,你非要给Hello生成一个名称为“myhello”的logger,他也就没法继承cn.lsw.base这个配置了。

那有人就要问了,他不是也应该继承了root的配置了么,那么会不会输出两遍呢?我们在配置文件中给了解释,如果你设置了additivity="false",就不会输出两遍,否则,看下面的输出:

这里要在加入一个类做对比: 

 
  1. import org.apache.logging.log4j.LogManager;

  2. import org.apache.logging.log4j.Logger;

  3. public class Test {

  4. private static Logger logger = LogManager.getLogger(Test.class.getName());

  5. public static void main(String[] args) {

  6. logger.trace("开始程序.");

  7. Hello hello= new Hello();

  8. // for (int i = 0; i < 10000;i++){

  9. if (!hello.hello()) {

  10. logger.error("hello");

  11. }

  12. // }

  13. logger.trace("退出程序.");

  14. }

  15. }

这里先把配置文件改一下方便对照,一个是刚才第一个logger的名称还是cn.lsw.base.log4j2.Hello,additivity去掉或改为true(因为默认是true,所以可以去掉),第二是把root的level改为info方便观察。 

然后运行Test,看控制台的日志输出:

 
  1. 2013-12-20 19:59:42.538 [main] INFO cn.lsw.base.log4j2.Test - test

  2. 2013-12-20 19:59:42.541 [main] TRACE cn.lsw.base.log4j2.Hello - entry

  3. 2013-12-20 19:59:42.541 [main] TRACE cn.lsw.base.log4j2.Hello - entry

  4. 2013-12-20 19:59:42.542 [main] ERROR cn.lsw.base.log4j2.Hello - Did it again!

  5. 2013-12-20 19:59:42.542 [main] ERROR cn.lsw.base.log4j2.Hello - Did it again!

  6. 2013-12-20 19:59:42.542 [main] INFO cn.lsw.base.log4j2.Hello - 我是info信息

  7. 2013-12-20 19:59:42.542 [main] INFO cn.lsw.base.log4j2.Hello - 我是info信息

  8. 2013-12-20 19:59:42.542 [main] DEBUG cn.lsw.base.log4j2.Hello - 我是debug信息

  9. 2013-12-20 19:59:42.542 [main] DEBUG cn.lsw.base.log4j2.Hello - 我是debug信息

  10. 2013-12-20 19:59:42.542 [main] WARN cn.lsw.base.log4j2.Hello - 我是warn信息

  11. 2013-12-20 19:59:42.542 [main] WARN cn.lsw.base.log4j2.Hello - 我是warn信息

  12. 2013-12-20 19:59:42.542 [main] FATAL cn.lsw.base.log4j2.Hello - 我是fatal信息

  13. 2013-12-20 19:59:42.542 [main] FATAL cn.lsw.base.log4j2.Hello - 我是fatal信息

  14. 2013-12-20 19:59:42.542 [main] DEBUG cn.lsw.base.log4j2.Hello - 我是debug信息

  15. 2013-12-20 19:59:42.542 [main] DEBUG cn.lsw.base.log4j2.Hello - 我是debug信息

  16. 2013-12-20 19:59:42.543 [main] TRACE cn.lsw.base.log4j2.Hello - exit

  17. 2013-12-20 19:59:42.543 [main] TRACE cn.lsw.base.log4j2.Hello - exit

  18. 2013-12-20 19:59:42.543 [main] ERROR cn.lsw.base.log4j2.Test - hello

可以看出,Test的trace日志没有输出,因为他继承了root的日志配置,只输出info即以上级别的日志。Hello 输出了trace及以上级别的日志,但是每个都输出了两遍。你可以试一下,把第一个logger的level该为error,那么error以上的级别也是输出两遍。这时候,只要加上additivity为false就可以避免这个问题了。

当然,你可以为每个logger 都在配置文件下面做不同的配置,也可以通过继承机制,对不同包下面的日志做不同的配置。因为loggers下面可以写很多歌logger。

下面在看一个稍微复杂的例子:

 
  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <configuration status="error">

  3. <!--先定义所有的appender-->

  4. <appenders>

  5. <!--这个输出控制台的配置-->

  6. <Console name="Console" target="SYSTEM_OUT">

  7. <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->

  8. <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/>

  9. <!--这个都知道是输出日志的格式-->

  10. <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>

  11. </Console>

  12. <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用-->

  13. <File name="log" fileName="log/test.log" append="false">

  14. <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>

  15. </File>

  16. <!--这个会打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->

  17. <RollingFile name="RollingFile" fileName="logs/app.log"

  18. filePattern="log/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">

  19. <PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/>

  20. <SizeBasedTriggeringPolicy size="50MB"/>

  21. </RollingFile>

  22. </appenders>

  23. <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->

  24. <loggers>

  25. <!--建立一个默认的root的logger-->

  26. <root level="trace">

  27. <appender-ref ref="RollingFile"/>

  28. <appender-ref ref="Console"/>

  29. </root>

  30. </loggers>

  31. </configuration>

说复杂,其实也不复杂,这一个例子主要是为了讲一下appenders。

这里定义了三个appender,Console,File,RollingFile,看意思基本也明白,第二个是写入文件,第三个是“循环”的日志文件,意思是日志文件大于阀值的时候,就开始写一个新的日志文件。

这里我们的配置文件里面的注释算比较详细的了。所以就大家自己看了。有一个比较有意思的是ThresholdFilter ,一个过滤器,其实每个appender可以定义很多个filter,这个功能很有用。如果你要选择控制台只能输出ERROR以上的类别,你就用ThresholdFilter,把level设置成ERROR,onMatch="ACCEPT" onMismatch="DENY" 的意思是匹配就接受,否则直接拒绝,当然有其他选择了,比如交给其他的过滤器去处理了之类的,详情大家自己去琢磨吧。

log4 日志级别使用相关推荐

  1. Go 学习笔记(54)— Go 第三方库之 uber-go/zap/lumberjack(记录日志到文件、支持自动分割日志、支持日志级别、打印调用文件、函数和行号)

    1. 简要说明 zap 是 uber 开源的 Go 高性能日志库,支持不同的日志级别, 能够打印基本信息等,但不支持日志的分割,这里我们可以使用 lumberjack 也是 zap 官方推荐用于日志分 ...

  2. syslog打印不带等级_printk的日志级别和控制台级别

    printk根据日志级别(loglevel)对消息进行分类.日志级别用宏定义,日志级别宏展开为一个字符串,在编译时由预处理器将它和消息文本拼接成一个字符串,因此printk 函数中日志级别宏和格式字符 ...

  3. log4j的日志级别(ssm中log4j的配置)

    log4j定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从高到低依次为:OFF.FATAL.ERROR.WARN.INFO.DEBUG.TRACE. ALL. 1. ALL ...

  4. 修改Hadoop的日志级别

    参考文章:http://www.cnblogs.com/jasondan/p/set_hadoop_log_level.html Hadoop版本:2.7.3. Hadoop的默认日志级别为INFO, ...

  5. 手写logback_springboot logback调整mybatis日志级别无效的解决

    springboot logback调整mybatis日志级别无效的解决 现象 在日志配置文件 logback-spring.xml 中,无论怎么修改级别,mybatis 的 sql 日志都会打印出来 ...

  6. SpringBoot实用小技巧之动态设置SpringBoot日志级别

    有时线上问题我们用打日志的方式来观察错误或埋点参数,但由于这些日志如果都打出来会占用大量存储空间而且覆盖了一些有效信息,所以线上级别一般设置INFO,调试级别用作特殊情况下.此时如果线上想查看调试级别 ...

  7. Logback中使用TurboFilter实现日志级别等内容的动态修改

    可能看到这个标题,读者会问:要修改日志的级别,不是直接修改log.xxx就好了吗?为何要搞那么复杂呢? 所以,先说一下场景,为什么要通过TurboFilter去动态的修改日志级别.我们在使用Java开 ...

  8. C语言日志级别和作用,自己写的C语言通用日志框架,可以控制日志输出等级

    /************************************c语言通用日志框架************************************ * * @author 南栀(ke ...

  9. java自定义日志级别_自定义log4j日志级别

    因为项目中需要输出一些特别的日志来做数据统计.如果开启log4j提供的INFO日志级别,每天生成的日志文件就会变得越来越大.这样就得写个定 时任务来删除这个文件.为了只输出所需的日志级别,唯有自己定义 ...

最新文章

  1. 第六次作业——团队作业
  2. junit测试起名字规则_如何在JUnit 5中替换规则
  3. c语言中的set是置1嘛,c ++ - 如何检查元素是否在std :: set中?
  4. LeetCode:2. 两数相加(中等)
  5. 稳定性测试怎么做,这篇文章彻底讲透了
  6. Day02:requests请求库,selenium请求库
  7. java和jsp交互 structs_Struts与jsp+javabean+servlet区别
  8. pytorch ImageFolder
  9. linux 端口映射 命令
  10. 工业相机在全息成像中的应用
  11. 新萝卜家园 Ghost XP SP3 电脑城装机专用版 10.5
  12. 实验室安全,研究生生涯发展与规划平时练习答案,雨课堂/学堂云
  13. 研究生教育学科专业目录(2022年)与研究生教育学科专业目录管理办法
  14. 小型餐厅管理系统 java_小型餐饮管理系统的设计与实现(JSP,MySQL)
  15. 从事IC设计工作强度大不大?是吃青春饭吗?
  16. Java Document 工具类
  17. JS中Math对象的方法
  18. 你会刷牙吗?图解正确刷牙方法
  19. 小明左、右手中分别拿两张纸牌(比如:黑桃10和红桃8,数字10和8可通过键盘录入),要求编写代码交换小明手中的牌
  20. 【学习笔记】域名资源记录(Resource Record)

热门文章

  1. accept 和 content-Type区别
  2. 用GetDta获取图片中柱状图数据
  3. busybox的实现原理分析(C语言实现简易版的busybox)
  4. CMOS器件与TTL器件CMOS电平与TTL电平
  5. 解决请在微信客服端打开链接问题
  6. android 键盘弹出时会将view里面的内容顶上去
  7. 阿里云添加管理员用户
  8. linux中的wget命令
  9. 【String】字符串中是否有空格(indexOf、split)
  10. SpringCloud 基本使用