OK,现在我们认真的研究下Logger的配置,进行相关配置扩展。

Log4j有三个主要的组件:Loggers(记录器),Appenders(输出源)和Layouts(布局)。其中,Logger负责记录日志,Appender负责输出到什么地方,Layout负责以什么格式输出,输出哪些附加信息等。综合使用这三个组件可以轻松的记录信息的类型和级别,并可以在运行时控制日志输出的样式和位置。



  • Log4J三个核心概念

公共类     Logger      
负责处理日志记录的大部分操作。 

公共接口   Appender    
负责控制日志记录的输出。 

公共抽象类   Layout    
负责格式化Appender的输出





Logger日志记录器是日志处理的核心组件。现在我们来认真的整理下这个组件。Logger就是Java代码中的logger,例如:

  1. public static Logger log = Logger.getLogger(Log4jTest.class);

Logger是有名字的,它的名字便是Logger.getLogger()方法的参数。如果参数为所在的类,Log4j会去类名作为logger的名称,比如org.linkinpark.commons.logtest.Log4jTest。

Loggers组件在此系统中被分为五个级别:TRACE→DEBUG→INFO→WARNING→ERROR→FATAL→OFF。等级高的level自动屏蔽等级低的level,这点一定要记住。

这里Log4j有一个规则:假设Loggers级别为P,如果在Loggers中发生了一个级别Q比P高,则可以启动,否则屏蔽掉。假设你定义的级别是info,那么error和warn的日志可以显示而比他低的debug信息就不显示了。



注意以下几点:

1,Logger为单态模式,相同名字的logger只会有一个实例。如果在构建一个同名的Logger,log4j会返回之前的Logger实例。

2,一般情况下都以类名作为Logger的名称。Logger的名字类似于Java中的Package,大小写敏感,用点分开且具有继承关系。log4j.properties中通过名称来配置Logger的属性。

3,在对Logger实例进行命名时,没有限制,可以取任意自己感兴趣的名字。一般情况下建议以类的所在位置来命名Logger实例,这是目前来讲比较有效的Logger命名方式。这样可以使得每个类建立自己的日志信息,便于管理。

4,Log4j中有一个根记录器rootLogger,它是所有Logger的父类。



  • logger的配置

在log.properties配置log4j.properties中,log4j.logger后面配置的是Logger,log4j.appender后面配置一个Appender。

  1. log4j.logger.org.linkinpark.commons.logtest.Log4jTest=INFO,console

如果某个Logger没有配置,则使用它的父亲配置,知道找到为止。一般情况下,只需要配置根记录器rootLogger即可,所有的logger都会沿用rootLogger的配置。

  • rootLogger配置

根记录器rootLogger直接用log4j.rootLogger配置即可。rootLogger是所有记录器的父亲,任何记录器都可以继承rootLogger的配置,代码如下:

  1. #log4j.rootLogger=DEBUG,console,file
  2. #log4j.logger.org.linkinpark.commons.logtest.Log4jTest=INFO
  3. log4j.rootLogger=INFO,console
  4.  
  5. #输出到控制台
  6. log4j.appender.console=org.apache.log4j.ConsoleAppender
  7. #设置输出样式
  8. log4j.appender.console.layout=org.apache.log4j.PatternLayout
  9. #日志输出信息格式为
  10. log4j.appender.console.layout.ConversionPattern=[%-d{yyyy-MM-dd HH:mm:ss}]-[%t-%5p]-[%C-%M(%L)]: %m%n

注意:如果要对某个Logger进行特殊的输出,只需要再配置一下该Logger就OK,覆盖父亲的配置即可。覆盖时,可以只配置级别,输出地,也可以2者都配置。



OK,现在我们举一个例子好了。

比如我现在有如下需求,一般的日志打印我都按照某一种特定的配置就够了,但是有一个类比较特殊,我需要进行特殊的配置那么要如何做呢?

1,写好2个Java源码,输出日志

2,主要是写好这个log4j.properties文件。先定义rootLogger,然后子类重新配置覆盖rootLogger就够了。但是丫的有一个问题就是说如果子类重新定义了appender,仍然会继承rootLogger的配置,也就是说2份日志输出了,我晕。

