2014-11-07 6 views
1

Я всегда задавался вопросом, можно ли программно установить уровень журнала java.util.logging на уровне нити pr.В Java - Могу ли я установить поток потока журнала?

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

Я думал об этом с помощью сервлет-фильтра и привязал его к его идентификатору сеанса. Но, насколько я вижу, уровни журналов, которые я могу установить в приложениях, не являются нитями аффинными. То есть если я установил уровень корня в FINE, это повлияет на все потоки в системе, а журнал заполняется другими 200 одновременными трафиками пользователей. Конечно, я могу потом отфильтровать журнал, но в любом случае произойдет сбой производительности.

У кого-нибудь есть опыт?

ответ

1

Я всегда задавался вопросом, можно ли программно установить уровень журнала java.util.logging на уровне нити pr.

Создать log filter захватить пользовательский контекст и установить уровень ALL для фильтруемого объекта:

public class UserFilter implements Filter { 

    private final Level lvl; 
    private final Object userContext; 

    public UserFilter(Level originalLevel, Object userContext) { 
     this.lvl = originalLevel; 
     this.userContext = userContext; 
    } 

    @Override 
    public boolean isLoggable(LogRecord record) { 
     if (!belongsTo(record, userContext)) { 
      int levelValue = this.lvl.intValue(); 
      if (record.getLevel().intValue() < levelValue 
        || levelValue == Level.OFF.intValue()) { 
       return false; 
      } 
     } 
     return true; 
    } 


    private boolean belongsTo(LogRecord record) { 
     /** 
     * Insert logic here. 
     */ 
     //return ((Integer) this.userContext) == record.getThreadId(); 
     return true; 
    } 
} 

Для вашего случая использования вы должны быть в состоянии создать сервлет фильтр, который будет:

  1. Создайте фильтр регистрации, который идентифицирует пользователя и фиксирует текущий уровень журнала.
  2. Установите фильтр регистрации, затем измените уровень на FINE.
0

Ну, вы всегда должны иметь возможность напрямую позвонить log(level, message); и получить реальный уровень, используя локальное сопоставление потоков.

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

public void debugExceptCritical(Logger l, String message) { 
    //critical would be your per-thread flag, 
    //just make sure to reset it when it is no longer used, e.g. in a servlet filter 
    l.log(critical ? ERROR : DEBUG, message); 
} 

В качестве альтернативы вы можете попробовать и получить класс, где это называется (я сделал это где-то, но не помните подробности, поэтому я должен был бы это посмотреть) и использовать эту информацию, чтобы получить регистратор внутри метода.

Глядя вызывающий:

StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); 
for(StackTraceElement elem : stackTrace) { 
    //look for the debugExceptCritical method or maybe just the class it contains 
    //if found take the class name of the next element to look up the correct logger 
} 

Альтернативы этому, в зависимости от протоколирования рамки вы на самом деле использовать, может быть подключить некоторый каждый поток фильтра/Appender/все в него. В Log4J я либо попытаюсь добавить свой собственный appender, который затем проверяет флаг critical, а также изменяет уровень событий журнала или всегда регистрирует критические действия и использует фильтр в потоке, который отклоняет те события журнала, когда флаг critial не установлен.

Смежные вопросы