Делаете простые изменения производительности уже скомпилированной банки? - PullRequest
5 голосов
/ 22 октября 2009

Как и многие пользователи log4j, у нас часто есть регистрация уровня отладки, которую стоит оценить дорого. Поэтому мы защищаем эти случаи с помощью кода вроде:

if( _logger.isDebugEnabled )
  _logger.debug("Interesting, my foojes are goofed up: " + getFullDetails())

Однако это страшнее, чем простой вызов _logger.debug, и иногда программист не понимает, что оценка может быть дорогой.

Кажется, что довольно просто написать программу, которая берет скомпилированный jar и защищает все вызовы _logger.debug проверкой isDebugEnabled Мы, вероятно, были бы готовы принять дополнительные накладные расходы на проверку isDebugEnabled во всех случаях.

Кто-нибудь пробовал этот подход или делал аналогичную постобработку банки?

Ответы [ 3 ]

4 голосов
/ 22 октября 2009

Вместо того, чтобы смотреть на изменение банки, я бы искал решение, используя Инструментарий с байт-кодом . Проблема будет заключаться в том, чтобы идентифицировать те части кода, которые вы хотите заключить в .isDebugEnabled() - вам придется идентифицировать объекты, которые используются только для вызовов log4j.

2 голосов
/ 22 октября 2009

Вы смотрели на AspectJ ? Это поддерживает аспекты, использующие переплетение байт-кода, и может перехватывать в ранее скомпилированном файле .jar .

1 голос
/ 22 октября 2009

Я считаю, что хорошим решением было бы то, что код будет эффективным, как .

Учтите, что log4j устарела. Сам автор оставил все как есть, чтобы избежать нарушения совместимости, но создал новый, SLF4J (http://www.slf4j.org/). Он предоставляет как фасад, так и реализацию, в соответствии с различием commons-logging / log4j, но без недостатков каждого ...

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


Наш код не использует slf4j, но у нас есть служебные методы, которые делают именно это. Это кодируется примерно следующим образом (из памяти):

    public enum LogLevel {
       FATAL, ERROR, WARNING, INFO, DEBUG;

       public void log(Logger logger, String format, Object... parameters) {
         if (isEnabled(logger)) {
            logImpl(logger, String.format(format, parameters));
         }
       }
       public boolean isEnabled(Logger logger) {
         switch(this) {
           case WARNING : return logger.isWarningEnabled();
           case INFO : return logger.isInfoEnabled();
           case DEBUG : return logger.isDebugEnabled();
           default: return true;
         }
       }
       private void logImpl(Logger logger, String message) {
         switch(this) {
           case WARNING : logger.warn(message);
           // other cases
         }
       }
    }

Используется как:

     public void myMethod(Object param) {
       LogLevel.WARNING.log(LOGGER, "What is my message ....", "myMethod", param);
     }

ОБНОВЛЕНИЕ : Если вам нужно вызвать метод в журнале ...

  • Одна из возможностей - использовать метод toString. Это уместно , если ваша регистрация 'техническая' , и будет использоваться также при отладке.

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

    public interface Detailable { // the name could also suggest logging?
      String getFullDetails();
    }
    

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...