Recursively include metrics from *value*.

    path
        The dot-separated path of the metric.
    value
        A dictionary or value from a dictionary. If a dictionary, ``_walk``
        will be called again with the each key/value pair as a new set of
        metrics.
    metrics
        The list of metrics that will be sent to carbon, formatted as::

            (path, value, timestamp)
    skip
        Whether or not to skip metrics when there's an error casting the value
        to a float. Defaults to `False`.

def _walk(path, value, metrics, timestamp, skip):
    '''
    Recursively include metrics from *value*.

    path
        The dot-separated path of the metric.
    value
        A dictionary or value from a dictionary. If a dictionary, ``_walk``
        will be called again with the each key/value pair as a new set of
        metrics.
    metrics
        The list of metrics that will be sent to carbon, formatted as::

            (path, value, timestamp)
    skip
        Whether or not to skip metrics when there's an error casting the value
        to a float. Defaults to `False`.
    '''
    log.trace(
        'Carbon return walking path: %s, value: %s, metrics: %s, '
        'timestamp: %s', path, value, metrics, timestamp
    )
    if isinstance(value, collections.Mapping):
        for key, val in six.iteritems(value):
            _walk('{0}.{1}'.format(path, key), val, metrics, timestamp, skip)
    elif isinstance(value, list):
        for item in value:
            _walk('{0}.{1}'.format(path, item), item, metrics, timestamp, skip)

    else:
        try:
            val = float(value)
            metrics.append((path, val, timestamp))
        except (TypeError, ValueError):
            msg = 'Error in carbon returner, when trying to convert metric: ' \
                  '{0}, with val: {1}'.format(path, value)
            if skip:
                log.debug(msg)
            else:
                log.info(msg)
                raise