Example #1
0
    def jolokia(self, read_requests, raise_error=True):
        '''
        :param read_requests: see https://jolokia.org/reference/html/protocol.html#post-request
        :type read_requests: list
        :param raise_error:
        :return: Jolokia response
        '''
        def set_read_type(x):
            x['type'] = 'read'

        # hack quick verify
        if (not self.url.endswith('jolokia/')) or ('?' in self.url) or (
                '&' in self.url):
            raise HttpError(
                "URL needs to end in jolokia/ and not contain ? and &",
                self.url)

        map(set_read_type, read_requests)

        r = self.__request(post_data=read_requests, raise_error=raise_error)

        try:
            return r.json()
        except Exception, e:
            raise HttpError(str(e), self.url), None, sys.exc_info()[2]
Example #2
0
    def jolokia(self, read_requests, raise_error=True):
        '''
        :param read_requests: see https://jolokia.org/reference/html/protocol.html#post-request
        :type read_requests: list
        :param raise_error:
        :return: Jolokia response
        '''
        def set_read_type(x):
            x['type'] = 'read'

        # hack quick verify
        parsed_url = urlparse.urlsplit(self.url)
        if (not parsed_url.path.endswith('/jolokia/')) or (
                '?' in self.url) or ('&' in self.url):
            raise HttpError(
                "URL needs to end in /jolokia/ and not contain ? and &",
                self.url)

        map(set_read_type, read_requests)
        for rr in read_requests:
            if 'mbean' not in rr:
                raise CheckError('missing "mbean" key in read request')

        r = self.__request(post_data=read_requests, raise_error=raise_error)

        try:
            return r.json()
        except Exception, e:
            raise HttpError(str(e), self.url), None, sys.exc_info()[2]
Example #3
0
    def __request(self, raise_error=True, post_data=None):
        if self.__r is None:
            if self.max_retries:
                s = requests.Session()
                s.mount('', HTTPAdapter(max_retries=self.max_retries))
            else:
                s = requests

            base_url = self.url
            basic_auth = None

            url_parsed = urlparse.urlsplit(base_url)
            if url_parsed and url_parsed.username and url_parsed.password:
                base_url = base_url.replace(
                    "{0}:{1}@".format(urllib.quote(url_parsed.username),
                                      urllib.quote(url_parsed.password)), "")
                base_url = base_url.replace(
                    "{0}:{1}@".format(url_parsed.username,
                                      url_parsed.password), "")
                basic_auth = (url_parsed.username, url_parsed.password)
            self.clean_url = base_url

            if self.oauth2:
                self._headers.update({
                    'Authorization':
                    'Bearer {}'.format(tokens.get(self.oauth2_token_name))
                })

            self._headers.update({'User-Agent': get_user_agent()})

            try:
                if post_data is None:
                    # GET or HEAD
                    get_method = getattr(s, self.__method)
                    self.__r = get_method(base_url,
                                          params=self.params,
                                          timeout=self.timeout,
                                          verify=self.verify,
                                          headers=self._headers,
                                          auth=basic_auth,
                                          allow_redirects=self.allow_redirects)
                else:
                    self.__r = s.post(base_url,
                                      params=self.params,
                                      timeout=self.timeout,
                                      verify=self.verify,
                                      headers=self._headers,
                                      auth=basic_auth,
                                      data=json.dumps(post_data))
            except requests.Timeout, e:
                raise HttpError('timeout',
                                self.clean_url), None, sys.exc_info()[2]
            except requests.ConnectionError, e:
                raise HttpError('connection failed',
                                self.clean_url), None, sys.exc_info()[2]
Example #4
0
    def __request(self, url, params=None, body=None):
        """Return json response"""
        if self.oauth2:
            self._headers.update(
                {'Authorization': 'Bearer {}'.format(tokens.get('uid'))})

        try:
            if body is None:
                response = requests.get(url,
                                        params=params,
                                        timeout=self.timeout,
                                        headers=self._headers)

                if not response.ok:
                    raise Exception(
                        'Elasticsearch query failed: {}'.format(url))

                return response.json()
            else:
                response = requests.post(url,
                                         params=params,
                                         json=body,
                                         timeout=self.timeout,
                                         headers=self._headers)

                if not response.ok:
                    raise Exception(
                        'Elasticsearch query failed: {} with response: {}'.
                        format(url, json.dumps(response.text)))

                return response.json()
        except requests.Timeout:
            raise HttpError('timeout', self.url), None, sys.exc_info()[2]
        except requests.ConnectionError:
            raise HttpError('connection failed',
                            self.url), None, sys.exc_info()[2]
        except Exception:
            raise
