Ejemplo n.º 1
0
def _QueryTotalReports(luci_project, limit=_DEFAULT_MAX_ROW_NUM):
    tags = [
        TotalFlakinessReport.GenerateTag('luci_project', luci_project),
        # Only displays one report per week, though we may generate report more
        # frequently.
        TotalFlakinessReport.GenerateTag('day', 1),
    ]

    query = TotalFlakinessReport.query()

    for tag in tags:
        query = query.filter(TotalFlakinessReport.tags == tag)

    return query.order(-TotalFlakinessReport.report_time).fetch(limit)
Ejemplo n.º 2
0
    def HandleGet(self):
        luci_project = self.request.get(
            'luci_project').strip() or DEFAULT_LUCI_PROJECT
        component = self.request.get('component_filter').strip()

        if component:
            return self.CreateRedirect(
                '/p/chromium/flake-portal/report/component?component=%s' %
                component)

        report_time = time_util.GetPreviousWeekMonday()

        # The report is a weekly report, though we may generate reports more
        # frequently. Uses the Monday report for the whole week.
        total_flakiness_report = TotalFlakinessReport.Get(
            report_time, luci_project)

        data = {
            'component':
            component,
            'luci_project':
            (luci_project if luci_project != DEFAULT_LUCI_PROJECT else ''),
        }
        if not total_flakiness_report:
            data['total_report'] = {}
            data['top_components'] = []
        else:
            data['total_report'] = total_flakiness_report.ToSerializable()
            data['top_components'] = _QueryTopComponents(
                total_flakiness_report.key)

        return {'template': 'flake/report/flake_report.html', 'data': data}
Ejemplo n.º 3
0
def SaveReportToDatastore(counters, report_date, save_test_report=False):
    # The entities to persist.
    entities = []
    for luci_project, p_counters in counters.iteritems():
        project_tag = ('luci_project', luci_project)
        report = TotalFlakinessReport.FromTallies(
            None, p_counters, report_date, additional_tags=[project_tag])
        entities.append(report)
        for component, c_counters in p_counters.iteritems():
            if component.startswith('_'):
                continue
            component_tag = ('component', component)
            component_row = ComponentFlakinessReport.FromTallies(
                report.key,
                c_counters,
                report_date,
                additional_tags=[project_tag, component_tag])
            entities.append(component_row)
            if not save_test_report:
                continue
            for test, t_counters in c_counters.iteritems():
                if test.startswith('_'):
                    continue
                test_tag = ('test', test)
                entities.append(
                    TestFlakinessReport.FromTallies(
                        component_row.key,
                        t_counters,
                        report_date,
                        additional_tags=[project_tag, component_tag,
                                         test_tag]))

    ndb.put_multi(entities)
Ejemplo n.º 4
0
    def testReport(self):
        report_time = datetime(2018, 8, 27)
        report = TotalFlakinessReport.Get(report_time, 'chromium')
        self.assertEqual(6, report.test_count)
        self.assertEqual(8, report.GetTotalOccurrenceCount())
        self.assertEqual(3, report.GetTotalCLCount())

        report_data = {
            'id': '2018-08-27@chromium',
            'test_count': 6,
            'bug_count': 4,
            'new_bug_count': 0,
            'impacted_cl_counts': {
                'cq_false_rejection': 3,
                'retry_with_patch': 0,
                'total': 3
            },
            'occurrence_counts': {
                'cq_false_rejection': 7,
                'retry_with_patch': 1,
                'total': 8
            }
        }

        self.assertEqual(report_data, report.ToSerializable())
        self.assertEqual('chromium', report.GetProject())
        self.assertIn('luci_project::chromium', report.tags)

        component_report_A = ComponentFlakinessReport.Get(
            report.key, 'ComponentA')
        self.assertEqual(4, component_report_A.test_count)
        self.assertEqual(6, component_report_A.GetTotalOccurrenceCount())
        self.assertEqual(3, component_report_A.GetTotalCLCount())
        self.assertEqual(3, component_report_A.false_rejected_cl_count)

        reports_queried_by_component = ComponentFlakinessReport.query(
            ComponentFlakinessReport.tags == 'component::ComponentA').fetch()
        self.assertEqual(component_report_A, reports_queried_by_component[0])

        component_test_report_A_B = TestFlakinessReport.Get(
            component_report_A.key, 'testB')
        self.assertEqual(1, component_test_report_A_B.test_count)
        self.assertEqual(2,
                         component_test_report_A_B.GetTotalOccurrenceCount())
        self.assertEqual(2, component_test_report_A_B.GetTotalCLCount())

        reports_queried_by_test = TestFlakinessReport.query(
            TestFlakinessReport.tags == 'test::testB').fetch()
        self.assertEqual(component_test_report_A_B, reports_queried_by_test[0])
