Как стать автором
Обновить

Комментарии 18

Советую еще обратить внимание на библиотечку aspect4log, существующую аж с 2014ого года
И с последней активностью в середине 2016.
Так бывает, когда разработчик один, а задача достаточно специфическая. Библиотечка покрыла все нужды своего создателя и логично прекратила свое развитие
Еще так бывает, когда проект заброшен.
Спасибо за наводку, интересно пронаблюдать другую точку зрения на решение тех же задач.

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

Мне показался такой путь трудным и ненадёжным. Поэтому в Eclair можно помимо ручного выбора формата для распечатки привязать ru.tinkoff.eclair.printer.Printer к типу аргумента (на весь контекст) и этот принтер будет выполнять свою работу в любом месте приложения, уже без ручного контроля.

Пользоваться aspect4log, оговорюсь, не приходилось. И во время разработки Eclair я о таком инструменте не знал, поэтому могу оценивать слишком поверхностно.
Все правильно, задача была именно минимальными усилиями логировать ход работы потенциально проблемных мест, а проблема сокрытия данных даже не возникала.
В чем преимущество ManualLogger перед @Slf4j аннотации ломбока? Я так понимаю, нет никаких проблем в их совместном использовании, тогда зачем понадобился целый бин?
В совместном использовании нет никаких проблем.
ru.tinkoff.eclair.logger.ManualLogger — это не отдельный бин, а interface, который реализован включенным в автоконфигурацию EclairLogger'ом.
В примере приведено внедрение через interface. Default'ный логгер его реализует, но делать это не обязательно.

Если сравнивать с @Slf4j, на ум приходят такие отличия:
1) Eclair включает имя логируемого метода в имя логгера (не только при ручном логировании, а вообще всегда), например: ru.tinkoff.eclair.example.Example.simple
Благодаря этому есть возможность настраивать через конфигурацию уровни доступного лога не только для пакета/класса, но и для отдельных методов.
Это бывает полезно, когда точно знаешь, в каком месте нужно повысить подробность лога до DEBUG или TRACE, но включать DEBUG для всего класса нет желания (из-за больших объёмов лога или проседания скорости).
2) ManualLogger имеет набор «сахарных» методов, например ManualLogger#warnIfDebugEnabled("some").
Такой метод может быть полезен, если в логике обрабатывается некоторое предупреждение (warning), которое не слишком важно, но если для текущей локации доступен DEBUG, то его нужно залогировать как WARN.
Того же можно добиться с помощью @Slf4j, но менее лаконично: if (log.isDebugEnabled()) { log.warn("some"); }
3) ManualLogger принимает в качестве аргументов Supplier'ы. На сколько я понимаю, в зависимости о того, что лежит «под» @Slf4j-логгером, ты не всегда имеешь возможность провернуть «ленивую» инициализацию аргументов.
4) В метод ManualLogger#log есть возможность передать LogLevel, определяемый динамически. Это тоже для особых ценителей. Не сказать, что сильно важная способность.

Если эти способности не востребованы, и достаточно стандартного интерфейса slf4j, а также сам Lombok не является проблемой, вполне можно ограничиться @Slf4j.

А почему так привязались именно к проксям? Есть же aspectj, там и оверхеда поменьше и ограничений таких как у Proxy нет.

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

Ну, AspectJ достаточно хорошо тестируется, чтобы ему можно было доверять. Я, честно, чаще на баги в Javac'е пока натыкался, чем на баги в AspectJ.
А время компиляции это вообще пыль, если можно увеличить перфоманс, убрав оверхед.
И кстати, спринг позволяет писать независимые от технологии (Dynamic Proxy или AspectJ) аспекты, зачем же руками прокси писать?

И кстати, спринг позволяет писать независимые от технологии (Dynamic Proxy или AspectJ) аспекты, зачем же руками прокси писать?

Всё спринговое AOP построено на проксях.
Target object: object being advised by one or more aspects. Also referred to as the advised object. Since Spring AOP is implemented using runtime proxies, this object will always be a proxied object.


Т.ч. «оверхед» никуда не денется.

Вот даже по вашей ссылке если перейти и прочитать дальше, то будет видно, что вы не правы =)


One such choice that is relevant to this chapter is that of which AOP framework (and which AOP style) to choose. You have the choice of AspectJ and/or Spring AOP, and you also have the choice of either the @AspectJ annotation-style approach or the Spring XML configuration-style approach. The fact that this chapter chooses to introduce the @AspectJ-style approach first should not be taken as an indication that the Spring team favors the @AspectJ annotation-style approach over the Spring XML configuration-style.

В спринге можно выбрать что будет использоваться Spring AOP или AspectJ (пару аннотаций повесить). Spring AOP поддерживает только небольшой сабсет возможностей AspectJ.
Load Time Weaving
Для @Transactional, кстати, можно выбрать AdviceMode (PROXY, ASPECTJ).
Спринговое AOP специально было разработано так, чтобы не привязываться к конкретной технологии (это так же написано в доке)

Spring всегда использует прокси для консистентного поведения.

Есть паттерн прокси, а есть класс в джаве java.lang.reflect.Proxy. В случае использования CGLIB или AspectJ не будет создан объект класса java.lang.reflect.Proxy. В статье, на которую вы ссылаетесь, написано всего лишь то, что всегда создаётся прокси как паттерн, не как класс из джавы. И в случае с CGLIB и AspectJ это "прокси" без оверхеда, потому что они меняют байткод.

Во всём обсуждении под «прокси» я подразумевал именно паттерн, а никак не его какую-то имплементацию. Похоже, что мы друг друга не поняли.

А, ну тогда я с вами в принципе согласен =)

Мысль сделать то же самое с помощью AspectJ, конечно, была. И в общем-то продолжает витать.

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

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