Example #5
0
    def _request(self, endpoint, q, method='get'):
        try:
            url = urlparse.urljoin(self.__service_url, endpoint)

            request = getattr(self.__session, method.lower())

            if method.lower() == 'post':
                response = request(url, json=q)
            else:
                response = request(url, params={'query': json.dumps(q)})

            if response.ok:
                return response.json()
            else:
                raise CheckError(
                    'EntitiesWrapper query failed: {} with status {}:{}'.
                    format(q, response.status_code, response.text))
        except requests.Timeout:
            raise HttpError('timeout',
                            self.__service_url), None, sys.exc_info()[2]
        except requests.ConnectionError:
            raise HttpError('connection failed',
                            self.__service_url), None, sys.exc_info()[2]
Example #6
0
    def actuator_metrics(self, prefix='zmon.response.', raise_error=True):
        """
        /metric responds with keys like: zmon.response.<status>.<method>.<end-point>

        Response map is ep->method->status->metric
        """
        response = self.json(raise_error=raise_error)
        if not isinstance(response, dict):
            raise HttpError('Invalid actuator metrics: response must be a JSON object', self.url)

        # for clojure projects we use the dropwizard servlet, there the json looks slightly different
        if "timers" in response:
            return map_dropwizard_timers(response['timers'], prefix)
        else:
            return map_spring_boot_metrics(response, prefix)
Example #7
0
    def healthrule_violations(self,
                              application,
                              time_range_type=BEFORE_NOW,
                              duration_in_mins=5,
                              start_time=None,
                              end_time=None,
                              severity=None):
        """
        Return Healthrule violations for AppDynamics application.

        :param application: Application name or ID
        :type application: str

        :param time_range_type: Valid time range type. Valid range types are BEFORE_NOW, BEFORE_TIME, AFTER_TIME and
                                BETWEEN_TIMES. Default is BEFORE_NOW.
        :type time_range_type: str

        :param duration_in_mins: Time duration in mins. Required for BEFORE_NOW, AFTER_TIME, BEFORE_TIME range types.
        :type duration_in_mins: int

        :param start_time: Start time (in milliseconds) from which the metric data is returned. Default is 5 mins ago.
        :type start_time: int

        :param end_time: End time (in milliseconds) until which the metric data is returned. Default is now.
        :type end_time: int

        :param severity: Filter results based on severity. Valid values CRITICAL or WARNING.
        :type severity: str

        :return: List of healthrule violations
        :rtype: list
        """
        try:
            if severity is not None and severity not in SEVERITIES:
                raise Exception(
                    'Invalid severity! Allowed values are: {}'.format(
                        ','.join(SEVERITIES)))

            params = self._prepare_time_range_params(time_range_type,
                                                     duration_in_mins,
                                                     start_time, end_time)

            resp = self.__session.get(
                self.healthrule_violations_url(application), params=params)

            resp.raise_for_status()

            json_resp = resp.json()

            if severity:
                # we need some filtering!
                return [e for e in json_resp if e['severity'] == severity]

            return json_resp
        except requests.Timeout:
            raise HttpError('timeout', self.url), None, sys.exc_info()[2]
        except requests.ConnectionError:
            raise HttpError('connection failed',
                            self.url), None, sys.exc_info()[2]
        except:
            logger.exception('AppDynamics request failed')
            raise
Example #8
0
    def metric_data(self,
                    application,
                    metric_path,
                    time_range_type=BEFORE_NOW,
                    duration_in_mins=5,
                    start_time=None,
                    end_time=None,
                    rollup=True):
        """
        AppDynamics's metric-data API

        :param application: Application name or ID
        :type application: str

        :param metric_path: The path to the metric in the metric hierarchy
        :type metric_path: str

        :param time_range_type: Valid time range type. Valid range types are BEFORE_NOW, BEFORE_TIME, AFTER_TIME and
                                BETWEEN_TIMES. Default is BEFORE_NOW.
        :type time_range_type: str

        :param duration_in_mins: Time duration in mins. Required for BEFORE_NOW, AFTER_TIME, BEFORE_TIME range types.
        :type duration_in_mins: int

        :param start_time: Start time (in milliseconds) from which the metric data is returned. Default is 5 mins ago.
        :type start_time: int

        :param end_time: End time (in milliseconds) until which the metric data is returned. Default is now.
        :type end_time: int

        :param rollup: By default, the values of the returned metrics are rolled up into a single data point
                       (rollup=true). To get separate results for all values within the time range, set the
                       rollup parameter to false.
        :type rollup: bool

        :return: metric values for a metric
        :rtype: list
        """
        try:
            if application is None:
                raise Exception('Argument application is mandatory')

            if metric_path is None:
                raise Exception('Argument metric_path is mandatory.')

            params = self._prepare_time_range_params(time_range_type,
                                                     duration_in_mins,
                                                     start_time, end_time)

            params['metric-path'] = metric_path

            params['rollup'] = rollup

            resp = self.__session.get(self.metric_data_url(application),
                                      params=params)

            resp.raise_for_status()

            return resp.json()
        except requests.Timeout:
            raise HttpError('timeout', self.url), None, sys.exc_info()[2]
        except requests.ConnectionError:
            raise HttpError('connection failed',
                            self.url), None, sys.exc_info()[2]
        except:
            logger.exception('AppDynamics request failed')
            raise