Ejemplo n.º 5
0
def _AddFlakesToCounters(counters, flake_info_dict, report_time,
                         save_test_report):
    """Queries all flakes that have happened after report_time and adds their info
    to counters.
  """
    query = Flake.query()
    query = query.filter(Flake.last_occurred_time >= report_time)

    cursor = None
    more = True
    while more:
        flakes, cursor, more = query.fetch_page(500, start_cursor=cursor)
        for flake in flakes:
            luci_project = flake.luci_project
            if luci_project not in counters:
                counters[luci_project] = _NewTally(
                    TotalFlakinessReport.MakeId(report_time, luci_project))
            _AddFlakeToTally(counters[luci_project], flake, report_time)

            component = flake.GetComponent()
            test = flake.normalized_test_name
            flake_info_dict[flake.key] = {
                'luci_project': luci_project,
                'component': component,
                'test': test
            }

            if component not in counters[luci_project]:
                counters[luci_project][component] = _NewTally(component)
            _AddFlakeToTally(counters[luci_project][component], flake,
                             report_time)

            if save_test_report:  # pragma: no branch.
                if test not in counters[luci_project][component]:
                    counters[luci_project][component][test] = _NewTally(test)
                _AddFlakeToTally(counters[luci_project][component][test],
                                 flake, report_time)
Ejemplo n.º 6
0
 def testGetFalseRejectedCLCount(self):
     report_time = datetime(2018, 8, 27)
     report = TotalFlakinessReport.Get(report_time, 'chromium')
     self.assertEqual(3, report.false_rejected_cl_count)
Ejemplo n.º 7
0
    def testBasicReportNoTestReports(self, _):
        report_date = datetime(2018, 8, 27)
        component_report.Report()

        report = TotalFlakinessReport.Get(report_date, 'chromium')
        self.assertEqual(6, report.test_count)
        self.assertEqual(4, report.bug_count)
        self.assertEqual(3, report.new_bug_count)

        expected_report_counts = {
            FlakeType.CQ_FALSE_REJECTION: (7, 3),
            FlakeType.RETRY_WITH_PATCH: (1, 0),
            FlakeType.CQ_HIDDEN_FLAKE: (0, 0),
            FlakeType.CI_FAILED_STEP: (0, 0)
        }

        for occurrence_count in report.occurrence_counts:
            self.assertEqual(
                expected_report_counts[occurrence_count.flake_type][0],
                occurrence_count.count)

        for cl_count in report.impacted_cl_counts:
            self.assertEqual(expected_report_counts[cl_count.flake_type][1],
                             cl_count.count)

        component_report_A = ComponentFlakinessReport.Get(
            report.key, 'ComponentA')
        self.assertEqual(4, component_report_A.test_count)
        self.assertEqual(3, component_report_A.bug_count)
        self.assertEqual(2, component_report_A.new_bug_count)

        expected_A_counts = {
            FlakeType.CQ_FALSE_REJECTION: (5, 3),
            FlakeType.RETRY_WITH_PATCH: (1, 0),
            FlakeType.CQ_HIDDEN_FLAKE: (0, 0),
            FlakeType.CI_FAILED_STEP: (0, 0)
        }

        for occurrence_count in component_report_A.occurrence_counts:
            self.assertEqual(expected_A_counts[occurrence_count.flake_type][0],
                             occurrence_count.count)

        for cl_count in component_report_A.impacted_cl_counts:
            self.assertEqual(expected_A_counts[cl_count.flake_type][1],
                             cl_count.count)

        component_report_unknown = ComponentFlakinessReport.Get(
            report.key, 'Unknown')
        self.assertEqual(1, component_report_unknown.test_count)
        self.assertEqual(1, component_report_unknown.bug_count)
        self.assertEqual(1, component_report_unknown.new_bug_count)

        expected_Unknown_counts = {
            FlakeType.CQ_FALSE_REJECTION: (1, 1),
            FlakeType.RETRY_WITH_PATCH: (0, 0),
            FlakeType.CQ_HIDDEN_FLAKE: (0, 0),
            FlakeType.CI_FAILED_STEP: (0, 0)
        }

        for occurrence_count in component_report_unknown.occurrence_counts:
            self.assertEqual(
                expected_Unknown_counts[occurrence_count.flake_type][0],
                occurrence_count.count)

        for cl_count in component_report_unknown.impacted_cl_counts:
            self.assertEqual(expected_Unknown_counts[cl_count.flake_type][1],
                             cl_count.count)
