def test_analyze_t(self):
        a = Analyzer()

        times = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
        values = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
        for (t, v) in zip(times, values):
            a.add_data(t, float(v))

        result = [(d.push_timestamp, d.state) for d in a.analyze_t(
            min_back_window=5, max_back_window=5, fore_window=5, t_threshold=2)
                  ]
        self.assertEqual(result, [(1, 'good'), (2, 'good'), (3, 'good'),
                                  (4, 'good'), (5, 'good'), (6, 'good'),
                                  (7, 'good'), (8, 'regression'), (9, 'good'),
                                  (10, 'good')])
Exemple #2
0
    def check_json(self, filename, expected_timestamps):
        """Parse JSON produced by http://graphs.mozilla.org/api/test/runs"""
        # Configuration for Analyzer
        FORE_WINDOW = 12
        BACK_WINDOW = 12
        THRESHOLD = 7

        payload = SampleData.get_perf_data(os.path.join('graphs', filename))
        runs = payload['test_runs']
        a = Analyzer()
        for r in runs:
            a.add_data(r[2], r[3], testrun_id=r[0],
                       revision_id=r[1][2])

        results = a.analyze_t(BACK_WINDOW, FORE_WINDOW, THRESHOLD)
        regression_timestamps = [d.push_timestamp for d in results if
                                 d.state == 'regression']
        self.assertEqual(regression_timestamps, expected_timestamps)
    def test_analyze_t(self):
        a = Analyzer()

        times = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
        values = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1,  1,  1,  1,  1,  1,  1]
        for (t, v) in zip(times, values):
            a.add_data(t, float(v))

        result = [(d.push_timestamp, d.state) for d in
                  a.analyze_t(back_window=5, fore_window=5, t_threshold=2)]
        self.assertEqual(result, [
            (1, 'good'),
            (2, 'good'),
            (3, 'good'),
            (4, 'good'),
            (5, 'good'),
            (6, 'good'),
            (7, 'good'),
            (8, 'regression'),
            (9, 'good'),
            (10, 'good')])
Exemple #4
0
def generate_new_alerts_in_series(signature):
    # get series data starting from either:
    # (1) the last alert, if there is one
    # (2) the alerts max age
    # (use whichever is newer)
    max_alert_age = (datetime.datetime.now() -
                     settings.PERFHERDER_ALERTS_MAX_AGE)
    series = PerformanceDatum.objects.filter(signature=signature).filter(
        push_timestamp__gte=max_alert_age).order_by('push_timestamp')
    existing_alerts = PerformanceAlert.objects.filter(
        series_signature=signature).select_related('summary').order_by(
            '-summary__result_set_id')[:1]
    if existing_alerts:
        series = series.filter(
            result_set_id__gt=existing_alerts[0].summary.result_set_id)

    a = Analyzer()
    for datum in series:
        timestamp = int(time.mktime(datum.push_timestamp.timetuple()))
        a.add_data(timestamp, datum.value, testrun_id=datum.result_set_id)
    prev = None
    analyzed_series = a.analyze_t()
    prev_testrun_id = None
    with transaction.atomic():
        for (prev, cur) in zip(analyzed_series, analyzed_series[1:]):
            # we can have the same testrun id in a sequence if there are
            # retriggers, so only set the prev_testrun_id if that isn't
            # the case
            if prev.testrun_id != cur.testrun_id:
                prev_testrun_id = prev.testrun_id

            if cur.state == 'regression':
                prev_value = cur.historical_stats['avg']
                new_value = cur.forward_stats['avg']
                if prev_value != 0:
                    pct_change = (100.0 * abs(new_value - prev_value) /
                                  float(prev_value))
                else:
                    pct_change = 0.0
                delta = (new_value - prev_value)

                is_regression = ((delta > 0 and signature.lower_is_better) or
                                 (delta < 0 and not signature.lower_is_better))

                if pct_change < settings.PERFHERDER_REGRESSION_THRESHOLD:
                    # ignore regressions below the configured regression
                    # threshold
                    continue

                summary, _ = PerformanceAlertSummary.objects.get_or_create(
                    repository=signature.repository,
                    result_set_id=cur.testrun_id,
                    prev_result_set_id=prev_testrun_id,
                    defaults={
                        'last_updated':
                        datetime.datetime.fromtimestamp(cur.push_timestamp)
                    })

                # django/mysql doesn't understand "inf", so just use some
                # arbitrarily high value for that case
                t_value = cur.t
                if t_value == float('inf'):
                    t_value = 1000

                a = PerformanceAlert.objects.create(
                    summary=summary,
                    series_signature=signature,
                    is_regression=is_regression,
                    amount_pct=pct_change,
                    amount_abs=delta,
                    prev_value=prev_value,
                    new_value=new_value,
                    t_value=t_value)
                a.save()
Exemple #5
0
def generate_new_alerts_in_series(signature):
    # get series data starting from either:
    # (1) the last alert, if there is one
    # (2) the alerts max age
    # (use whichever is newer)
    max_alert_age = datetime.datetime.now() - settings.PERFHERDER_ALERTS_MAX_AGE
    series = (
        PerformanceDatum.objects.filter(signature=signature)
        .filter(push_timestamp__gte=max_alert_age)
        .order_by("push_timestamp")
    )
    existing_alerts = (
        PerformanceAlert.objects.filter(series_signature=signature)
        .select_related("summary")
        .order_by("-summary__result_set_id")[:1]
    )
    if existing_alerts:
        series = series.filter(result_set_id__gt=existing_alerts[0].summary.result_set_id)

    a = Analyzer()
    for datum in series:
        timestamp = int(time.mktime(datum.push_timestamp.timetuple()))
        a.add_data(timestamp, datum.value, testrun_id=datum.result_set_id)
    prev = None
    analyzed_series = a.analyze_t()
    prev_testrun_id = None
    with transaction.atomic():
        for (prev, cur) in zip(analyzed_series, analyzed_series[1:]):
            # we can have the same testrun id in a sequence if there are
            # retriggers, so only set the prev_testrun_id if that isn't
            # the case
            if prev.testrun_id != cur.testrun_id:
                prev_testrun_id = prev.testrun_id

            if cur.state == "regression":
                prev_value = cur.historical_stats["avg"]
                new_value = cur.forward_stats["avg"]
                if prev_value != 0:
                    pct_change = 100.0 * abs(new_value - prev_value) / float(prev_value)
                else:
                    pct_change = 0.0
                delta = new_value - prev_value

                is_regression = (delta > 0 and signature.lower_is_better) or (
                    delta < 0 and not signature.lower_is_better
                )

                if pct_change < settings.PERFHERDER_REGRESSION_THRESHOLD:
                    # ignore regressions below the configured regression
                    # threshold
                    continue

                summary, _ = PerformanceAlertSummary.objects.get_or_create(
                    repository=signature.repository,
                    result_set_id=cur.testrun_id,
                    prev_result_set_id=prev_testrun_id,
                    defaults={"last_updated": datetime.datetime.fromtimestamp(cur.push_timestamp)},
                )

                # django/mysql doesn't understand "inf", so just use some
                # arbitrarily high value for that case
                t_value = cur.t
                if t_value == float("inf"):
                    t_value = 1000

                a = PerformanceAlert.objects.create(
                    summary=summary,
                    series_signature=signature,
                    is_regression=is_regression,
                    amount_pct=pct_change,
                    amount_abs=delta,
                    prev_value=prev_value,
                    new_value=new_value,
                    t_value=t_value,
                )
                a.save()
    def handle(self, *args, **options):
        if options['server']:
            server_params = urlparse(options['server'])
            server_protocol = server_params.scheme
            server_host = server_params.netloc
        else:
            server_protocol = settings.TREEHERDER_REQUEST_PROTOCOL
            server_host = settings.TREEHERDER_REQUEST_HOST

        if not options['project']:
            raise CommandError("Must specify at least one project with "
                               "--project")

        pc = PerfherderClient(protocol=server_protocol,
                              host=server_host)

        option_collection_hash = pc.get_option_collection_hash()

        # print csv header
        print ','.join(["project", "platform", "signature", "series",
                        "testrun_id", "push_timestamp", "change",
                        "percent change", "t-value", "revision"])

        for project in options['project']:
            if options['signature']:
                signatures = [options['signature']]
                signature_data = pc.get_performance_signatures(
                    project, signatures=signatures,
                    interval=options['time_interval'])
            else:
                signature_data = pc.get_performance_signatures(
                    project, interval=options['time_interval'])
                signatures = []
                signatures_to_ignore = set()
                # if doing everything, only handle summary series
                for (signature, properties) in signature_data.iteritems():
                    signatures.append(signature)
                    if 'subtest_signatures' in properties:
                        # Don't alert on subtests which have a summary
                        signatures_to_ignore.update(properties['subtest_signatures'])
                signatures = [signature for signature in signatures
                              if signature not in signatures_to_ignore]

            for signature in signatures:
                series = pc.get_performance_data(
                    project, signatures=signature,
                    interval=options['time_interval'])[signature]

                series_properties = signature_data.get(signature)

                a = Analyzer()

                for (result_set_id, timestamp, value) in zip(
                        series['result_set_id'], series['push_timestamp'],
                        series['value']):
                    a.add_data(timestamp, value, testrun_id=result_set_id)

                for r in a.analyze_t():
                    if r.state == 'regression':
                        resultsets = pc.get_resultsets(project,
                                                       id=r.testrun_id)
                        if len(resultsets):
                            revision = resultsets[0]['revision']
                        else:
                            revision = ''
                        initial_value = r.historical_stats['avg']
                        new_value = r.forward_stats['avg']
                        if initial_value != 0:
                            pct_change = 100.0 * abs(new_value - initial_value) / float(initial_value)
                        else:
                            pct_change = 0.0
                        delta = (new_value - initial_value)
                        print ','.join(map(
                            lambda v: str(v),
                            [project, series_properties['machine_platform'],
                             signature, self._get_series_description(
                                 option_collection_hash,
                                 series_properties),
                             r.testrun_id, r.push_timestamp, delta,
                             pct_change, r.t, revision[0:12]]))
