def http_request(self, method, path, body=None, response_formatter=None, error_formatter=None, **params):
        try:
            # Check if it's ok to submit
            if not self._should_submit():
                raise HttpBackoff("Too many timeouts. Won't try again for {1} seconds.".format(*self._backoff_status()))

            # Construct the url
            if self.api_key:
                params['api_key'] = self.api_key
            if self.application_key:
                params['application_key'] = self.application_key
            url = "/api/%s/%s?%s" % (self.api_version, path.lstrip('/'), urlencode(params))
            try:
                conn = self.http_conn_cls(self.api_host, timeout=self.timeout)
            except __HOLE__:
                # timeout= parameter is only supported 2.6+
                conn = self.http_conn_cls(self.api_host)

            # Construct the body, if necessary
            headers = {}
            if isinstance(body, dict):
                body = json.dumps(body)
                headers['Content-Type'] = 'application/json'

            try:
                start_time = time.time()

                # Make the request
                try:
                    conn.request(method, url, body, headers)
                except timeout_exceptions:
                    # Keep a count of the timeouts to know when to back off
                    self._timeout_counter += 1
                    raise HttpTimeout('%s %s timed out after %d seconds.' % (method, url, self.timeout))
                except socket.error as e:
                    # Translate the low level socket error into a more
                    # descriptive one
                    raise ClientError("Could not request %s %s%s: %s" % (method, self.api_host, url, e))

                # If the request succeeded, reset the timeout counter
                self._timeout_counter = 0

                # Parse the response as json
                response = conn.getresponse()
                duration = round((time.time() - start_time) * 1000., 4)
                log.info("%s %s %s (%sms)" % (response.status, method, url, duration))
                response_str = response.read()
                if response_str:
                    try:
                        if is_p3k():
                            response_obj = json.loads(response_str.decode('utf-8'))
                        else:
                            response_obj = json.loads(response_str)
                    except ValueError:
                        raise ValueError('Invalid JSON response: {0}'.format(response_str))

                    if response_obj and 'errors' in response_obj:
                        raise ApiError(response_obj)
                else:
                    response_obj = None
                if response_obj is None and self.json_responses:
                    response_obj = {}
                if self.json_responses or response_formatter is None:
                    return response_obj
                else:
                    return response_formatter(response_obj)
            finally:
                conn.close()
        except ClientError as e:
            if self.swallow:
                log.error(str(e))
                if self.json_responses or error_formatter is None:
                    return {'errors': e.args[0]}
                else:
                    return error_formatter({'errors': e.args[0]})
            else:
                raise
        except ApiError as e:
            if self.swallow:
                for error in e.args[0]['errors']:
                    log.error(str(error))
                if self.json_responses or error_formatter is None:
                    return e.args[0]
                else:
                    return error_formatter(e.args[0])
            else:
                raise
dataset/ETHPy150Open DataDog/dogapi/src/dogapi/http/base.py/BaseDatadog.http_request