Beispiel #1
0
 def test_clienterror_exception(self):
     args = [ "GET", "http://localhost:8080", HTTPError("oh no") ]
     kwargs = { "method": "GET", "url": "http://localhost:8080", "exception": HTTPError("oh no") }
     with pytest.raises(ClientError):
         raise ClientError(*args)
     with pytest.raises(DatadogException):
         raise ClientError(*args)
     with pytest.raises(ClientError):
         raise ClientError(**kwargs)
     with pytest.raises(DatadogException):
         raise ClientError(**kwargs)
Beispiel #2
0
    def request(cls, method, url, headers, params, data, timeout, proxies,
                verify, max_retries):
        """
        Wrapper around `urlfetch.fetch` method.

        TO IMPLEMENT:
        * `max_retries`
        """
        # No local certificate file can be used on Google App Engine
        validate_certificate = True if verify else False

        # Encode parameters in the url
        url_with_params = "{url}?{params}".format(
            url=url, params=urllib.urlencode(params))

        try:
            result = urlfetch.fetch(url=url_with_params,
                                    method=method,
                                    headers=headers,
                                    validate_certificate=validate_certificate,
                                    deadline=timeout,
                                    payload=data)

            cls.raise_on_status(result)

        except urlfetch.DownloadError as e:
            raise ClientError(method, url, e)
        except urlfetch_errors.DeadlineExceededError:
            raise HttpTimeout(method, url, timeout)

        return result
    def request(cls, method, url, headers, params, data, timeout, proxies,
                verify, max_retries):
        """
        Wrapper around `urlfetch.fetch` method.

        TO IMPLEMENT:
        * `max_retries`
        """
        # No local certificate file can be used on Google App Engine
        validate_certificate = True if verify else False

        # Encode parameters in the url
        url_with_params = "{url}?{params}".format(
            url=url, params=urllib.urlencode(params))

        try:
            result = urlfetch.fetch(
                url=url_with_params,
                method=method,
                headers=headers,
                validate_certificate=validate_certificate,
                deadline=timeout,
                payload=data,
                # setting follow_redirects=False may be slightly faster:
                # https://cloud.google.com/appengine/docs/python/microservice-performance#use_the_shortest_route
                follow_redirects=False)

            cls.raise_on_status(result)

        except urlfetch.DownloadError as e:
            raise ClientError(method, url, e)
        except urlfetch_errors.DeadlineExceededError:
            raise HttpTimeout(method, url, timeout)

        return result
Beispiel #4
0
    def request(cls, method, url, headers, params, data, timeout, proxies, verify, max_retries):
        try:

            with cls._session_lock:
                if cls._session is None:
                    cls._session = requests.Session()
                    http_adapter = requests.adapters.HTTPAdapter(max_retries=max_retries)
                    cls._session.mount('https://', http_adapter)

            result = cls._session.request(
                method, url,
                headers=headers, params=params, data=data,
                timeout=timeout,
                proxies=proxies, verify=verify)

            result.raise_for_status()

        except requests.ConnectionError as e:
            raise _remove_context(ClientError(method, url, e))
        except requests.exceptions.Timeout:
            raise _remove_context(HttpTimeout(method, url, timeout))
        except requests.exceptions.HTTPError as e:
            if e.response.status_code in (400, 401, 403, 404, 409, 429):
                # This gets caught afterwards and raises an ApiError exception
                pass
            else:
                raise _remove_context(HTTPError(e.response.status_code, result.reason))
        except TypeError as e:
            raise TypeError(
                u"Your installed version of `requests` library seems not compatible with"
                u"Datadog's usage. We recommand upgrading it ('pip install -U requests')."
                u"If you need help or have any question, please contact [email protected]"
            )

        return result