Exemple #7
0
def generate_new_alerts_in_series(signature):
    series = PerformanceDatum.objects.filter(
        signature=signature).order_by(
            'push_timestamp')
    existing_alerts = PerformanceAlert.objects.filter(
        series_signature=signature).select_related(
            'summary').order_by('-summary__result_set_id')[:1]
    if existing_alerts:
        series = series.filter(
            result_set_id__gt=existing_alerts[0].summary.result_set_id)

    a = Analyzer()
    for datum in series:
        timestamp = int(time.mktime(
            datum.push_timestamp.timetuple()))
        a.add_data(timestamp, datum.value,
                   testrun_id=datum.result_set_id)
    prev = None
    analyzed_series = a.analyze_t()

    with transaction.atomic():
        for (prev, cur) in zip(analyzed_series, analyzed_series[1:]):
            if cur.state == 'regression':
                prev_value = cur.historical_stats['avg']
                new_value = cur.forward_stats['avg']
                if prev_value != 0:
                    pct_change = (100.0 * abs(new_value -
                                              prev_value) /
                                  float(prev_value))
                else:
                    pct_change = 0.0
                delta = (new_value - prev_value)

                is_regression = ((delta > 0 and signature.lower_is_better) or
                                 (delta < 0 and not signature.lower_is_better))

                if pct_change < settings.PERFHERDER_REGRESSION_THRESHOLD:
                    # ignore regressions below the configured regression
                    # threshold
                    continue

                summary, _ = PerformanceAlertSummary.objects.get_or_create(
                    repository=signature.repository,
                    result_set_id=cur.testrun_id,
                    prev_result_set_id=prev.testrun_id,
                    defaults={
                        'last_updated': datetime.datetime.fromtimestamp(
                            cur.push_timestamp)
                    })

                # django/mysql doesn't understand "inf", so just use some
                # arbitrarily high value for that case
                t_value = cur.t
                if t_value == float('inf'):
                    t_value = 1000

                a = PerformanceAlert.objects.create(
                    summary=summary,
                    series_signature=signature,
                    is_regression=is_regression,
                    amount_pct=pct_change,
                    amount_abs=delta,
                    prev_value=prev_value,
                    new_value=new_value,
                    t_value=t_value)
                a.save()
Exemple #8
0
    def handle(self, *args, **options):
        if options['server']:
            server_params = urlparse(options['server'])
            server_protocol = server_params.scheme
            server_host = server_params.netloc
        else:
            server_protocol = settings.TREEHERDER_REQUEST_PROTOCOL
            server_host = settings.TREEHERDER_REQUEST_HOST

        if not options['project']:
            raise CommandError("Must specify at least one project with "
                               "--project")

        pc = PerfherderClient(protocol=server_protocol, host=server_host)

        option_collection_hash = pc.get_option_collection_hash()

        # print csv header
        print ','.join([
            "project", "platform", "signature", "series", "testrun_id",
            "push_timestamp", "change", "percent change", "t-value", "revision"
        ])

        for project in options['project']:
            if options['signature']:
                signatures = [options['signature']]
                signature_data = pc.get_performance_signatures(
                    project,
                    signatures=signatures,
                    interval=options['time_interval'])
            else:
                signature_data = pc.get_performance_signatures(
                    project, interval=options['time_interval'])
                signatures = []
                signatures_to_ignore = set()
                # if doing everything, only handle summary series
                for (signature, properties) in signature_data.iteritems():
                    signatures.append(signature)
                    if 'subtest_signatures' in properties:
                        # Don't alert on subtests which have a summary
                        signatures_to_ignore.update(
                            properties['subtest_signatures'])
                signatures = [
                    signature for signature in signatures
                    if signature not in signatures_to_ignore
                ]

            for signature in signatures:
                series = pc.get_performance_data(
                    project,
                    signatures=signature,
                    interval=options['time_interval'])[signature]

                series_properties = signature_data.get(signature)

                a = Analyzer()

                for (result_set_id, timestamp,
                     value) in zip(series['result_set_id'],
                                   series['push_timestamp'], series['value']):
                    a.add_data(timestamp, value, testrun_id=result_set_id)

                for r in a.analyze_t():
                    if r.state == 'regression':
                        resultsets = pc.get_resultsets(project,
                                                       id=r.testrun_id)
                        if len(resultsets):
                            revision = resultsets[0]['revision']
                        else:
                            revision = ''
                        initial_value = r.historical_stats['avg']
                        new_value = r.forward_stats['avg']
                        if initial_value != 0:
                            pct_change = 100.0 * abs(new_value - initial_value
                                                     ) / float(initial_value)
                        else:
                            pct_change = 0.0
                        delta = (new_value - initial_value)
                        print ','.join(
                            map(lambda v: str(v), [
                                project, series_properties['machine_platform'],
                                signature,
                                self._get_series_description(
                                    option_collection_hash, series_properties),
                                r.testrun_id, r.push_timestamp, delta,
                                pct_change, r.t, revision[0:12]
                            ]))
