Использование аннотаций для ведения журнала трассировки

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

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 -clause, либо только в конце метода:

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

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

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

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

Ответ 1

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

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

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

Ответ 2

Аннотации и точки 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);

У кого есть дорогое выражение, включен ли трассировка или нет.

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

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

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

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

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

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

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

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

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

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

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

Ответ 3

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

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

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

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