所以以后建议控制子类重写覆盖rootLogger配置的时候,只重写日志级别好了,其他的别动。OK,现在贴出代码:

  1. package org.linkinpark.commons.logtest;
  2.  
  3. import org.apache.log4j.Logger;
  4.  
  5. /**
  6. * @创建作者: LinkinPark
  7. * @创建时间: 2016年2月23日
  8. * @功能描述: 这个类用log4j的rootLogger默认输出
  9. */
  10. public class Log4jTest
  11. {
  12.  
  13. public static Logger log = Logger.getLogger(Log4jTest.class);
  14.  
  15. /**
  16. * @创建时间: 2016年2月22日
  17. * @相关参数:
  18. * @功能描述: 定义一个输出日志的方法
  19. * <p>
  20. * trace→debug→info→warn→error→fatal→off
  21. * 级别依次升高,级别高的level会屏蔽级别低的level。
  22. * </p>
  23. */
  24. public static void logTest()
  25. {
  26. System.out.println("=======这里是rootLogger类的日志输出======");
  27. if (log.isDebugEnabled())
  28. {
  29. log.debug("debug级别的日志输出");
  30. }
  31. log.trace("trace级别的日志输出");
  32. log.info("info级别的日志输出");
  33. log.warn("warn级别的日志输出");
  34. log.error("error级别的日志输出");
  35. log.fatal("fatal级别的日志输出");
  36. try
  37. {
  38. System.out.println(9 / 0);
  39. }
  40. catch (RuntimeException e)
  41. {
  42. log.error(e.getMessage());
  43. }
  44. }
  45.  
  46. public static void main(String[] args)
  47. {
  48. logTest();
  49. }
  50.  
  51. }
  1. package org.linkinpark.commons.logtest;
  2.  
  3. import org.apache.log4j.Logger;
  4.  
  5. /**
  6. * @创建作者: LinkinPark
  7. * @创建时间: 2016年2月23日
  8. * @功能描述: 这个类重新配置,来重写rootLogger的日志级别
  9. */
  10. public class Log4jTest1
  11. {
  12.  
  13. public static Logger log = Logger.getLogger(Log4jTest1.class);
  14.  
  15. /**
  16. * @创建时间: 2016年2月22日
  17. * @相关参数:
  18. * @功能描述: 定义一个输出日志的方法
  19. * <p>
  20. * trace→debug→info→warn→error→fatal→off
  21. * 级别依次升高,级别高的level会屏蔽级别低的level。
  22. * </p>
  23. */
  24. public static void logTest()
  25. {
  26. System.out.println("=======这里是特定类的日志输出======");
  27. log.info("info级别的日志输出");
  28. log.warn("warn级别的日志输出");
  29. log.error("error级别的日志输出");
  30. log.fatal("fatal级别的日志输出");
  31. try
  32. {
  33. throw new NullPointerException("人工抛出一个异常");
  34. }
  35. catch (RuntimeException e)
  36. {
  37. log.error(e.getMessage());
  38. }
  39. }
  40.  
  41. public static void main(String[] args)
  42. {
  43. logTest();
  44. Log4jTest.logTest();
  45. }
  46.  
  47. }
  1. # 可设置级别:TRACE→DEBUG→INFO→WARNING→ERROR→FATAL→OFF
  2. # 高级别level会屏蔽低级别level。
  3. # debug:显示debug、info、error
  4. # info:显示info、error
  5.  
  6. #log4j.rootLogger=DEBUG,console,file
  7. log4j.logger.org.linkinpark.commons.logtest.Log4jTest1=ERROR
  8. log4j.rootLogger=INFO,console
  9.  
  10. # 一下是rootLogger的配置,子类默认继承,但是子类重写下面配置=rootLogger+自己配置,我晕
  11. #输出到控制台
  12. log4j.appender.console=org.apache.log4j.ConsoleAppender
  13. #设置输出样式
  14. log4j.appender.console.layout=org.apache.log4j.PatternLayout
  15. #日志输出信息格式为
  16. log4j.appender.console.layout.ConversionPattern=[%-d{yyyy-MM-dd HH:mm:ss}]-[%t-%5p]-[%C-%M(%L)]: %m%n
  17.  
  18. #输出到文件(这里默认为追加方式)
  19. #log4j.appender.file=org.apache.log4j.FileAppender
  20. #log4j.appender.file.File=F:/LinkinPark/logs/Log4J.log
  21. #样式为TTCCLayout
  22. #log4j.appender.file.layout=org.apache.log4j.TTCCLayout
  23.  
  24. #自定义样式
  25. #%c 输出所属的类目,通常就是所在类的全名
  26. #%C 输出Logger所在类的名称,通常就是所在类的全名
  27. #%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss , SSS},%d{ABSOLUTE},%d{DATE}
  28. #%F 输出所在类的类名称,只有类名。
  29. #%l 输出语句所在的行数,包括类名+方法名+文件名+行数
  30. #%L 输出语句所在的行数,只输出数字
  31. #%m 输出代码中指定的讯息,如log(message)中的message
  32. #%M 输出方法名
  33. #%p 输出日志级别,即DEBUG,INFO,WARN,ERROR,FATAL
  34. #%r 输出自应用启动到输出该log信息耗费的毫秒数
  35. #%t 输出产生该日志事件的线程名
  36. #%n 输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n”
  37. #%% 用来输出百分号“%”
  38. #log4j.appender.Linkin.layout.ConversionPattern=%n[%l%d{yy/MM/dd HH:mm:ss:SSS}][%C-%M] %m
  39. #log4j.appender.Linkin.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss}[%C]-[%p] %m%n
  40. #log4j.appender.Linkin.layout.ConversionPattern = %d{ABSOLUTE} %5p %t %c{2}:%L - %m%n

