docs: def xpoll(self, channel_id=None, json=None, ack=False,
                follow=False, pause=None, **kwargs):
          """Retrieve logType, event entries iteratively in a non-greedy manner.
  
          Generator function to return logType, event entries from poll
          API request.
  
          Args:
              channel_id (str): The channel ID.
              json (dict): Payload/request body.
              ack (bool): True to acknowledge read.
              follow (bool): True to continue polling after channelId empty.
              pause (float): Seconds to sleep between poll when follow and channelId empty.
              **kwargs: Supported :meth:`~pancloud.httpclient.HTTPClient.request` parameters.
  
          Yields:
              dictionary with single logType and event entries.
  
          """
          def _ack(channel_id, **kwargs):
              r = self.ack(channel_id, **kwargs)
  
              if not (200 <= r.status_code < 300):
                  try:
                      r_json = r.json()
                  except ValueError as e:
                      raise PanCloudError('Invalid JSON: %s' % e)
                  if 'errorCode' in r_json and 'errorMessage' in r_json:
                      raise PanCloudError('%s: %s' %
                                          (r_json['errorCode'],
                                           r_json['errorMessage']))
                  else:
                      raise PanCloudError('%s %s' % (r.status_code,
                                                     r.reason))
  
              if r.status_code == 200:
                  return
              else:
                  raise PanCloudError('ack: status_code: %d' %
                                      r.status_code)
  
          while True:
              r = self.poll(channel_id, json, **kwargs)
              try:
                  r_json = r.json()
              except ValueError as e:
                  raise PanCloudError('Invalid JSON: %s' % e)
  
              if not (200 <= r.status_code < 300):
                  if 'errorCode' in r_json and 'errorMessage' in r_json:
                      raise PanCloudError('%s: %s' %
                                          (r_json['errorCode'],
                                           r_json['errorMessage']))
                  else:
                      raise PanCloudError('%s %s' % (r.status_code,
                                                     r.reason))
  
              if not r_json and not follow:
                  return
  
              for x in r_json:
                  yield x
  
              # XXX don't ack if empty response?
              if ack:
                  _ack(channel_id, **kwargs)
  
              if not r_json and pause is not None:
                  self._debug('sleep %.2fs', pause)
                  time.sleep(pause)