Logback 配置

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: logback 会在类路径下寻找名为 logback-test.xml 的文件。如果没有找到,logback 会继续寻找名为 logback.groovy 的文件。如果没有找到,logback 会继续寻找名为 logback.xml 的文件。如果没有找到,将会通过 JDK 提供的 ServiceLoader 工具在类路径下寻找文件 META-INFO/services/ch.qos.logback.classic.spi.Configurator,该文件的内容为实现了 Configurator 接口的实现类的全限定类名。如果以上都没有成功,logback 会通过 BasicConfig

网络异常,图片无法展示
|


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%n</pattern>
        </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 模式

<configuration debug ="true">
复制代码


也会打印如上的日志信息、这个 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);
    }
}
复制代码


配置文件元素

<configuration> 为根元素、包含 0 或多个 <appender> 元素,其后跟 0 或多个 <logger> 元素,其后再跟最多只能存在一个的 <root> 元素

网络异常,图片无法展示
|


变量

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

<configuration>
    <property name="USER_NAME" value="/data/logs" />
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>${USER_NAME}/myApp.log</file>
        <encoder>
            <pattern>%msg%n</pattern>
        </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> 元素包裹的。

<included>
    <appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d - %m%n</pattern>
        </encoder>
    </appender>
</included>
复制代码


如果目标未见是可选的

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



目录
相关文章
|
缓存 Java API
logback配置
一、logback介绍 logback分成三个模块:logback-core,logback- classic,logback-access。 logback-core:提供了logBack的核心功能,是另外两个组件的基础; logback-classic:实现了SLF4J API; logback
704 0
|
4月前
|
监控 Java 测试技术
日志框架到底是Logback 还是 Log4j2
日志框架到底是Logback 还是 Log4j2
43 0
|
Java API 计算机视觉
springboot启动报错LoggerFactory is not a Logback LoggerContext but Logback...
今天做人脸识别的Demo,引入的百度的API,里面用了slf4j,然后就导致日志冲突了。
|
XML 安全 Oracle
logback的使用和logback.xml详解
logback的使用和logback.xml详解
|
安全 Java API
(一)Logback介绍及架构
(一)Logback介绍及架构
|
监控 Java Shell
(二)Logback配置
Logback通过加载配置文件的方式来初始化配置,配置文件的加载顺序如下: 1)Logback首先会去类路径下找名为logback-test.xml的文件。 2)如果没有找到如上文件,会去类路径下找名为logback.groovy的文件。 3)如果没有找到如上文件,会去类路径下找名logback.xml的文件。
(二)Logback配置
|
Java jenkins Linux
Logback使用总结
整理了下logback的常用点功能,并记录了一些在使用过程中的疑问,和问题的排错过程,防止自己再犯类似错误,也希望对路过的你有所帮助。
639 0
|
XML Java API
05、logback(日志实现框架)(一)
05、logback(日志实现框架)(一)
05、logback(日志实现框架)(一)
|
Java 应用服务中间件 API
05、logback(日志实现框架)(二)
05、logback(日志实现框架)(二)
05、logback(日志实现框架)(二)
|
SQL Java
日志 - Logback 详解
日志 - Logback 详解
173 0
日志 - Logback 详解