Example #9
0
 def json(self, raise_error=True):
     r = self.__request(raise_error=raise_error)
     try:
         return r.json()
     except Exception, e:
         raise HttpError(str(e), self.url), None, sys.exc_info()[2]
Example #10
0
class HttpWrapper(object):
    def __init__(
        self,
        url,
        method='GET',
        params=None,
        base_url=None,
        timeout=10,
        max_retries=0,
        allow_redirects=None,
        verify=True,
        oauth2=False,
        oauth2_token_name='uid',
        headers=None,
    ):
        if method.lower() not in ('get', 'head'):
            raise CheckError(
                'Invalid method. Only GET and HEAD are supported!')

        if not base_url and not absolute_http_url(url):
            # More verbose error message!
            raise ConfigurationError(
                'HTTP wrapper improperly configured. Invalid base_url. Check entity["url"] or call with absolute url.'
            )

        self.url = (base_url + url if not absolute_http_url(url) else url)
        self.clean_url = None
        self.params = params
        self.timeout = timeout
        self.max_retries = max_retries
        self.verify = verify
        self._headers = headers or {}
        self.oauth2 = oauth2
        self.oauth2_token_name = oauth2_token_name
        self.__method = method.lower()

        self.allow_redirects = True if allow_redirects is None else allow_redirects
        if self.__method == 'head' and allow_redirects is None:
            self.allow_redirects = False

        self.__r = None

    def __request(self, raise_error=True, post_data=None):
        if self.__r is None:
            if self.max_retries:
                s = requests.Session()
                s.mount('', HTTPAdapter(max_retries=self.max_retries))
            else:
                s = requests

            base_url = self.url
            basic_auth = None

            url_parsed = urlparse.urlsplit(base_url)
            if url_parsed and url_parsed.username and url_parsed.password:
                base_url = base_url.replace(
                    "{0}:{1}@".format(urllib.quote(url_parsed.username),
                                      urllib.quote(url_parsed.password)), "")
                base_url = base_url.replace(
                    "{0}:{1}@".format(url_parsed.username,
                                      url_parsed.password), "")
                basic_auth = (url_parsed.username, url_parsed.password)
            self.clean_url = base_url

            if self.oauth2:
                self._headers.update({
                    'Authorization':
                    'Bearer {}'.format(tokens.get(self.oauth2_token_name))
                })

            self._headers.update({'User-Agent': get_user_agent()})

            try:
                if post_data is None:
                    # GET or HEAD
                    get_method = getattr(s, self.__method)
                    self.__r = get_method(base_url,
                                          params=self.params,
                                          timeout=self.timeout,
                                          verify=self.verify,
                                          headers=self._headers,
                                          auth=basic_auth,
                                          allow_redirects=self.allow_redirects)
                else:
                    self.__r = s.post(base_url,
                                      params=self.params,
                                      timeout=self.timeout,
                                      verify=self.verify,
                                      headers=self._headers,
                                      auth=basic_auth,
                                      data=json.dumps(post_data))
            except requests.Timeout, e:
                raise HttpError('timeout',
                                self.clean_url), None, sys.exc_info()[2]
            except requests.ConnectionError, e:
                raise HttpError('connection failed',
                                self.clean_url), None, sys.exc_info()[2]
            except Exception, e:
                raise HttpError(str(e),
                                self.clean_url), None, sys.exc_info()[2]
