Я не знаю, если с помощью 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 доступна в виде локальной переменной потока, поэтому ее необходимо установить для каждого потока, инициированного веб-сервером.
Для этой инициализации я использовал 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>
И регистрация может быть, например, в инициализаторе пружинной безопасности:
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);
}