code: @SafeVarargs
      public static <T> Function<Throwable, T> get(
              Predicate<Throwable> logFilter, Class<? extends Throwable>... ignoredThrowableTypes) {
          StackTraceElement[] stackTrace = Arrays.stream(Thread.currentThread().getStackTrace())
                  .filter(element -> !element.getClassName().equals(ExceptionLogger.class.getName()))
                  .filter(element -> !(element.getClassName().equals(Thread.class.getName())
                                       && "getStackTrace".equals(element.getMethodName())))
                  .toArray(StackTraceElement[]::new);
          Collection<Class<? extends Throwable>> ignoredThrowableTypesList = Arrays.asList(ignoredThrowableTypes);
          return delegate.get(logFilter, ignoredThrowableTypesList, stackTrace);
      }
docs: Returns a function that can be used in the {@link CompletableFuture#exceptionally(Function)} method.
  It unwraps {@link CompletionException CompletionExceptions},
  {@link InvocationTargetException InvocationTargetExceptions} and {@link ExecutionException ExecutionExceptions}
  first, and then adds a fresh {@code CompletionException} as wrapper with the stacktrace of the caller of this
  method and logs it afterwards.
  The rewrapped exception is only logged if the given {@code logFilter} predicate allows the exception and the
  class of it is not in the {@code ignoredThrowableTypes}.
  
  @param <T> The return type of the function.
  @param logFilter The predicate the unwrapped exception is tested against.
  @param ignoredThrowableTypes The throwable types that should never be logged.
  @return A function which logs the given throwable and returns {@code null}.