Starting to construct the Summary dashboard

This commit is contained in:
Gaël Métais
2014-09-01 19:46:05 +02:00
parent 2570033791
commit 1570a4ce92
3 changed files with 169 additions and 31 deletions
+23 -2
View File
@@ -35,6 +35,24 @@
<div ng-show="view == 'summary' && !phantomasResults.error" class="summary">
<h2>Summary</h2>
<div class="notations">
<div>
<div ng-class="notations.domComplexity">{{notations.domComplexity}}</div>
<div>DOM size</div>
</div>
<div>
<div ng-class="notations.domManipulations">{{notations.domManipulations}}</div>
<div>DOM read and write Requests</div>
</div>
<div>
<div ng-class="notations.duplicatedDomQueries">{{notations.duplicatedDomQueries}}</div>
<div>Duplicated DOM queries</div>
</div>
</div>
<div>Javascript manipulation time: {{totalJSTime}} ms</div>
<div>Javascript onDOMReady time: {{phantomasResults.metrics.domContentLoadedEnd - phantomasResults.metrics.domContentLoaded}} ms</div>
<div>Scripts count: {{phantomasResults.metrics.jsCount}}</div>
@@ -42,6 +60,7 @@
<div>DOM max depth: {{phantomasResults.metrics.DOMelementMaxDepth}}</div>
<div>DOM queries: {{phantomasResults.metrics.DOMqueries}}</div>
<div>DOM inserts: {{phantomasResults.metrics.DOMinserts}}</div>
<div>Duplicated DOM queries: {{phantomasResults.metrics.DOMqueriesDuplicated}}</div>
<div>Events bound: {{phantomasResults.metrics.eventsBound}}</div>
<div>document.write() calls: {{phantomasResults.metrics.documentWriteCalls}}</div>
<div>eval calls: {{phantomasResults.metrics.evalCalls}}</div>
@@ -74,6 +93,7 @@
<div>Params</div>
<div><!-- details --></div>
<div>Duration</div>
<div>Start time</div>
</div>
<div ng-repeat="node in javascript.children"
ng-if="(!slowRequestsOn || node.data.time > slowRequestsLimit)
@@ -163,20 +183,21 @@
<div ng-if="node.data.time > slowRequestsLimit" class="warningIcon" title="Slower than {{slowRequestsLimit}} ms"></div>
</div>
<div class="duration" ng-if="node.data.time == undefined"></div>
<div class="startTime">{{node.data.timestamp}}</div>
</div>
</div>
</div>
<div ng-show="view == 'metrics' && !phantomasResults.error" class="metrics">
<h2>Metrics from Phantomas report</h2>
<p>Phantomas is a web performance metrics collector. You can it find <a href="https://github.com/macbre/phantomas" target="_blank">here</a>.</p>
<p><a href="https://github.com/macbre/phantomas" target="_blank">Phantomas</a> is a web performance metrics collector. You can find here the (almost) entire list of metrics from Phantomas.</p>
<div ng-repeat="(moduleName, module) in metricsModule">
<h4>{{moduleName}}</h4>
<div ng-repeat="(metricName, metric) in module" ng-if="phantomasResults.metrics[metricName] >= 0" class="module" id="metric_{{metricName}}">
<div class="value">
{{metricName}}: {{phantomasResults.metrics[metricName]}}
<span ng-if="metric.unit == 'ms' || metric.unit == 'bytes'">{{metric.unit}}</span>
<span ng-if="metric.unit == 'ms' || metric.unit == 'bytes' || metric.unit == '%'">{{metric.unit}}</span>
</div>
<div class="legend">
{{metric.desc}}
+95 -29
View File
@@ -6,39 +6,15 @@ app.controller('ResultsCtrl', function ($scope) {
$scope.phantomasMetadata = window._phantomas_metadata.metrics;
$scope.view = 'summary';
$scope.slowRequestsOn = false;
$scope.slowRequestsLimit = 5;
if ($scope.phantomasResults.offenders && $scope.phantomasResults.offenders.javascriptExecutionTree) {
if ($scope.phantomasResults.metrics && $scope.phantomasResults.offenders && $scope.phantomasResults.offenders.javascriptExecutionTree) {
// Get the execution tree from the offenders
$scope.javascript = JSON.parse($scope.phantomasResults.offenders.javascriptExecutionTree);
// Read the main elements of the tree and sum the total time
$scope.totalJSTime = 0;
treeRunner($scope.javascript, function(node) {
if (node.data.time) {
$scope.totalJSTime += node.data.time;
}
if (node.data.type !== 'main') {
// Don't check the children
return false;
}
});
}
if ($scope.phantomasResults.metrics && $scope.phantomasResults.offenders) {
// Get the Phantomas modules from metadata
$scope.metricsModule = {};
for (var metricName in $scope.phantomasMetadata) {
var metric = $scope.phantomasMetadata[metricName];
if (!$scope.metricsModule[metric.module]) {
$scope.metricsModule[metric.module] = {};
}
$scope.metricsModule[metric.module][metricName] = metric;
}
initSummaryView();
initExecutionView();
initMetricsView();
}
@@ -63,6 +39,96 @@ app.controller('ResultsCtrl', function ($scope) {
node.data.showDetails = !isOpen;
};
function initSummaryView() {
// Read the main elements of the tree and sum the total time
$scope.totalJSTime = 0;
treeRunner($scope.javascript, function(node) {
if (node.data.time) {
$scope.totalJSTime += node.data.time;
}
if (node.data.type !== 'main') {
// Don't check the children
return false;
}
});
$scope.notations = {
domComplexity: 'A',
domManipulations: 'A',
duplicatedDomQueries: 'A'
};
var domComplexityScore = $scope.phantomasResults.metrics.DOMelementsCount;
if (domComplexityScore > 500) {
$scope.notations.domComplexity = 'B';
}
if (domComplexityScore > 1000) {
$scope.notations.domComplexity = 'C';
}
if (domComplexityScore > 1500) {
$scope.notations.domComplexity = 'D';
}
if (domComplexityScore > 2000) {
$scope.notations.domComplexity = 'E';
}
if (domComplexityScore > 3000) {
$scope.notations.domComplexity = 'F';
}
var domManipulationsScore = $scope.phantomasResults.metrics.DOMinserts + $scope.phantomasResults.metrics.DOMqueries * 0.5 + $scope.totalJSTime;
if (domManipulationsScore > 50) {
$scope.notations.domManipulations = 'B';
}
if (domManipulationsScore > 100) {
$scope.notations.domManipulations = 'C';
}
if (domManipulationsScore > 200) {
$scope.notations.domManipulations = 'D';
}
if (domManipulationsScore > 500) {
$scope.notations.domManipulations = 'E';
}
if (domManipulationsScore > 1000) {
$scope.notations.domManipulations = 'F';
}
var duplicatedDomQueries = $scope.phantomasResults.metrics.DOMqueriesDuplicated;
if (duplicatedDomQueries > 5) {
$scope.notations.duplicatedDomQueries = 'B';
}
if (duplicatedDomQueries > 10) {
$scope.notations.duplicatedDomQueries = 'C';
}
if (duplicatedDomQueries > 20) {
$scope.notations.duplicatedDomQueries = 'D';
}
if (duplicatedDomQueries > 50) {
$scope.notations.duplicatedDomQueries = 'E';
}
if (duplicatedDomQueries > 100) {
$scope.notations.duplicatedDomQueries = 'F';
}
}
function initExecutionView() {
$scope.slowRequestsOn = false;
$scope.slowRequestsLimit = 5;
}
function initMetricsView() {
// Get the Phantomas modules from metadata
$scope.metricsModule = {};
for (var metricName in $scope.phantomasMetadata) {
var metric = $scope.phantomasMetadata[metricName];
if (!$scope.metricsModule[metric.module]) {
$scope.metricsModule[metric.module] = {};
}
$scope.metricsModule[metric.module][metricName] = metric;
}
}
function parseBacktrace(str) {
if (!str) {
return null;
+51
View File
@@ -40,6 +40,56 @@ h4 {
text-align: left;
}
.notations {
display: table;
width: 25em;
margin: 0 auto;
border-spacing: 0.5em;
}
.notations > div {
display: table-row;
}
.notations > div > div {
display: table-cell;
height: 2.5em;
vertical-align: middle;
font-weight: bold;
}
.notations .A, .notations .B, .notations .C, .notations .D, .notations .E, .notations .F, .notations .NA {
width: 2.5em;
font-size: 2em;
text-align: center;
border-radius: 0.5em;
}
.notations .A {
/* green */
background: #00DB61;
}
.notations .B {
/* green */
background: #CAD63D;
}
.notations .C {
/* yellow */
background: #FFD119;
}
.notations .D {
/* orange */
background: #FFA319;
}
.notations .E {
/* red */
background: #FF6600;
}
.notations .F {
/* red */
background: #FF1919;
}
.notations .NA {
/* Non applicable */
background: #CCC;
}
.metrics h4 {
padding-left: 2em;
@@ -155,6 +205,7 @@ input.textFilter {
right: 3em;
top: -3em;
width: 45em;
min-height: 1em;
padding: 0 1em 1em;
background: #fff;
border: 2px solid #f1c40f;