OK,现在我们来看下控制台输出,没问题。

  1. =======这里是特定类的日志输出======
  2. [2016-02-23 00:23:54]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest1-logTest(24)]: error级别的日志输出
  3. [2016-02-23 00:23:54]-[main-FATAL]-[org.linkinpark.commons.logtest.Log4jTest1-logTest(25)]: fatal级别的日志输出
  4. [2016-02-23 00:23:54]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest1-logTest(32)]: 人工抛出一个异常
  5. =======这里是rootLogger类的日志输出======
  6. [2016-02-23 00:23:54]-[main- INFO]-[org.linkinpark.commons.logtest.Log4jTest-logTest(27)]: info级别的日志输出
  7. [2016-02-23 00:23:54]-[main- WARN]-[org.linkinpark.commons.logtest.Log4jTest-logTest(28)]: warn级别的日志输出
  8. [2016-02-23 00:23:54]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest-logTest(29)]: error级别的日志输出
  9. [2016-02-23 00:23:54]-[main-FATAL]-[org.linkinpark.commons.logtest.Log4jTest-logTest(30)]: fatal级别的日志输出
  10. [2016-02-23 00:23:54]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest-logTest(37)]: / by zero



  • 类别category配置

logger还有一个类别(category)的概念,荣国设置类别来设置类别下所有的logger。category类似于Java的package,效果和Logger的名字等价。这里也举一个例子好了:

