Log4J: Стратегии создания экземпляров Регистратора

Я нашел ответ @ https://rider-support.jetbrains.com/hc/en-us/community/posts/360001334920-Optimize-imports-add-reference-option-to-put-using -directives-inside-namespace

Файл | Настройки | Редактор | Код Стиль | C # | Код Стиль | Ссылка Квалификация | Добавьте директиву using для самой глубокой области видимости

69
задан Community 23 May 2017 в 11:46
поделиться

9 ответов

Обычно регистраторы настраиваются для каждого класса, потому что это хороший логический компонент. Потоки уже являются частью сообщений журнала (если ваш фильтр отображает их), поэтому такое нарезание логгеров, вероятно, излишне.

Что касается логгеров на основе приложений или уровней, проблема в том, что вам нужно найти место для прикрепления этого объекта Logger. Ничего особенного. Более серьезная проблема заключается в том, что некоторые классы могут использоваться на нескольких уровнях из нескольких приложений ... может быть сложно правильно настроить ваш регистратор. Или, по крайней мере, сложно.

... и последнее, что вам нужно, - это неверные предположения в настройках журналирования.

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

45
ответ дан 24 November 2019 в 13:52
поделиться

Лучший и самый простой способ создания пользовательских регистраторов, не связанных с каким-либо именем класса:

// create logger
Logger customLogger = Logger.getLogger("myCustomLogName");

// create log file, where messages will be sent, 
// you can also use console appender
FileAppender fileAppender = new FileAppender(new PatternLayout(), 
                                             "/home/user/some.log");

// sometimes you can call this if you reuse this logger 
// to avoid useless traces
customLogger.removeAllAppenders();

// tell to logger where to write
customLogger.addAppender(fileAppender);

 // send message (of type :: info, you can use also error, warn, etc)
customLogger.info("Hello! message from custom logger");

сейчас, если вам нужен другой регистратор в том же классе, нет проблем :) просто создайте новый

// create logger
Logger otherCustomLogger = Logger.getLogger("myOtherCustomLogName");

Теперь посмотрите приведенный выше код и создайте новый fileappender, чтобы ваш вывод был отправлен в другой файл

Это полезно (по крайней мере) для 2 ситуаций

  • , когда вы хотите отделить ошибку от информации, и предупреждает

  • , когда вы управляете несколькими процессами и вам нужен вывод из каждого процесса

пс. есть вопросы ? не стейсняйся спросить! :) [1 110]

2
ответ дан Rodislav Moldovan 24 November 2019 в 13:52
поделиться

При развертывании нескольких EAR / WAR может быть лучше упаковать файл log4j.jar выше в иерархии загрузчика классов.
То есть не в WAR или EAR, а в System-classloader вашего контейнера, в противном случае несколько экземпляров Log4J будут записывать в один и тот же файл одновременно, что приведет к странному поведению.

0
ответ дан Bas 24 November 2019 в 13:52
поделиться

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

Создание журналов для каждого класса имеет то преимущество, что позволяет включать / выключать ведение журнала в структуре пакетов ваших классов:

log4j.logger.org.apache = INFO
log4j.logger.com.example = DEBUG
log4j.logger.com.example.verbose = ERROR

Выше установит весь код библиотеки apache на уровень INFO , переключит ведение журнала с вашего собственного кода на уровень DEBUG , за исключением подробного пакета.

32
ответ дан 24 November 2019 в 13:52
поделиться

Распространенное соглашение - «класс pr регистратора и использование имени класса в качестве его имени». Это хороший совет.

Мой личный опыт показывает, что эту переменную регистратора НЕ следует объявлять статической, а следует объявлять переменной экземпляра, которая извлекается для каждого нового. Это позволяет платформе регистрации обрабатывать два вызова по-разному в зависимости от того, откуда они пришли. Статическая переменная одинакова для ВСЕХ экземпляров этого класса (в этом загрузчике классов).

Также вы должны изучить все возможности с вашим выбранным сервером ведения журнала. У вас могут быть возможности, о которых вы не ожидали.

