#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 или более поздней.