Java 如何在 logback 自动加载 logback.xml 之前定义 logback 变量/属性?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24235296/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to define logback variables/properties before logback auto-load logback.xml?
提问by JBT
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):
我的公司有一个环境管理工具,使您能够在 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>
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.
所以,在这种情况下,我想LOG_FILE
从环境(或操作系统,如果你愿意的话)中查找属性,并在 logback 加载 logback.xml 之前将其传递给 logback,以便它知道LOG_FILE
. 那么,我怎样才能做到这一点?顺便说一句,我知道如何以编程方式定义文件附加程序,但这不是我想要的。
Thank you very much.
非常感谢。
采纳答案by JBT
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.
首先,将 logback.xml 放在 classpath 之外,以便 logback 不会自动加载任何内容。
Second, add the settings from the environment to system properties so that logback can look them up when parsing logback.xml.
其次,将环境中的设置添加到系统属性中,以便 logback 在解析 logback.xml 时可以查找它们。
Third, programmatically configure logback in the application code. (The official logback documentation has one nice exampleof that. )
第三,在应用程序代码中以编程方式配置 logback。(官方的 logback 文档有一个很好的例子。)
Done.
完毕。
回答by Alexandre Santos
Define a propertyin logback.xml
and load it into the "context":
定义属性中logback.xml
,并加载到“上下文”:
<property scope="context" name="logfolder" value="${location.of.the.log.folder}" />
Then define your appender referencing the property:
然后定义引用该属性的 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>
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.
所以默认范围,即“本地”可能就足够了。
回答by antak
I want to look up the
LOG_FILE
property from the environment (or OS, if you will)
我想
LOG_FILE
从环境(或操作系统,如果你愿意的话)中查找属性
Here are the alternatives:
以下是替代方案:
If by environment, you mean what's generally known as environment variables, you can refer to them directly in the configuration filewithout much hassle.
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.PropertyDefinerthat grabs and returns the value.
e.g.
public class MyCompanyEnvironmentGrabber extends PropertyDefinerBase { @Override public String getPropertyValue() { return ...; // grab the value from company environment } }
There's apparentlyreports one can programmatically set up a variable before
logback.xml
is loaded by putting it before any calls tologger
, and being careful of the ClassLoader load order... However, I think this is very brittle as not usingstatic logger
is very hard to control when the code base becomes complex.
如果说environment,您指的是通常称为环境变量的内容,则可以直接在配置文件中引用它们,而不会很麻烦。
如果您的意思不是环境变量,而是需要自定义代码才能访问的内容,您可以实现一个自定义 ch.qos.logback.core.spi.PropertyDefiner来获取并返回值。
例如
public class MyCompanyEnvironmentGrabber extends PropertyDefinerBase { @Override public String getPropertyValue() { return ...; // grab the value from company environment } }
有明显表示,有一个可以编程设置前一个变量
logback.xml
是通过将它的任何调用之前加载logger
,并小心的类加载器加载顺序的。不过,我想,因为这是很脆不使用static logger
是很难控制的时候代码库变得复杂。
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:
总而言之,由于logback.xml
在 Java 实例启动后几乎立即加载,将值动态设置为变量的安全方法似乎仅限于:
- Setting it outside the Java program, such as through a calling shell script, by the use of environment variables or system properties (
-D
). - Returning it via the
ch.qos.logback.core.spi.PropertyDefiner
callback. - Setting it up in a
ch.qos.logback.classic.spi.LoggerContextListener
as done in this answer. - Artificially delaying the loading of
logback.xml
as how the OP has done in his answer.
- 使用环境变量或系统属性 (
-D
)在 Java 程序之外设置它,例如通过调用 shell 脚本。 - 通过
ch.qos.logback.core.spi.PropertyDefiner
回调返回它。 - 如本答案中所做的那样在a
ch.qos.logback.classic.spi.LoggerContextListener
中进行设置。 - 人为地延迟加载,
logback.xml
就像 OP 在他的回答中所做的那样。
回答by Jurass
Try this:
尝试这个:
In logback.xml reference your Property by %property{myProperty}:
在 logback.xml 中,通过 %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");