Конфигурирование 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
, я смущен тем, где я могу определить регистраторы и сделать их доступными для пути к классам.
Я не считаю, что это является нарушением основной цели SLF4J (как фасад), потому что мой код с использованием API SLF4J никогда не узнает, что эти журналы существуют. Мой код просто выполняет обычные вызовы API SLF4J, который затем пересылает их на log4j Loggers, который он находит на пути к классам.
Но как мне настроить эти log4j Loggers на пути к классам... в Java?!
Ответы
Ответ 1
Вы можете добавить/удалить 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 в пути к классам.
Примечание:
Вы можете взять любой Logger.getLogger(...)
, который вам нравится добавлять. Я просто взял корневой журнал, потому что он находится в нижней части всех вещей и будет обрабатывать все, что передается через другие приложения в других категориях (если не настроено иначе, установив флаг аддитивности).
Если вам нужно знать, как работает журнал, и как решено, где записываются журналы прочитайте это руководство для получения дополнительной информации об этом.
Короче:
Logger fizz = LoggerFactory.getLogger("com.fizz")
предоставит вам регистратор для категории "com.fizz".
В приведенном выше примере это означает, что все, что было зарегистрировано с ним, будут переданы в консоль и файл appender в корневом журнале.
Если вы добавите Logger.getLogger( "com.fizz" ). AddAppender (newAppender)
то запись из fizz
будет обрабатываться всеми добавками из корневого регистратора и newAppender
.
Вы не создаете Loggers с конфигурацией, вы просто предоставляете обработчики для всех возможных категорий в вашей системе.
Ответ 2
Похоже, вы пытаетесь использовать log4j с "обоих концов" (конец потребителя и конец конфигурации).
Если вы хотите скопировать код с slf4j api, но заранее определите (и программно) конфигурацию log4j Loggers, возвращаемую классом pathpath, у вас абсолютно есть какая-то адаптация ведения журнала который использует ленивую конструкцию.
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. Надеюсь, это помогло!
Ответ 3
В том случае, если вы определили приложение в свойствах 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);