Make it possible to trigger benchmarks of particular benchmarks

This commit is contained in:
Hannes Verschore 2015-11-12 08:22:06 -08:00
Родитель 5ed59a936d
Коммит a5f6b333c0
13 изменённых файлов: 3474 добавлений и 93 удалений

Просмотреть файл

@ -0,0 +1,40 @@
<?php
/* 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/. */
require_once("DB.php");
require_once("Build.php");
class Regression extends DB {
public static $db = "awfy_regression";
public function __construct($id) {
$this->id = $id;
}
function bug() {
return $this->select("bug");
}
function status() {
return $this->select("status");
}
function build_id() {
return $this->select("build_id");
}
function build() {
return Build::FromId($this->build_id());
}
function prev_build_id() {
return $this->select("prev_build_id");
}
function prev_build() {
return Build::FromId($this->prev_build_id());
}
}

Просмотреть файл

@ -72,6 +72,14 @@ class Run extends DB {
return $this->select("approx_stamp");
}
public function finish_stamp() {
return $this->select("finish_stamp");
}
public function detector() {
return $this->select("detector");
}
public function builds() {
$qRun = mysql_query("SELECT approx_stamp from awfy_builds
WHERE id = {$this->id}") or die(mysql_error());

Просмотреть файл

@ -1,10 +1,14 @@
<?php
require_once("VersionControl/HGWeb.php");
require_once("DB/Mode.php");
require_once("DB/Vendor.php");
class VersionControl {
public function forMode($mode_id) {
$mode = new Mode($mode_id);
$vendor = new Vendor($mode->vendor_id());
$mode = Mode::FromId($mode_id);
$vendor = Vendor::FromId($mode->vendor_id());
$url = $vendor->csetURL();
if (strpos($url, "hg.mozilla.org") !== false)
@ -12,31 +16,4 @@ class VersionControl {
throw new Exception("Not implemented version control system.");
}
}
class HGWeb {
public function __construct($url) {
$this->url = str_replace("/rev/", "/", $url);
}
public function equal($revision1, $revision2) {
return $revision1 == $revision2;
}
public function isAfter($revision1, $revision2) {
// test if is before
$html = file_get_contents($this->url."pushloghtml?fromchange=$revision1&tochange=$revision2");
if (strpos($html, "pushlogentry") !== false)
return false;
// test if is after
$html = file_get_contents($this->url."pushloghtml?fromchange=$revision2&tochange=$revision1");
if (strpos($html, "pushlogentry") !== false)
return true;
throw new Exception("Couldn't find relationship between $revision1 and $revision2.");
}
}

Просмотреть файл

@ -0,0 +1,48 @@
<?php
require_once("Revision.php");
class HGWeb {
public function __construct($url) {
$this->url = str_replace("/rev/", "/", $url);
}
public function equal($revision1, $revision2) {
return $revision1 == $revision2;
}
public function isAfter($revision1, $revision2) {
// test if is before
$html = file_get_contents($this->url."pushloghtml?fromchange=$revision1&tochange=$revision2");
if (strpos($html, "pushlogentry") !== false)
return false;
// test if is after
$html = file_get_contents($this->url."pushloghtml?fromchange=$revision2&tochange=$revision1");
if (strpos($html, "pushlogentry") !== false)
return true;
throw new Exception("Couldn't find relationship between $revision1 and $revision2.");
}
public function revisions($from, $to) {
$html = file_get_contents($this->url."pushloghtml?fromchange=$from&tochange=$to");
preg_match_all('#<tr class="pushlogentry .*"><td>(<cite>(.*)<br/><span class="date">(.*)</span></cite>)*</td><td class="age"><a href="/integration/mozilla-inbound/rev/.*">(.*)</a></td><td><strong>(.*) &mdash; (.*)</td></tr>#', $html, $matches);
$revisions = Array();
$prev_date = "";
for ($i = 0; $i < count($matches[0]); $i++) {
$date = empty($matches[3][$i]) ? $prev_date : $matches[3][$i];
$revision = $matches[4][$i];
$author = $matches[5][$i];
$message = $matches[6][$i];
$message = strip_tags($message);
$revisions[] = new Revision($author, $date, $revision, $message);
$prev_date = $date;
}
return $revisions;
}
}

Просмотреть файл

@ -0,0 +1,25 @@
<?php
class Revision {
public function __construct($author, $date, $revision, $message) {
$this->author = $author;
$this->date = $date;
$this->revision = $revision;
$this->message = $message;
}
public function author() {
return $this->author;
}
public function date() {
return $this->date;
}
public function revision() {
return $this->revision;
}
public function message() {
return $this->message;
}
}

Просмотреть файл

@ -348,9 +348,10 @@ html, body {
padding-left: 6px;
padding-right: 6px; }
.regression .status .stamp, .regression .status .name {
white-space: nowrap; }
white-space: nowrap;
color: #484848; }
.regression .status .extra {
width: 75%; }
width: 90%; }
.regression .status .extra input[type=text] {
width: 85%; }
.regression .range iframe {
@ -374,6 +375,11 @@ html, body {
padding-top: 6px;
padding-bottom: 12px;
margin-right: 6px; }
.regression .inline_regression table {
width: 100%; }
.regression .inline_regression td, .regression .inline_regression th {
background-color: white;
padding: 6px; }
.box {
border-collapse: separate;

Просмотреть файл

@ -0,0 +1,38 @@
<?php
/* 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/. */
require_once("../internals.php");
require_once("../lib/DB/Regression.php");
require_once("../lib/VersionControl.php");
init_database();
$postdata = file_get_contents("php://input");
$request = json_decode($postdata);
$id = (int)$request->id;
$regression = Regression::FromId($id);
$build = $regression->build() or throw_exception("Couldn't retrieve the build of regression $id.");
$prev_build = $regression->prev_build() or throw_exception("Couldn't retrieve the prev_build of regression $id.");
$regression->build()->revision();
$regression->prev_build()->revision();
$versionControl = VersionControl::forMode($build->mode_id());
$revisions = $versionControl->revisions($prev_build->revision(), $build->revision());
$data = Array();
foreach ($revisions as $revision) {
$data[] = Array(
"author" => $revision->author,
"date" => $revision->date,
"revision" => $revision->revision,
"message" => $revision->message
);
}
echo json_encode($data);

Просмотреть файл

@ -4,10 +4,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
require_once("../internals.php");
require_once("data-func.php");
require_once("../lib/RetriggerController.php");
init_database();
require_once("data-func.php");
require_once("../lib/RetriggerController.php");
require_once("../lib/DB/Regression.php");
$postdata = file_get_contents("php://input");
$request = json_decode($postdata);
@ -24,33 +27,35 @@ $minimal = isset($request->minimal) ? !!$request->minimal : false;
$data = array();
for ($i=0; $i < count($ids); $i++) {
$db_regression = Regression::FromId($ids[$i]);
if (!$db_regression) {
$data[] = Array();
continue;
}
$db_build = $db_regression->build();
$db_run = $db_build->run();
$db_prev_build = $db_regression->prev_build();
$query = mysql_query("SELECT awfy_regression.id, machine, mode_id, awfy_run.finish_stamp,
build_id, prev_build_id, cset, bug, awfy_regression.status, detector,
awfy_run.id as run_id
FROM awfy_regression
INNER JOIN awfy_build ON build_id = awfy_build.id
INNER JOIN awfy_run ON run_id = awfy_run.id
WHERE awfy_regression.id = ".$ids[$i]."
LIMIT 1") or die(mysql_error());
$output = mysql_fetch_assoc($query);
$regression = array(
"id" => $output["id"],
"machine" => $output["machine"],
"mode" => $output["mode_id"],
"stamp" => $output["finish_stamp"],
"cset" => $output["cset"],
"bug" => $output["bug"],
"status" => $output["status"],
"build_id" => $output["build_id"],
"detector" => $output["detector"],
"run_id" => $output["run_id"],
"prev_run_id" => get("build", $output["prev_build_id"], "run_id"),
"id" => $db_regression->id,
"machine" => $db_run->machine_id(),
"mode" => $db_build->mode_id(),
"stamp" => $db_run->finish_stamp(),
"cset" => $db_build->revision(),
"bug" => $db_regression->bug(),
"status" => $db_regression->status(),
"build_id" => $db_build->id,
"detector" => $db_run->detector(),
"run_id" => $db_run->id,
"prev_run_id" => $db_prev_build->run_id(),
"scores" => array(),
"retriggerable" => RetriggerController::retriggerable($output["machine"], $output["mode_id"])
"retriggerable" => RetriggerController::retriggerable($db_run->machine_id(),
$db_build->mode_id())
);
$qScores = mysql_query("SELECT * FROM awfy_regression_score
WHERE regression_id = '".$output["id"]."'") or die(mysql_error());
WHERE regression_id = '".$regression["id"]."'") or die(mysql_error());
while ($scores = mysql_fetch_assoc($qScores)) {
$suite_version_id = get("score", $scores["score_id"], "suite_version_id");
$score = array(
@ -60,24 +65,21 @@ for ($i=0; $i < count($ids); $i++) {
"noise" => $scores["noise"]
);
//if (!$minimal) { // minimal outdated. Used to be slow. Not anymore.
if ($output["prev_build_id"] && !$minimal) {
$qPrevScore = mysql_query("SELECT score
FROM awfy_score
WHERE build_id = ".$output["prev_build_id"]." AND
suite_version_id = ".$suite_version_id."
LIMIT 1") or die(mysql_error());
if (mysql_num_rows($qPrevScore) == 1) {
$prevScore = mysql_fetch_assoc($qPrevScore);
$score["prev_score"] = $prevScore["score"];
$score["prev_cset"] = get("build", $output["prev_build_id"], "cset");
}
}
$qPrevScore = mysql_query("SELECT score
FROM awfy_score
WHERE build_id = ".$db_prev_build->id." AND
suite_version_id = ".$suite_version_id."
LIMIT 1") or die(mysql_error());
if (mysql_num_rows($qPrevScore) == 1) {
$prevScore = mysql_fetch_assoc($qPrevScore);
$score["prev_score"] = $prevScore["score"];
$score["prev_cset"] = $db_prev_build->revision();
}
$regression["scores"][] = $score;
}
$qScores = mysql_query("SELECT * FROM awfy_regression_breakdown
WHERE regression_id = '".$output["id"]."'") or die(mysql_error());
WHERE regression_id = '".$db_regression->id."'") or die(mysql_error());
while ($scores = mysql_fetch_assoc($qScores)) {
$suite_test_id = get("breakdown", $scores["breakdown_id"], "suite_test_id");
$suite_version_id = get("suite_test", $suite_test_id, "suite_version_id");
@ -89,26 +91,23 @@ for ($i=0; $i < count($ids); $i++) {
"noise" => $scores["noise"]
);
//if (!$minimal) { // minimal outdated. Used to be slow. Not anymore.
if ($output["prev_build_id"] && !$minimal) {
$qPrevScore = mysql_query("SELECT awfy_breakdown.score
FROM awfy_breakdown
LEFT JOIN awfy_score ON score_id = awfy_score.id
WHERE awfy_score.build_id = ".$output["prev_build_id"]." AND
suite_test_id = ".$suite_test_id."
LIMIT 1") or die(mysql_error());
if (mysql_num_rows($qPrevScore) == 1) {
$prevScore = mysql_fetch_assoc($qPrevScore);
$score["prev_score"] = $prevScore["score"];
$score["prev_cset"] = get("build", $output["prev_build_id"], "cset");
}
}
$qPrevScore = mysql_query("SELECT awfy_breakdown.score
FROM awfy_breakdown
LEFT JOIN awfy_score ON score_id = awfy_score.id
WHERE awfy_score.build_id = ".$db_prev_build->id." AND
suite_test_id = ".$suite_test_id."
LIMIT 1") or die(mysql_error());
if (mysql_num_rows($qPrevScore) == 1) {
$prevScore = mysql_fetch_assoc($qPrevScore);
$score["prev_score"] = $prevScore["score"];
$score["prev_cset"] = $db_prev_build->revision();
}
$regression["scores"][] = $score;
}
if (!$minimal) {
$qStatus = mysql_query("SELECT * FROM awfy_regression_status
WHERE regression_id = '".$output["id"]."'
WHERE regression_id = '".$db_prev_build->id."'
ORDER BY stamp DESC
LIMIT 1") or die(mysql_error());
$status = mysql_fetch_assoc($qStatus);

Просмотреть файл

@ -18,6 +18,7 @@
<script src="js/angular-ui.js"></script>
<script src="https://login.persona.org/include.js"></script>
<script src="js/persona.js"></script>
<script src="js/moment.js"></script>
<script type="text/javascript" src="js/ng-google-chart.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>

Просмотреть файл

@ -20,6 +20,12 @@ awfyCtrl.filter('linkify', function($sce, $parse) {
};
})
awfyCtrl.filter('fromNow', function() {
return function(dateString) {
return moment.unix(dateString/1000).fromNow()
};
});
awfyCtrl.controller('addCtrl', ['$scope', '$http', '$routeParams', 'RegressionService', '$location',
function ($scope, $http, $routeParams, regression, $location) {
var data = {};
@ -63,6 +69,11 @@ awfyCtrl.controller('regressionCtrl', ['$scope', '$http', '$routeParams', '$q',
}
$scope.noise = noise
updateNoiseCount();
$scope.regression.range = undefined
$http.post('data-regression-range.php', {id:regression_id}).then(function(data){
$scope.regression.range = data.data
});
});
$scope.statusPopup = function(regression) {
@ -95,11 +106,11 @@ awfyCtrl.controller('regressionCtrl', ['$scope', '$http', '$routeParams', '$q',
modalDialog.open("partials/bug.html", regression);
}
$scope.showRetriggerPopup = function(regression) {
$scope.showRetriggerPopup = function(regression, cset) {
var retrigger = {
"machine": regression.machine,
"mode": regression.mode,
"cset": regression.cset,
"cset": cset,
"suites": [],
"submit": function() {
var benchmarks = [];

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -54,26 +54,35 @@
<span ng-if="regression.detector==0">No (new regression might still get detected in the future.)</span>
</td></tr>
<tr class='retriggerable' ng-if='regression.retriggerable'><th>Retrigger</th><td>
<a class='link' ng-click='showRetriggerPopup(regression)'>Click here to re-run the benchmarks.</a>
<a class='link' ng-click='showRetriggerPopup(regression, regression.cset)'>Click here to re-run the benchmarks.</a>
</td></tr>
</table>
</div>
<div class='info'>
<div ng-if='obsolete'>
This regression report is possibly obsolete. More specific revisions have been triggered and finished. Please annotate/report the more specific regression and mark this as obsolete.
</div>
</div>
<div class='status'>
<span class="add" ng-if="currentUser&&!addComment" ng-click="addCommentFn()">&#xe081;</span>
<table class='box'>
<tr ng-if="addComment">
<td class='stamp'></td>
<td class='name'>{{currentUser}}</td>
<td class='extra'>
<input type='text' ng-model='newcomment'>
<input type='button' value='Save' ng-click='saveCommentFn(newcomment)'>
</td>
</tr>
<tr ng-repeat="status in states">
<td class='stamp'>{{status.stamp | date:'dd MMM yy HH:mm'}}</td>
<td class='name'>{{status.name}}</td>
<td class='extra' ng-bind-html="status.extra | linkify"></td>
<td class='stamp' ng-attr-title='{{status.stamp | date:"dd MMM yy HH:mm"}}'>
{{status.stamp | fromNow}}
</td>
<td class='extra'>
<span ng-bind-html="status.extra | linkify"></span>
- <span class='name'>by {{status.name}}</span>
</td>
</tr>
</table>
</div>
@ -122,7 +131,20 @@
Regression range:
</div>
<div class='content' ng-if='regression.range_url'>
<iframe ng-src='{{regression.range_url}}'></iframe>
<div class='inline_regression' ng-if=regression.retriggerable>
<center ng-if='regression.range == undefined'>- loading -</center>
<table ng-if='regression.range != undefined'>
<tr><th>Push date</th><th>Changeset</th><th>Author</th><th>Commit message</th><th>run</th</tr>
<tr ng-repeat='range in regression.range'>
<td>{{range.date}}</td><td>{{range.revision}}</td>
<td>{{range.author}}</td><td>{{range.message}}</td>
<td>
<a class='link' ng-click='showRetriggerPopup(regression, range.revision)'>run</a>
</td>
</tr>
</table>
</div>
<iframe ng-src='{{regression.range_url}}' ng-if='!regression.retriggerable'></iframe>
</div>
<div class='content' ng-if='!regression.range_url'>
<center>- There are different regression ranges for the different scores. To see the regression range click on a specific score and on the graph click the regressed point. Click on the 'changelog' there. -</center>

Просмотреть файл

@ -46,6 +46,7 @@
.stamp, .name {
white-space: nowrap;
color: lighten($_darkgrey, 15);
}
.extra {
@ -54,7 +55,7 @@
width:85%;
}
width: 75%;
width: 90%;
}
}
@ -94,3 +95,13 @@
margin-right: $unit;
}
}
.inline_regression {
table {
width: 100%;
}
td,th {
background-color: get($_box, bg);
padding: $unit;
}
}