This decorator modifies current function such that its start, end, and
    duration is logged in console. If the task name is not given, it will
    attempt to infer it from the function name. Optionally, the decorator
    can log information into files.

def task(name=None, t=INFO, *args, **kwargs):
    """
    This decorator modifies current function such that its start, end, and
    duration is logged in console. If the task name is not given, it will
    attempt to infer it from the function name. Optionally, the decorator
    can log information into files.
    """

    def c_run(name, f, t, args, kwargs):
        def run(*largs, **lkwargs):
            thread = __get_current_thread()
            old_name = __THREAD_PARAMS[thread][__THREAD_PARAMS_FNAME_KEY]
            __THREAD_PARAMS[thread][__THREAD_PARAMS_FNAME_KEY] = name

            r = log(name, f, t, largs, lkwargs, *args, **kwargs)

            __THREAD_PARAMS[thread][__THREAD_PARAMS_FNAME_KEY] = old_name
            return r

        return run

    if callable(name):
        f = name
        name = f.__name__

        return c_run(name, f, t, args, kwargs)

    if name == None:
        def wrapped(f):
            name = f.__name__
            return c_run(name, f, t, args, kwargs)

        return wrapped
    else:
        return lambda f: c_run(name, f, t, args, kwargs)