summaryrefslogtreecommitdiffstats
path: root/testing/talos/talos/scripts/report.py
diff options
context:
space:
mode:
Diffstat (limited to 'testing/talos/talos/scripts/report.py')
-rw-r--r--testing/talos/talos/scripts/report.py148
1 files changed, 148 insertions, 0 deletions
diff --git a/testing/talos/talos/scripts/report.py b/testing/talos/talos/scripts/report.py
new file mode 100644
index 0000000000..f5b952371a
--- /dev/null
+++ b/testing/talos/talos/scripts/report.py
@@ -0,0 +1,148 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import argparse
+import collections
+import csv
+import os
+import sys
+from calendar import day_name
+from datetime import datetime
+
+import compare
+import numpy
+import six
+
+sys.path.insert(1, os.path.join(sys.path[0], ".."))
+
+
+def get_branch(platform):
+ if platform.startswith("OSX"):
+ return compare.branch_map["Inbound"]["pgo"]["id"]
+ return compare.branch_map["Inbound"]["nonpgo"]["id"]
+
+
+def get_all_test_tuples():
+ ret = []
+ for test in compare.test_map:
+ for platform in compare.platform_map:
+ ret.extend(get_tuple(test, platform))
+ return ret
+
+
+def get_tuple(test, platform):
+ return [
+ (
+ compare.test_map[test]["id"],
+ get_branch(platform),
+ compare.platform_map[platform],
+ test,
+ platform,
+ )
+ ]
+
+
+def generate_report(tuple_list, filepath, mode="variance"):
+ avg = []
+
+ for test in tuple_list:
+ testid, branchid, platformid = test[:3]
+ data_dict = compare.getGraphData(testid, branchid, platformid)
+ week_avgs = []
+
+ if data_dict:
+ data = data_dict["test_runs"]
+ data.sort(key=lambda x: x[3])
+ data = data[int(0.1 * len(data)) : int(0.9 * len(data) + 1)]
+ time_dict = collections.OrderedDict()
+ days = {}
+
+ for point in data:
+ time = datetime.fromtimestamp(point[2]).strftime("%Y-%m-%d")
+ time_dict[time] = time_dict.get(time, []) + [point[3]]
+
+ for time in time_dict:
+ runs = len(time_dict[time])
+ weekday = datetime.strptime(time, "%Y-%m-%d").strftime("%A")
+ variance = numpy.var(time_dict[time])
+ if mode == "variance":
+ days[weekday] = days.get(weekday, []) + [variance]
+ elif mode == "count":
+ days[weekday] = days.get(weekday, []) + [runs]
+
+ line = ["-".join(test[3:])]
+ for day in day_name:
+ if mode == "variance":
+ # removing top and bottom 10% to reduce outlier influence
+ # pylint --py3k W1619
+ tenth = len(days[day]) / 10
+ average = numpy.average(sorted(days[day])[tenth : tenth * 9 + 1])
+ elif mode == "count":
+ average = numpy.average(days[day])
+ line.append("%.3f" % average)
+ week_avgs.append(average)
+
+ outliers = is_normal(week_avgs)
+ for j in six.moves.range(7):
+ if j in outliers:
+ line[j + 1] = "**" + str(line[j + 1]) + "**"
+
+ avg.append(line)
+
+ with open(filepath, "wb") as report:
+ avgs_header = csv.writer(report, quoting=csv.QUOTE_ALL)
+ avgs_header.writerow(["test-platform"] + list(day_name))
+ for line in avg:
+ out = csv.writer(report, quoting=csv.QUOTE_ALL)
+ out.writerow(line)
+
+
+def is_normal(y):
+ # This is a crude initial attempt at detecting normal distributions
+ # TODO: Improve this
+ limit = 1.5
+ clean_week = []
+ outliers = []
+ # find a baseline for the week
+ if (min(y[0:4]) * limit) <= max(y[0:4]):
+ for i in six.moves.range(1, 5):
+ if y[i] > (y[i - 1] * limit) or y[i] > (y[i + 1] * limit):
+ outliers.append(i)
+ continue
+ clean_week.append(y[i])
+ else:
+ clean_week = y
+
+ # look at weekends now
+ # pylint --py3k W1619
+ avg = sum(clean_week) / len(clean_week)
+ for i in six.moves.range(5, 7):
+ # look for something outside of the 20% window
+ if (y[i] * 1.2) < avg or y[i] > (avg * 1.2):
+ outliers.append(i)
+ return outliers
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Generate weekdays reports")
+ parser.add_argument("--test", help="show only the test named TEST")
+ parser.add_argument("--platform", help="show only the platform named PLATFORM")
+ parser.add_argument("--mode", help="select mode", default="variance")
+ args = parser.parse_args()
+ tuple_list = get_all_test_tuples()
+ f = "report"
+ if args.platform:
+ tuple_list = [x for x in tuple_list if x[4] == args.platform]
+ f += "-%s" % args.platform
+
+ if args.test:
+ tuple_list = [x for x in tuple_list if x[3] == args.test]
+ f += "-%s" % args.test
+
+ f += "-%s" % args.mode
+ generate_report(tuple_list, filepath=f + ".csv", mode=args.mode)
+
+
+if __name__ == "__main__":
+ main()