diff --git a/config_example.json b/config_example.json
index 8759fcf..8cd417c 100644
--- a/config_example.json
+++ b/config_example.json
@@ -11,7 +11,7 @@
"port": 80,
"stratumHost": "cryppit.com",
"stats": {
- "updateInterval": 15,
+ "updateInterval": 60,
"historicalRetention": 43200,
"hashrateWindow": 300,
"redis": {
diff --git a/libs/api.js b/libs/api.js
index 53ebd70..3a433ab 100644
--- a/libs/api.js
+++ b/libs/api.js
@@ -18,8 +18,7 @@ module.exports = function(logger, portalConfig, poolConfigs){
res.end(portalStats.statsString);
return;
case 'pool_stats':
- res.writeHead(200, {'content-encoding': 'gzip'});
- res.end(portalStats.statPoolHistoryBuffer);
+ res.end(JSON.stringify(portalStats.statPoolHistory));
return;
case 'live_stats':
res.writeHead(200, {
diff --git a/libs/stats.js b/libs/stats.js
index 459ff14..62b7f00 100644
--- a/libs/stats.js
+++ b/libs/stats.js
@@ -20,7 +20,6 @@ module.exports = function(logger, portalConfig, poolConfigs){
this.statHistory = [];
this.statPoolHistory = [];
- this.statPoolHistoryBuffer;
this.stats = {};
this.statsString = '';
@@ -84,7 +83,6 @@ module.exports = function(logger, portalConfig, poolConfigs){
_this.statHistory.forEach(function(stats){
addStatPoolHistory(stats);
});
- deflateStatPoolHistory();
});
}
@@ -96,7 +94,7 @@ module.exports = function(logger, portalConfig, poolConfigs){
for (var pool in stats.pools){
data.pools[pool] = {
hashrate: stats.pools[pool].hashrate,
- workers: stats.pools[pool].workerCount,
+ workerCount: stats.pools[pool].workerCount,
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){
@@ -245,8 +239,6 @@ module.exports = function(logger, portalConfig, poolConfigs){
}
}
- deflateStatPoolHistory();
-
redisStats.multi([
['zadd', 'statHistory', statGatherTime, _this.statsString],
['zremrangebyscore', 'statHistory', '-inf', '(' + retentionTime]
diff --git a/website/pages/stats.html b/website/pages/stats.html
index d7193b3..435a28f 100644
--- a/website/pages/stats.html
+++ b/website/pages/stats.html
@@ -4,11 +4,18 @@
padding: 18px;
}
- #topCharts > div > svg{
+ #topCharts > div > div > svg{
display: block;
height: 280px;
}
+ .chartWrapper{
+ border: solid 1px #c7c7c7;
+ border-radius: 5px;
+ padding: 5px;
+ margin-bottom: 18px;
+ }
+
.chartLabel{
font-size: 1.2em;
text-align: center;
@@ -16,24 +23,27 @@
}
.chartHolder{
- border: solid 1px #c7c7c7;
- border-radius: 5px;
- padding: 5px;
- margin-bottom: 18px;
+
}
-
Workers Per Pool
-
+
-
Hashrate Per Pool
-
+
-
Blocks Pending Per Pool
-
+
+
Blocks Pending Per Pool
+
+
diff --git a/website/static/stats.js b/website/static/stats.js
index 4d5b885..10e43d6 100644
--- a/website/static/stats.js
+++ b/website/static/stats.js
@@ -1,29 +1,57 @@
-var poolWorkerData = [];
-var poolHashrateData = [];
-var poolBlockData = [];
+var poolWorkerData;
+var poolHashrateData;
+var poolBlockData;
var poolWorkerChart;
var poolHashrateChart;
var poolBlockChart;
-function buildChartData(data){
+var statData;
+var poolKeys;
+
+function buildChartData(){
var pools = {};
- for (var i = 0; i < data.length; i++){
- var time = data[i].time * 1000;
- for (var pool in data[i].pools){
- var a = pools[pool] = (pools[pool] || {
+ poolKeys = [];
+ for (var i = 0; i < statData.length; i++){
+ for (var pool in statData[i].pools){
+ 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: [],
workers: [],
blocks: []
});
- a.hashrate.push([time, data[i].pools[pool].hashrate || 0]);
- a.workers.push([time, data[i].pools[pool].workers || 0]);
- a.blocks.push([time, data[i].pools[pool].blocks.pending])
+ if (pName in statData[i].pools){
+ a.hashrate.push([time, statData[i].pools[pName].hashrate]);
+ 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){
poolWorkerData.push({
key: pool,
@@ -47,21 +75,26 @@ function getReadableHashRateString(hashrate){
hashrate = hashrate / 1024;
i++;
} 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(){
nv.addGraph(function() {
poolWorkerChart = nv.models.stackedAreaChart()
+ .margin({left: 40, right: 40})
.x(function(d){ return d[0] })
.y(function(d){ return d[1] })
.useInteractiveGuideline(true)
.clipEdge(true);
- poolWorkerChart.xAxis.tickFormat(function(d) {
- return d3.time.format('%X')(new Date(d))
- });
+ poolWorkerChart.xAxis.tickFormat(timeOfDayFormat);
poolWorkerChart.yAxis.tickFormat(d3.format('d'));
@@ -73,13 +106,12 @@ function displayCharts(){
nv.addGraph(function() {
poolHashrateChart = nv.models.lineChart()
+ .margin({left: 60, right: 40})
.x(function(d){ return d[0] })
.y(function(d){ return d[1] })
.useInteractiveGuideline(true);
- poolHashrateChart.xAxis.tickFormat(function(d) {
- return d3.time.format('%X')(new Date(d))
- });
+ poolHashrateChart.xAxis.tickFormat(timeOfDayFormat);
poolHashrateChart.yAxis.tickFormat(function(d){
return getReadableHashRateString(d);
@@ -96,9 +128,7 @@ function displayCharts(){
.x(function(d){ return d[0] })
.y(function(d){ return d[1] });
- poolBlockChart.xAxis.tickFormat(function(d) {
- return d3.time.format('%X')(new Date(d))
- });
+ poolBlockChart.xAxis.tickFormat(timeOfDayFormat);
d3.select('#poolBlocks').datum(poolBlockData).call(poolBlockChart);
@@ -115,36 +145,56 @@ function TriggerChartUpdates(){
nv.utils.windowResize(TriggerChartUpdates);
$.getJSON('/api/pool_stats', function(data){
- buildChartData(data);
+ statData = data;
+ buildChartData();
displayCharts();
});
statsSource.addEventListener('message', function(e){
var stats = JSON.parse(e.data);
- var time = stats.time * 1000;
- for (var pool in stats.pools){
- for (var i = 0; i < poolWorkerData.length; i++){
- if (poolWorkerData[i].key === pool){
- poolWorkerData[i].values.shift();
- poolWorkerData[i].values.push([time, stats.pools[pool].workerCount]);
- break;
- }
- }
- for (var i = 0; i < poolHashrateData.length; i++){
- if (poolHashrateData[i].key === pool){
- poolHashrateData[i].values.shift();
- poolHashrateData[i].values.push([time, stats.pools[pool].hashrate]);
- break;
- }
- }
- for (var i = 0; i < poolBlockData.length; i++){
- if (poolBlockData[i].key === pool){
- poolBlockData[i].values.shift();
- poolBlockData[i].values.push([time, stats.pools[pool].blocks.pending]);
- break;
+ 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;
+ for (var f = 0; f < poolKeys.length; f++) {
+ var pool = poolKeys[f];
+ for (var i = 0; i < poolWorkerData.length; i++) {
+ if (poolWorkerData[i].key === pool) {
+ poolWorkerData[i].values.shift();
+ poolWorkerData[i].values.push([time, pool in stats.pools ? stats.pools[pool].workerCount : 0]);
+ break;
+ }
+ }
+ for (var i = 0; i < poolHashrateData.length; i++) {
+ if (poolHashrateData[i].key === pool) {
+ poolHashrateData[i].values.shift();
+ poolHashrateData[i].values.push([time, pool in stats.pools ? stats.pools[pool].hashrate : 0]);
+ break;
+ }
+ }
+ for (var i = 0; i < poolBlockData.length; i++) {
+ if (poolBlockData[i].key === pool) {
+ poolBlockData[i].values.shift();
+ poolBlockData[i].values.push([time, pool in stats.pools ? stats.pools[pool].blocks.pending : 0]);
+ break;
+ }
}
}
+ TriggerChartUpdates();
}
- TriggerChartUpdates();
+
});
\ No newline at end of file