2017-01-29 4 views
1

Я пишу приложение, которое использует log4j 2.5, и все отлично работает. Чтобы повысить производительность, я хотел сделать асинхронный асинхронный журнал, но не хотел добавлять зависимость от сбоев, поэтому решил использовать Async Appenders. Я нашел несколько примеров того, как их использовать, но я думаю, что в этом что-то пошло не так :(log4j duplicate messages при использовании AsyncAppender

Я не использую конфигурационный файл xml, но вместо этого создаю все мои регистраторы в коде. Что я делаю сначала создаю свои приложения, а потом создаю Async Appenders для каждого из них, где я ссылаюсь на их имя.

Я получаю повторяющиеся сообщения, потому что для каждого appender у меня есть как сам appender, так и AsyncAppender, отправляющий мои сообщения к этому Appender

Мой код:

addAppenderToLogger(fileAppender, logger) 
addAppenderToLogger(rollingFileAppender, logger) 

AsyncAppender.createAppender(
    names.map(name => AppenderRef.createAppenderRef(
    name, Level.getLevel("INFO"), null 
)), errorRef, true, 0, 2048, s"async-appender", false, null, config, true 
) 

Я создаю 1 AsyncAppender для обоих моих приложений.

Пример для дублирующих журналов:

2017-01-26 13: 21: 33619 [запуск задачи Палач рабоче-1] INFO Короткий текст - Начиная помечать ID 973376

2017- 01-26 13: 21: 33,619 INFO short-text - Начальная отметка ID 2497995

2017-01-26 13: 21: 33,619 [Исполнитель-рабочий работник-1] INFO short-text - начало тегов ID 973376

2017-01-26 13: 21: 33619 [запуск задачи Палач рабоче-2] INFO Короткий текст - Начиная помечать ID 2497995

ответ

1

Если вы добавите как FileAppender и AsyncAppender к вашему logger, то это станет узким местом, и вы потеряете преимущество асинхронного ведения журнала.

Добавьте только AsyncAppender к вашим регистраторам и пусть AsyncAppender указывает на FileAppender через AppenderRef.


Что касается программной конфигурации, некоторые тесты Log4j2 делают что-то похожее на то, что вы пытаетесь сделать. Например, this one:

final LoggerContext context = LoggerContext.getContext(false); 
final Configuration config = context.getConfiguration(); 
final PatternLayout layout = PatternLayout.createDefaultLayout(config); 
final Appender appender = WriterAppender.createAppender(layout, null, writer, writerName, false, true); 
appender.start(); 
config.addAppender(appender); 

final Level level = null; 
final Filter filter = null; 
for (final LoggerConfig loggerConfig : config.getLoggers().values()) { 
    loggerConfig.addAppender(appender, level, filter); 
} 
config.getRootLogger().addAppender(appender, level, filter); 

Надеюсь, это полезно.

+0

То, что я делал раньше, создавал приставки и добавлял их в регистратор, после чего создавал Async Appender с помощью «AppenderRefs», а затем удалял исходные приложения. Это похоже на работу, но это довольно уродливое решение (создание, а затем удаление). Я теперь пробовал, что вы сделали, но я получаю исключение NullPointerException. Где я должен создавать приложения? В главном Logger? И AsyncAppender, который я создаю в своем логгере контекста приложения? Потому что просто создавать их как переменные недостаточно (создает исключение NullPointerException) – sid802

+0

Корневой регистратор должен ссылаться на AsyncAppender, а AsyncAppender должен ссылаться на FileAppender. Другие регистраторы, полученные из того же LoggerContext (~ 1 на 1 с приложением), будут маршрутизировать события в их родительский регистратор (корневой журнал). –

+0

Но как я могу сделать свой AsyncAppender ссылкой на FileAppender, если он не был зарегистрирован ни с каким журналом/контекстом? Например: вал fileAppender = createFileAppender (имя) вал RollingFileAppender = createRollingFileAppender (имя, folderNameExt) вал curLogger = ctx.getLogger (имя) addAppenderToLogger (createAsyncAdapter (Array (fileAppender.getName, rollingFileAppender.getName) , fileAppender.getName), curLogger) ctx.getLogger (имя) .setLevel (Level.ALL) приводит к NullPointerException, потому что во время выполнения, то createAsyncAdapter не знает имен в Appender в – sid802