def METHOD_NAME(*args, **kw):
    # default to logger that was passed by module, but
    # can override by passing logger=foo as function parameter.
    # make sure this doesn't conflict with one of the parameters
    # you are expecting
    filename = os.path.normcase(inspect.getsourcefile(func))
    func_name = func.__name__
    if hasattr(func, 'func_code'):
        lineno = func.func_code.co_firstlineno
    else:
        lineno = func.__code__.co_firstlineno
    l2 = kw.get('logger', logger)
    if l2 is None:
        l2 = logging.getLogger("trace.%s" % func.__module__)
    if isinstance(l2, str):
        l2 = logging.getLogger(l2)
    message = "ENTER %s("
    message = message + ', '.join([safe_repr(arg) for arg in args])
    if args and kw:
        message += ', '
    for k, v in list(kw.items()):
        message = message + "%s=%s" % (k, safe_repr(v))
    message = message + ")"
    frame = inspect.getouterframes(inspect.currentframe())[1][0]
    doLog(l2, logging.INFO, os.path.normcase(frame.f_code.co_filename),
          frame.f_lineno, message, args=[func_name], exc_info=None,
          func=frame.f_code.co_name)
    try:
        result = "Bad exception raised: Exception was not a derived "\
                 "class of 'Exception'"
        try:
            result = func(*args, **kw)
        except (KeyboardInterrupt, Exception) as e:
            result = "EXCEPTION RAISED"
            doLog(l2, logging.INFO, filename, lineno,
                  "EXCEPTION: %s\n", args=[e],
                  exc_info=sys.exc_info(), func=func_name)
            raise
    finally:
        doLog(l2, logging.INFO, filename, lineno,
              "LEAVE %s --> %s\n", args=[func_name, result],
              exc_info=None, func=func_name)
    return result