从logback配置文件读取环境变量


69

我有这个logback.xml文件:

<configuration debug="true" scan="true" scanPeriod="60 seconds">

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

  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <File>${MY_HOME}/logs/mylog.log</File>

    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <FileNamePattern>logs/my.%d{yyyy-MM-dd}.log</FileNamePattern>
      <MaxHistory>30</MaxHistory>
    </rollingPolicy>

    <layout class="ch.qos.logback.classic.PatternLayout">
      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level - %msg%n</Pattern>
    </layout>

  </appender> 

  <root level="TRACE">
    <appender-ref ref="FILE"/>
  </root>

</configuration>

并且${MY_HOME}是定义的系统变量(echo $MY_HOME在Linux上显示正确的路径)。

事实是,logback似乎无法正确读取它,它将日志存储在 MY_HOME_IS_UNDEFINED/logs/my.log

我究竟做错了什么?非常感谢!

编辑:我犯了一个错误,并把OSC_HOME放在我真正的意思是MY_HOME的地方。对于那个很抱歉

Answers:


68

与其他人所说的相反,logback文档明确指出“在替换期间,首先在本地范围内查找属性,在​​上下文范围内查找属性,在​​系统属性范围内查找第三,在OS环境中查找第四和最后” 。因此,如果该属性是在环境中定义的,则logback会找到它。

在Eclipse中运行项目时遇到同样的问题。如果这是您遇到的问题,则可以通过转到运行配置->环境并添加MY_HOME到环境变量中来解决。

不太确定为什么默认情况下不加载本机环境。甚至还有一个选项“将环境附加到本机环境”,这似乎对我没有任何影响。


1
环境变量对我有用,但是我必须重新启动Eclipse才能使用它们。看到我对这个问题的回答
Brad Cupit 2012年

1
这与IntelliJ IDEA相同。完全重新启动应用程序将获取环境变量。
耶勒·登汉堡

30

有一种从配置文件读取环境变量的替代方法。您可以使用上下文侦听器将自定义变量放回登录上下文。

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true" scan="true" scanPeriod="30 seconds">

    <!-- THIS IS OUR CUSTOM CONTEXT LISTENER -->
    <contextListener class="com.myapp.logging.listener.LoggerStartupListener"/>

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

    <appender name="FILEOUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${MY_HOME}/${LOG_FILE}.log</file>
        <append>true</append>
        <!-- Support multiple-JVM writing to the same log file -->
        <prudent>true</prudent>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- Daily rollover -->
            <fileNamePattern>${MY_HOME}/${LOG_FILE}.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- Keep 7 days' worth of history -->
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>[%-5level] %d{HH:mm:ss.SSS} [%.6thread] %logger - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="FILEOUT"/>
    </root>
</configuration>

LoggerStartupListener.java

package com.myapp.logging.listener;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.LoggerContextListener;
import ch.qos.logback.core.Context;
import ch.qos.logback.core.spi.ContextAwareBase;
import ch.qos.logback.core.spi.LifeCycle;

public class LoggerStartupListener extends ContextAwareBase implements LoggerContextListener, LifeCycle {

    private static final String DEFAULT_LOG_FILE = "MYAPP";

    private boolean started = false;

    @Override
    public void start() {
        if (started) return;

        String userHome = System.getProperty("user.home"); 

        String logFile = System.getProperty("log.file"); // log.file is our custom jvm parameter to change log file name dynamicly if needed

        logFile = (logFile != null && logFile.length() > 0) ? logFile : DEFAULT_LOG_FILE;

        Context context = getContext();

        context.putProperty("MY_HOME", userHome);
        context.putProperty("LOG_FILE", logFile);

        started = true;
    }

    @Override
    public void stop() {
    }

    @Override
    public boolean isStarted() {
        return started;
    }

    @Override
    public boolean isResetResistant() {
        return true;
    }

    @Override
    public void onStart(LoggerContext context) {
    }

    @Override
    public void onReset(LoggerContext context) {
    }

    @Override
    public void onStop(LoggerContext context) {
    }

    @Override
    public void onLevelChange(Logger logger, Level level) {
    }
}

1
需要的日志包含aws ec2实例ID。这就是我必须采取的方法。
n00b

17

你可能是认真的MY_HOME。在您的配置文件中有的参考OSC_HOME。请参阅变量替换详细信息,Logback的规则。

您可以将环境变量作为Java System属性传递,然后Logback将执行变量替换。您可以在命令行中将其作为JVM选项传递。例如:

java -DMY_HOME=${MY_HOME} -cp ... MainClass

或者,您可以在配置文件本身中定义MY_HOME。

<configuration debug="true" scan="true" scanPeriod="60 seconds">
  <property name="MY_HOME" value="/home/my" />
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <File>${MY_HOME}/logs/mylog.log</File>
  </appender> 
</configuration>

4
通过您答案中的链接:“在替换期间,首先在本地范围内查找属性,在​​上下文范围内查找属性,在​​系统属性范围内查找第三,在OS环境中查找第四,最后。” 因此,应该查看os环境变量吗?
蒂姆·波特

1
@TimPote是的,它将查看OS环境变量
Brad Cupit 2012年

1

如果使用的是Eclipse,则必须重新启动它以获取环境变量,但不能使用:File-> Restart

相反,您实际上必须完全关闭它,然后重新启动它



-4

事情实际上是按照设计的方式进行的:执行变量替换时,logback根本不读取环境变量。引用文档

可以在配置文件本身中,在外部属性文件中或系统属性中定义替换变量的值。

因此,请使用上述解决方案之一或获取OSC_HOME_IS_UNDEFINED:)


1
Logback确实会读取OS环境变量。在Scopes下,它提到了“ OS环境”,它是Oracle关于环境变量的文档的链接
Brad Cupit 2012年

3
上面的引用确实暗示不支持OS环境变量。但是,我在文档中找不到以上引用。当前文档明确提到了OS环境变量。
塞基(Ceki)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.