logback.xml给变量指定默认值

沐雨橙风 沐雨橙风     2022-09-03     251

关键词:

随着通用日志组件转入 Slf4j,logback 也变成了默认的日志实现,像 log4j 一样,logback.xml 中也可以使用系统属性或环境变量,如 ${catalina.home}。在 log4j.properties 中,如果变量在系统属性和环境变量中找不到的话默认为 "" 空字符串,而到了 logback.xml 中如果某个变量找不到默认就是 "变量名_IS_UNDEFINED" 了,这样就比较奇怪了。

那如何在没有配置 catalina.home 系统属性或环境变量时设置一个默认值呢,例如,没有 catalina.home  时取值为 ".",这时值日志文件的路径就是

./logs/unmi-%d{yyyy-MM-dd}.log

了,也就是生成中当前目录下的 logs 子目录中,这样算是很友好的方式。下面就来分析怎么一步步找到答案的,没耐心或是只求结果的话,直接滚屏到下面就行。

我们的问题是,对于下面那样的 logback.xml 配置:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8"?>
 
<configuration>
 
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder charset="UTF-8">
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>
 
    <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${catalina.home}/logs/unmi-%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>10</maxHistory>
        </rollingPolicy>
 
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>
 
    <root level="DEBUG">
        <appender-ref ref="stdout" />
        <appender-ref ref="RollingFile" />
    </root>
</configuration>

因为测试时直接在 Eclipse 或控制台下执行,在未定义 catalina.home 的情况下,一运行就会在当前目录下生成 catalina.home_IS_UNDEFINED 目录,其中有 logs 子目录,再才是 unmi-2014-05-19.log 这个日志文件。

技术分享

搜索了网上关于默认值的解决方案,有说在 logback.xml 中写条件表达式,例如:

1
2
3
4
5
6
7
8
<if condition="property(‘catalina.home‘)==null">
    <then>
        <fileNamePattern>logs/unmi-%d{yyyy-MM-dd}.log</fileNamePattern>
    </then>
    <else>
        <fileNamePattern>${catalina.home}/logs/unmi-%d{yyyy-MM-dd}.log</fileNamePattern>
    </else>
</if>

参考: http://logback.qos.ch/manual/configuration.html#conditional 和 http://stackoverflow.com/questions/15911303/how-can-i-configure-logback-conditionally-based-on-context-name

上面的 if-then-else 是有问题的 The FileNamePattern option must be set before using TimeBasedRollingPolicy,需要把 if 的覆盖范围扩大,不过试了也不怎么爽。

回到  IS_UNDEFINED, 它总是有来头的,搜索源代码可找到它出现在 https://github.com/qos-ch/logback/blob/master/logback-core/src/main/java/ch/qos/logback/core/util/OptionHelper.java#L103:

final static String _IS_UNDEFINED = "_IS_UNDEFINED";

 

还有一处未被使用,这样就有突破口了,再跟踪代码,找到 logback 是怎么取到相对应变量值的 https://github.com/qos-ch/logback/blob/master/logback-core/src/main/java/ch/qos/logback/core/subst/NodeToStringTransformer.java#L102,handleVariable 方法代码片断:

01
02
03
04
05
06
07
08
09
10
11
12
 if (n.defaultPart == null) {
  stringBuilder.append(key + CoreConstants.UNDEFINED_PROPERTY_SUFFIX);
  cycleCheckStack.pop();
  return;
}
 
Node defaultPart = (Node) n.defaultPart;
StringBuilder defaultPartBuffer = new StringBuilder();
compileNode(defaultPart, defaultPartBuffer, cycleCheckStack);
cycleCheckStack.pop();
String defaultVal = defaultPartBuffer.toString();
stringBuilder.append(defaultVal);

注:从这个类的 lookupKey(String key) 方法中可以知道  logback 从四个地方取变量值,分别是 propertyContainer0, propertyContrainer1, System, Evn,前两不知道没关系,后两个我们明白先从 System 属性,没有再从环境变量中取。

上面我们会想到 Node 除了有 payload 还有一个 defaultPart 用了设定默认值部分。至于默认值怎么设置,猜测试是 ${catalina.home:abc},没用,不过别急,logback  的测试用例告诉了我们表达式的写法。

见 https://github.com/qos-ch/logback/blob/master/logback-core/src/test/java/ch/qos/logback/core/util/OptionHelperTest.java#L99, 看到这样写代默认值的表达式

${v2:-toto}        //格式是 ${变量名:-默认值},光有冒号还不够,再加条短线后面才是默认值

所以学习它后,前面的日志文件名配置部分就写成

1
2
<!-- 如果没有定义  catalina.home  系统属性或环境变量时,生成的日志文件在 ./logs 目录下 -->
<fileNamePattern>${catalina.home:-.}/logs/unmi-%d{yyyy-MM-dd}.log</fileNamePattern>

完整的 logback.xml 内容如下:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8"?>
 
<configuration>
 
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder charset="UTF-8">
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>
 
    <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${catalina.home:-.}/logs/unmi-%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>10</maxHistory>
        </rollingPolicy>
 
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>
 
    <root level="DEBUG">
        <appender-ref ref="stdout" />
        <appender-ref ref="RollingFile" />
    </root>
</configuration>

多看看这 OptionHelperTest 测试用例,还能发现默认值也能用变量,如

${B:-${A}}

 

本文链接 https://unmi.cc/logback-xml-variable-with-default-value/, 来自 隔叶黄莺 Unmi Blog

logback.xml可以写if吗