OK,我们复制前面的log4jTest到一个新的包logtest1下,2份Java代码不变,然后设置配置文件控制不同的日志级别,来看看效果。

  



  1. # 可设置级别:TRACE→DEBUG→INFO→WARNING→ERROR→FATAL→OFF
  2. # 高级别level会屏蔽低级别level。
  3. # debug:显示debug、info、error
  4. # info:显示info、error
  5.  
  6. #log4j.rootLogger=DEBUG,console,file
  7. #子类重新定义日志级别,logger的名字是日志类的权限类名
  8. #log4j.logger.org.linkinpark.commons.logtest.Log4jTest1=ERROR
  9. #子类重新定义日志级别,category的名字是日志类的包名,可以将category理解为Java的package。
  10. log4j.category.org.linkinpark.commons.logtest1=ERROR
  11. log4j.rootLogger=DEBUG,console
  12.  
  13. # 以下是rootLogger的配置,子类默认继承,但是子类重写下面配置=rootLogger+自己配置,我晕
  14. #输出到控制台
  15. log4j.appender.console=org.apache.log4j.ConsoleAppender
  16. #设置输出样式
  17. log4j.appender.console.layout=org.apache.log4j.PatternLayout
  18. #日志输出信息格式为
  19. log4j.appender.console.layout.ConversionPattern=[%-d{yyyy-MM-dd HH:mm:ss}]-[%t-%5p]-[%C-%M(%L)]: %m%n
  20.  
  21. #输出到文件(这里默认为追加方式)
  22. #log4j.appender.file=org.apache.log4j.FileAppender
  23. #log4j.appender.file.File=F:/LinkinPark/logs/Log4J.log
  24. #样式为TTCCLayout
  25. #log4j.appender.file.layout=org.apache.log4j.TTCCLayout
  26.  
  27. #自定义样式
  28. #%c 输出所属的类目,通常就是所在类的全名
  29. #%C 输出Logger所在类的名称,通常就是所在类的全名
  30. #%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss , SSS},%d{ABSOLUTE},%d{DATE}
  31. #%F 输出所在类的类名称,只有类名。
  32. #%l 输出语句所在的行数,包括类名+方法名+文件名+行数
  33. #%L 输出语句所在的行数,只输出数字
  34. #%m 输出代码中指定的讯息,如log(message)中的message
  35. #%M 输出方法名
  36. #%p 输出日志级别,即DEBUG,INFO,WARN,ERROR,FATAL
  37. #%r 输出自应用启动到输出该log信息耗费的毫秒数
  38. #%t 输出产生该日志事件的线程名
  39. #%n 输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n”
  40. #%% 用来输出百分号“%”
  41. #log4j.appender.Linkin.layout.ConversionPattern=%n[%l%d{yy/MM/dd HH:mm:ss:SSS}][%C-%M] %m
  42. #log4j.appender.Linkin.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss}[%C]-[%p] %m%n
  43. #log4j.appender.Linkin.layout.ConversionPattern = %d{ABSOLUTE} %5p %t %c{2}:%L - %m%n

OK,我们现在看下控制台输出:没问题,成功输出我们自己定义的特定的包下面的日志,并且按照我们自己配置的日志级别。

  1. =======这里是特定包下面类的日志输出======
  2. [2016-02-23 00:39:56]-[main-ERROR]-[org.linkinpark.commons.logtest1.Log4jTest1-logTest(30)]: error级别的日志输出
  3. [2016-02-23 00:39:56]-[main-FATAL]-[org.linkinpark.commons.logtest1.Log4jTest1-logTest(31)]: fatal级别的日志输出
  4. [2016-02-23 00:39:56]-[main-ERROR]-[org.linkinpark.commons.logtest1.Log4jTest1-logTest(38)]: 人工抛出一个异常
  5. =======这里是rootLogger类的日志输出======
  6. [2016-02-23 00:39:56]-[main-DEBUG]-[org.linkinpark.commons.logtest.Log4jTest-logTest(29)]: debug级别的日志输出
  7. [2016-02-23 00:39:56]-[main- INFO]-[org.linkinpark.commons.logtest.Log4jTest-logTest(32)]: info级别的日志输出
  8. [2016-02-23 00:39:56]-[main- WARN]-[org.linkinpark.commons.logtest.Log4jTest-logTest(33)]: warn级别的日志输出
  9. [2016-02-23 00:39:56]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest-logTest(34)]: error级别的日志输出
  10. [2016-02-23 00:39:56]-[main-FATAL]-[org.linkinpark.commons.logtest.Log4jTest-logTest(35)]: fatal级别的日志输出
  11. [2016-02-23 00:39:56]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest-logTest(42)]: / by zero

OK,下一篇我会整理到日志的输出组件Appender。

