Как отключить обработчик консоли по умолчанию при использовании API ведения журналов Java?

93

Привет, я пытаюсь реализовать ведение журнала java в своем приложении. Я хочу использовать два обработчика. Обработчик файлов и мой собственный обработчик консоли. Оба моих обработчика работают нормально. Мой журнал отправляется в файл и на консоль. Мой журнал также отправляется обработчику консоли по умолчанию, что мне не нужно. Если вы запустите мой код, вы увидите дополнительные две строки, отправленные на консоль. Я не хочу использовать обработчик консоли по умолчанию. Кто-нибудь знает, как отключить обработчик консоли по умолчанию. Я хочу использовать только два созданных мной обработчика.

Handler fh = new FileHandler("test.txt");
fh.setFormatter(formatter);
logger.addHandler(fh);

Handler ch = new ConsoleHandler();
ch.setFormatter(formatter);
logger.addHandler(ch);

import java.util.Date;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

public class LoggingExample {
    private static Logger logger = Logger.getLogger("test");

    static {
        try {
            logger.setLevel(Level.INFO);

            Formatter formatter = new Formatter() {

                @Override
                public String format(LogRecord arg0) {
                    StringBuilder b = new StringBuilder();
                    b.append(new Date());
                    b.append(" ");
                    b.append(arg0.getSourceClassName());
                    b.append(" ");
                    b.append(arg0.getSourceMethodName());
                    b.append(" ");
                    b.append(arg0.getLevel());
                    b.append(" ");
                    b.append(arg0.getMessage());
                    b.append(System.getProperty("line.separator"));
                    return b.toString();
                }

            };

            Handler fh = new FileHandler("test.txt");
            fh.setFormatter(formatter);
            logger.addHandler(fh);

            Handler ch = new ConsoleHandler();
            ch.setFormatter(formatter);
            logger.addHandler(ch);

            LogManager lm = LogManager.getLogManager();
            lm.addLogger(logger);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        logger.info("why does my test application use the standard console logger ?\n" + " I want only my console handler (Handler ch)\n " + "how can i turn the standard logger to the console off. ??");
    }
}
громко
источник
1
Могу я осторожно предложить использовать b.append(formatMessage(arg0))вместо b.append(arg0.getMessage()). С помощью formatMessageметода вы делаете ваш форматтер совместимым с использованием public void log(Level level, String msg, Object param1)и аналогичными методами.
Виктор

Ответы:

102

Обработчик консоли по умолчанию прикреплен к корневому регистратору, который является родительским для всех других регистраторов, включая ваш. Итак, я вижу два пути решения вашей проблемы:

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

logger.setUseParentHandlers(false);

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

Logger globalLogger = Logger.getLogger("global");
Handler[] handlers = globalLogger.getHandlers();
for(Handler handler : handlers) {
    globalLogger.removeHandler(handler);
}

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

Петер Торок
источник
2
setUseParentHandlers работает, спасибо. как я могу удалить обработчик консоли по умолчанию из корневого регистратора?
Loudiyimo
10
Вы также можете использовать Logger.getLogger ("") - это работает для меня там, где "global" нет (может быть результатом SLF4J в миксе?)
sehugg
2
Если вы хотите slf4j, я предлагаю вам использовать это LogManager.getLogManager().reset(); SLF4JBridgeHandler.install();
Somatik
8
"" - это идентификатор корневого регистратора. "global" - это именованный регистратор (дочерний элемент root), который создается по умолчанию и должен использоваться в простых сценариях регистрации
Паоло Фулгони 01
1
Этот ответ не работает для меня, но ответ Доминика работает
BullyWiiPlaza
109

Просто делать

LogManager.getLogManager().reset();
Доминик
источник
1
Спасибо, это правильный ответ. Ответ, отмеченный как правильный, не работает.
Андреас Л.
1
Это должно указывать на то, что это повлияет на каждый обработчик для каждого имени, Loggerпоэтому это может быть проблемой для более сложной системы журналов. Это следует вызвать один раз в начале процесса, чтобы убедиться, что это не повлияет на Futur Logger. И, конечно же, тот, кому понадобится консоль, должен будет получить ConsoleHandlerкак и ожидалось.
AxelH
20

Это странно, но Logger.getLogger("global") в моей настройке не работает (как и Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)).

Однако Logger.getLogger("")делает свою работу хорошо.

Надеюсь, эта информация также поможет кому-то ...

Дайм
источник
3
может кто-нибудь сказать нам, почему getLogger (Logger.GLOBAL_LOGGER_NAME) не работает, а getLogger ("") работает?
deinocheirus 01
2
@deinocheirus см. мой комментарий к этому ответу
Паоло Фульгони 01
9

Выполните сброс конфигурации и установите корневой уровень на ВЫКЛ.

LogManager.getLogManager().reset();
Logger globalLogger = Logger.getLogger(java.util.logging.Logger.GLOBAL_LOGGER_NAME);
globalLogger.setLevel(java.util.logging.Level.OFF);
Мануэль
источник
5

Вы должны указать своему регистратору, чтобы он не отправлял свои сообщения родительскому регистратору:

...
import java.util.logging.*;
...
Logger logger = Logger.getLogger(this.getClass().getName());
logger.setUseParentHandlers(false);
...

Однако это следует сделать перед добавлением дополнительных обработчиков в регистратор.

Просто говорю
источник
В моем случае это сработало, хотя мне пришлось вручную добавить обработчик для этого регистратора.
Sachin Gorade