При чтении документации log4j 2 ожидается, что конфигурация будет загружена, если соответствующий файл конфигурации находится в пути к классам. Но мне нужно точно знать, что файл конфигурации был правильно обработан. Есть ли способ проверить, действительно ли файл конфигурации, который я ожидал загрузить, был найден и успешно загружен?

Я пишу код, который будет использоваться другими разработчиками, и может случиться так, что log4j 2, который является неотъемлемой частью библиотеки, которую мы пишем, не был правильно настроен, потому что файл не был в пути к классам или неправильно настроен. Если log4j 2 не настроен должным образом, я должен остановить дальнейшую обработку нашей библиотеки, он должен выдать серьезные ошибки, и по этому поводу нужно много говорить. Я не могу позволить коду продолжаться. Итак, в итоге мне нужно знать, что log4j 2 правильно обработал ожидаемый файл конфигурации.

Кроме того, я бы предпочел использовать API log4j 2, а не библиотеку Core, но если Core - единственный способ, пусть так и будет.

5
Jose Martinez 20 Май 2014 в 01:57

3 ответа

Лучший ответ

Вы можете выполнить некоторую проверку, используя только api: вы можете зарегистрировать StatusListener с помощью StatusLogger. StatusLogger используется внутри Log4J для регистрации деталей внутри Log4J. Большая часть этого внутреннего журнала связана с конфигурацией.

Например:

public class HaltingStatusListener implements StatusListener {
    public Level getStatusLevel() {
        return Level.ERROR;
    }
    public void log(StatusData data) {
        throw new BigDealException("Internal log4j error detected: "
                + data.getMessage());
    }
}

Однако этого может быть недостаточно для ваших нужд. Еще одна вещь, которую вы можете проверить:

LoggerContext context = LogManager.getContext();
if (context instanceof SimpleLoggerContext) {
    throw new BigDealException(
            "Log4j did not find config file & uses default setup");
}

Если вы хотите углубиться в детали и проверить приложения / регистраторы и т. Д., Вам нужно будет использовать основные классы. В этом случае отправьте сообщение в список рассылки log4j-user, чтобы вовлечь других членов команды.

ОБНОВИТЬ: Команда Log4J в настоящее время предполагает, что сбой инициализации Log4J не критичен и не должен останавливать приложение. Вы можете попросить об улучшении, при котором log4j останавливает приложение (генерирует исключение), если, например, основной jar не был найден или файл конфигурации не был найден. Вы можете подать заявку на участие в Jira или задать вопрос в списке рассылки.

4
Remko Popma 19 Май 2014 в 23:52

Другой возможный вариант - просто проверить StatusLogger напрямую:

StatusLogger.getLogger().getStatusData()
        .stream()
        .filter(s -> s.getLevel().isMoreSpecificThan(Level.ERROR))
        .forEach(s ->
            System.out.println(s.getFormattedStatus())
        );

Это напечатает все внутренние статусы log4j2 с уровнем ошибок ERROR и FATAL

2
Anton Balaniuc 1 Фев 2018 в 17:56

Похоже, у меня это сработало. Это полезно, поскольку оно создает простую программную конфигурацию, если файл конфигурации не найден. Это делает небольшой пакет утилит более переносимым в среды, где возможен конфликт файлов конфигурации.

private static boolean configured = false;

private static void buildLog()
{
    try
    {

        final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
        System.out.println("Configuration found at "+ctx.getConfiguration().toString());

        if(ctx.getConfiguration().toString().contains(".config.DefaultConfiguration"))
        {

            System.out.println("\n\n\nNo log4j2 config available. Configuring programmatically\n\n");



            ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory
                    .newConfigurationBuilder();

            builder.setStatusLevel(Level.ERROR);
            builder.setConfigurationName("IkodaLogBuilder");

            AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE")
                    .addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
            appenderBuilder.add(builder.newLayout("PatternLayout").addAttribute("pattern",
                    "%d [%t]  %msg%n%throwable"));
            builder.add(appenderBuilder);



            LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout").addAttribute("pattern",
                    "%d [%t] %-5level: %msg%n");

            appenderBuilder = builder.newAppender("file", "File").addAttribute("fileName", "./logs/ikoda.log")
                    .add(layoutBuilder);
            builder.add(appenderBuilder);


            builder.add(builder.newLogger("ikoda", Level.DEBUG)
                    .add(builder.newAppenderRef("file"))
                    .add(builder.newAppenderRef("Stdout"))
                    .addAttribute("additivity", false));

            builder.add(builder.newRootLogger(Level.DEBUG)
                    .add(builder.newAppenderRef("file"))
                    .add(builder.newAppenderRef("Stdout")));
            ((org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false)).start(builder.build());
            ctx.updateLoggers();
        }
        else
        {
            System.out.println("Configuration file found.");
        }
        configured=true;
    }
    catch(Exception e)
    {
        System.out.println("\n\n\n\nFAILED TO CONFIGURE LOG4J2"+e.getMessage());
        configured=true;
    }
}
2
Jake 24 Мар 2018 в 02:12