Starting to construct the Summary dashboard
This commit is contained in:
@@ -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}}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user