Example #1
0
class Stats():
    """
    This class is responsible for creating and updating database entry(document in Elasticsearch DB)
    There are two usage options:
    1. without arguments - as a based class of TestStatsMixin - for saving test statistics
    2. with arguments - as a separate object to update an existing document
    """
    def __init__(self, *args, **kwargs):
        self._test_index = kwargs.get('test_index', None)
        self._test_id = kwargs.get('test_id', None)
        self._es_doc_type = "test_stats"
        self.elasticsearch = ES()
        self._stats = {}
        if not self._test_id:
            super(Stats, self).__init__(*args, **kwargs)

    def get_doc_id(self):
        return self._test_id

    def create(self):
        self.elasticsearch.create_doc(index=self._test_index,
                                      doc_type=self._es_doc_type,
                                      doc_id=self._test_id,
                                      body=self._stats)

    def update(self, data):
        """
        Update document
        :param data: data dictionary
        """
        try:
            self.elasticsearch.update_doc(index=self._test_index,
                                          doc_type=self._es_doc_type,
                                          doc_id=self._test_id,
                                          body=data)
        except Exception as ex:  # pylint: disable=broad-except
            LOGGER.error('Failed to update test stats: test_id: %s, error: %s',
                         self._test_id, ex)

    def exists(self):
        return self.elasticsearch.exists(index=self._test_index,
                                         doc_type=self._es_doc_type,
                                         id=self._test_id)
class BaseResultsAnalyzer():  # pylint: disable=too-many-instance-attributes
    def __init__(
            self,
            es_index,
            es_doc_type,
            send_email=False,
            email_recipients=(),  # pylint: disable=too-many-arguments
            email_template_fp="",
            query_limit=1000,
            logger=None):
        self._es = ES()
        self._conf = self._es._conf  # pylint: disable=protected-access
        self._es_index = es_index
        self._es_doc_type = es_doc_type
        self._limit = query_limit
        self._send_email = send_email
        self._email_recipients = email_recipients
        self._email_template_fp = email_template_fp
        self.log = logger if logger else LOGGER

    def get_all(self):
        """
        Get all the test results in json format
        """
        return self._es.search(index=self._es_index, size=self._limit)  # pylint: disable=unexpected-keyword-arg

    def get_test_by_id(self, test_id):
        """
        Get test results by test id
        :param test_id: test id created by performance test
        :return: test results in json format
        """
        if not self._es.exists(
                index=self._es_index, doc_type=self._es_doc_type, id=test_id):
            self.log.error('Test results not found: {}'.format(test_id))
            return None
        return self._es.get(index=self._es_index,
                            doc_type=self._es_doc_type,
                            id=test_id)

    def _test_version(self, test_doc):
        if test_doc['_source'].get('versions'):
            for value in ('scylla-server', 'scylla-enterprise-server'):
                key = test_doc['_source']['versions'].get(value)
                if key:
                    return key

        self.log.error('Scylla version is not found for test %s',
                       test_doc['_id'])
        return None

    def render_to_html(self, results, html_file_path=""):
        """
        Render analysis results to html template
        :param results: results dictionary
        :param html_file_path: Boolean, whether to save html file on disk
        :return: html string
        """
        self.log.info("Rendering results to html using '%s' template...",
                      self._email_template_fp)
        loader = jinja2.FileSystemLoader(
            os.path.dirname(os.path.abspath(__file__)))
        print(os.path.dirname(os.path.abspath(__file__)))
        env = jinja2.Environment(loader=loader,
                                 autoescape=True,
                                 extensions=['jinja2.ext.loopcontrols'])
        template = env.get_template(self._email_template_fp)
        html = template.render(results)
        self.log.info("Results has been rendered to html")
        if html_file_path:
            with open(html_file_path, "w") as html_file:
                html_file.write(html)
            self.log.info("HTML report saved to '%s'.", html_file_path)
        return html

    def send_email(self, subject, content, html=True, files=()):
        if self._send_email and self._email_recipients:
            self.log.debug('Send email to {}'.format(self._email_recipients))
            email = Email()
            email.send(subject,
                       content,
                       html=html,
                       recipients=self._email_recipients,
                       files=files)
        else:
            self.log.warning(
                "Won't send email (send_email: %s, recipients: %s)",
                self._send_email, self._email_recipients)

    def gen_kibana_dashboard_url(self, dashboard_path=""):
        return "%s/%s" % (self._conf.get('kibana_url'), dashboard_path)