Java 如何在Logback中设置类似MDC的变量,但对于整个应用程序/JVM?

Java 如何在Logback中设置类似MDC的变量,但对于整个应用程序/JVM?,java,logback,Java,Logback,我想在我的日志文件中有一个应用程序记录某些内容的指示器。这意味着整个应用程序的变量相同,但应用程序实例之间的变量不同。为此,我尝试使用MDC,希望如果我直接在main方法中设置它,该变量将被新生成的线程接管。这在使用log4j时或多或少是可行的,但在使用logback时根本不起作用。我知道您可以在日志文件中显示系统变量,但可能有多个应用程序实例在同一台机器上运行,因此这不起作用。那么,我应该如何将这个变量发送到日志文件中呢?我将使用JVM系统属性。当JVM启动时,您可以使用标记-Dthings.

我想在我的日志文件中有一个应用程序记录某些内容的指示器。这意味着整个应用程序的变量相同,但应用程序实例之间的变量不同。为此,我尝试使用MDC,希望如果我直接在main方法中设置它,该变量将被新生成的线程接管。这在使用log4j时或多或少是可行的,但在使用logback时根本不起作用。我知道您可以在日志文件中显示系统变量,但可能有多个应用程序实例在同一台机器上运行,因此这不起作用。那么,我应该如何将这个变量发送到日志文件中呢?

我将使用JVM系统属性。当JVM启动时,您可以使用标记
-Dthings.that.arent.bacon=turkey bacon
,或通过编程方式设置每个进程的属性:
System.setProperty(“no.not.what.they.tell.You”,“turkey bacon不是bacon”)


如果您使用的是SLF4J/LogBack,则LogBack中似乎已经支持此功能:

我认为不可能为整个应用程序设置MDC变量

我正在做的是扩展我想要的appender,以静态方式设置所需的参数,并为每次调用受保护的void append(ILOGingEvent eventObject)方法设置它。这是我的套接字附加器示例:

package my.package

import org.slf4j.MDC;

import java.util.ResourceBundle;

import ch.qos.logback.classic.net.SocketAppender;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.LoggingEvent;

public class MyLogbackSocketAppenderWithMDCEnabled extends SocketAppender {
    /**
     * Example parameter calculated
     * This is a list of public IPs of the server
     */
    private static final String public_ips = MyNetUtility.getPublicIps();

    /**
     * Example parameter extracted from a .properties
     *
     **/
    private static final String versio;
    static {
        String versioAux = null;
        try {
            final ResourceBundle app = ResourceBundle.getBundle("application");
            versioAux = app.getString("versio");
        } catch (final Exception e) {
            ; /*If we have problems loading the bundle, versio=null*/
        }
        versio = versioAux;
    }

    @Override
    protected void append(ILoggingEvent eventObject) {
        if (eventObject instanceof LoggingEvent) {

            /*Setting of the parameters in the MDC*/
            MDC.put("public_ips", public_ips);
            if (versio != null) {
                MDC.put("versio", versio);
            }

            final LoggingEvent loggingEvent = ((LoggingEvent) eventObject);

            /* This loads the MDC in the event */
            loggingEvent.getMDCPropertyMap();
        }

        super.append(eventObject);
    }
}
然后我在logback.xml中使用它,就像普通的SocketAppender一样,具有相同的配置属性:

  <appender name="SOCKET" class="my.package.MyLogbackSocketAppenderWithMDCEnabled">

    <remoteHost>${logger.host}</remoteHost>
    <port>${logger.port}</port>
    <reconnectionDelay>10000</reconnectionDelay>
    <includeCallerData>false</includeCallerData>

  </appender>

${logger.host}
${logger.port}
10000
假的

也许这不是一个干净的解决方案,但它是有效的。

属性的定义是您要搜索的吗

您可以定义属性
并在模式
%-5级属性{APP_INSTANCE}[%thread]:%message%n
中使用它。看

如果需要,可以先检查属性是否存在:

<if condition='isDefined("APP_INSTANCE")'>
  <then>
    ...
  </then>
</if>

...

这似乎适用于像我正在写入的文件这样的配置,但如何在日志模式本身中使用它?如果所需的属性只能从应用程序内部访问(例如使用打包在其中的.property文件),该怎么办或者,如果我们没有修改启动参数的权限,您可以在模式中使用property关键字。