Конфигурирование Log4j Loggers Programmatically

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

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

  • Logger 1 «FileLogger» регистрирует DEBUG и добавляет к DailyRollingFileAppender
  • Logger 2 «TracingLogger» регистрирует TRACE + и присоединяется к JmsAppender
  • Logger 3 «ErrorLogger» регистрирует ERROR + и добавляет к другому JmsAppender

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

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

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

Но как мне настроить эти log4j Loggers на пути к classам … в Java ?!

Вы можете добавить / удалить Appender программно в 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 в курсе classpath.

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

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

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

даст вам регистратор для категории «com.fizz».
В приведенном выше примере это означает, что все, что было зарегистрировано с ним, будут переданы в консоль и файл appender в корневом журнале.
Если вы добавите приложение в Logger.getLogger («com.fizz»). AddAppender (newAppender), то регистрация из fizz будет обрабатываться всеми добавками из корневого регистратора и newAppender .
Вы не создаете Loggers с конфигурацией, вы просто предоставляете обработчики для всех возможных категорий в вашей системе.

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

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

 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); 
  • Почему бы не использовать java.util.logging?
  • Давайте будем гением компьютера.