Настройка Log4j Регистраторов Программно


Я пытаюсь использовать SLF4J (с log4j привязка) в первый раз.

Я хотел бы настроить 3 разных именованных регистратора, которые могут быть возвращены LoggerFactory, который будет регистрировать разные уровни и передавать сообщения разным приложениям:

  • Logger 1 "FileLogger" журналы отладки и добавляет к DailyRollingFileAppender
  • Logger 2 "TracingLogger" регистрирует трассировку+ и добавляет к JmsAppender
  • Logger 3 "ErrorLogger" регистрирует ошибку+ и добавляет к другому JmsAppender

кроме того, я хочу, чтобы они были настроены программно (в Java, в отличие от XML или a log4j.properties file).

Я думаю, что, как правило, я бы определил эти LoggerС в какой-нибудь загрузчик код, например init() метод. Однако, потому что я хочу использовать slf4j-log4j, Я смущен тем, где я мог бы определить регистраторы и сделать их доступными для classpath.

Я не верить это a нарушение основной цели SLF4J (как фасад), потому что мой код, использующий API SLF4J, никогда не узнает, что эти регистраторы существуют. Мой код просто делает обычные вызовы SLF4J API, который затем пересылает их на log4j Loggers, которые он находит на пути к классам.

но как я могу настроить эти log4j регистраторы на classpath...in Ява?!

3 170

3 ответа:

вы можете добавить / удалить приложение программно в Log4j:

  ConsoleAppender console = new ConsoleAppender(); //create appender
  //configure the appender
  String PATTERN = "%d [%p|%c|%C{1}] %m%n";
  console.setLayout(new PatternLayout(PATTERN)); 
  console.setThreshold(Level.FATAL);
  console.activateOptions();
  //add appender to any Logger (here is root)
  Logger.getRootLogger().addAppender(console);

  FileAppender fa = new FileAppender();
  fa.setName("FileLogger");
  fa.setFile("mylog.log");
  fa.setLayout(new PatternLayout("%d %-5p [%c{1}] %m%n"));
  fa.setThreshold(Level.DEBUG);
  fa.setAppend(true);
  fa.activateOptions();

  //add appender to any Logger (here is root)
  Logger.getRootLogger().addAppender(fa);
  //repeat with all other desired appenders

Я бы предложил вам поместить его в init() где-нибудь, где вы уверены, что это будет выполнено прежде всего. Затем вы можете удалить все существующие приложения в корневом регистраторе с помощью

 Logger.getRootLogger().getLoggerRepository().resetConfiguration();

и начните с добавления своего собственного. Вам нужно log4j в пути к классам, конечно, чтобы это работало.

замечание:
Вы можете взять любой Logger.getLogger(...) вы любите добавлять приложения. Я просто взял корневой регистратор, потому что он находится в нижней части всех вещей и будет обрабатывать все, что передается через другие приложения в других категориях (если не настроено иначе, установив флаг аддитивности).

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

  Logger fizz = LoggerFactory.getLogger("com.fizz")

даст вам регистратор для категории " com.шипеть."
Для приведенного выше примера это означает, что все записанное с ним будет передано в консоль и файловый аппендер на корневом регистраторе.
Если вы добавляете приложение к Лесоруб.getLogger ("com.шипеть.)"addAppender(newAppender) затем вход из fizz будет обрабатываться всеми приложениями из корневого регистратора и newAppender.
Вы не создаете регистраторы с конфигурацией, вы просто предоставляете обработчики для всех возможных категорий в вашей системе.

похоже, что вы пытаетесь использовать log4j с "обоих концов" (конец потребителя и конец конфигурации).

Если вы хотите кодировать против slf4j api, но заранее определить (и программно) конфигурацию log4j Loggers, что classpath будет возвращать, вы абсолютно чтобы иметь какую-то адаптацию к журналированию, которая использует ленивую конструкцию.

public class YourLoggingWrapper {
    private static boolean loggingIsInitialized = false;

    public YourLoggingWrapper() {
        // ...blah
    }

    public static void debug(String debugMsg) {
        log(LogLevel.Debug, debugMsg);
    }

    // Same for all other log levels your want to handle.
    // You mentioned TRACE and ERROR.

    private static void log(LogLevel level, String logMsg) {
        if(!loggingIsInitialized)
            initLogging();

        org.slf4j.Logger slf4jLogger = org.slf4j.LoggerFactory.getLogger("DebugLogger");

        switch(level) {
        case: Debug:
            logger.debug(logMsg);
            break;
        default:
            // whatever
        }
    }

    // log4j logging is lazily constructed; it gets initialized
    // the first time the invoking app calls a log method
    private static void initLogging() {
        loggingIsInitialized = true;

        org.apache.log4j.Logger debugLogger = org.apache.log4j.LoggerFactory.getLogger("DebugLogger");

        // Now all the same configuration code that @oers suggested applies...
        // configure the logger, configure and add its appenders, etc.
        debugLogger.addAppender(someConfiguredFileAppender);
    }

при таком подходе вам не нужно беспокоиться о том, где/когда ваши регистраторы log4j настраиваются. Первый раз в classpath просит за них, они вам лениво построил, сдал назад, и через slf4j. Надеюсь, что это помогло!

в случае, если вы определили приложение в свойствах log4j и хотите обновить его программно, установите имя в свойствах log4j и получите его по имени.

вот пример записи log4j. properties:

log4j.appender.stdout.Name=console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.Threshold=INFO

чтобы обновить его, выполните следующие действия:

((ConsoleAppender) Logger.getRootLogger().getAppender("console")).setThreshold(Level.DEBUG);