private void output(String level, Supplier<String> supplier, String color, Object... data) {
    StringBuilder builder = new StringBuilder();
    if (useAnsiColor) {
      builder.append(color);
    }

    builder.append(level);
    builder.append(" ");

    // ISO, because obvz (sortable, standard), and offset because this may be
    // shared/discussed/debugged outside someone's console, at which point a
    // vague clock time without its timezone is useless.
    builder.append(ZonedDateTime.now(ZoneId.systemDefault()).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));

    builder.append(" ");
    builder.append(supplier.get());

    if (useAnsiColor) {
      builder.append(ANSI_RESET);
    }

    if (data != null) {
      for (Object datum : data) {
        if (datum instanceof Throwable) {
          builder.append(getStackTraceAsString((Throwable) datum));
        } else if (datum instanceof UUID) {
          builder.append("JobId: ");
          builder.append(((UUID) datum).toString());
        } else if (datum instanceof EventCode) {
          builder.append("EventCode: ");
          builder.append(((EventCode) datum).toString());
        } else if (datum != null) {
          builder.append(datum);
        }
      }
    }

    // Write to standard error, as these are debug logs for which any buffering
    // won't help us at all.
    System.err.println(builder.toString());
  }
Constructs a logger that drops all logs at a level below {@code minLevel}.
portability-api-launcher/src/main/java/org/datatransferproject/launcher/monitor/ConsoleMonitor.java