Создание подкласса org.apache.log4j.Logger без изменения %C?

#java #log4j

#java #log4j

Вопрос:

Чтобы включить такие вещи, как

 logger.info("This is a formatted number: %.2f", number)
  

Я решил написать подкласс org.apache.log4j.Logger . Я знаю, я мог бы написать класс-оболочку для достижения того же результата, но поскольку я добавляю много приложений к регистратору во время выполнения, я предпочитаю использовать наследование.

Подкласс выглядит следующим образом:

 public final class FormatLogger extends Logger {

private final static FormatLoggerFactory factory = new FormatLoggerFactory();

protected FormatLogger(String name) {
    super(name);
}

public static Logger getLogger(String name) {
    return Logger.getLogger(name, factory);
}

public void fatal(String formatter, Object... args)  {
    log(Level.FATAL, formatter, args);
}

public void log(Level level, String formatter, Object... args) {
    if (super.isEnabledFor(level)) {
        super.log(level, String.format(formatter, args));
    }
}
}
  

Все работает хорошо — все, кроме одного: в тексте сообщения теперь добавляется имя подкласса logger вместо имени класса, вызывающего logger.
В качестве макета шаблона я использую следующий формат:

 [%d{yyyyMMdd HHmmss}] %-5p [%t] %C: %m%n
  

т.е. все выглядит следующим образом:

 [20110525 214515] INFO  [main] org.xyz.FormatLogger: This is a formatted number: 23.23
  

вместо:

 [20110525 214515] INFO  [main] org.xyz.Main: This is a formatted number: 23.23
  

Есть ли какой-нибудь способ сделать это «правильно», чтобы «% C» продолжал печатать исходное имя класса?

Комментарии:

1. Вы могли бы просто использовать log5j, который является оболочкой вокруг log4j и предоставляет интерфейс logger в стиле vararg. Нет причин изобретать велосипед. code.google.com/p/log5j

2. Незначительное дополнение к отточенному продукту — это не изобретение колеса, IHMO. Для меня переключение на другую библиотеку и перенос всех существующих вызовов log4j — это гораздо больше хлопот, чем добавление нескольких строк кода. Конечно, если кто-то запускает новый проект, имеет смысл использовать log5j или logcenter.

Ответ №1:

Я делал что-то подобное, но в итоге я создал оболочку и передал ей имя класса. Затем с этим именем класса я добавил его в начало всех 4 уровней ведения журнала, которые я все равно уже перенес. Это довольно запутанно, но я не смог найти другого способа сделать это. Мои операторы ведения журнала теперь выдают имя регистратора, а затем имя пакета / класса. Это немного громоздко, но я бы предпочел иметь дополнительную информацию, а не иметь недостаточно информации.

Ответ №2:

Решение довольно простое: добавьте полное имя класса (FQCN), т.Е.:

 static String FQCN = FormatLogger.class.getName()   ".";
  

Затем метод log (..) должен быть изменен следующим образом:

 super.log(FQCN, level, String.format(formatter, args), null);
  

Это прекрасно показано в примере MyLogger.java это поставляется с log4j. -1 за мою собственную лень!

Комментарии:

1. Не волнуйтесь, я думаю, что я это тоже пропустил. Я сделал фактически то же самое, но это было намного сложнее. Спасибо, что указали на это.

2. Небольшое дополнение: я смог заставить это работать с log4j версии 1.2.15, но не с версией 1.2.16 (выдает мне «?» в позиции % C).

Ответ №3:

Удалите «.» в конце строки FQCN, чтобы правильно войти в систему с Log4J версии 1.2.16 или более поздней.