Fixed stat page erroring when coins were added. Changed default stat update interval to 60 seconds.
This commit is contained in:
parent
201d02d10b
commit
cf74cd4119
|
@ -11,7 +11,7 @@
|
||||||
"port": 80,
|
"port": 80,
|
||||||
"stratumHost": "cryppit.com",
|
"stratumHost": "cryppit.com",
|
||||||
"stats": {
|
"stats": {
|
||||||
"updateInterval": 15,
|
"updateInterval": 60,
|
||||||
"historicalRetention": 43200,
|
"historicalRetention": 43200,
|
||||||
"hashrateWindow": 300,
|
"hashrateWindow": 300,
|
||||||
"redis": {
|
"redis": {
|
||||||
|
|
|
@ -18,8 +18,7 @@ module.exports = function(logger, portalConfig, poolConfigs){
|
||||||
res.end(portalStats.statsString);
|
res.end(portalStats.statsString);
|
||||||
return;
|
return;
|
||||||
case 'pool_stats':
|
case 'pool_stats':
|
||||||
res.writeHead(200, {'content-encoding': 'gzip'});
|
res.end(JSON.stringify(portalStats.statPoolHistory));
|
||||||
res.end(portalStats.statPoolHistoryBuffer);
|
|
||||||
return;
|
return;
|
||||||
case 'live_stats':
|
case 'live_stats':
|
||||||
res.writeHead(200, {
|
res.writeHead(200, {
|
||||||
|
|
|
@ -20,7 +20,6 @@ module.exports = function(logger, portalConfig, poolConfigs){
|
||||||
|
|
||||||
this.statHistory = [];
|
this.statHistory = [];
|
||||||
this.statPoolHistory = [];
|
this.statPoolHistory = [];
|
||||||
this.statPoolHistoryBuffer;
|
|
||||||
|
|
||||||
this.stats = {};
|
this.stats = {};
|
||||||
this.statsString = '';
|
this.statsString = '';
|
||||||
|
@ -84,7 +83,6 @@ module.exports = function(logger, portalConfig, poolConfigs){
|
||||||
_this.statHistory.forEach(function(stats){
|
_this.statHistory.forEach(function(stats){
|
||||||
addStatPoolHistory(stats);
|
addStatPoolHistory(stats);
|
||||||
});
|
});
|
||||||
deflateStatPoolHistory();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +94,7 @@ module.exports = function(logger, portalConfig, poolConfigs){
|
||||||
for (var pool in stats.pools){
|
for (var pool in stats.pools){
|
||||||
data.pools[pool] = {
|
data.pools[pool] = {
|
||||||
hashrate: stats.pools[pool].hashrate,
|
hashrate: stats.pools[pool].hashrate,
|
||||||
workers: stats.pools[pool].workerCount,
|
workerCount: stats.pools[pool].workerCount,
|
||||||
blocks: stats.pools[pool].blocks
|
blocks: stats.pools[pool].blocks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,11 +102,7 @@ module.exports = function(logger, portalConfig, poolConfigs){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function deflateStatPoolHistory(){
|
|
||||||
zlib.gzip(JSON.stringify(_this.statPoolHistory), function(err, buffer){
|
|
||||||
_this.statPoolHistoryBuffer = buffer;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.getGlobalStats = function(callback){
|
this.getGlobalStats = function(callback){
|
||||||
|
|
||||||
|
@ -245,8 +239,6 @@ module.exports = function(logger, portalConfig, poolConfigs){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deflateStatPoolHistory();
|
|
||||||
|
|
||||||
redisStats.multi([
|
redisStats.multi([
|
||||||
['zadd', 'statHistory', statGatherTime, _this.statsString],
|
['zadd', 'statHistory', statGatherTime, _this.statsString],
|
||||||
['zremrangebyscore', 'statHistory', '-inf', '(' + retentionTime]
|
['zremrangebyscore', 'statHistory', '-inf', '(' + retentionTime]
|
||||||
|
|
|
@ -4,11 +4,18 @@
|
||||||
padding: 18px;
|
padding: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#topCharts > div > svg{
|
#topCharts > div > div > svg{
|
||||||
display: block;
|
display: block;
|
||||||
height: 280px;
|
height: 280px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chartWrapper{
|
||||||
|
border: solid 1px #c7c7c7;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 5px;
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
.chartLabel{
|
.chartLabel{
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -16,24 +23,27 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.chartHolder{
|
.chartHolder{
|
||||||
border: solid 1px #c7c7c7;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 5px;
|
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div id="topCharts">
|
<div id="topCharts">
|
||||||
|
|
||||||
|
<div class="chartWrapper">
|
||||||
<div class="chartLabel">Workers Per Pool</div>
|
<div class="chartLabel">Workers Per Pool</div>
|
||||||
<div class="chartHolder"><svg id="poolWorkers"/></div>
|
<div class="chartHolder"><svg id="poolWorkers"/></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chartWrapper">
|
||||||
<div class="chartLabel">Hashrate Per Pool</div>
|
<div class="chartLabel">Hashrate Per Pool</div>
|
||||||
<div class="chartHolder"><svg id="poolHashrate"/></div>
|
<div class="chartHolder"><svg id="poolHashrate"/></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chartWrapper">
|
||||||
<div class="chartLabel">Blocks Pending Per Pool</div>
|
<div class="chartLabel">Blocks Pending Per Pool</div>
|
||||||
<div class="chartHolder"><svg id="poolBlocks"/></div>
|
<div class="chartHolder"><svg id="poolBlocks"/></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,57 @@
|
||||||
var poolWorkerData = [];
|
var poolWorkerData;
|
||||||
var poolHashrateData = [];
|
var poolHashrateData;
|
||||||
var poolBlockData = [];
|
var poolBlockData;
|
||||||
|
|
||||||
var poolWorkerChart;
|
var poolWorkerChart;
|
||||||
var poolHashrateChart;
|
var poolHashrateChart;
|
||||||
var poolBlockChart;
|
var poolBlockChart;
|
||||||
|
|
||||||
function buildChartData(data){
|
var statData;
|
||||||
|
var poolKeys;
|
||||||
|
|
||||||
|
function buildChartData(){
|
||||||
|
|
||||||
var pools = {};
|
var pools = {};
|
||||||
|
|
||||||
for (var i = 0; i < data.length; i++){
|
poolKeys = [];
|
||||||
var time = data[i].time * 1000;
|
for (var i = 0; i < statData.length; i++){
|
||||||
for (var pool in data[i].pools){
|
for (var pool in statData[i].pools){
|
||||||
var a = pools[pool] = (pools[pool] || {
|
if (poolKeys.indexOf(pool) === -1)
|
||||||
|
poolKeys.push(pool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (var i = 0; i < statData.length; i++){
|
||||||
|
|
||||||
|
var time = statData[i].time * 1000;
|
||||||
|
|
||||||
|
for (var f = 0; f < poolKeys.length; f++){
|
||||||
|
var pName = poolKeys[f];
|
||||||
|
var a = pools[pName] = (pools[pName] || {
|
||||||
hashrate: [],
|
hashrate: [],
|
||||||
workers: [],
|
workers: [],
|
||||||
blocks: []
|
blocks: []
|
||||||
});
|
});
|
||||||
a.hashrate.push([time, data[i].pools[pool].hashrate || 0]);
|
if (pName in statData[i].pools){
|
||||||
a.workers.push([time, data[i].pools[pool].workers || 0]);
|
a.hashrate.push([time, statData[i].pools[pName].hashrate]);
|
||||||
a.blocks.push([time, data[i].pools[pool].blocks.pending])
|
a.workers.push([time, statData[i].pools[pName].workerCount]);
|
||||||
|
a.blocks.push([time, statData[i].pools[pName].blocks.pending])
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
a.hashrate.push([time, 0]);
|
||||||
|
a.workers.push([time, 0]);
|
||||||
|
a.blocks.push([time, 0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
poolWorkerData = [];
|
||||||
|
poolHashrateData = [];
|
||||||
|
poolBlockData = [];
|
||||||
|
|
||||||
for (var pool in pools){
|
for (var pool in pools){
|
||||||
poolWorkerData.push({
|
poolWorkerData.push({
|
||||||
key: pool,
|
key: pool,
|
||||||
|
@ -47,21 +75,26 @@ function getReadableHashRateString(hashrate){
|
||||||
hashrate = hashrate / 1024;
|
hashrate = hashrate / 1024;
|
||||||
i++;
|
i++;
|
||||||
} while (hashrate > 1024);
|
} while (hashrate > 1024);
|
||||||
return hashrate.toFixed(2) + byteUnits[i];
|
return Math.round(hashrate) + byteUnits[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
function timeOfDayFormat(timestamp){
|
||||||
|
var dStr = d3.time.format('%I:%M %p')(new Date(timestamp));
|
||||||
|
if (dStr.indexOf('0') === 0) dStr = dStr.slice(1);
|
||||||
|
return dStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayCharts(){
|
function displayCharts(){
|
||||||
|
|
||||||
nv.addGraph(function() {
|
nv.addGraph(function() {
|
||||||
poolWorkerChart = nv.models.stackedAreaChart()
|
poolWorkerChart = nv.models.stackedAreaChart()
|
||||||
|
.margin({left: 40, right: 40})
|
||||||
.x(function(d){ return d[0] })
|
.x(function(d){ return d[0] })
|
||||||
.y(function(d){ return d[1] })
|
.y(function(d){ return d[1] })
|
||||||
.useInteractiveGuideline(true)
|
.useInteractiveGuideline(true)
|
||||||
.clipEdge(true);
|
.clipEdge(true);
|
||||||
|
|
||||||
poolWorkerChart.xAxis.tickFormat(function(d) {
|
poolWorkerChart.xAxis.tickFormat(timeOfDayFormat);
|
||||||
return d3.time.format('%X')(new Date(d))
|
|
||||||
});
|
|
||||||
|
|
||||||
poolWorkerChart.yAxis.tickFormat(d3.format('d'));
|
poolWorkerChart.yAxis.tickFormat(d3.format('d'));
|
||||||
|
|
||||||
|
@ -73,13 +106,12 @@ function displayCharts(){
|
||||||
|
|
||||||
nv.addGraph(function() {
|
nv.addGraph(function() {
|
||||||
poolHashrateChart = nv.models.lineChart()
|
poolHashrateChart = nv.models.lineChart()
|
||||||
|
.margin({left: 60, right: 40})
|
||||||
.x(function(d){ return d[0] })
|
.x(function(d){ return d[0] })
|
||||||
.y(function(d){ return d[1] })
|
.y(function(d){ return d[1] })
|
||||||
.useInteractiveGuideline(true);
|
.useInteractiveGuideline(true);
|
||||||
|
|
||||||
poolHashrateChart.xAxis.tickFormat(function(d) {
|
poolHashrateChart.xAxis.tickFormat(timeOfDayFormat);
|
||||||
return d3.time.format('%X')(new Date(d))
|
|
||||||
});
|
|
||||||
|
|
||||||
poolHashrateChart.yAxis.tickFormat(function(d){
|
poolHashrateChart.yAxis.tickFormat(function(d){
|
||||||
return getReadableHashRateString(d);
|
return getReadableHashRateString(d);
|
||||||
|
@ -96,9 +128,7 @@ function displayCharts(){
|
||||||
.x(function(d){ return d[0] })
|
.x(function(d){ return d[0] })
|
||||||
.y(function(d){ return d[1] });
|
.y(function(d){ return d[1] });
|
||||||
|
|
||||||
poolBlockChart.xAxis.tickFormat(function(d) {
|
poolBlockChart.xAxis.tickFormat(timeOfDayFormat);
|
||||||
return d3.time.format('%X')(new Date(d))
|
|
||||||
});
|
|
||||||
|
|
||||||
d3.select('#poolBlocks').datum(poolBlockData).call(poolBlockChart);
|
d3.select('#poolBlocks').datum(poolBlockData).call(poolBlockChart);
|
||||||
|
|
||||||
|
@ -115,36 +145,56 @@ function TriggerChartUpdates(){
|
||||||
nv.utils.windowResize(TriggerChartUpdates);
|
nv.utils.windowResize(TriggerChartUpdates);
|
||||||
|
|
||||||
$.getJSON('/api/pool_stats', function(data){
|
$.getJSON('/api/pool_stats', function(data){
|
||||||
buildChartData(data);
|
statData = data;
|
||||||
|
buildChartData();
|
||||||
displayCharts();
|
displayCharts();
|
||||||
});
|
});
|
||||||
|
|
||||||
statsSource.addEventListener('message', function(e){
|
statsSource.addEventListener('message', function(e){
|
||||||
var stats = JSON.parse(e.data);
|
var stats = JSON.parse(e.data);
|
||||||
|
statData.push(stats);
|
||||||
|
|
||||||
|
|
||||||
|
var newPoolAdded = (function(){
|
||||||
|
for (var p in stats.pools){
|
||||||
|
if (poolKeys.indexOf(p) === -1)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
})();
|
||||||
|
|
||||||
|
if (newPoolAdded || Object.keys(stats.pools).length > poolKeys.length){
|
||||||
|
buildChartData();
|
||||||
|
displayCharts();
|
||||||
|
}
|
||||||
|
else {
|
||||||
var time = stats.time * 1000;
|
var time = stats.time * 1000;
|
||||||
for (var pool in stats.pools){
|
for (var f = 0; f < poolKeys.length; f++) {
|
||||||
for (var i = 0; i < poolWorkerData.length; i++){
|
var pool = poolKeys[f];
|
||||||
if (poolWorkerData[i].key === pool){
|
for (var i = 0; i < poolWorkerData.length; i++) {
|
||||||
|
if (poolWorkerData[i].key === pool) {
|
||||||
poolWorkerData[i].values.shift();
|
poolWorkerData[i].values.shift();
|
||||||
poolWorkerData[i].values.push([time, stats.pools[pool].workerCount]);
|
poolWorkerData[i].values.push([time, pool in stats.pools ? stats.pools[pool].workerCount : 0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (var i = 0; i < poolHashrateData.length; i++){
|
for (var i = 0; i < poolHashrateData.length; i++) {
|
||||||
if (poolHashrateData[i].key === pool){
|
if (poolHashrateData[i].key === pool) {
|
||||||
poolHashrateData[i].values.shift();
|
poolHashrateData[i].values.shift();
|
||||||
poolHashrateData[i].values.push([time, stats.pools[pool].hashrate]);
|
poolHashrateData[i].values.push([time, pool in stats.pools ? stats.pools[pool].hashrate : 0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (var i = 0; i < poolBlockData.length; i++){
|
for (var i = 0; i < poolBlockData.length; i++) {
|
||||||
if (poolBlockData[i].key === pool){
|
if (poolBlockData[i].key === pool) {
|
||||||
poolBlockData[i].values.shift();
|
poolBlockData[i].values.shift();
|
||||||
poolBlockData[i].values.push([time, stats.pools[pool].blocks.pending]);
|
poolBlockData[i].values.push([time, pool in stats.pools ? stats.pools[pool].blocks.pending : 0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TriggerChartUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TriggerChartUpdates();
|
|
||||||
});
|
});
|
Loading…
Reference in New Issue