• logback 配置


    1. logback 配置

    logback的配置方式包括:编程配置、XML文件配置、Groovy文件配置。对于使用log4j的用户,还可以通过logback提供的工具( http://logback.qos.ch/translator/ ) log4j.properties配置文件转换为logback.xml格式。

    logback 初始化配置的步骤如下:

    1. 在类路径下依次查找 logback.groovy, logback-test.xml, logback.xml文件;
    2. 若找到配置文件,则读取文件,配置logback
    3. 如果没找到任何配置文件,且JVM包含ServiceLoader(JDK 6以上),则由ServiceLoader解析com.qos.logback.classic.spi.Configurator的实现。
    4. 如果以上均失败,则使用BasicConfigurator的默认配置,输出日志到控制台。

     

    34两步用于在没找到配置文件时提供默认配置。

     

    1.1 logback的默认配置

    不提供配置文件,logback使用其默认配置。先给个示例代码:

    package chapters.configuration;

     

    import org.slf4j.Logger;

    import org.slf4j.LoggerFactory;

     

    public class MyApp1 {

    final static Logger logger = LoggerFactory.getLogger(MyApp1.class);

     

    public static void main(String[] args) {

    logger.info("Entering application.");

     

    Foo foo = new Foo();

    foo.doIt();

    logger.info("Exiting application.");

    }

    }

    Foo类如下:

    package chapters.configuration;

     

    import org.slf4j.Logger;

    import org.slf4j.LoggerFactory;

     

    public class Foo {

    static final Logger logger = LoggerFactory.getLogger(Foo.class);

     

    public void doIt() {

    logger.debug("Did it again!");

    }

    }

     

    假设类路径下不包含配置文件,logback使用BasicConfigurator的默认配置。该配置root logger使用ConsoleAppender,级别为DBUEG,输出格式PatternLayoutEncoder pattern%d{HH:mm:ss.SSS}[%thread]%-5level%logger{36}-%msg%n

    上例的输出如下:

    15:22:09.106 [main] INFO  manual.configuration.MyApp1 - Entering application.

    15:22:09.121 [main] DEBUG manual.configuration.Foo - Did it again!

    15:22:09.121 [main] INFO  manual.configuration.MyApp1 - Exiting application.

    MyApp1通过org.slf4j.LoggerFactoryorg.slf4j.Logger类和logback连接,除了配置logback的代码(完全可以没有),在代码上没有任何调用logback的类,在编译时依赖slf4j,但不依赖logback,所以很容易移植到其他的日志框架。

     

    1.2 使用logback-test.xmllogback.xml进行配置

    下面的XML配置文件等效于BasicConfigurator的默认配置:

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

    <configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

    <!-- encoders are assigned by default the type ch.qos.logback.classic.encoder.PatternLayoutEncoder -->

    <encoder>

    <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n

    </pattern>

    </encoder>

    </appender>

     

    <root level="debug">

    <appender-ref ref="STDOUT" />

    </root>

    </configuration>

    将该文件命名为logback.xmllogback-test.xml放在类路径下,运行MyApp1,可以得出和上面相同的输出。

     

    1.3 出现warningerrors时输出状态信息

    如果在解析配置文件时出错,logback会自动将解析错误信息输出到控制台;如果代码里已指定状态监听器,为了避免重复输出,logback会禁用自动输出功能。

    下面演示如何主动查询logback的解析状态信息(除了查询内部状态的两行代码,其他和MyApp1完全一致)

    public static void main(String[] args) {

    // 假设SLF4Jlogback绑定

    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();

    // 打印logback的内部状态

    StatusPrinter.print(lc);

    }

    其输出如下:

    15:34:26,052 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]

    15:34:26,052 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]

    15:34:26,052 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.xml]

    15:34:26,052 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Setting up default configuration.

     

    15:34:26.099 [main] INFO  chapters.configuration.MyApp2 - Entering application.

    15:34:26.114 [main] DEBUG chapters.configuration.Foo - Did it again!

    15:34:26.114 [main] INFO  chapters.configuration.MyApp2 - Exiting application.

    可以看到,后面的输出和上个例子完全一样,前面的一段输出为logback的内部状态信息。

    除了使用StatusPrinter,也在配置文件中设置(前提是配置文件无错),此时没有出错,也能输出logback内部信息。配置方法:将configuration元素的debug属性设置为true,如下所示:

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

    <configuration debug="true">

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

    <!-- encoders are assigned by default the type ch.qos.logback.classic.encoder.PatternLayoutEncoder -->

    <encoder>

    <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n

    </pattern>

    </encoder>

    </appender>

     

    <root level="debug">

    <appender-ref ref="STDOUT" />

    </root>

    </configuration>

    debug属性只控制logback内部状态数据,对其他不存在任何影响。

     

    1.4 通过系统属性指定默认配置文件位置

    使用系统属性"logback.configurationFile"可以指定logback的默认配置文件位置。该属性值可以是URL、类路径下的文件或应用外的文件路径,如下所示:

    java -Dlogback.configurationFile=/path/to/config.xml chapters.configuration.MyApp1

    文件扩展名必须为.xml.groovy

     

    1.5 修改后自动重新载入配置文件

    logback可以自动扫描配置文件,在配置文件改变时自动重新配置。配置方法:

    configurationscan属性设置为true:

    <configuration scan="true">

      

    </configuration>

    扫描时间间隔默认1 min 1次,通过configurationscanPeriod属性可以修改时间间隔:

    <configuration scan="true" scanPeriod="30 seconds">

       

    </configuration>

    NOTE:如果没指定时间单位,默认单位为毫秒

     

    1.6 直接调用JoranConfigurator

    logback的配置依赖于Joran库,该库为logback-core的一部分。logback在找到配置文件后会调用JoranConfigurator进行配置,如下所示:

    package chapters.configuration;

     

    import org.slf4j.Logger;

    import org.slf4j.LoggerFactory;

     

    import ch.qos.logback.classic.LoggerContext;

    import ch.qos.logback.classic.joran.JoranConfigurator;

    import ch.qos.logback.core.joran.spi.JoranException;

    import ch.qos.logback.core.util.StatusPrinter;

     

    public class MyApp3 {

    final static Logger logger = LoggerFactory.getLogger(MyApp3.class);

     

    public static void main(String[] args) {

    // assume SLF4J is bound to logback in the current environment

    LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();

     

    try {

    JoranConfigurator configurator = new JoranConfigurator();

    configurator.setContext(context);

    // Call context.reset() to clear any previous configuration, e.g. default

    // configuration. For multi-step configuration, omit calling context.reset().

    context.reset();

    configurator.doConfigure(args[0]);

    } catch (JoranException je) {

    // StatusPrinter will handle this

    }

    StatusPrinter.printInCaseOfErrorsOrWarnings(context);

     

    logger.info("Entering application.");

     

    Foo foo = new Foo();

    foo.doIt();

    logger.info("Exiting application.");

    }

    }

    先获得当前起作用的LoggerContext,然后创建JoranConfigurator实例,设置其作用的context实例,重置context,然后载入配置文件进行配置。

     

    1.7 查看状态信息

    logback的内置状态数据保存在StatusManager对象中,通过LoggerContext可以获得。

    为了节省内存,StatusManager将状态信息分两部分保存:header部分和tail部分。header部分保存前H个信息,tail部分保存后T个信息,H=T=150

    logback-classic里一个称为ViewStatusMessagesServlet的服务器。该服务器以HTML表格的形式打印StatusManager的内容,如下所示:

    clip_image001

    将下面的内容添加到WEB-INF/web.xml文件,可以将该服务器添加到网络应用:

    <servlet>

    <servlet-name>ViewStatusMessages</servlet-name>

    <servlet-class>ch.qos.logback.classic.ViewStatusMessagesServlet</servlet-class>

    </servlet>

     

    <servlet-mapping>

    <servlet-name>ViewStatusMessages</servlet-name>

    <url-pattern>/lbClassicStatus</url-pattern>

    </servlet-mapping>

     

    1.8 监听状态信息

    StatusManager添加StatusListener监听器,能实时监控状态信息,特别是logback配置之后的信息。logback自带的StatusListener的实现称作OnConsoleStatusListener,即,将所有的状态信息打印到控制台。

    下面演示为StatusManger注册OnConsoleStatusListener的实例:

    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();

    StatusManager statusManager = lc.getStatusManager();

    OnConsoleStatusListener onConsoleListener = new OnConsoleStatusListener();

    statusManager.add(onConsoleListener); 

    监听器只输出监听器注册后的信息,所以将监听器放在配置文件最前面比较合适(而且可以在一个配置文件中注册多个监听器),配置方法如下:

    <configuration debug="false">

    <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />

     … the rest of the configuration file

    </configuration>

     

    1.9 停止 logback-classic

    通过停止logback context,可以释放logback-classic占用的资源。停止context会关闭所有和对应logger连接的appender,并停止对应的线程:

    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();

    lc.stop();

    对网络应用,则调用ServletContextListenercontextDestroyed方法。

     

    1. 配置文件语法

    clip_image002

    如上图所示,XML配置文件根元素为<configuration>,可以包含[0,)<appender>[0,)<logger>以及[0,1]<root>元素。

     

     <logger>

    属性:

    属性名

    类型

    Use

    描述

    name

    string

    必须

     

    additivity

    bool

    可选

    是否向上级logger传递信息,默认为true

    level

    string

    可选

    TRACE,DEBUG,INFO,WARN,ERROR,ALL,OFF,不区分大小写,另有额外的两个值:INHERITEDNULL,表示从父logger继承。

    子元素:

    元素名

    minOccurs

    maxOccurs

    描述

    appender-ref

    0

    unbounded

    表示将对应的appender添加到该logger

     

    <root>

    用于配置root loggerroot logger为特殊类型的logger,因为root logger名恒为"ROOT",所以无name属性,additivity对其无效,所以只剩下一个属性需要配置:level。其可用值为:TRACE,DEBUG,INFO,WARN,ALL,OFF,不能为INHERITEDNULL

    类似于<logger><root>可以包含0或多个<appender-ref>

    实例:假如不想看到"chapters.configuration"包中任何DEBUG信息,如下

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

    <configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

    <!-- encoders are assigned by default the type ch.qos.logback.classic.encoder.PatternLayoutEncoder -->

    <encoder>

    <pattern>

    %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n

    </pattern>

    </encoder>

    </appender>

     

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

     

    <!-- 严格的说,下面的level属性是不需要的,因为root的默认值为DEBUG -->

    <root level="DEBUG">

    <appender-ref ref="STDOUT" />

    </root>

     

    </configuration>

    "chapters.configuration"level属性设置为"INFO",这样DEBUG信息均被过滤掉了。如果将该配置文件作为参数传递给MyApp3,其输出如下:

    20:59:32.913 [main] INFO  chapters.configuration.MyApp3 - Entering application.

    20:59:32.917 [main] INFO  chapters.configuration.MyApp3 - Exiting application.

    此时由"chapters.configuration.Foo"生成的DEBUG信息被抑制。

     

    可以按照自己的想法随意设置多个loggerlevel,比如,将chapters.configuration 包设置INFO,单独把Foo设置为DEBUG,如下所示:

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

    <configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

    <!-- encoders are assigned by default the type ch.qos.logback.classic.encoder.PatternLayoutEncoder -->

    <encoder>

    <pattern>

    %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n

    </pattern>

    </encoder>

    </appender>

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

    <logger name="chapters.configuration.Foo" level="DEBUG" />

    <root level="DEBUG">

    <appender-ref ref="STDOUT" />

    </root>

    </configuration>

    用该文件作为参数运行MyApp3,输出如下:

    21:16:56.913 [main] INFO  chapters.configuration.MyApp3 - Entering application.

    21:16:56.915 [main] DEBUG chapters.configuration.Foo - Did it again!

    21:16:56.916 [main] INFO  chapters.configuration.MyApp3 - Exiting application.

    下面列出上面各个logger对应的level:

    Logger

    指定的 Level

    实际的 Level

    root

    DEBUG

    DEBUG

    chapters.configuration

    INFO

    INFO

    chapters.configuration.MyApp3

    null

    INFO

    chapters.configuration.Foo

    DEBUG

    DEBUG

    由此可见,MyApp3INFOFoo.doIt()DEBUG都启用了。而root logger总是为非NULL的,其默认值为DEBUG

     

    <appender>

    clip_image003

    <appender>用于配置日志输出位置。属性:

    属性名

    类型

    Use

    描述

    name

    string

    required

    appender名,可随意取

    class

    string

    required

    appender对应的类,需包含完整路径,如输出到console对应的:class="ch.qos.logback.core.ConsoleAppender"

    子元素:

    元素名

    minOccurs

    maxOccurs

    layout

    0

    1

    encoder

    0

    unbounded

    filter

    0

    unbounded

     

    layout

    layout元素必须包含class元素,包含layout类的完全限定名。

     

    <configuration>

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">

    <file>myApp.log</file>

    <!-- encoders are assigned by default the type ch.qos.logback.classic.encoder.PatternLayoutEncoder -->

    <encoder>

    <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>

    </encoder>

    </appender>

     

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

    <encoder>

    <pattern>%msg%n</pattern>

    </encoder>

    </appender>

     

    <root level="debug">

    <appender-ref ref="FILE" />

    <appender-ref ref="STDOUT" />

    </root>

    </configuration>

     

    2.6 定义变量

    可以在配置文件中定义变量,也可以从外部导入。在logbackXML配置文件中可以用<property><variable>(1.07之后)定义变量。下面定义一个变量,用于定义输出文件位置:

    <configuration>

    <property name="USER_HOME" value="/home/sebastien" />

     

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">

    <file>${USER_HOME}/myApp.log</file>

    <encoder>

    <pattern>%msg%n</pattern>

    </encoder>

    </appender>

     

    <root level="debug">

    <appender-ref ref="FILE" />

    </root>

    </configuration>

    也可以用系统变量达到相同的目的:

    java -DUSER_HOME="/home/sebastien" MyApp2

    然后在配置文件中引用该变量:

    <configuration>

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">

    <file>${USER_HOME}/myApp.log</file>

    <encoder>

    <pattern>%msg%n</pattern>

    </encoder>

    </appender>

     

    <root level="debug">

    <appender-ref ref="FILE" />

    </root>

    </configuration>

    如果需要很多变量,则以一个单独的文件存放所有变量比较合适:

    下面的配置文件引用了一个变量:

    <configuration>

    <property file="src/main/java/chapters/configuration/variables1.properties" />

     

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">

    <file>${USER_HOME}/myApp.log</file>

    <encoder>

    <pattern>%msg%n</pattern>

    </encoder>

    </appender>

     

    <root level="debug">

    <appender-ref ref="FILE" />

    </root>

    </configuration>

    该文件包含variables1.properties属性文件的引用。属性文件中定义的变量会被作为本地变量引入,variable.properties文件格式如下:

    USER_HOME=/home/sebastien

    也可以直接引用类路径下的文件:

    <configuration>

    <property resource="resource1.properties" />

     

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">

    <file>${USER_HOME}/myApp.log</file>

    <encoder>

    <pattern>%msg%n</pattern>

    </encoder>

    </appender>

     

    <root level="debug">

    <appender-ref ref="FILE" />

    </root>

    </configuration>

     

    作用域

    还可以对上面定义的变量进行作用域限制,local, contextsystem,分别对应配置范围,logback程序范围及JVM范围,定义方式如下:

    <configuration>

    <property scope="context" name="nodeId" value="firstNode" />

     

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">

    <file>/opt/${noteId}/myApp.log</file>

    <encoder>

    <pattern>%msg%n</pattern>

    </encoder>

    </appender>

     

    <root level="debug">

    <appender-ref ref="FILE" />

    </root>

    </configuration>

    scope可用值有:local, context system

     

    默认值

    假设变量名为aName,指定其默认值为golder,指定语法为:"${aName:-golden}"

     

    嵌套变量

    嵌套指一个变量可以引用另一个变量。包括值嵌套、名嵌套以及默认值嵌套。

    值嵌套

    USER_HOME=/home/sebastien

    fileName=myApp.log

    destination=${USER_HOME}/${fileName}

    destination变量值包含对USER_HOME变量值和fileName变量值的引用。

    名嵌套

    当引用一个变量时,变量名可能包含对其他变量的引用。例如,如果变量"userid"的值为"alice",则"${${userid}.password}"表示名为"alice.password"的变量。

    默认值嵌套

    如变量"id"未分配值,变量"userid"值为"alice",则"${id:-${userid}}"

  • 相关阅读:
    常用 Git 命令
    Flex布局
    React-Redux系列4:增加listData列表数据
    React-Redux系列3:修改Store state的值
    React-Redux系列2:Provider提供器和Connect连接器
    React-Redux系列1:简介和安装
    Redux中间件redux-saga中间件之安装、配置、使用
    Redux中间件redux-thunk中间件之安装、配置、使用
    Redux优化之JS纯函数(Pure Function)
    浅谈JS纯函数
  • 原文地址:https://www.cnblogs.com/jiawei-whu/p/4768710.html
Copyright © 2020-2023  润新知