Log 之log的基本架构及必须知道特性

1.log的基本架构

一个日志记录器最基本的架构由三块组成:

  • Logger 日志记录器
  • Appender 日志追加器(目的地)
  • Layout 日志输出格式

其中Logger 是我们开发者在代码中直接使用的对象是通过LoggerFactory来得到的

package org.slf4j; 
public interface Logger {
  // Logger 是一个org.slf4j的一个接口,包含如下方法
  public void trace(String message);
  public void debug(String message);
  public void info(String message); 
  public void warn(String message); 
  public void error(String message); 
}

//取得Logger 对象
Logger rootLogger = LoggerFactory.getLogger(MyClass.class);

架构中的每个组件,后续文章将讲解。

2.log中必须知道的特性

2.1 Logger 中的特性

package ch.qos.logback.classic;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.classic.util.LoggerNameUtil;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.spi.AppenderAttachable;
import ch.qos.logback.core.spi.AppenderAttachableImpl;
import ch.qos.logback.core.spi.FilterReply;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
import org.slf4j.spi.LocationAwareLogger;
public final class Logger implements org.slf4j.Logger, LocationAwareLogger, AppenderAttachable<ILoggingEvent>, Serializable {
    private static final long serialVersionUID = 5454405123156820674L;
    public static final String FQCN = Logger.class.getName();
    private String name;
    private transient Level level;
    private transient int effectiveLevelInt;
    private transient Logger parent;
    private transient List<Logger> childrenList;
    private transient AppenderAttachableImpl<ILoggingEvent> aai;
    private transient boolean additive = true;
    final transient LoggerContext loggerContext;
    private static final int DEFAULT_CHILD_ARRAY_SIZE = 5;

从Logger的源码中我们可以看到 他有一个name ,level,parent ,childrenList 属性。从parent,childrenList 我们可以推测Logger有继承的特点;level 分级别。
日志配置文件中的体现形式:

<logger name="chapters.configuration" level="INFO"/>

2.1.1 Logger的 命名层次结构

logback官方文档中

Named Hierarchy
A logger is said to be an ancestor of another logger if its name followed by a dot is a prefix of the descendant logger name. A logger is said to be a parent of a child logger if there are no ancestors between itself and the descendant logger.

For example, the logger named “com.foo” is a parent of the logger named “com.foo.Bar”. Similarly, “java” is a parent of “java.util” and an ancestor of “java.util.Vector”.

大概的意思 name为com.foo的logger 是 name为com.foo.Bar的的父Logger。
所谓的命名层次结构,个人理解就是Logger中的继承并且Logger中的name 是以包为单位的。
我们在上篇文章就讲过,我们开发者可以针对抽象层编程, Logger的最顶层抽象为org.slf4j.Logger。 他的name为 root,root就跟Object差不多的意思.

package org.slf4j;

public interface Logger {
    String ROOT_LOGGER_NAME = "ROOT";

2.1.1 Logger的 level

该属性指定Logger记录器的日志输出级别。 logback官方文档中可以有以下几个可选值

The set of possible levels (TRACE, DEBUG, INFO, WARN and ERROR) are defined in the ch.qos.logback.classic.Level class.

同样的 level 也具有继承特性,其中 root默认level =debug。也就是说 一个Logger 如果没有显示指出 level的value那么该 logger 将向上查找第一个显示定义了level属性的上级logger并以他的level做为日志输出级别。如下图
这里写图片描述

2.1.2 Logger根据level 输出不同级别的日志

logback 官方文档中 日志输出策略

Basic Selection Rule
A log request of level p issued to a logger having an effective level q, is enabled if p >= q. (如果要想输出 p级别的日志,那就得确保 p>= 该logger 生效的级别q.)
This rule is at the heart of logback. It assumes that levels are ordered as follows: TRACE < DEBUG < INFO < WARN < ERROR.

这里写图片描述

2.2 Appender中的特性

日志追加器即日志的输出目的地。logback的官方文档中

Appender Additivity
The output of a log statement of logger L will go to all the appenders in L and its ancestors. This is the meaning of the term “appender additivity”.
However, if an ancestor of logger L, say P, has the additivity flag set to false, then L’s output will be directed to all the appenders in L and its ancestors up to and including P but not the appenders in any of the ancestors of P.
Loggers have their additivity flag set to true by default.

appender 通常是 Logger 关联的一个属性值,因为 Logger 有继承特性,那就会导致 下层Logger 将会有多个 appender 。如下图:
这里写图片描述

从图中我们可以看出 名为x的logger 有两个appender 分别是 A-x1,A-x2 但是输出目标确有A1,A-x1,A-x2三个,是因为 名为root 的logger 有个appender 为A1。

如果我们只想将日志输出到 本logger中,而不想输出到父类logger中我们可以将该logger的属性additivity=false。

猜你喜欢

转载自blog.csdn.net/u014297148/article/details/80071250
log