Подтвердить что ты не робот

Очистка шума из трассировки стека Java

Мои трассировки стека Java содержат много записей, которые мне не нужны, показывая вызов метода через прокси и методы отражения Spring и тому подобное. Это может сделать довольно сложным выделить часть трассировки стека, которая фактически из моего кода. Ruby on Rails включает в себя "очиститель трассировки стека", где вы можете указать список шаблонов трассировки стека, чтобы опустить из печатных трасс стека - какой лучший способ сделать что-то подобное, универсально, для Java?

Было бы лучше, если бы это работало повсюду, в том числе в бегуне Eclipse jUnit.

4b9b3361

Ответ 1

имеет предпочтение Шаблоны фильтра трассировки стека (посмотрите на java > junit или найдите stacktrace в настройках). Вы можете игнорировать пакеты (также с подстановочными знаками), классы или методы. Работает для прямых тестовых вызовов (через Run как Test), а не для командной строки, например, ant или maven.

Ответ 2

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

IntelliJ
(источник: jetbrains.com)

и Анализ внешних трассировок стека.

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

ОБНОВЛЕНИЕ: я реализовал фильтрацию нерелевантных линий трассировки стека в журналах для , а также следую LBCLASSIC-325.

Ответ 3

Я на самом деле написал библиотеку с открытым исходным кодом MgntUtils (доступна на Github и maven central), которая содержит несколько утилит. Вот ссылка на статью о библиотеке: Java-библиотека с открытым исходным кодом MgntUtils. Одна из утилит - это универсальный фильтр стековой трассировки, который я широко использовал и нашел его очень полезным. Класс называется TextUtils и имеет метод getStacktrace() с несколькими переопределенными сигнатурами. Он принимает экземпляр Throwable и позволяет установить префикс пакета соответствующих пакетов. Допустим, ваша балансовая единица всегда находится в пакетах, начинающихся с "com.plain. *". Таким образом, вы устанавливаете такой префикс и делаете это

logger.info(TextUtils.getStacktrace(e, true, "com.plain."));

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

TextUtils.getStacktrace(e);

Это будет делать то же самое. Для установки префикса просто используйте метод

setRelevantPackage("com.plain.");

Также, если вы используете среду Spring, вы можете добавить следующий сегмент в конфигурацию Spring, а затем все у вас будет настроено:

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
  <property name="targetClass" value="com.mgnt.utils.TextUtils"/>
  <property name="targetMethod" value="setRelevantPackage"/>
  <property name="arguments" value="com.plain."/>
</bean>

Библиотека поставляется с хорошо написанным (я надеюсь) Javadoc, который объясняет все подробно. Но вот небольшой тизер: вы получите следующую трассировку стека:

at com.plain.BookService.listBooks()
at com.plain.BookService$$FastClassByCGLIB$$e7645040.invoke()
at net.sf.cglib.proxy.MethodProxy.invoke()
...
at com.plain.LoggingAspect.logging()
at sun.reflect.NativeMethodAccessorImpl.invoke0()
...
at com.plain.BookService$$EnhancerByCGLIB$$7cb147e4.listBooks()
at com.plain.web.BookController.listBooks()

вместо

at com.plain.BookService.listBooks()
at com.plain.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.plain.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.plain.BookService$$EnhancerByCGLIB$$7cb147e4.listBooks()
at com.plain.web.BookController.listBooks()

Ответ 4

Для log4j:

package package1;

public class FilteringThrowableRenderer implements ThrowableRenderer {
    private static final String PACKAGES_SEPARATOR = "\\s*,\\s*";

    private final static String TRACE_PREFIX = "\tat ";

    private static final String FILTERED_WARNING = " [Stacktrace is filtered]";

    ThrowableRenderer defaultRenderer = new EnhancedThrowableRenderer();

    List<String> skippedLinePrefixes;

    public FilteringThrowableRenderer() {
        String skippedPackagesString = "java,org"; // TODO: move it to config
        String[] skippedPackages =
            skippedPackagesString.trim().split(PACKAGES_SEPARATOR);
        skippedLinePrefixes = new ArrayList<String>(skippedPackages.length);
        for (String packageName : skippedPackages) {
            skippedLinePrefixes.add(TRACE_PREFIX + packageName);
        }
    }

    @Override
    public String[] doRender(Throwable throwable) {
        String[] initialTrace = defaultRenderer.doRender(throwable);
        if (!skippedLinePrefixes.isEmpty()) {
            List<String> result = new ArrayList<String>(initialTrace.length);

            boolean filtered = false;
            trace: for (String element : initialTrace) {
                for (String skippedLinePrefix : skippedLinePrefixes) {
                    if (element.startsWith(skippedLinePrefix)) {
                        filtered = true;
                        continue trace;
                    }
                }
                result.add(element);
            }
            if (filtered && result.size() > 0) {
                result.set(0, result.get(0) + FILTERED_WARNING);
            }
            return result.toArray(new String[result.size()]);
        } else {
            return initialTrace;
        }
    }
}

чтобы включить его с кодом:

ThrowableRendererSupport loggerRepository =
    (ThrowableRendererSupport) LogManager.getLoggerRepository();
loggerRepository.setThrowableRenderer(new FilteringThrowableRenderer());

или с log4j.properties:

log4j.throwableRenderer=package1.FilteringThrowableRenderer

Ответ 5

Не совсем то, что вы ищете (и, насколько мне известно, универсального решения для вашей проблемы нет, по крайней мере, я никогда не слышал о знаменитом инструменте для очистки и извлечения информации из Java stacktraces).

В любом случае этот пост от 05 июля 2011 года в блоге Faux описывает Java-агент на ранних этапах, целью которого является обогащение ( а не фильтровать) трассировки стека. Он поддерживает ссылку на репозиторий git с проектом mavenized. Может быть, вы можете пойти отсюда, настроить его код и бросить свое собственное решение (кто знает, может даже начать проект с открытым исходным кодом).

Ответ 6

Этот плагин довольно приятный

https://marketplace.eclipse.org/content/grep-console

Просто обобщенная утилита форматирования grep для консоли Eclipse, поэтому никаких дополнительных зависимостей нет. Я отформатирую весь свой неулокальный шум на серый текст.