如何在logback auto-load logback.xml之前定义logback变量/属性?

时间:2014-06-16 00:27:09

标签: java logback

我的公司有一个环境管理工具,使您能够以编程方式在Java中查找环境中的属性。我想利用这个工具来配置logback。例如,假设我有一个logback.xml,如下所示(特别是文件appender部分):

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- console appender -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd/HH:mm:ss.SSS} [%thread] %-5level %logger{20}: %msg%n</pattern>
        </encoder>
    </appender>

    <!-- file appender -->
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>${LOG_FILE:-/default/log/file/path</file>
        <encoder>
            <pattern>%d{yyyy-MM-dd/HH:mm:ss.SSS} [%thread] %-5level %logger{20}: %msg%n</pattern>
        </encoder>
    </appender>

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

所以,在这种情况下,我想从环境(或OS,如果你愿意)查找LOG_FILE属性,并在logback加载logback.xml之前将其传递给logback,以便它知道LOG_FILE的值。那么,我该如何实现呢?顺便说一句,我知道如何以编程方式定义文件追加器,但这不是我想要的。

非常感谢。

4 个答案:

答案 0 :(得分:15)

logback.xml中的

Define a property并将其加载到“上下文”中:

<property scope="context" name="logfolder" value="${location.of.the.log.folder}" />

然后定义引用属性的appender:

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>${logfolder}/logfile.log</file>
    <append>true</append>
    <encoder>
        <pattern>[%d{ISO8601}] [%p] [%t] [%c] [%m]%n</pattern>
    </encoder>
</appender>

来自documentation

  

具有上下文范围的属性将插入到上下文中并持续   只要上下文或直到它被清除。一旦定义,a   上下文范围中的属性是上下文的一部分。因此,它是   可用于所有日志记录事件,包括发送到远程主机的事件   通过序列化。

因此默认范围是“本地”可能就足够了。

答案 1 :(得分:11)

经过一番搔痒,我正在解决以下问题。

首先,将logback.xml放在classpath之外,以便logback不会自动加载任何内容。

其次,将环境中的设置添加到系统属性中,以便在解析logback.xml时,logback可以查找它们。

第三,以编程方式配置应用程序代码中的logback。 (官方的logback文档有one nice example。)

完成。

答案 2 :(得分:10)

  

我想从环境(或OS,如果你愿意)查找LOG_FILE属性

以下是替代方案:

  1. 如果通过环境,您的意思是environment variables,通常称为refer to them directly in the configuration file,您可以implement a custom ch.qos.logback.core.spi.PropertyDefiner毫不费力。

  2. 如果您不是指环境变量,而是需要自定义代码才能访问的内容,您可以apparently抓取并返回该值。

    e.g。

    public class MyCompanyEnvironmentGrabber extends PropertyDefinerBase {
    
        @Override
        public String getPropertyValue() {
            return ...; // grab the value from company environment
        }
    }
    
  3. in a ch.qos.logback.classic.spi.LoggerContextListener as done in this answer报告可以通过在logback.xml的任何调用之前将其置于加载logger之前以编程方式设置变量,并注意ClassLoader加载顺序...但是,我认为这非常脆弱,因为当代码库变得复杂时,不使用static logger 很难控制。

  4. 总而言之,由于logback.xml几乎在Java实例启动后立即加载,因此将值动态设置为变量的安全方法似乎仅限于:

    1. 通过使用环境变量或系统属性(-D)将其设置在Java程序之外,例如通过调用shell脚本。
    2. 通过ch.qos.logback.core.spi.PropertyDefiner回调退回。
    3. 设置as how the OP has done in his answer
    4. 人为延迟加载logback.xml -keep

答案 3 :(得分:0)

尝试一下:

在logback.xml中,按%property {myProperty}引用您的媒体资源:

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>
            %property{myProperty} - %m%n%wEx
        </pattern>
    </encoder>
    </appender>

在应用程序运行时设置属性:

LoggerContext loggerContext = (LoggerContext)LoggerFactory.getILoggerFactory();
loggerContext.putProperty("myProperty", "myProperty12345");