开发者

Read environment variables from logback configuration file

I have this logback.xml file:

<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.开发者_JAVA百科%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>

And ${MY_HOME} is a defined system variable (echo $MY_HOME on linux shows the correct path).

The thing is that logback doesnt seem to read it properly, it stores the logs under MY_HOME_IS_UNDEFINED/logs/my.log

What am I doing wrong? Thanks a lot!

EDIT: I made a mistake and put OSC_HOME where I really meant MY_HOME. Sorry about that


Contrary to what the others have said, the logback documentation explicitly states that "During substitution, properties are looked up in the local scope first, in the context scope second, in the system properties scope third, and in the OS environment fourth and last". So if the property is defined in the environment, logback will find it.

I was having the same issue when running my project in Eclipse. If that's the issue you're having, it can be fixed by going to Run Configurations -> Environment and adding MY_HOME to the environment variables.

Not really sure why it isn't loading the native environment by default. There's even an option called "Append environment to native environment" which doesn't seem to have any effect for me.


There is an alternative way to read environment variables from config file. you can put your custom variables to logback context with context listener.

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) {
    }
}


You perhaps mean MY_HOME. In your config file there is reference for OSC_HOME. See Variable substitution rules of Logback for details.

You can pass environment variable as a Java System property and then Logback will perform the variable substitution. You can pass this as JVM option in your command line. For example:

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

Or You can define MY_HOME in your config file itself.

<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>


If you're using Eclipse you have to restart it to pick up environment variables, but you can't use: File -> Restart

Instead you actually have to fully shut it down and then start it back up again.


Things are actually working as designed: logback doesn't read environment variables at all when doing variable substitution. Quoting the documentation:

The value of the substituted variable can be defined in the configuration file itself, in an external properties file or as a system property.

So, either use one of the mentioned solutions or get OSC_HOME_IS_UNDEFINED :)


Instead of using environmental variables, you can use tag to declare variables in logback.xml.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