commit
4aa1eef586
@ -1,4 +1,5 @@
|
|||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
|
var d3 = require('d3');
|
||||||
|
|
||||||
var MAX_HISTORY = 1008;
|
var MAX_HISTORY = 1008;
|
||||||
var MAX_PEER_PROPAGATION = 36;
|
var MAX_PEER_PROPAGATION = 36;
|
||||||
@ -128,23 +129,34 @@ History.prototype.getBlockPropagation = function()
|
|||||||
{
|
{
|
||||||
var propagation = [];
|
var propagation = [];
|
||||||
|
|
||||||
var sorted = _(this._items)
|
_.forEach(this._items, function(n, key)
|
||||||
.sortByOrder('height', false)
|
{
|
||||||
.slice(0, MAX_BLOCK_PROPAGATION)
|
_.forEach(n.propagTimes, function(p, i)
|
||||||
.reverse()
|
|
||||||
.forEach(function(n, key)
|
|
||||||
{
|
{
|
||||||
_.forEach(n.propagTimes, function(p, i)
|
var prop = _.result(p, 'propagation', -1);
|
||||||
{
|
|
||||||
var prop = _.result(p, 'propagation', -1);
|
|
||||||
|
|
||||||
if(prop >= 0)
|
if(prop >= 0)
|
||||||
propagation.push(prop);
|
propagation.push(prop);
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
.value();
|
|
||||||
|
|
||||||
return propagation;
|
var x = d3.scale.linear()
|
||||||
|
.domain([0, 20000])
|
||||||
|
.interpolate(d3.interpolateRound);
|
||||||
|
|
||||||
|
var data = d3.layout.histogram()
|
||||||
|
.frequency(false)
|
||||||
|
.bins(x.ticks(MAX_BINS))
|
||||||
|
(propagation);
|
||||||
|
|
||||||
|
var freqCum = 0;
|
||||||
|
var histo = data.map(function(val) {
|
||||||
|
freqCum += val.length;
|
||||||
|
var cumPercent = (freqCum / Math.max(1, propagation.length));
|
||||||
|
return {x: val.x, dx: val.dx, y: val.y, frequency: val.length, cumulative: freqCum, cumpercent: cumPercent};
|
||||||
|
});
|
||||||
|
|
||||||
|
return histo;
|
||||||
}
|
}
|
||||||
|
|
||||||
History.prototype.history = function()
|
History.prototype.history = function()
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"body-parser": "1.12.3",
|
"body-parser": "1.12.3",
|
||||||
|
"d3": "^3.5.5",
|
||||||
"debug": "2.1.3",
|
"debug": "2.1.3",
|
||||||
"express": "4.12.3",
|
"express": "4.12.3",
|
||||||
"geoip-lite": "1.1.6",
|
"geoip-lite": "1.1.6",
|
||||||
|
@ -184,7 +184,7 @@ div.small-title-miner {
|
|||||||
|
|
||||||
.page-latency {
|
.page-latency {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 400px;
|
top: 395px;
|
||||||
left: 15px;
|
left: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +239,7 @@ table td.peerPropagationChart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.th-nodetype {
|
.th-nodetype {
|
||||||
width: 200px;
|
width: 220px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.th-latency {
|
.th-latency {
|
||||||
@ -302,8 +302,7 @@ table td.peerPropagationChart {
|
|||||||
padding: 5px 0;
|
padding: 5px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jqsfield .tooltip-arrow,
|
.jqsfield .tooltip-arrow {
|
||||||
.d3-tip .tooltip-arrow {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
@ -312,7 +311,8 @@ table td.peerPropagationChart {
|
|||||||
border-top-color: #fff;
|
border-top-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datamaps-hoverover .tooltip-arrow {
|
.datamaps-hoverover .tooltip-arrow,
|
||||||
|
.d3-tip .tooltip-arrow {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -5px;
|
top: -5px;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
@ -321,6 +321,11 @@ table td.peerPropagationChart {
|
|||||||
border-bottom-color: #fff;
|
border-bottom-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.d3-tip .tooltip-arrow {
|
||||||
|
top: 0px;
|
||||||
|
left: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
.hoverinfo {
|
.hoverinfo {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
@ -33,7 +33,7 @@ function StatsCtrl($scope, $filter, socket, _, toastr) {
|
|||||||
|
|
||||||
$scope.orderTable = function(predicate, reverse)
|
$scope.orderTable = function(predicate, reverse)
|
||||||
{
|
{
|
||||||
if(predicate != $scope.predicate)
|
if(!_.isEqual(predicate, $scope.predicate))
|
||||||
{
|
{
|
||||||
$scope.reverse = reverse;
|
$scope.reverse = reverse;
|
||||||
$scope.predicate = predicate;
|
$scope.predicate = predicate;
|
||||||
|
@ -121,18 +121,15 @@ angular.module('netStatsApp.directives', []).
|
|||||||
|
|
||||||
var tip = d3.tip()
|
var tip = d3.tip()
|
||||||
.attr('class', 'd3-tip')
|
.attr('class', 'd3-tip')
|
||||||
.offset([-10, 0])
|
.offset([10, 0])
|
||||||
|
.direction('s')
|
||||||
.html(function(d) {
|
.html(function(d) {
|
||||||
return '<div class="tooltip-arrow"></div><div class="tooltip-inner"><b>' + (d.x/1000) + 's - ' + ((d.x + d.dx)/1000) + 's</b>: ' + Math.round(d.y * 100) + "%" + "</div>";
|
return '<div class="tooltip-arrow"></div><div class="tooltip-inner"><b>' + (d.x/1000) + 's - ' + ((d.x + d.dx)/1000) + 's</b><div class="small">Percent: <b>' + Math.round(d.y * 100) + '%</b>' + '<br>Frequency: <b>' + d.frequency + '</b><br>Cumulative: <b>' + Math.floor(d.cumpercent*100) + '%</b></div></div>';
|
||||||
})
|
})
|
||||||
|
|
||||||
scope.init = function()
|
scope.init = function()
|
||||||
{
|
{
|
||||||
// Init data
|
var data = scope.data;
|
||||||
var data = d3.layout.histogram()
|
|
||||||
.frequency(false)
|
|
||||||
.bins(x.ticks(TICKS))
|
|
||||||
(scope.data);
|
|
||||||
|
|
||||||
// Adjust y axis
|
// Adjust y axis
|
||||||
y.domain([0, d3.max(data, function(d) { return d.y; })]);
|
y.domain([0, d3.max(data, function(d) { return d.y; })]);
|
||||||
@ -198,8 +195,6 @@ angular.module('netStatsApp.directives', []).
|
|||||||
.attr("d", line(data));
|
.attr("d", line(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.init();
|
|
||||||
|
|
||||||
scope.$watch('data', function() {
|
scope.$watch('data', function() {
|
||||||
scope.init();
|
scope.init();
|
||||||
}, true);
|
}, true);
|
||||||
|
@ -42,6 +42,22 @@ angular.module('netStatsApp.filters', [])
|
|||||||
return (! mining ? 'icon-cancel' : 'icon-check');
|
return (! mining ? 'icon-cancel' : 'icon-check');
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
.filter('hashpowerClass', function() {
|
||||||
|
return function(mining) {
|
||||||
|
if(! mining)
|
||||||
|
return 'text-gray';
|
||||||
|
|
||||||
|
return 'text-success';
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter('hashrateFilter', function() {
|
||||||
|
return function(hashrate) {
|
||||||
|
if(typeof hashrate === 'undefined' || !hashrate)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return hashrate/1000;
|
||||||
|
}
|
||||||
|
})
|
||||||
.filter('nodeVersion', function($sce) {
|
.filter('nodeVersion', function($sce) {
|
||||||
return function(version) {
|
return function(version) {
|
||||||
if(typeof version !== 'undefined')
|
if(typeof version !== 'undefined')
|
||||||
|
@ -116,6 +116,8 @@ block content
|
|||||||
i.icon-clock(data-toggle="tooltip", data-placement="top", title="Node latency", ng-click="orderTable(['-stats.active', 'stats.latency'], false)")
|
i.icon-clock(data-toggle="tooltip", data-placement="top", title="Node latency", ng-click="orderTable(['-stats.active', 'stats.latency'], false)")
|
||||||
th
|
th
|
||||||
i.icon-mining(data-toggle="tooltip", data-placement="top", title="Is mining", ng-click="orderTable(['-stats.active', '-stats.mining'], false)")
|
i.icon-mining(data-toggle="tooltip", data-placement="top", title="Is mining", ng-click="orderTable(['-stats.active', '-stats.mining'], false)")
|
||||||
|
th
|
||||||
|
i.icon-mining(data-toggle="tooltip", data-placement="top", title="Hashrate", ng-click="orderTable(['-stats.active', '-stats.mining', '-stats.hashrate'], false)")
|
||||||
th
|
th
|
||||||
i.icon-group(data-toggle="tooltip", data-placement="top", title="Peers", ng-click="orderTable(['-stats.active', '-stats.peers'], false)")
|
i.icon-group(data-toggle="tooltip", data-placement="top", title="Peers", ng-click="orderTable(['-stats.active', '-stats.peers'], false)")
|
||||||
th
|
th
|
||||||
@ -139,10 +141,12 @@ block content
|
|||||||
span.small #[ ]({{node.info.ip}})
|
span.small #[ ]({{node.info.ip}})
|
||||||
td
|
td
|
||||||
div.small(ng-bind-html="node.info.node | nodeVersion")
|
div.small(ng-bind-html="node.info.node | nodeVersion")
|
||||||
//- div.small {{node.info.os}}, {{node.info.os_v}}
|
td(class="{{ node.stats | latencyClass }}")
|
||||||
td.small(class="{{ node.stats | latencyClass }}") {{node.stats | latencyFilter}}
|
span.small {{node.stats | latencyFilter}}
|
||||||
td(class="{{ node.stats.mining | miningClass : node.stats.active }}")
|
td(class="{{ node.stats.mining | miningClass : node.stats.active }}")
|
||||||
i(class="{{ node.stats.mining | miningIconClass }}")
|
i(class="{{ node.stats.mining | miningIconClass }}")
|
||||||
|
td(class="{{ node.stats.mining | hashpowerClass }}")
|
||||||
|
span.small {{node.stats.hashrate | hashrateFilter}} kH/s
|
||||||
td(class="{{ node.stats.peers | peerClass : node.stats.active }}", style="padding-left: 11px;") {{node.stats.peers}}
|
td(class="{{ node.stats.peers | peerClass : node.stats.active }}", style="padding-left: 11px;") {{node.stats.peers}}
|
||||||
td(style="padding-left: 15px;") {{node.stats.pending}}
|
td(style="padding-left: 15px;") {{node.stats.pending}}
|
||||||
td(class="{{ node.stats | blockClass : bestBlock }}") {{'#'}}{{ node.stats.block.number | number }}
|
td(class="{{ node.stats | blockClass : bestBlock }}") {{'#'}}{{ node.stats.block.number | number }}
|
||||||
|
Loading…
Reference in New Issue
Block a user