Как настроить несколько log4j для разных войн в одном EAR?
-
11-09-2019 - |
Вопрос
У меня есть EAR с такими структурами, как:
APP.ear
- APP1.war
- WEB-INF/classes/log4j.properties
- APP2.war
- WEB-INF/classes/log4j.properties
- app1-ejb.jar
- app2-ejb.jar
- log4j.jar
- spring.jar
- commons-lang.jar (...and other jar)
Я хочу, чтобы у каждой WAR был свой журнал приложений.Но похоже, что приведенная выше конфигурация не работает.Журнал APP1 и APP2 попадает в журнал APP1.Есть ли способ создать отдельные журналы приложений?
Решение
Оказывается, это невозможно из-за загрузчика классов.Иерархия загрузчика классов выглядит следующим образом:
Загрузчик классов приложения -> Загрузчик классов Ejb -> военный загрузчик классов
Чтобы иметь отдельный журнал для отдельной войны, можно поместить log4j.jar внутрь войны и позволить log4j использовать загрузчик классов войны.Но поскольку и app1-ejb.jar, и app2-ebj.jar также должны использовать log4j, log4j.jar можно разместить только на верхнем уровне.Таким образом, log4j находится на уровне загрузчика классов приложения.
Я могу указать одну конфигурацию log4j для регистрации разных пакетов в разных файлах.Но для общей библиотеки, такой как Spring, журнал нельзя разделить.
Другие советы
Причина, по которой это не сработало, заключается в том, что log4j присутствует в корневом каталоге: вместо этого позвольте каждой войне иметь Log4j.jar в своем каталоге WEB-INF/lib и удалите log4j.jar из корня.
Для получения дополнительной информации об этом обратитесь к моей статье в блоге по этому поводу.http://techcrawler.wordpress.com/
Это также можно сделать путем динамического изменения свойства FILE в файле свойств с помощью PropertyConfigurator в коде.
Logback — эффективное решение этой проблемы.Изучив различные способы работы с log4j, мы решили переключиться на Logback.Я использовал следующую конфигурацию с банкой Logback внутри веб-приложения.
Файл журнала внутри веб-приложения, который включает внешний файл:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="10 seconds">
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<contextName>${project.artifactId}</contextName>
<jmxConfigurator />
<include file="${logback.configuration.filepath}" />
</configuration>
${logback.configuration.filepath}
заменяется во время фильтрации Maven точным путем, внешним по отношению к веб-приложению файла конфигурации (что-то вроде /opt/server/conf/loback.included.conf).
И затем содержание logback.included.conf
(этот файл является частью проекта, поставляемого вместе с build-helper:attach-artifact
, так ${project.artifactId}
также заменяется во время фильтрации Maven):
<?xml version="1.0" encoding="UTF-8" ?>
<included>
<appender name="file" class="ch.qos.logback.core.FileAppender">
<file>/var/log/server/${project.artifactId}.log</file>
<encoder>
<pattern>[@/%contextName] %date{ISO8601} [%-5level] %thread:[%logger] %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="file" />
</root>
</included>
Единственное ограничение: содержимое включаемого файла должно соответствовать содержимому включающего файла.По сути, просто пишу правила.