Использование аннотаций для регистрации трассировки - PullRequest
11 голосов
/ 09 апреля 2011

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

String LOG_METHOD = "nameOfMethod(String,List<Long>):void";
if(logger.isTraceEnabled()) { 
    Object[] params = new Object[] { string, list };
    logger.trace(CompanyMessages.newMethodInstanceMessage(this, LOG_METHOD, params)); 
}

и заканчиваться следующим образом (либо в finally -пункте, либо в конце метода:

if(logger.isTraceEnabled()) { 
    logger.trace(CompanyMessages.leaveMethodInstanceMessage(this, LOG_METHOD)); 
}

На самом деле кода больше, но это основная идея. Это загромождает код, и другие кодеры постоянно путают его со своими собственными интерпретациями, которые не используют определенный класс CompanyMessages, который необходим для форматирования сообщений, которые должны быть прочитаны инструментами мониторинга. Поэтому я ищу способ избавиться от кода all , описанного выше, и просто предоставить все методы, для которых требуется трассировка, с аннотациями, такими как: @LogBefore('logLevel') & @LogAfter('logLevel')

Причина, по которой я выбираю это решение, состоит в том, чтобы сделать его таким, чтобы другие разработчики не изучали ничего нового, а использовали аннотации вместо кода. Я работаю в серверной среде, в которой мы развертываем сотни веб-приложений и десятки разработчиков. Поэтому я искал способ реализовать это в веб-приложении без большого количества дополнительного кодирования или дополнительных больших библиотек. Это означает, что я ищу небольшую стабильную реализацию AOP с использованием аннотаций, похожих на предложенные мной, которые легко настроить в каждом веб-приложении. Производительность также важна. Какой самый простой пример для реализации этого с АОП?

Редактировать: Я нашел что-то очень похожее на то, что я ищу, но у этого есть пара проблем. Все классы, для которых необходимо ведение журнала, должны быть настроены, что потребует больше ресурсов, чем просто использование аннотаций. Будет ли это исправлено в конфигурации пружины <aop:aspectj-autoproxy/>?

Ответы [ 3 ]

5 голосов
/ 09 апреля 2011

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

Посмотрите на AspectJ или Spring AOP.

Это потребует некоторого изучения принципов АОП и выбранного вами API, но это определенно стоит усилий. В частности, ведение журналов и трассировка являются одними из первых учебных пособий AOP, с которыми вы столкнетесь, и это довольно легко сделать без необходимости углубляться.

5 голосов
/ 09 апреля 2011

Аннотации и точки AOP действительны.Используйте аннотации, чтобы предупредить платформу AOP о регистрации.

Еще одна вещь, которую я хотел бы сделать, это исправить ваш регистратор.

У вас есть:

String LOG_METHOD = "nameOfMethod(String,List<Long>):void"
if(logger.isTraceEnabled()) { 
    Object[] params = new Object[] { string, list };
    logger.trace(CompanyMessages.newMethodInstanceMessage(this, LOG_METHOD, params) ); 
}

Вместо этого рассмотрите что-то вродеэто:

logger.trace(this, LOG_METHOD, string, list);

и вы можете реализовать это следующим образом:

public void trace(Object obj, Object args...) {
    if (parentLogger.isTraceEnabled()) {
        logger.trace(CompanyMessages.newMethodInstanceMessage(obj, LOG_METHOD, args);
    }
}

Большинство утилит ведения журнала были написаны до того, как у нас были varargs в Java, поэтому мы по-прежнему видим такие вещи, как вымы уже написали.

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

logger.trace("My message: " + string + " with list " + list);

Имеет дорогостоящее выражение независимо от того, включена трассировка или нет.

Но используя varargs, вы можете получить и то, и другое.Просто используйте что-то вроде MessageFormat (что вы, вероятно, уже делаете), вы можете легко получить:

logger.trace("My message: {0} with list {1}", string, list);

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

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

Он не решает вашу проблему напрямую, динамически генерируя информацию трассировки.Но это простая золотая середина, которая легко и постепенно очищает существующую базу кода.

Кроме того, есть 2 других варианта.

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

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

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

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

Как минимум, оберните свой регистратор.Он является инкрементным, безопасным и постепенно очистит ваш код и поможет вести журналы, где аннотации могут вообще не работать.

3 голосов
/ 09 апреля 2011

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

Таким образом, нет никакого способа добавить аннотации и готово к работе, вы, классы, начинаете регистрировать свои методы.

Решение должно быть АОП - именно эта проблема АОП была изобретена в первую очередь. Определите классы / методы / действия для каждого метода, и у вас возникла проблема.

Ну, возможно, вы можете заставить его работать с аннотациями и модификацией классов во время выполнения, но в итоге вы получите самодельный AOP: -)

...