Beispiel #5
0
    def request(cls,
                method,
                path,
                body=None,
                attach_host_name=False,
                response_formatter=None,
                error_formatter=None,
                **params):
        """
        Make an HTTP API request

        :param method: HTTP method to use to contact API endpoint
        :type method: HTTP method string

        :param path: API endpoint url
        :type path: url

        :param body: dictionnary to be sent in the body of the request
        :type body: dictionary

        :param response_formatter: function to format JSON response from HTTP API request
        :type response_formatter: JSON input function

        :param error_formatter: function to format JSON error response from HTTP API request
        :type error_formatter: JSON input function

        :param attach_host_name: link the new resource object to the host name
        :type attach_host_name: bool

        :param params: dictionnary to be sent in the query string of the request
        :type params: dictionary

        :returns: JSON or formated response from HTTP API request
        """

        try:
            # Check if it's ok to submit
            if not cls._should_submit():
                raise HttpBackoff(
                    "Too many timeouts. Won't try again for {1} seconds.".
                    format(*cls._backoff_status()))

            # Import API, User and HTTP settings
            from datadog.api import _api_key, _application_key, _api_host, \
                _swallow, _host_name, _proxies, _max_retries, _timeout

            # Check keys and add then to params
            if _api_key is None:
                raise ApiNotInitialized(
                    "API key is not set."
                    " Please run 'initialize' method first.")
            params['api_key'] = _api_key
            if _application_key:
                params['application_key'] = _application_key

            # Construct the url
            url = "%s/api/%s/%s" % (_api_host, cls._api_version,
                                    path.lstrip("/"))

            # Attach host name to body
            if attach_host_name and body:
                # Is it a 'series' list of objects ?
                if 'series' in body:
                    # Adding the host name to all objects
                    for obj_params in body['series']:
                        if 'host' not in obj_params:
                            obj_params['host'] = _host_name
                else:
                    if 'host' not in body:
                        body['host'] = _host_name

            # If defined, make sure tags are defined as a comma-separated string
            if 'tags' in params and isinstance(params['tags'], list):
                params['tags'] = ','.join(params['tags'])

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

            # Process requesting
            start_time = time.time()
            try:
                # Use a session to set a max_retries parameters
                s = requests.Session()
                http_adapter = requests.adapters.HTTPAdapter(
                    max_retries=_max_retries)
                s.mount('https://', http_adapter)

                # Request
                result = s.request(method,
                                   url,
                                   headers=headers,
                                   params=params,
                                   data=body,
                                   timeout=_timeout,
                                   proxies=_proxies)

                result.raise_for_status()
            except requests.ConnectionError as e:
                raise ClientError("Could not request %s %s%s: %s" %
                                  (method, _api_host, url, e))
            except requests.exceptions.Timeout as e:
                cls._timeout_counter += 1
                raise HttpTimeout('%s %s timed out after %d seconds.' %
                                  (method, url, _timeout))
            except requests.exceptions.HTTPError as e:
                if e.response.status_code == 404 or e.response.status_code == 400:
                    pass
                else:
                    raise
            except TypeError as e:
                raise TypeError(
                    "Your installed version of 'requests' library seems not compatible with"
                    "Datadog's usage. We recommand upgrading it ('pip install -U requests')."
                    "If you need help or have any question, please contact [email protected]"
                )

            # Request succeeded: log it and reset the timeout counter
            duration = round((time.time() - start_time) * 1000., 4)
            log.info("%s %s %s (%sms)" %
                     (result.status_code, method, url, duration))
            cls._timeout_counter = 0

            # Format response content
            content = result.content

            if content:
                try:
                    if is_p3k():
                        response_obj = json.loads(content.decode('utf-8'))
                    else:
                        response_obj = json.loads(content)
                except ValueError:
                    raise ValueError(
                        'Invalid JSON response: {0}'.format(content))

                if response_obj and 'errors' in response_obj:
                    raise ApiError(response_obj)
            else:
                response_obj = None
            if response_formatter is None:
                return response_obj
            else:
                return response_formatter(response_obj)

        except ClientError as e:
            if _swallow:
                log.error(str(e))
                if error_formatter is None:
                    return {'errors': e.args[0]}
                else:
                    return error_formatter({'errors': e.args[0]})
            else:
                raise
        except ApiError as e:
            if _swallow:
                for error in e.args[0]['errors']:
                    log.error(str(error))
                if error_formatter is None:
                    return e.args[0]
                else:
                    return error_formatter(e.args[0])
            else:
                raise