docs: def reducer(*, name = None, metric = call_default):
      """Decorator to measure a function that consumes many items.
  
      The wrapped ``func`` should take either a single ``iterable`` argument or
      ``*args`` (plus keyword arguments).
  
      :arg function metric: f(name, count, total_time)
      :arg str name: name for the metric
      """
      class instrument_reducer_decorator(object):
          def __init__(self, func):
              self.orig_func = func
              self.wrapping = wraps(func)
              self.metric_name = name if name is not None else func.__module__ + '.' +func.__name__
              self.varargs = inspect.getargspec(func).varargs is not None
              if self.varargs:
                  self.method = _varargs_to_iterable_method(func)
                  self.func = _varargs_to_iterable_func(func)
                  self.callme = _iterable_to_varargs_func(self._call)
              else:
                  self.method = func
                  self.func = func
                  self.callme = self._call
  
          # we need _call/callme b/c CPython short-circurits CALL_FUNCTION to
          # directly access __call__, bypassing our varargs decorator
          def __call__(self, *args, **kwargs):
              return self.callme(*args, **kwargs)
  
          def _call(self, iterable, **kwargs):
              it = counted_iterable(iterable)
              t = time.time()
              try:
                  return self.func(it, **kwargs)
              finally:
                  metric(self.metric_name, it.count, time.time() - t)
  
          def __get__(self, instance, class_):
              metric_name = name if name is not None else\
                  ".".join((class_.__module__, class_.__name__, self.orig_func.__name__))
  
              def wrapped_method(iterable, **kwargs):
                  it = counted_iterable(iterable)
                  t = time.time()
                  try:
                      return self.method(instance, it, **kwargs)
                  finally:
                      metric(metric_name, it.count, time.time() - t)
  
              # wrap in func version b/c self is handled for us by descriptor (ie, `instance`)
              if self.varargs: wrapped_method = _iterable_to_varargs_func(wrapped_method)
              wrapped_method = self.wrapping(wrapped_method)
              return wrapped_method
  
      return instrument_reducer_decorator