多个WAR共享相同的logback.xml

时间:2016-06-16 16:08:35

标签: war logback

以下回溯设置是否安全且良好。

我有多个WAR(已部署WebSphere 8.5.5)并希望它们共享一个logback.xml

-Dlogback.configurationFile=/opt/logback.xml -Dlogback.ContextSelector=JNDI

logback.xml使用带有SiftingAppenderJNDIBasedContextDiscriminator,因此每个WAR都会获得自己的日志文件。

<appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
    <discriminator class="ch.qos.logback.classic.sift.JNDIBasedContextDiscriminator">
        <defaultValue>unknown</defaultValue>
    </discriminator>
    <sift>
        <appender name="FILE-${contextName}" class="ch.qos.logback.core.FileAppender">
            <file>/var/log/${contextName}.log</file>
            <encoder>
                <pattern>%-50(%level %logger{35}) cn=%contextName - %msg%n</pattern>
            </encoder>
        </appender>
    </sift>
</appender>

每个WAR web.xml都有contextName

<env-entry>
  <description>JNDI logging context for this app</description>
  <env-entry-name>logback/context-name</env-entry-name>
  <env-entry-type>java.lang.String</env-entry-type>
  <env-entry-value>ContextNameWebAppA</env-entry-value>
</env-entry>

1 个答案:

答案 0 :(得分:0)

我不知道使用Jndi鉴别器是安全的还是一种好的做法,但是 它似乎是Logback解决这个问题的方式:http://logback.qos.ch/manual/loggingSeparation.html
它们表明在将此添加到您的配置中时性能会更好:

<filter>
  <filter-name>LoggerContextFilter</filter-name>
  <filter-class>ch.qos.logback.classic.selector.servlet.LoggerContextFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>LoggerContextFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

另一方面,我可以分享我尝试做的事情,以避免设置系统属性logback.ContextSelector=JNDI

我使用MDCBasedDiscriminator来获取用MDC.put(key,value)定义的辨别值 MDC映射可用作线程局部变量,因此必须为Web服务器启动的每个线程设置它 对于此初始化,我使用了javax.servlet.Filter放置在其他过滤器之前,此过滤器将在MDC中放置正确的值。

我不认为这比你做的更好,但它可以替代JNDI属性,问题是关闭日志在unknown.log

以下是一些代码:

public class WarLoggingFilter implements Filter {
    private static final String WAR_NAME_ATTRIBUTE = "WAR_NAME";
    private String warName;

    @Override
    public void init(final FilterConfig filterConfig) throws ServletException {
        warName = filterConfig.getInitParameter(WAR_NAME_ATTRIBUTE);
    }

    @Override
    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
            throws IOException, ServletException {
        insertIntoMDC(warName);
        chain.doFilter(request, response);
    }

    private void clearMDC() {
        MDC.remove(WAR_NAME_ATTRIBUTE);
    }

    private static void insertIntoMDC(final String warName) {
        MDC.put(WAR_NAME_ATTRIBUTE, warName);
    }

    @Override
    public void destroy() {
        clearMDC();
    }


    /**
     * Register this filter in the servlet context. Adds the necessary init
     * parameter.
     *
     * @param warName
     * @param servletContext
     */
    public static void registerMe(final String warName, final ServletContext servletContext) {
        // MDC for the startup thread
        insertIntoMDC(warName);
        // MCD for next threads
        final Dynamic addFilter = servletContext.addFilter(warName, WarLoggingFilter.class);
        addFilter.setInitParameter(WarLoggingFilter.WAR_NAME_ATTRIBUTE, warName);
        addFilter.addMappingForUrlPatterns(null, false, "/*");

    }

}

和logback文件:

<appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
        <discriminator class="ch.qos.logback.classic.sift.MDCBasedDiscriminator">
            <key>WAR_NAME</key>
            <defaultValue>unknown</defaultValue>
        </discriminator>
        <sift>
            <appender name="FILE-${WAR_NAME}" class="ch.qos.logback.core.FileAppender">
                <file>/tmp/${WAR_NAME}.log</file>
                <encoder>
                    <pattern>%date{ISO8601} %-5level %logger{30}\(%line\) - %message%n</pattern>
                </encoder>
            </appender>
        </sift>
    </appender>

注册可以是例如spring security initializer:

public class MySecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

    /**
     * Invoked before the springSecurityFilterChain is added.
     *
     * @param servletContext
     *            the {@link ServletContext}
     */
    @Override
    protected void beforeSpringSecurityFilterChain(final ServletContext servletContext) {
        // Tell logback to log this web app events in a separate file
        WarLoggingFilter.registerMe("my_webapp", servletContext);
    }