log4j2: расположение для установки системного свойства Log4jContextSelector для асинхронного ведения журнала
Я пытаюсь настроить асинхронное ведение журнала (по соображениям производительности) в веб-методах REST, которые в настоящее время выполняются на сервере профилей liberty.
для этого я установил следующее свойство:
System.setProperty("Log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
моя проблема в том, что независимо от того, где я это делаю, иногда это работает и ведение журнала очень быстро, а иногда и нет.
я попробовал (a) в конструкторе для класса, содержащего все остальные веб-методы b) в фильтре метод doFilter, вызываемый до Метода REST c) в методе init фильтра (d) в самом методе REST
ни одно из этих местоположений не работает последовательно.
может ли кто-нибудь предложить объяснение этого поведения и, если возможно, предложенный способ устранения проблемы.
EDIT: похоже, что log4j инициализируется до вызова setProperty. Поэтому мне нужно настроить свойство через профиль liberty.
4 ответов
существует недокументированный метод установки этого значения для вашего проекта без необходимости вручную передавать значение системного свойства во время запуска.
Добавить файл с именем log4j2.component.properties
в вашем classpath. Это можно сделать в большинстве проектов maven или gradle, сохранив его в src/main/resources
.
это файл просто . Задайте значение для селектора контекста, добавив в файл следующую строку.
Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
Log4j попытается прочитать систему сначала собственность. Если системное свойство имеет значение null, то оно будет возвращаться к значениям, хранящимся в этом файле по умолчанию.
код, который выполняет эту настройку, находится по адресу Log4jContextFactory.java: 91.
моя проблема в том, что независимо от того, где я это делаю, иногда это работает и ведение журнала очень быстро, а иногда и нет.
добавьте этот код в статический блок инициализатора в классе, который определяет вашу главную точку входа.
public class MainClass {
// NOTE: Nothing can appear before this initializer
// NOTE: This initializer must be in the class that contains your entry point
static {
System.setProperty("Log4jContextSelector",
"org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
}
public static void main(final String[] args) {
// Do anything you want to here
}
}
согласно спецификации Java, статическая инициализация происходит в том порядке, в котором она объявлена. Следовательно,System.setProperty
вызов гарантированно произойдет до инициализации Log4j.
поэтому, по-видимому, мне нужно было добавить строку в jvm.файл параметров
-DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
jvm.файл опций находится здесь:
${server.config.dir}/jvm.options
и этот каталог можно найти по ссылке:
в моем случае это: C:\eclipse\runtime\usr\servers\serverName
Log4j был инициализирован перед вызовом метода main. Поэтому он не может выбрать свойство Log4jContextSelector из системы и по умолчанию работает синхронно.
чтобы проверить то же самое: удалите зависимость disruptor, если ваш проект все еще идет вверх, то он не становится асинхронным.
Если вы добавляете свойство через-DLog4jContextSelector=org.апаш.лесозаготовительный.к log4j.ядро.асинхронный.AsyncLoggerContextSelector после удаления проекта disruptor не пойдет вверх.
Если вы используете tomcat, добавьте системные свойства в catalina.свойства. И не забудьте использовать immediateFlush= "false".