summaryrefslogtreecommitdiffstats
path: root/scripts/gettopchanges.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/gettopchanges.py')
-rw-r--r--scripts/gettopchanges.py181
1 files changed, 181 insertions, 0 deletions
diff --git a/scripts/gettopchanges.py b/scripts/gettopchanges.py
new file mode 100644
index 0000000..1b7282a
--- /dev/null
+++ b/scripts/gettopchanges.py
@@ -0,0 +1,181 @@
+import sys, json, calendar, time
+from dbaccess import execQuery, database
+from misc import (
+ textToId, idToText, getContext, getTimestampFromContext, getSnapshots,
+ benchmarkToComponents, printJSONHeader)
+
+
+
+# Gets the top changes for a specific context by considering only the
+# last change in each time series.
+#
+# An additional filter is applied by only considering results from
+# test cases matching test_case_ids.
+#
+# NOTE: The result may contain at most one change from a given time series.
+def getTopChangesForContext_last(
+ host_id, platform_id, branch_id, regressions, premature, limit,
+ test_case_ids):
+
+ query = (
+ "SELECT change.benchmarkId, change.metricId, sha1Id, last_timestamp, ")
+ query += ("greatest(score, premature_score)" if premature else "score")
+ query += (
+ " AS final_score"
+ " FROM"
+ " (SELECT benchmarkId, metricId, max(timestamp) AS last_timestamp"
+ " FROM change"
+ " WHERE hostId = %s"
+ " AND platformId = %s"
+ " AND branchId = %s"
+ " AND regression = %s")
+ args = [host_id, platform_id, branch_id, regressions]
+
+ if len(test_case_ids) > 0:
+ query += (
+ " AND testCaseId IN (%s" + ", %s"*(len(test_case_ids) - 1) + ")"
+ )
+ args += test_case_ids
+
+ query += (
+ " GROUP BY benchmarkId, metricId) AS last_change"
+ " , change"
+ " WHERE last_change.benchmarkId = change.benchmarkId"
+ " AND last_change.metricId = change.metricId"
+ " AND change.timestamp = last_timestamp"
+ " ORDER BY final_score DESC, last_timestamp DESC"
+ " LIMIT %s"
+ )
+ args.append(limit)
+
+ return execQuery(query, args)
+
+
+# Gets the top changes for a specific context by considering all
+# changes in the given time scope.
+#
+# An additional filter is applied by only considering results from
+# test cases matching test_case_ids.
+#
+# NOTE: The result may contain any number of changes from a given time
+# series.
+def getTopChangesForContext_timeScope(
+ host_id, platform_id, branch_id, regressions, premature, limit,
+ test_case_ids, lo_timestamp):
+
+ query = "SELECT benchmarkId, metricId, sha1Id, timestamp, "
+ query += ("greatest(score, premature_score)" if premature else "score")
+ query += (
+ " AS final_score"
+ " FROM change"
+ " WHERE hostId = %s"
+ " AND platformId = %s"
+ " AND branchId = %s"
+ " AND regression = %s"
+ " AND timestamp >= %s")
+ args = [host_id, platform_id, branch_id, regressions, lo_timestamp]
+
+ if len(test_case_ids) > 0:
+ query += (
+ " AND testCaseId IN (%s" + ", %s"*(len(test_case_ids) - 1) + ")"
+ )
+ args += test_case_ids
+
+ query += (
+ " ORDER BY final_score DESC, timestamp DESC"
+ " LIMIT %s"
+ )
+ args.append(limit)
+
+ return execQuery(query, args)
+
+
+# Returns test case IDs corresponding to the names in test_case_filter.
+def getTestCaseIdsFromFilter(test_case_filter):
+ return (execQuery(
+ "SELECT id FROM testCase"
+ " WHERE value IN (%s" + ", %s"*(len(test_case_filter) - 1) + ")",
+ tuple(test_case_filter))
+ if ((test_case_filter != None) and (len(test_case_filter) > 0))
+ else ())
+
+
+class GetTopChanges:
+
+ def __init__(
+ self, test_case_filter, regressions, last, timescope, premature, limit):
+ self.test_case_filter = test_case_filter
+ self.regressions = regressions
+ self.last = last
+ self.timescope = timescope
+ self.premature = premature
+ self.limit = limit
+
+
+ # Gets the top changes for a specific context.
+ def getTopChangesForContext(
+ self, host_id, platform_id, branch_id, lo_timestamp):
+
+ test_case_ids = getTestCaseIdsFromFilter(self.test_case_filter)
+
+ return (
+ getTopChangesForContext_last(
+ host_id, platform_id, branch_id, self.regressions,
+ self.premature, self.limit, test_case_ids)
+ if self.last else
+ getTopChangesForContext_timeScope(
+ host_id, platform_id, branch_id, self.regressions,
+ self.premature, self.limit, test_case_ids, lo_timestamp)
+ )
+
+
+ # Gets the top changes for all contexts.
+ def getTopChangesForAllContexts(self):
+
+ # Compute lowest timestamp (secs since 1970) in time scope (days ago):
+ curr_timestamp = calendar.timegm(time.gmtime())
+ secs_in_day = 24 * 60 * 60
+ lo_timestamp = (
+ -1 if (self.timescope < 0) else
+ curr_timestamp - self.timescope * secs_in_day)
+
+ context_ids = execQuery(
+ "SELECT DISTINCT hostId, platformId, branchId FROM context "
+ "ORDER BY hostId, platformId, branchId", ())
+
+ contexts = []
+
+ for host_id, platform_id, branch_id in context_ids:
+ top_changes = self.getTopChangesForContext(
+ host_id, platform_id, branch_id, lo_timestamp)
+ contexts.append({
+ "hostId": host_id,
+ "platformId": platform_id,
+ "branchId": branch_id,
+ "topchanges": top_changes
+ })
+
+ return contexts
+
+
+ def execute(self):
+ self.contexts = self.getTopChangesForAllContexts()
+ self.writeOutput()
+
+
+ def writeOutputAsJSON(self):
+ printJSONHeader()
+ json.dump({
+ 'database': database(),
+ 'regressions': self.regressions,
+ 'last': self.last,
+ 'timescope': self.timescope,
+ 'premature': self.premature,
+ 'limit': self.limit,
+ 'contexts': self.contexts
+ }, sys.stdout)
+
+
+class GetTopChangesAsJSON(GetTopChanges):
+ def writeOutput(self):
+ self.writeOutputAsJSON()