Но одна вещь беспокоит меня некоторое время. Печально известный признак « след из стека » — следы из стека, содержащие сотни нерелевантных, загадочных, часто автоматически генерируемых методов. Фреймворки AOP и чрезмерно спроектированные библиотеки имеют тенденцию производить безумно длинные трассы выполнения. Позвольте мне показать пример из жизни. В примере приложения я использую следующий стек технологий:
Цвета важны. В соответствии с цветом фреймворка / слоя я нарисовал образец стека трассировки, вызванный исключением, которое выдается где-то глубоко при попытке извлечь данные из базы данных:
Уже не так приятно, тебе не кажется? Размещение Spring между приложением и Hibernate на первой диаграмме было огромным упрощением. Spring Framework — это связующий код, который связывает и перехватывает вашу бизнес-логику с окружающими слоями. Вот почему код приложения разбросан и чередуется десятками строк технических вызовов (см. Зеленые линии). Я вложил в приложение как можно больше материала (Spring AOP, аннотации на уровне метода @Secured, настраиваемые аспекты и перехватчики и т. Д.), Чтобы подчеркнуть проблему, но это не зависит от Spring. Серверы EJB генерируют одинаково ужасные следы стека (… из ада) между вызовами EJB. Должен ли я заботиться? Подумайте об этом, когда вы невинно вызываете BookService.listBooks() из BookController.listBooks() ожидаете ли вы увидеть это?
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
at com.blogspot.nurkiewicz.BookService.listBooks()at com.blogspot.nurkiewicz.BookService$$FastClassByCGLIB$$e7645040.invoke()at net.sf.cglib.proxy.MethodProxy.invoke()at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint()at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed()at com.blogspot.nurkiewicz.LoggingAspect.logging()at sun.reflect.NativeMethodAccessorImpl.invoke0()at sun.reflect.NativeMethodAccessorImpl.invoke()at sun.reflect.DelegatingMethodAccessorImpl.invoke()at java.lang.reflect.Method.invoke()at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs()at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod()at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke()at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()at org.springframework.aop.interceptor.AbstractTraceInterceptor.invoke()at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()at org.springframework.transaction.interceptor.TransactionInterceptor.invoke()at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke()at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept()at com.blogspot.nurkiewicz.BookService$$EnhancerByCGLIB$$7cb147e4.listBooks()at com.blogspot.nurkiewicz.web.BookController.listBooks() |
А вы когда-нибудь замечали, что между ними есть особенность? В том-то и дело, что в трассировке стека сейчас так много шума, что следовать реальной бизнес-логике практически невозможно. Один из лучших инструментов для устранения неполадок, который у нас есть, состоит из ненужных вещей, связанных с фреймворком, которые нам не нужны в 99% случаев.
Инструменты и IDE делают хорошую работу по снижению шума. Eclipse имеет шаблоны фильтров трассировки стека для Junit , IntelliJ IDEA поддерживает настройку свертывания консоли . См. Также: Удаление шума из следов стека Java , что вдохновило меня на написание этой статьи. Так почему бы не иметь такую возможность в самом корне — в каркасе журналирования, таком как Logback?
Я реализовал очень простое улучшение в Logback. По сути, вы можете определить набор шаблонов фреймов трассировки стека, которые предполагается исключить из трасс стека. Как правило, вы будете использовать имена пакетов или классов, которые вас не интересуют. Это пример logback.xml с включенной новой функцией:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
<root level="ALL"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} | %-5level | %thread | %logger{1} | %m%n%rEx{full, java.lang.reflect.Method, org.apache.catalina, org.springframework.aop, org.springframework.security, org.springframework.transaction, org.springframework.web, sun.reflect, net.sf.cglib, ByCGLIB } </pattern> </encoder> </appender></root> |
Я немного экстремален в фильтрации почти всей среды Spring + отражения Java и классов CGLIB. Но это просто, чтобы дать вам представление, сколько вы можете получить. Та же самая ошибка после применения моего улучшения к Logback:
Напоминаем, зеленый — это наше приложение. Наконец, в одном месте, наконец, вы действительно можете увидеть, что делал ваш код, когда произошла ошибка:
в com.blogspot.nurkiewicz.DefaultBookHelper.findBooks () в com.blogspot.nurkiewicz.BookService.listBooks () в com.blogspot.nurkiewicz.LoggingAspect.logging () на com.blogspot.nurkiewicz.web.BookController.listBooks ()
Simpler? Если вам нравится эта функция, я открыл тикет LBCLASSIC-325 : фильтрация выбранных кадров трассировки стека . Голосуй и обсуждай. Это только подтверждение концепции, но если вы хотите взглянуть на реализацию (улучшения приветствуются!), Она доступна в моей ветке Logback (около 20 строк кода).
Ссылка: Фильтрация нерелевантных линий трассировки стека в журналах от нашего партнера JCG