...,直接滚屏到下面就行。我们的问题是,对于下面那样的logback.xml配置:本回答被提问者采纳 查看详情

统一日志处理(代码片段)

resources目录下新建logback-spring.xml<?xmlversion="1.0"encoding="UTF-8"?><configurationscan="true"scanPeriod="10seconds"><!--日志级别从低到高分为TRACE<DEBUG<INFO<WARN<ERROR<FATAL,如果设置为WARN,则低于WARN的信息都不会输出--><!--sc... 查看详情

logback日志系统

参考技术Alogback的易用性不用多讲,只需要通过下面两行就可以在console中输出日志:程序运行时,logback会查找默认的配置文件logback.xml或者logback-test.xml文件,如果没有找到它就会使用默认的配置,将日志打印到console中。下面是... 查看详情

默认初始化值初始化

默认初始化  变量没有指定初始值,则被默认初始化。  内置类型:全局变量的内置类型没有指定初始值,被初始化为0;局部变量则不被初始化。  类:执行默认构造函数(如果默认构造函数是编译器合成的,类中的内... 查看详情

是否可以从 DB 添加 logback.xml 配置值?

】是否可以从DB添加logback.xml配置值?【英文标题】:Isitpossibletoaddlogback.xmlconfigurationvaluesfromDB?【发布时间】:2020-11-1708:26:38【问题描述】:我想从数据库动态配置logback.xml值。这是我的logback.xml文件:<configuration><appendername... 查看详情

springboot中logging.config的logback默认配置文件地址

在springboot配置logback配置文件路径的时候当logging.config不特殊指定基于约定默认加载:resources文件夹下的logback-spring.xml文件 查看详情

golang变量

一、变量的概念变量是程序的基本组成单位。变量表示内存中的一个存储区域,该区域有自己的名称(变量名)和类型(数据类型)。变量相当于内存中一个数据存储空间的表示,你可以把变量看做是一个房间的门牌号,通过门牌号... 查看详情

5.任意值类型推论联合类型

1.任意值any,可以将任意类型的变量赋值给该类型的变量,没有指定类型的变量默认为any 也可以用来定义不定类型的数组 2.上面说到没有指定类型的变量默认为any类型的,但是当声明变量时定义了该变量值,则默认变量... 查看详情

logback-结合springprofile使用

...profile来进行配置环境的快速切换。这里我们使用默认的logback.xml和dev环境下的logback-dev.xml。这俩个配置文件之间的区别就是logback-dev.xml不将日志打入到控制台。logback.xml内容如下:logback-dev.xml内容如下:这里我们需要在spring不同... 查看详情

springboot默认的logback

1、在resource目录下写logback.xml文件2、<?xmlversion="1.0"encoding="UTF-8"?><configuration><includeresource="org/springframework/boot/logging/logback/base.xml"/><jmxConfigurator/><!-- 查看详情

logback的日志文件,默认是存放到啥位置

参考技术Alogback类似于log日志体系,可以将一些日志信息输出到tomcat文件夹内,示例如下:logback.xml里面的内容配置:<?xmlversion="1.0"encoding="UTF-8"?><!--文件输出日志(文件大小策略进行文件输出,超过指定大小... 查看详情

springboot使用默认的logback配置logback-spring.xml每天一个日志文件(代码片段)

文章目录logbackapplication.yml配置logback-spring.xml内容部署启动(2)application.yml放在resources下使用logbackspringboot配置每天一个日志文件logback-spring.xmlspringboot工程配置文件可以放在多个地方,可以直接放在resources目录下,也可以放... 查看详情

将类变量作为默认值分配给类方法参数

】将类变量作为默认值分配给类方法参数【英文标题】:assigningclassvariableasdefaultvaluetoclassmethodargument【发布时间】:2013-02-1719:32:37【问题描述】:我想在一个类中使用取自该类的默认值参数构建一个方法。一般来说,我会过滤一... 查看详情

给变量一个默认值的最好方法(模拟 Perl ||, ||= )

】给变量一个默认值的最好方法(模拟Perl||,||=)【英文标题】:Bestwaytogiveavariableadefaultvalue(simulatePerl||,||=)【发布时间】:2011-08-2318:30:39【问题描述】:我喜欢在Perl中做这样的事情:如果$bar为空或未定义,$foo=$bar||$baz将$baz分配... 查看详情

logback.xml配置示例

<?xmlversion="1.0"encoding="UTF-8"?><configuration><!--在没有定义${LOG_HOME}系统变量的时候,可以设置此本地变量。提交测试、上线时,要将其注释掉,使用系统变量。--><!--本地环境<propertyname="LOG_HOME"value="C:/logs"/>-->< 查看详情

logback.xml常用配置详解<configuration;and<logger;

logback配置详解(一)<configuration>and<logger>  一:根节点<configuration>包含的属性:  scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。scanPeriod:设置监测... 查看详情

如何加载指定路径的logback.xml

...之后通过相对位置找到另外文件路径。参考技术A代码FilelogbackFile=newFile("./conf/logback.xml");if(logbackFile.exists())LoggerContextlc=(LoggerContext)LoggerFactory.getILoggerFactory();JoranConfiguratorconfigurator=newJoranConfigurator();configurator.setContext(lc);lc.r... 查看详情

springboot使用默认的logback配置logback-spring.xml每天一个日志文件(代码片段)

文章目录logbackapplication.yml配置logback-spring.xml内容部署启动(2)application.yml放在resources下使用logbackspringboot配置每天一个日志文件logback-spring.xmlspringboot工程配置文件可以放在多个地方,可以直接放在resources目录下,也可以放... 查看详情