|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +categories: [Java] |
| 4 | +description: none |
| 5 | +keywords: Java |
| 6 | +--- |
| 7 | +# Logback日志实战 |
| 8 | +logback 用于日志记录,可以将日志输出到控制台、文件、数据库和邮件等,相比其它所有的日志系统,logback 更快并且更小,包含了许多独特并且有用的特性。 |
| 9 | + |
| 10 | +## Logback优点 |
| 11 | +Logback和log4j非常相似,优点如下: |
| 12 | +- Logback的内核重写,在一些关键执行路径上性能提升10倍以上。同时,初始化内存加载也更小。 |
| 13 | +- Logback经过数年的测试,这是简单重要的原因选择logback而不是log4j。 |
| 14 | +- 因为logback-classic非常自然地实现了SLF4J,所以切换到log4j非常容易,只需要提供另一个jar包就OK,不需要去动通过SLF4JAPI实现的代码。 |
| 15 | +- 非常充分的文档 |
| 16 | +- 当配置文件修改了,Logback-classic能自动重新加载配置文件。扫描过程快且安全,它并不需要另外创建一个扫描线程。 |
| 17 | +- Lilith是log事件的观察者,和log4j的chainsaw类似。而lilith还能处理大数量的log数据 。 |
| 18 | +- 在谨慎模式下,多个FileAppender实例跑在多个JVM下,能够安全地写到同一个日志文件。RollingFileAppender会有些限制。Logback的FileAppender和它的子类包括 RollingFileAppender能够非常友好地从I/O异常中恢复。 |
| 19 | +- 开发人员经常需要判断不同的Logback配置文件在不同的环境下(开发,测试,生产)。而这些配置文件仅仅只有一些很小的不同,可以通过,来实现,这样一个配置文件就可以适应多个环境。 |
| 20 | +- 有些时候,需要诊断一个问题,需要打出日志。在log4j,只有降低日志级别,不过这样会打出大量的日志,会影响应用性能。在Logback,你可以继续保持那个日志级别而除掉某种特殊情况,如alice这个用户登录,它的日志将打在DEBUG级别而其他用户可以继续打在WARN级别。要实现这个功能只需加4行XML配置。可以参考MDCFIlter 。 |
| 21 | +- 它可以用来分割日志文件根据任何一个给定的运行参数。如,SiftingAppender能够区别日志事件跟进用户的Session,然后每个用户会有一个日志文件。 |
| 22 | +- RollingFileAppender在产生新文件的时候,会自动压缩已经打出来的日志文件。压缩是个异步过程,在压缩过程中应用不会受任何影响。 |
| 23 | +- Logback在打出堆栈树日志时,会带上包的数据。 |
| 24 | +- 通过设置TimeBasedRollingPolicy或者SizeAndTimeBasedFNATP的maxHistory属性,你可以控制已经产生日志文件的最大数量。 |
| 25 | + |
| 26 | +## logback的加载 |
| 27 | +我们简单分析一下logback加载过程,当我们使用logback-classic.jar时,应用启动,那么logback会按照如下顺序进行扫描: |
| 28 | +- 在系统配置文件System Properties中寻找是否有logback.configurationFile对应的value |
| 29 | +- 在classpath下寻找是否有logback.groovy(即logback支持groovy与xml两种配置方式) |
| 30 | +- 在classpath下寻找是否有logback-test.xml |
| 31 | +- 在classpath下寻找是否有logback.xml |
| 32 | + |
| 33 | +以上任何一项找到了,就不进行后续扫描,按照对应的配置进行logback的初始化,具体代码实现可见ch.qos.logback.classic.util.ContextInitializer类的findURLOfDefaultConfigurationFile方法。当所有以上四项都找不到的情况下,logback会调用ch.qos.logback.classic.BasicConfigurator的configure方法,构造一个ConsoleAppender用于向控制台输出日志,默认日志输出格式为"%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"。 |
| 34 | + |
| 35 | +## logback的configuration |
| 36 | +logback的重点应当是Appender、Logger、Pattern,在这之前先简单了解一下logback的,只有三个属性: |
| 37 | +scan:当scan被设置为true时,当配置文件发生改变,将会被重新加载,默认为truescanPeriod:检测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认为毫秒,当scan=true时这个值生效,默认时间间隔为1分钟debug:当被设置为true时,将打印出logback内部日志信息,实时查看logback运行信息,默认为false |
| 38 | + |
| 39 | +### logger |
| 40 | +logger用来设置某一个包或者具体某一个类的日志打印级别、以及指定**。 |
| 41 | + |
| 42 | +可以包含零个或者多个元素,标识这个appender将会添加到这个logger。 |
| 43 | + |
| 44 | +仅有一个name属性、一个可选的level属性和一个可选的additivity属性: |
| 45 | +- name:用来指定受此logger约束的某一个包或者具体的某一个类 |
| 46 | +- level:用来设置打印级别,五个常用打印级别从低至高依次为TRACE、DEBUG、INFO、WARN、ERROR,如果未设置此级别,那么当前logger会继承上级的级别 |
| 47 | +- additivity:是否向上级logger传递打印信息,默认为true |
| 48 | + |
| 49 | +也是元素,但是 它是根logger,只有一个level属性,因为它的name就是ROOT ,源码在LoggerContext中: |
| 50 | +``` |
| 51 | +public LoggerContext() { |
| 52 | + super(); |
| 53 | + this.loggerCache = new ConcurrentHashMap<String, Logger>(); |
| 54 | + this.loggerContextRemoteView = new LoggerContextVO(this); |
| 55 | + this.root = new Logger(Logger.ROOT_LOGGER_NAME, null, this); |
| 56 | + this.root.setLevel(Level.DEBUG); |
| 57 | + loggerCache.put(Logger.ROOT_LOGGER_NAME, root); |
| 58 | + initEvaluatorMap(); |
| 59 | + size = 1; |
| 60 | + this.frameworkPackages = new ArrayList<String>(); |
| 61 | +} |
| 62 | +``` |
| 63 | +看到第一个参数就是Root的name,而这个Logger.ROOT_LOGGER_NAME的定义为 final public String ROOT_LOGGER_NAME = "ROOT" ,由此可以看出节点的name就是"ROOT"。 |
| 64 | + |
| 65 | +## 引入依赖 |
| 66 | +logback 天然的支持 slf4j,不需要像其他日志框架一样引入适配层(如 log4j 需引入 slf4j-log4j12 )。logback 只是将适配相关代码放入了 logback-classic。 |
| 67 | +```xml |
| 68 | +<dependencies> |
| 69 | + <dependency> |
| 70 | + <groupId>junit</groupId> |
| 71 | + <artifactId>junit</artifactId> |
| 72 | + <version>4.12</version> |
| 73 | + <scope>test</scope> |
| 74 | + </dependency> |
| 75 | + <!-- logback+slf4j --> |
| 76 | + <dependency> |
| 77 | + <groupId>org.slf4j</groupId> |
| 78 | + <artifactId>slf4j-api</artifactId> |
| 79 | + <version>1.7.28</version> |
| 80 | + <type>jar</type> |
| 81 | + <scope>compile</scope> |
| 82 | + </dependency> |
| 83 | + <dependency> |
| 84 | + <groupId>ch.qos.logback</groupId> |
| 85 | + <artifactId>logback-core</artifactId> |
| 86 | + <version>1.2.3</version> |
| 87 | + <type>jar</type> |
| 88 | + </dependency> |
| 89 | + <dependency> |
| 90 | + <groupId>ch.qos.logback</groupId> |
| 91 | + <artifactId>logback-classic</artifactId> |
| 92 | + <version>1.2.3</version> |
| 93 | + <type>jar</type> |
| 94 | + </dependency> |
| 95 | + </dependencies> |
| 96 | +``` |
| 97 | + |
| 98 | + |
| 99 | + |
| 100 | + |
0 commit comments