0
ответ дан 24 November 2019 в 13:52
поделиться

Как было сказано другими, я бы создал регистратор для каждого класса:

private final static Logger LOGGER = Logger.getLogger(Foo.class);

или

private final Logger logger = Logger.getLogger(this.getClass());

. Однако в прошлом я счел полезным иметь другую информацию в регистраторе. Например, если у вас есть веб-сайт, вы можете включать идентификатор пользователя в каждое сообщение журнала. Таким образом, вы можете отслеживать все, что делает пользователь (очень полезно для отладки проблем и т. Д.).

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

Еще одно преимущество использования MDC состоит в том, что при использовании SL4J вы можете изменять настройки в зависимости от значений в вашем MDC. Так что, если вы хотите регистрировать всю активность конкретного пользователя на уровне DEBUG и оставлять всех остальных пользователей на уровне ОШИБКИ, вы можете это сделать. Вы также можете перенаправить другой вывод в разные места в зависимости от вашего MDC.

Некоторые полезные ссылки:

http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/MDC.html

http://www.slf4j.org/api/ index.html? org / slf4j / MDC.html

10
ответ дан 24 November 2019 в 13:52
поделиться

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

Logger logger = Logger.getLogger(MyClass.class);

... разработчики часто забывают заменить "MyClass" на текущее имя класса, и несколько регистраторов всегда указывают не в том месте. Это плохо.

Я иногда писал:

static Logger logger = LogUtil.getInstance(); 

И:

class LogUtil {
   public Logger getInstance() {
      String callingClassName = 
         Thread.currentThread().getStackTrace()[2].getClass().getCanonicalName();
      return Logger.getLogger(callingClassName);
   }
}

«2» в этом коде может быть неправильным, но суть здесь; снизьте производительность (при загрузке класса, как статическая переменная), чтобы найти имя класса, чтобы разработчик действительно не имел возможности ошибиться при вводе этого слова или ввести какую-либо ошибку.

Обычно я не в восторге от потери производительность, чтобы предотвратить ошибку разработчика во время выполнения, но если это происходит как одноэлементный, один раз? Для меня это часто звучит как хорошая сделка.

13
ответ дан 24 November 2019 в 13:52
поделиться
  • Создайте по одному регистратору для каждого класса.
  • Если у вас есть зависимости, требующие Commons Logging (весьма вероятно), используйте мост slf4j для Commons Logging. Создайте экземпляры своих регистраторов (для каждого класса) с помощью интерфейса Commons Logging: private static final Log log = LogFactory.getLog (MyClass.class);
  • Проявите этот шаблон в своей среде IDE с помощью ярлыков. Для этой цели я использую живые шаблоны IDEA .
  • Предоставляйте контекстную информацию потокам, используя NDC (локальный стек строк потока) или MDC (поток локальная карта String →?).

Примеры шаблонов:

private static final Log log = LogFactory.getLog($class$.class); // live template 'log'

if (log.isDebugEnabled())
    log.debug(String.format("$string$", $vars$)); // live template 'ld', 'lw', 'le' ...
4
ответ дан 24 November 2019 в 13:52
поделиться

Другой вариант: вы можете попробовать пересечение AspectJ при ведении журнала. Проверьте здесь: Упростите ведение журнала . (Если вы не хотите использовать AOP , вы можете посмотреть slf4j )

//Without AOP

    Class A{
       methodx(){
        logger.info("INFO");
       }
    }

    Class B{
       methody(){
        logger.info("INFO");
       }
    }

//With AOP

    Class A{
       methodx(){
         ......
       }
    }

    Class B{
       methody(){
         ......
       }
    }

    Class LoggingInterceptor{

       //Catched defined method before process
       public void before(...xyz){
         logger.info("INFO" + ...xyz);
       }

       //Catched defined method after processed          
       public void after(...xyz){
         logger.info("INFO" + ...xyz);
       }
       .....

    }

PS: AOP будет лучше, это DRY (Не повторяйся) путь.

3
ответ дан 24 November 2019 в 13:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: