Logback 配置

logback 的配置

  1. logback 会在类路径下寻找名为 logback-test.xml 的文件。
  2. 如果没有找到,logback 会继续寻找名为 logback.groovy 的文件。
  3. 如果没有找到,logback 会继续寻找名为 logback.xml 的文件。
  4. 如果没有找到,将会通过 JDK 提供的 ServiceLoader 工具在类路径下寻找文件 META-INFO/services/ch.qos.logback.classic.spi.Configurator,该文件的内容为实现了 Configurator 接口的实现类的全限定类名。
  5. 如果以上都没有成功,logback 会通过 BasicConfigurator 为自己进行配置,并且日志将会全部在控制台打印出来。

默认的配置

public void configure(LoggerContext lc) {
    addInfo("Setting up default configuration.");
    
    ConsoleAppender<ILoggingEvent> ca = new ConsoleAppender<ILoggingEvent>();
    ca.setContext(lc);
    ca.setName("console");
    LayoutWrappingEncoder<ILoggingEvent> encoder = new LayoutWrappingEncoder<ILoggingEvent>();
    encoder.setContext(lc);
    

    // same as 
    // PatternLayout layout = new PatternLayout();
    // layout.setPattern("%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n");
    TTLLLayout layout = new TTLLLayout();

    layout.setContext(lc);
    layout.start();
    encoder.setLayout(layout);
    
    ca.setEncoder(encoder);
    ca.start();
    
    Logger rootLogger = lc.getLogger(Logger.ROOT_LOGGER_NAME);
    rootLogger.addAppender(ca);
}

layout 的格式

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

配置文件

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%npattern>
        encoder>
    appender>

    <root level="debug">
        <appender-ref ref="STDOUT" />
    root>
configuration>
private static void test4(){
    Logger logger = LoggerFactory.getLogger(Main.class);
    LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory();
    StatusPrinter.print(lc);
    logger.info("Entering application.");
}

日志打印

23:31:06,033 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
23:31:06,033 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
23:31:06,033 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [file:/Users/xxx/IdeaProjects/logbackTest/target/classes/logback.xml]
23:31:06,121 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
23:31:06,122 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
23:31:06,130 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
23:31:06,137 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
23:31:06,188 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to DEBUG
23:31:06,188 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[ROOT]
23:31:06,188 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.
23:31:06,190 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@4bb4de6a - Registering current configuration as safe fallback point

也可以在 xm 配置中设置为 debug 模式


也会打印如上的日志信息、这个 debug = true 内部实现机制就是一个 StatusListener 。等同如下

<configuration>
    <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
    
configuration>	
public class OnConsoleStatusListener extends OnPrintStreamStatusListenerBase {
    @Override
    protected PrintStream getPrintStream() {
        return System.out;
    }
}

指定配置文件

java -Dlogback.configurationFile=/path/to/config.xml 启动类

或者在启动之前通过 System 设置

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.util.ContextInitializer;

public class ServerMain {
    static {
        System.setProperty(ContextInitializer.CONFIG_FILE_PROPERTY, "configurationFile.xml");
    }
    private static final Logger LOGGER = LoggerFactory.getLogger(ServerMain.class);
    public static void main(String[] args) {
        LOGGER.info("xxxxxxxx");
    }
}

更新自动加载

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

默认是 一分钟扫描一次、看文件是否更改、如果没有指定时间单位、默认为毫秒

如何确定文件是否更新了

public boolean changeDetected() {
    int len = fileWatchList.size();
    for (int i = 0; i < len; i++) {
        long lastModified = lastModifiedList.get(i);
        File file = fileWatchList.get(i);
        if (lastModified != file.lastModified()) {
            return true;
        }
    }
    return false;
    // return (lastModified != fileToScan.lastModified() && lastModified != SENTINEL);
}

更新整个 LoggerContext

private void performXMLConfiguration(LoggerContext lc, URL mainConfigurationURL) {
    JoranConfigurator jc = new JoranConfigurator();
    jc.setContext(context);
    StatusUtil statusUtil = new StatusUtil(context);
    List<SaxEvent> eventList = jc.recallSafeConfiguration();

    URL mainURL = ConfigurationWatchListUtil.getMainWatchURL(context);
    lc.reset();
    long threshold = System.currentTimeMillis();
    try {
        jc.doConfigure(mainConfigurationURL);
        if (statusUtil.hasXMLParsingErrors(threshold)) {
            fallbackConfiguration(lc, eventList, mainURL);
        }
    } catch (JoranException e) {
        fallbackConfiguration(lc, eventList, mainURL);
    }
}

配置文件元素

为根元素、包含 0 或多个 元素,其后跟 0 或多个 元素,其后再跟最多只能存在一个的 元素

Logback 配置_第1张图片

变量

在配置文件的开始定义了一个变量,之后通过引用这个变量指定了日志文件的路径。

<configuration>
    <property name="USER_NAME" value="/data/logs" />

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>${USER_NAME}/myApp.logfile>
        <encoder>
            <pattern>%msg%npattern>
        encoder>
    appender>

    <root level="debug">
        <appender-ref ref="FILE" />
    root>    
configuration>

也可以在启动命令中指定变量值

java -DUSER_HOME="/data/logs" MyApp3

也可以将其放置到一个配置文件中

    <property file="F:\project\logback-examples\src\main\resources\variables1.properties"/>
    <property resource="resource1.properties" />

一个是绝对路径、一个是 classpath 下的资源

作用域

  • local 本地范围的属性存在配置文件的加载过程中、配置文件每加载一次、变量就会被重新定义一次
  • context 作用域的范围延伸至 loggerContext 中
  • system 作用域整个 JVM 都有效
<configuration debug ="true">

    <property name="local" scope="local" value="local-value" />
    <property name="context" scope="context" value="context-value" />
    <property name="system" scope="system" value="system-value" />

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${local}====%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="debug">
        <appender-ref ref="STDOUT" />
    </root>

</configuration>
private static void test6(){
    Logger logger = LoggerFactory.getLogger(Main.class);
    logger.info("print local value");
    LoggerContext loggerContext  = (LoggerContext) LoggerFactory.getILoggerFactory();
    logger.info("print context value:{}", loggerContext.getProperty("context"));
    logger.info("print system value:{}", System.getProperty("system"));
}

打印

local-value====20:09:40.055 [main] INFO  com.demo.test.Main - print local value
local-value====20:09:40.057 [main] INFO  com.demo.test.Main - print context value:context-value
local-value====20:09:40.059 [main] INFO  com.demo.test.Main - print system value:system-value

在进行变量替换的时候,会先从本地范围去找,再从上下文去找,再从系统属性中去找,最后会去系统的环境变量中去找。

默认值

在某些情况下,如果某个变量没有被声明,或者为空,默认值则非常有用。在 bash shell 中,默认值可以通过 “:-” 来指定。例如:假设变量 aName 没有被定义,"${aNme:-golden}" 会被解释成 “golden” 。

引入文件

<configuration>
    <include file="src/main/resources/includedConfig.xml" />
		<include url="http://some.host.com/includedConfig.xml"/>
    <root level="DEBUG">
        <appender-ref ref="includedConsole" />
    root>
configuration>

目标文件必须是由 元素包裹的。

<included>
    <appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d - %m%npattern>
        encoder>
    appender>
included>

如果目标未见是可选的

<include optional="true" ..../>

你可能感兴趣的:(Logback,java,Logback)