Я создал новый обработчик журнала для JUL, который расширяет java.util.logging.Handler.

Есть ли какой-либо стандартизированный способ реагирования на ошибки, возникающие во время обработки LogRecord (например, LogLog в log4j)?

Простое использование JUL-Logger приводит к другому LogRecord, который должен обрабатываться тем же обработчиком.

Итак, я в основном ищу (стандартный) способ регистрации сообщений без создания бесконечного цикла. На данный момент я сравниваю sourceClassName, чтобы предотвратить такой цикл.

3
Roman 23 Фев 2016 в 15:25

2 ответа

Лучший ответ

На данный момент я ищу это решение:

public class MyHandler extends Handler {
  private final static String className = MyHandler.class.getName();
  private final static Logger logLogger = Logger.getLogger(className);
  ...

  @Override
  public void publish(LogRecord record) {
    if (!super.isLoggable(record)) {
      return;
    }

    String loggerName = record.getLoggerName(); //EDIT: Was getSourceClassName before
    if (loggerName != null && loggerName.equals(className)) {
      // This is our own log line; returning immediately to prevent endless loops
      return;
    }

    try {
      // ... do actual handling...
    } catch(Exception e) {
      logLogger.logp(level.SEVERE, className, "publish", "something went wrong", e);
    }
  }
}
0
Roman 26 Фев 2016 в 12:43

Об исключениях, возникающих внутри обработчика, следует сообщать с помощью Handler.reportError (String, Exception, int). Это сообщает о сбоях в установленный ErrorManager, который можно настроить. Это должно позаботиться о большинстве бесконечных циклов.

Однако, если акт публикации зависит от библиотеки, которая также генерирует записи журнала, вам придется прибегнуть к обнаружению цикла. Используйте java.lang.ThreadLocal и некоторые своего рода перечисление для отслеживания изменений состояния.

public class HandlerReentrance extends Handler {

    private static final Level PUBLISH = Level.ALL;
    private static final Level REPORT = Level.OFF;

    private static final ThreadLocal<Level> LOCAL = new ThreadLocal<>();

    @Override
    public void publish(LogRecord record) {
        if (LOCAL.get() == null) {
            LOCAL.set(PUBLISH);
            try {
                doPublish(record);
            } finally {
                LOCAL.remove();
            }
        } else {
            final Level last = LOCAL.get();
            if (PUBLISH.equals(last)) {
                LOCAL.set(REPORT);
                try {
                    reportLoop(record);
                } finally {
                    LOCAL.set(last);
                }
            }
        }
    }

    private void doPublish(LogRecord record) {
        if (isLoggable(record)) {
           //Insert code.
        }
    }

    private void reportLoop(LogRecord record) {
        //Insert code.
    }

    @Override
    public void flush() {
    }

    @Override
    public void close() {
    }
}
1
jmehrens 23 Фев 2016 в 18:19