log4j2 - настроить перенаправление / игнорирование stderr для определенного пакета - PullRequest
0 голосов
/ 24 октября 2018

Я использую стороннюю библиотеку в своих тестах.Библиотека выводит исключения в stderr, и они отображаются в консоли.

Я хочу игнорировать их.

Я смог написать код взлома java для перехватаstderr

System.setErr(new PrintStream(new OutputStream() { public void write(int b) { } }));

Но это отключит все stderr при запуске junit - я хочу просто отключить stderr из определенного пакета.

У меня естьlog4j2-test.xml для моих юнитов, но я не смог найти ни одного примера, показывающего, как управлять stderr на уровне пакета .

Есть идеи?

1 Ответ

0 голосов
/ 24 октября 2018

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

«Простая» реализация этого:

    System.setErr(new PrintStream(new OutputStream() {
        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            Exception e = new Exception();
            StackTraceElement[] elements = e.getStackTrace();
            boolean hasSeenPrintStackTrace = false;
            for (int i = 0; i < elements.length; i++) {
                if (
                    elements[i].getClassName().equals("java.lang.Throwable") &&
                    elements[i].getMethodName().equals("printStackTrace")
                ) {
                    hasSeenPrintStackTrace = true;
                } else {
                    if (hasSeenPrintStackTrace) {
                        if (
                            elements[i].getClassName().equals("me.ferrybig.testpackage.ExceptionTester") &&
                            elements[i].getMethodName().equals("log1")
                        ) {
                            return;
                        }
                    }
                }
            }
            System.out.write(b, off, len);
        }

        @Override
        public void write(byte[] b) throws IOException {
            // TODO copy above implementation to here, exceptions printing only seems to use the above method
            System.out.write(b);
        }
        public void write(int b) {
            // TODO copy above implementation to here, exceptions printing only seems to use the above method
            System.out.write(b);
        }
    }));

Приведенный выше код в основном следует всем элементам трассировки стека, пока не найдет класс java.lang.Throwable,и метод printStackTrace.С этого момента он устанавливает логический флаг, поэтому он может проверять все фреймов, следующих за ним, и сканировать, если они содержат определенную комбинацию класса и метода.Затем он используется для фильтрации , которая записывает вызов, поэтому он не заканчивается в конечном выводе.

Полный демонстрационный класс: http://tpcg.io/5xnlZ7

...