how to define logback variables/properties before logback auto-load logback.xml?

我与影子孤独终老i 提交于 2021-02-06 14:50:09

问题


My company has an environment management tool that enables you to look up properties from the environment programmatically in Java. I want to leverage this tool to configure logback. For example, suppose I have a logback.xml as follows (the file appender section in particular):

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

So, in this case, I want to look up the LOG_FILE property from the environment (or OS, if you will), and pass it to logback before logback loads the logback.xml so that it will know the value of LOG_FILE. So, how can I achieve that? BTW, I know how to define a file appender programmatically, but that's not what I want here.

Thank you very much.


回答1:


Define a property in logback.xml and load it into the "context":

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

Then define your appender referencing the property:

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

From the documentation:

A property with context scope is inserted into the context and lasts as long as the context or until it is cleared. Once defined, a property in context scope is part of the context. As such, it is available in all logging events, including those sent to remote hosts via serialization.

So the default scope, which is "local" may well be sufficient.




回答2:


After quite a bit of scratching my head, I am settling with the following solution.

First, put logback.xml outside classpath so that logback will not automatically load anything.

Second, add the settings from the environment to system properties so that logback can look them up when parsing logback.xml.

Third, programmatically configure logback in the application code. (The official logback documentation has one nice example of that. )

Done.




回答3:


I want to look up the LOG_FILE property from the environment (or OS, if you will)

Here are the alternatives:

  1. If by environment, you mean what's generally known as environment variables, you can refer to them directly in the configuration file without much hassle.

  2. If you don't mean environment variables, but rather something that requires custom code to access, you can implement a custom ch.qos.logback.core.spi.PropertyDefiner that grabs and returns the value.

    e.g.

    public class MyCompanyEnvironmentGrabber extends PropertyDefinerBase {
    
        @Override
        public String getPropertyValue() {
            return ...; // grab the value from company environment
        }
    }
    
  3. There's apparently reports one can programmatically set up a variable before logback.xml is loaded by putting it before any calls to logger, and being careful of the ClassLoader load order... However, I think this is very brittle as not using static logger is very hard to control when the code base becomes complex.

All told, since logback.xml is loaded almost immediately after the Java instance starts, safe ways of dynamically setting the value to a variable seems limited to:

  1. Setting it outside the Java program, such as through a calling shell script, by the use of environment variables or system properties (-D).
  2. Returning it via the ch.qos.logback.core.spi.PropertyDefiner callback.
  3. Setting it up in a ch.qos.logback.classic.spi.LoggerContextListener as done in this answer.
  4. Artificially delaying the loading of logback.xml as how the OP has done in his answer.



回答4:


Try this:

In logback.xml reference your Property by %property{myProperty}:

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

Set the Property during the application runtime:

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


来源:https://stackoverflow.com/questions/24235296/how-to-define-logback-variables-properties-before-logback-auto-load-logback-xml

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!