Example #11
0
                                      auth=basic_auth,
                                      data=json.dumps(post_data))
            except requests.Timeout, e:
                raise HttpError('timeout',
                                self.clean_url), None, sys.exc_info()[2]
            except requests.ConnectionError, e:
                raise HttpError('connection failed',
                                self.clean_url), None, sys.exc_info()[2]
            except Exception, e:
                raise HttpError(str(e),
                                self.clean_url), None, sys.exc_info()[2]
        if raise_error:
            try:
                self.__r.raise_for_status()
            except requests.HTTPError, e:
                raise HttpError(str(e),
                                self.clean_url), None, sys.exc_info()[2]
        return self.__r

    def json(self, raise_error=True):
        r = self.__request(raise_error=raise_error)
        try:
            return r.json()
        except Exception, e:
            raise HttpError(str(e), self.url), None, sys.exc_info()[2]

    def jolokia(self, read_requests, raise_error=True):
        '''
        :param read_requests: see https://jolokia.org/reference/html/protocol.html#post-request
        :type read_requests: list
        :param raise_error:
        :return: Jolokia response
Example #12
0
    def query_batch(self,
                    metrics,
                    start=5,
                    end=0,
                    time_unit='minutes',
                    start_absolute=None,
                    end_absolute=None):
        """
        Query kairosdb for several checks at once.

        :param metrics: list of KairosDB metric queries, one query per metric name.
        [
            {
                'name': 'metric_name',      # name of the metric
                'group_by': ['foo'],        # list of fields to group by
                'aggregators': [            # list of aggregator objects
                    {                       # structure of a single aggregator
                        'name': 'max',
                        'sampling': {
                            'value': '1',
                            'unit': 'minutes'
                        },
                        'align_sampling': True
                    }
                ],
                'tags': {                   # dict with filtering tags
                    'key': ['max']          # a key is a tag name, list of values is used to filter
                                            # all the records with given tag and given values
                }
            }
        ]
        :type metrics: dict

        :param start: Relative start time. Default is 5.
        :type start: int

        :param end: End time. Default is 0.
        :type end: int

        :param time_unit: Time unit ('seconds', 'minutes', 'hours'). Default is 'minutes'.
        :type time_unit: str.

        :param start_absolute: Absolute start time in milliseconds, overrides the start parameter which is relative
        :type start_absolute: long

        :param end_absolute: Absolute end time in milliseconds, overrides the end parameter which is relative
        :type end_absolute: long

        :return: Array of results for each queried metric
        :rtype: list
        """
        url = os.path.join(self.url, DATAPOINTS_ENDPOINT)

        if start < 1 or end < 0:
            raise ValueError(
                'Time relative "start" and "end" must be greater than or equal to 1'
            )

        q = {'metrics': metrics}

        if start_absolute is None:
            q['start_relative'] = {'value': start, 'unit': time_unit}
        else:
            q['start_absolute'] = start_absolute

        if end_absolute is None:
            if end > 0:
                q['end_relative'] = {'value': end, 'unit': time_unit}
        else:
            q['end_absolute'] = end_absolute

        try:
            response = self.__session.post(url, json=q)
            if response.ok:
                return response.json()['queries']
            else:
                raise Exception(
                    'KairosDB Query failed: {} with status {}:{}'.format(
                        q, response.status_code, response.text))
        except requests.Timeout:
            raise HttpError('timeout', self.url), None, sys.exc_info()[2]
        except requests.ConnectionError:
            raise HttpError('connection failed',
                            self.url), None, sys.exc_info()[2]
Example #13
0
    def query(self,
              name,
              group_by=None,
              tags=None,
              start=5,
              end=0,
              time_unit='minutes',
              aggregators=None):
        """
        Query kairosdb.

        :param name: Metric name.
        :type name: str

        :param group_by: List of fields to group by.
        :type group_by: list

        :param tags: Filtering tags.
        :type tags: dict

        :param start: Relative start time. Default is 5.
        :type start: int

        :param end: End time. Default is 0.
        :type end: int

        :param time_unit: Time unit ('seconds', 'minutes', 'hours'). Default is 'minutes'.
        :type time_unit: str.

        :param aggregators: List of aggregators.
        :type aggregators: list

        :return: Result queries.
        :rtype: dict
        """
        url = os.path.join(self.url, DATAPOINTS_ENDPOINT)

        if start < 1 or end < 0:
            raise ValueError(
                'Time relative "start" and "end" must be greater than or equal to 1'
            )

        if group_by is None:
            group_by = []

        q = {
            'start_relative': {
                'value': start,
                'unit': time_unit
            },
            'metrics': [{
                'name': name,
                'group_by': group_by
            }]
        }

        if end > 0:
            q['end_relative'] = {'value': end, 'unit': time_unit}

        if aggregators:
            q['metrics'][0]['aggregators'] = aggregators

        if tags:
            q['metrics'][0]['tags'] = tags

        try:
            response = self.__session.post(url, json=q)
            if response.ok:
                return response.json()['queries'][0]
            else:
                raise Exception(
                    'KairosDB Query failed: {} with status {}:{}'.format(
                        q, response.status_code, response.text))
        except requests.Timeout:
            raise HttpError('timeout', self.url), None, sys.exc_info()[2]
        except requests.ConnectionError:
            raise HttpError('connection failed',
                            self.url), None, sys.exc_info()[2]