code: public static <T> Handler<T> mdcEventLoop(final Handler<T> handler) {
      if (handler == null) {
        // Throw here instead of getting NPE inside the handler so we can see the stack trace
        throw new IllegalArgumentException("handler may not be null");
      }
  
      final Map<String, String> mdc = MDC.getCopyOfContextMap();
      final Context context = Vertx.currentContext();
  
      if (context == null) {
        // Throw here instead of getting NPE inside the handler so we can see the stack trace
        throw new IllegalStateException("Expecting to be on an Vert.x event loop context");
      }
  
      return t -> context.runOnContext((v) -> {
        Map<String, String> restore = MDC.getCopyOfContextMap();
        try {
          if (mdc == null) {
            MDC.clear();
          } else {
            MDC.setContextMap(mdc);
          }
          handler.handle(t);
        } finally {
          if (restore == null) {
            MDC.clear();
          } else {
            MDC.setContextMap(restore);
          }
        }
      }
docs: Wrap a Handler in a way that will preserve the SLF4J MDC context.
  The context from the current thread at the time of this method call
  will be cached and restored within the wrapper at the time the
  handler is invoked. This version delegates the handler call using
  {@link Context#runOnContext(Handler)} from the current context that
  calls this method, ensuring the handler call will run on the correct
  event loop.