Exemple #9
0
def generate_new_alerts_in_series(signature):
    # get series data starting from either:
    # (1) the last alert, if there is one
    # (2) the alerts max age
    # (use whichever is newer)
    max_alert_age = (datetime.datetime.now() -
                     settings.PERFHERDER_ALERTS_MAX_AGE)
    series = PerformanceDatum.objects.filter(signature=signature).filter(
        push_timestamp__gte=max_alert_age).order_by('push_timestamp')
    existing_alerts = PerformanceAlert.objects.filter(
        series_signature=signature).select_related(
            'summary').order_by('-summary__result_set_id')[:1]
    if existing_alerts:
        series = series.filter(
            result_set_id__gt=existing_alerts[0].summary.result_set_id)

    a = Analyzer()
    for datum in series:
        timestamp = int(time.mktime(
            datum.push_timestamp.timetuple()))
        a.add_data(timestamp, datum.value,
                   testrun_id=datum.result_set_id)
    prev = None

    min_back_window = signature.min_back_window
    if min_back_window is None:
        min_back_window = settings.PERFHERDER_ALERTS_MIN_BACK_WINDOW
    max_back_window = signature.max_back_window
    if max_back_window is None:
        max_back_window = settings.PERFHERDER_ALERTS_MAX_BACK_WINDOW
    fore_window = signature.fore_window
    if fore_window is None:
        fore_window = settings.PERFHERDER_ALERTS_FORE_WINDOW
    alert_threshold = signature.alert_threshold
    if alert_threshold is None:
        alert_threshold = settings.PERFHERDER_REGRESSION_THRESHOLD

    analyzed_series = a.analyze_t(min_back_window=min_back_window,
                                  max_back_window=max_back_window,
                                  fore_window=fore_window)
    prev_testrun_id = None
    with transaction.atomic():
        for (prev, cur) in zip(analyzed_series, analyzed_series[1:]):
            # we can have the same testrun id in a sequence if there are
            # retriggers, so only set the prev_testrun_id if that isn't
            # the case
            if prev.testrun_id != cur.testrun_id:
                prev_testrun_id = prev.testrun_id

            if cur.state == 'regression':
                prev_value = cur.historical_stats['avg']
                new_value = cur.forward_stats['avg']
                if prev_value != 0:
                    pct_change = (100.0 * abs(new_value -
                                              prev_value) /
                                  float(prev_value))
                else:
                    pct_change = 0.0
                delta = (new_value - prev_value)

                is_regression = ((delta > 0 and signature.lower_is_better) or
                                 (delta < 0 and not signature.lower_is_better))

                if pct_change < alert_threshold:
                    # ignore regressions below the configured regression
                    # threshold
                    continue

                summary, _ = PerformanceAlertSummary.objects.get_or_create(
                    repository=signature.repository,
                    framework=signature.framework,
                    result_set_id=cur.testrun_id,
                    prev_result_set_id=prev_testrun_id,
                    defaults={
                        'last_updated': datetime.datetime.fromtimestamp(
                            cur.push_timestamp)
                    })

                # django/mysql doesn't understand "inf", so just use some
                # arbitrarily high value for that case
                t_value = cur.t
                if t_value == float('inf'):
                    t_value = 1000

                a = PerformanceAlert.objects.create(
                    summary=summary,
                    series_signature=signature,
                    is_regression=is_regression,
                    amount_pct=pct_change,
                    amount_abs=delta,
                    prev_value=prev_value,
                    new_value=new_value,
                    t_value=t_value)
                a.save()