public static String getShortenedStackTrace(Throwable t) {
        StringBuilder trace = new StringBuilder();

        final List<Throwable> causalChain = Throwables.getCausalChain(t)
                .stream()
                .filter(c -> StringUtils.isNotBlank(c.getMessage()))
                .collect(Collectors.toList());

        int position = 0;
        for (Throwable c : causalChain) {
            if (position > 0) {
                trace.append("Caused by: ");
            }
            appendWithNewline(trace, c);
            Arrays.stream(c.getStackTrace()).findFirst().ifPresent(firstStackElement -> {
                trace.append("\tat ");
                appendWithNewline(trace, firstStackElement);
                final int more = c.getStackTrace().length - 1;
                if (more > 0) {
                    trace.append("\t... ").append(more);
                    appendWithNewline(trace, " more");
                }
            });

            position++;
        }

        return trace.toString();
    }
@Test
    public void getShortenedStackTrace2More() {
        final IOException ioException = new IOException("io message");
        final StackTraceElement traceElement = new StackTraceElement("FileReader", "process", "FileReader.java", 42);
        ioException.setStackTrace(new StackTraceElement[]{traceElement, traceElement, traceElement});

        final String shortTrace = ExceptionUtils.getShortenedStackTrace(ioException);

        final String expected = "java.io.IOException: io message\n" +
                "\tat FileReader.process(FileReader.java:42)\n" +
                "\t... 2 more\n";

        assertThat(shortTrace).isEqualTo(expected);
    }