Log4j扩展使用--日志记录器Logger的更多相关文章

  1. Log4j扩展使用--日志格式化器Layout

    Layout:格式化输出日志信息 OK,前面我已经知道了.Appender必须使用一个与之相关联的Layout,这样才能知道怎样格式化输出日志信息. 日志格式化器Layout负责格式化日志信息,方法l ...

  2. Java日志系统---Logger之简单入门

    Java 中自带的日志系统,今天抽空了解了一点,算是入了门,所以将自己的一些心得记录下来,以备日后查看,有兴趣的朋友,看到此文章,觉得有错误或需要添加的地方,请在下方评论留言,大家可以共同进步,谢谢: ...

  3. tomcat源码阅读之日志记录器(Logger)

    UML图: 1.Logger接口中定义了日志的级别:FATAL.ERROR.WARNING.INFORMATION.DEBUG,通过接口函数getVerbosity获取日志级别,setVerbosit ...

  4. Log4j扩展使用--自定义输出

    写在前面的话 log4j支持自定义的输出.所有的输出都实现了自Appender接口.一般来说,自定义输出值需要继承AppenderSkeleton类,并实现几个方法就可以了. 写这篇博客,我主要也是想 ...

  5. ASP.NET Core搭建多层网站架构【7-使用NLog日志记录器】

    2020/01/29, ASP.NET Core 3.1, VS2019, NLog.Web.AspNetCore 4.9.0 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站 ...

  6. log4j、logback日志框架与统一接口slf4j说明

    log4j 传入日志框架,老项目中使用较多. 日志级别 根日志级别 log4j.rootLogger=info 默认日志级别,设置后对于没有设置子级别的日志输出都走这个默认值. 子类日志级别 log4 ...

  7. 《手把手教你》系列基础篇(八十七)-java+ selenium自动化测试-框架设计基础-Log4j 2实现日志输出-上篇(详解教程)

    1.简介 Apache Log4j 是一个非常古老的日志框架,并且是多年来最受欢迎的日志框架. 它引入了现代日志框架仍在使用的基本概念,如分层日志级别和记录器. 2015 年 8 月 5 日,该项目管 ...

  8. Log4j 输出的日志中时间比系统时间少了8小时的解决方法,log4j日志文件重复输出

    1. 第一个问题:时间少了8小时 Log4j 输出的日志中,时间比系统时间少了8小时,但是 eclipse 控制台输出的日志的时间却是对的. log4j配置如下: #all logger output ...

  9. spring log4j.properties 没有日志的问题

    一.   log4j.properties 1. log4j.properties放在spring工程的src/main/rescours目录下无法读取. 测试后发现需要把log4j.properti ...

随机推荐

  1. Linux笔记---硬盘添加

    BZ创建了一个块云硬盘添加到了虚拟机里,然后按照平时挂在U盘的方式去挂载硬盘: mount  -t ext4 /dev/vdb  /mnt/xxxx 结果报出以下错误: mount: wrong fs ...

  2. virtuoso数据库的安装方法

    数据库virtuoso有两种安装配置方式 第一种就是直接在系统中默认安装,拷贝virtuoso的安装文件,直接默认安装. 第二种是配置安装方式 参考地址:http://vos.openlinksw.c ...

  3. Java学习笔记8(面向对象一:概念、private)

    面向过程的思想:遇到问题,想,我该怎么解决这个问题?然后一步一步解决 面向对象的思想:遇到一件事的时候,思考,我该让谁来做,至于他怎样去做,不是我需要考虑的事情,只要最后做好就行 实际举例:我们要组装 ...

  4. 【转】adb shell dumpsys 命令

    adb shell dumpsys,默认打印出当前系统所有service信息,在后面可加上具体的服务名 需要列出当前运行的服务,可运行: adb shell dumpsys | findstr DUM ...

  5. 使用阿里云镜像maven管理配置开发环境

    修改方法:在~/.m2目录下的settings.xml文件中,(如果该文件不存在,则需要从maven/conf目录下拷贝一份),找到<mirrors>标签,添加如下子标签: <mir ...

  6. golang其实也可以优先调度

    线上一个服务有个严重问题,处理消息数1k/s提升不上去,经过查看是阻塞在了一个新加的函数上,这个函数负责收集信息,送到一个channel上,再由某个函数处理,这个处理函数很简单,看不出任何问题,最大的 ...

  7. ES6小点心之通用弹窗

    小点心,顾名思义,开箱即食,拿来即用. 前端业务逻辑主要分为[交互效果]和[数据展示]两方面.数据展示可使用 MVVM 框架来实现.前端的交互效果常用的也就那么几种,比如弹窗,楼层定位,倒计时,下拉刷 ...

  8. python基础之实现sql增删改查

    # encoding:utf-8 # Author:"richie" # Date:2017/8/2 import re key_l = ['id', 'name', 'age', ...

  9. 小乔注:java关键字this

    java中当一个对象创建后,java虚拟机就会给这个对象分配一个指向自己的指针,称为this.this随实例化对象而产生,因此this只用于非静态方法体内.主要有以下四点应用: 1.调用当前类的成员变 ...

  10. 访问taotao-portal 中controller中返回taotaoresult 测试httppost方法 出现406错误

    方案:1.检查jackson包是否存在 @controller @RequestMapping(value = "/httpclient/post",method=RequestM ...