import functools


def logging(f):
    """Decorate a function to log its calls."""

    @functools.wraps(f)
    def decorated(*args, **kwargs):
        sargs = map(str, args)
        skwargs = (f'{key}={value}' for key, value in kwargs.items())
        print(f'{f.__name__}({", ".join([*sargs, *skwargs])})...')
        try:
            value = f(*args, **kwargs)
        except Exception as cause:
            print(f'! {cause}')
            raise
        print(f'=> {value}')
        return value

    return decorated