private IRubyObject log(Level level, ThreadContext ctx, IRubyObject[] args, Block block) {
    IRubyObject nil = ctx.getRuntime().getNil();
    IRubyObject message = args.length == 1 ? args[0] : null;
    if (block.isGiven()) {
      if (isSufficientLevel(level)) {
        message = block.yield(ctx, nil);
      }
    }
    if (message != null) {
      if (!(message instanceof RubyString)) {
        message = message.inspect();
      }
      String messageString = message.asString().decodeString();
      switch (level) {
        case DEBUG: logger.debug(messageString); break;
        case INFO: logger.info(messageString); break;
        case WARN: logger.warn(messageString); break;
        case ERROR: logger.error(messageString); break;
      }
    }
    return nil;
  }