def METHOD_NAME(*args, **kwargs):
    """
    Decorator that logs the entry, exit and execution time.
    """
    logger = logging.getLogger('oasislmf')
    def actual_oasis_log(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            func_name = func.__name__
            caller_module_name = func.__globals__.get('__name__')
            if func_name == '__init__':
                logger.debug("RUNNING: {}.{}".format(
                    caller_module_name, func_name))
            else:
                logger.info("RUNNING: {}.{}".format(
                    caller_module_name, func_name))
            args_name = getargspec(func)[0]
            args_dict = dict(zip(args_name, args))
            if logger.level <= logging.DEBUG:
                for key, value in args_dict.items():
                    if key == "self":
                        continue
                    logger.debug("    {} == {}".format(key, value))
                if len(args) > len(args_name):
                    for i in range(len(args_name), len(args)):
                        logger.debug("    {}".format(args[i]))
                for key, value in kwargs.items():
                    logger.debug("    {} == {}".format(key, value))
            start = time.time()
            result = func(*args, **kwargs)
            end = time.time()
            # Only log timestamps on functions which took longer than 10ms
            if (end - start) > 0.01:
                logger.info(
                    "COMPLETED: {}.{} in {}s".format(
                        caller_module_name, func_name, round(end - start, 2)))
            else:
                logger.debug(
                    "COMPLETED: {}.{} in {}s".format(
                        caller_module_name, func_name, round(end - start, 2)))
            return result
        return wrapper
    if len(args) == 1 and callable(args[0]):
        return actual_oasis_log(args[0])
    else:
        return actual_oasis_log