Index: dashboard/dashboard/benchmark_health_report.py |
diff --git a/dashboard/dashboard/benchmark_health_report.py b/dashboard/dashboard/benchmark_health_report.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f4a78f32702b37683942b2d144b0b6b2288307a6 |
--- /dev/null |
+++ b/dashboard/dashboard/benchmark_health_report.py |
@@ -0,0 +1,89 @@ |
+# Copyright 2017 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+"""Provides the web interface for a report on benchmark alert health.""" |
+ |
+import datetime |
+import json |
+ |
+from dashboard import alerts |
+from dashboard import list_tests |
+from dashboard import update_test_suites |
+from dashboard.common import request_handler |
+from dashboard.common import utils |
+from dashboard.models import anomaly |
+ |
+ |
+class BenchmarkHealthReportHandler(request_handler.RequestHandler): |
+ |
+ def get(self): |
+ """Renders the UI for the group report page.""" |
+ self.RenderStaticHtml('benchmark_health_report.html') |
+ |
+ def post(self): |
+ """Returns data about the alerts for a benchmark. |
+ |
+ Request parameters: |
+ master: If specified, the master to list benchmarks for. If no arguments |
+ are specified, benchmarks will be listed for chromium.perf. |
+ benchmark: If specified, the name of the benchmark to gather details for. |
+ num_days: With benchmark, number of days backwards in time to get data. |
+ bug: If specified, the id of the bug to gather details for. |
+ |
+ Outputs: |
+ JSON for the /group_report page XHR request. |
+ """ |
+ master = self.request.get('master') |
+ benchmark = self.request.get('benchmark') |
+ response_values = {} |
+ |
+ if benchmark: |
+ num_days = int(self.request.get('num_days')) |
+ response_values = self._GetResponseValuesForBenchmark( |
+ benchmark, num_days, master) |
+ else: |
+ response_values = self._GetResponseValuesForMaster(master) |
+ |
+ self.response.out.write(json.dumps(response_values)) |
+ |
+ def _GetResponseValuesForBenchmark(self, benchmark, num_days, master): |
+ values = {} |
+ |
+ # The cached test suite info contains info about monitoring and bots. |
+ benchmarks = update_test_suites.FetchCachedTestSuites() |
+ sheriff = self._GetSheriffForBenchmark(benchmark, master, benchmarks) |
+ if sheriff: |
+ query = anomaly.Anomaly.query(anomaly.Anomaly.sheriff == sheriff) |
+ query = query.filter(anomaly.Anomaly.is_improvement == False) |
+ query = query.filter( |
+ anomaly.Anomaly.timestamp > |
+ datetime.datetime.now() - datetime.timedelta(days=num_days)) |
+ query = query.order(-anomaly.Anomaly.timestamp) |
+ anomalies = query.fetch() |
+ anomalies = [a for a in anomalies if self._BenchmarkName(a) == benchmark] |
+ values['monitored'] = True |
+ values['alerts'] = alerts.AnomalyDicts(anomalies) |
+ else: |
+ values['monitored'] = False |
+ |
+ values['bots'] = benchmarks[benchmark]['mas'][master].keys() |
+ return values |
+ |
+ def _GetSheriffForBenchmark(self, benchmark, master, benchmarks): |
+ # TODO(sullivan): There can be multiple sheriffs; implement this. |
+ if not benchmarks[benchmark]['mon']: |
+ return None |
+ monitored_test_path = benchmarks[benchmark]['mon'][0] |
+ pattern = '%s/*/%s/%s' % (master, benchmark, monitored_test_path) |
+ monitored_tests = list_tests.GetTestsMatchingPattern( |
+ pattern, list_entities=True) |
+ return monitored_tests[0].sheriff |
+ |
+ def _BenchmarkName(self, alert): |
+ return utils.TestPath(alert.test).split('/')[2] |
+ |
+ def _GetResponseValuesForMaster(self, master): |
+ benchmarks = update_test_suites.FetchCachedTestSuites() |
+ benchmarks = [b for b in benchmarks if master in benchmarks[b]['mas']] |
+ return {'benchmarks': sorted(benchmarks)} |