Ejemplo n.º 8
0
def Report(save_test_report=False):
    """Creates report data for a given week.

  Iterates over flakes have happened in the week, and adds information we can
    directly get from flakes (component, test name, occurrences_counts in the
    week) to the counters.

  Then iterates all flake occurrences happened in the week (using projection
    query to lower latency and cost) to count distinct impacted CLs.

  After the totals are accummulated, persists the entities to datastore.

  Args:
    save_test_report (bool): True if save TestFlakinessReport entries, otherwise
      False. Noted: an error "too much contention on these datastore entities"
      may fire when also save TestFlakinessReport entries.
  """
    report_date = time_util.GetMidnight(
        time_util.GetDateDaysBeforeNow(days=DAYS_IN_A_WEEK))
    if TotalFlakinessReport.Get(report_date, DEFAULT_LUCI_PROJECT):
        raise ReportExistsException('Report already exist for {}'.format(
            time_util.FormatDatetime(report_date, day_only=True)))

    # TODO(crbug.com/920926): Use classes instead of a big dict for temp data.
    # Data structure to accumulate the counts in.
    # After tallying, should look something like this:
    # {
    #   'chromium': {
    #     '_id': '2018-08-27',
    #     # Totals
    #     '_bugs': set([FlakeIssue.key, ...]),
    #     '_impacted_cls': {
    #         FlakeType.CQ_FALSE_REJECTION: set([12345, 12346, ...]),
    #         FlakeType.RETRY_WITH_PATCH: set([12348, ...])
    #     },
    #     '_occurrences': {
    #         FlakeType.CQ_FALSE_REJECTION: 100,
    #         FlakeType.RETRY_WITH_PATCH: 1800},
    #     '_tests': set(['test1', ...]),
    #     'component1': {
    #       # Per-component Totals
    #       '_id': 'component1',
    #       '_bugs': set([FlakeIssue.key, ...]),
    #       '_impacted_cls': {
    #           FlakeType.CQ_FALSE_REJECTION: set([12345, 12346, ...]),
    #           FlakeType.RETRY_WITH_PATCH: set([12348, ...])
    #       },
    #       '_occurrences': {
    #           FlakeType.CQ_FALSE_REJECTION: 10,
    #           FlakeType.RETRY_WITH_PATCH: 100},
    #       '_tests': set(['test1', ...]),
    #       'test1': {
    #         # Per-(component/test) Totals
    #         '_id': 'test1',
    #         '_bugs': set([FlakeIssue.key, ...]),
    #         '_impacted_cls': {
    #             FlakeType.CQ_FALSE_REJECTION: set([12345]),
    #             FlakeType.RETRY_WITH_PATCH: set([12348])
    #         },
    #         '_occurrences': {
    #           FlakeType.CQ_FALSE_REJECTION: 1,
    #           FlakeType.RETRY_WITH_PATCH: 18},
    #         '_tests': set(['test1']),
    #       }, ...<more tests>
    #     }, ...<more components>
    #   },
    #   ... <more project>
    # }
    counters = {}

    # A dict with key as each flake's ndb key and value as each flake's component
    # and normalized_test_name.
    flake_info_dict = {}

    end = report_date + datetime.timedelta(days=7)

    _AddFlakesToCounters(counters, flake_info_dict, report_date,
                         save_test_report)
    _AddDistinctCLsToCounters(counters, flake_info_dict, report_date, end,
                              save_test_report)
    SaveReportToDatastore(counters, report_date, save_test_report)