Skip to content

Commit

Permalink
fixed getMinerStats()/getHashrates() etc.
Browse files Browse the repository at this point in the history
 * aggregate() with proper match options
 * verify range/days req params
 * fixed tools/stats.js to support rescan with a custom interval.
 * show percent at a tooltip
  • Loading branch information
hackmod committed May 5, 2018
1 parent bcfbc9b commit 2603e78
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 43 deletions.
7 changes: 6 additions & 1 deletion public/js/controllers/StatsController.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ angular.module('BlocksApp').controller('StatsController', function($stateParams,
* Created by chenxiangyu on 2016/8/5.
*/
scope.init = function(dataset, chartid) {
var total = 0;
dataset.forEach(function(d) {
total += d.count;
});

var svg = d3.select(chartid)
.append("g");

Expand Down Expand Up @@ -139,7 +144,7 @@ angular.module('BlocksApp').controller('StatsController', function($stateParams,
div.style("left", d3.event.pageX + 10 + "px");
div.style("top", d3.event.pageY - 25 + "px");
div.style("display", "inline-block");
div.html((d.data._id) + "<br>" + (d.data.count) + " ");
div.html((d.data._id) + "<br>" + (d.data.count) + "<br>(" + d3.format(".2%")(d.data.count / total) + ")");
});
slice
.on("mouseout", function (d) {
Expand Down
118 changes: 94 additions & 24 deletions routes/stats.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,55 +14,125 @@ module.exports = function(req, res) {
res.status(400).send();

else if (req.body.action=="miners")
getMinerStats(res)
getMinerStats(req, res)

else if (req.body.action=="hashrate")
getHashrate(res);

else if (req.body.action=="hashrates")
getHashrates(res);
getHashrates(req, res);

}
/**
Aggregate miner stats
**/
var getMinerStats = function(res) {
BlockStat.aggregate([
{ $group: {
_id: '$miner',
count: {$sum: 1} }
}
], function (err, result) {
if (err) {
console.error(err);
res.status(500).send();
} else {
res.write(JSON.stringify(result));
res.end();
}
var getMinerStats = function(req, res) {
var range = 6*60*60; // 6 hours
// check validity of range
if (req.body.range && req.body.range < 60 * 60 * 24 * 7) {
range = parseInt(req.body.range);
if (range < 1800) { // minimal 30 minutes
range = 1800;
}
}

var timebefore = parseInt((new Date())/1000) - range;
Block.find({ timestamp: { $lte: timebefore } }, "timestamp number")
.lean(true).sort('-number').limit(1).exec(function (err, docs) {
if (err || !docs) {
console.error(err);
res.status(500).send();
res.end();
return;
}
var blockNumber = docs[0].number;
console.log('getMinerStats(): blockNumber = ' + blockNumber);
Block.aggregate([
{ $match: { number: { $gte: blockNumber } } },
{ $group: {
_id: '$miner',
timestamp: {$min: '$timestamp' },
count: {$sum: 1} }
}
], function (err, result) {
if (err) {
console.error(err);
res.status(500).send();
} else {
res.write(JSON.stringify(result));
res.end();
}
});
});
}

/**
Aggregate network hashrates
**/
var getHashrates = function(res) {
BlockStat.aggregate([{
$group: {
var getHashrates = function(req, res) {
// setup default range
//var range = 7 * 24 * 60 * 60; /* 7 days */
//var range = 14 * 24 * 60 * 60; /* 14 days */
//var range = 30 * 24 * 60 * 60; /* 1 months */
//var range = 2 * 30 * 24 * 60 * 60; /* 2 months */
var range = 6 * 30 * 24 * 60 * 60; /* 6 months */
if (req.body.days && req.body.days <= 365) {
var days = parseInt(req.body.days);
if (days <= 1) {
days = 1;
}
range = days * 60 * 60 * 24;
} else if (req.body.range && req.body.range < 31536000 /* 60 * 60 * 24 * 365 */) {
range = parseInt(req.body.range);
if (range < 30 * 60) {
range = 30 * 60; /* minimal range */
}
}

// select mod
var rngs = [ 30*60, 60*60, 2*60*60, 4*60*60, 6*60*60,
12*60*60, 24*60*60, 7*24*60*60, 14*24*60*60, 30*24*60*60
];
var mods = [ 1, 1, 2, 10, 10,
15, 30, 15*60, 30*60, 30*60,
60*60
];
var i = 0;
rngs.forEach(function(r) {
if (range > r) {
i++;
}
return;
});
var mod = mods[i];

var timestamp = parseInt((new Date())/1000) - range;

BlockStat.aggregate([
{ $match: { timestamp: { $gte: timestamp } } },
{ $group: {
_id: {
timestamp: {
$subtract: [ '$timestamp', { $mod: [ '$timestamp', 3600 ] } ]
$subtract: [ '$timestamp', { $mod: [ '$timestamp', mod ] } ]
}
},
blockTime: { $avg: '$blockTime' },
difficulty: { $max: '$difficulty' }
difficulty: { $max: '$difficulty' },
count: { $sum: 1 }
}},
{ $project: {
"_id": 0,
"timestamp": '$_id.timestamp',
"blockTime": 1,
"difficulty": 1,
"count": 1,
}
}]).sort('_id.timestamp').exec(function(err, docs) {
}]).sort('timestamp').exec(function(err, docs) {
var hashrates = [];
docs.forEach(function(doc) {
doc.instantHashrate = doc.difficulty / doc.blockTime;
doc.unixtime = doc._id.timestamp;
doc.timestamp = doc._id.timestamp;
doc.unixtime = doc.timestamp; /* FIXME */
doc.timestamp = doc.timestamp;
});
res.write(JSON.stringify({"hashrates": docs}));
res.end();
Expand Down
92 changes: 74 additions & 18 deletions tools/stats.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,35 @@ var Web3 = require('web3');
var mongoose = require( 'mongoose' );
var BlockStat = require( '../db.js' ).BlockStat;

var updateStats = function() {
var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
var updateStats = function(range, interval, rescan) {
var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));

mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost/blockDB');
mongoose.set('debug', true);

var latestBlock = web3.eth.blockNumber;
getStats(web3, latestBlock, null, latestBlock - 1000);

interval = Math.abs(parseInt(interval));
if (!range) {
range = 1000;
}
range *= interval;
if (interval >= 10) {
latestBlock -= latestBlock % interval;
}
getStats(web3, latestBlock, null, latestBlock - range, interval, rescan);
}


var getStats = function(web3, blockNumber, nextBlock, endBlock) {
if (blockNumber <= endBlock)
process.exit(9);
var getStats = function(web3, blockNumber, nextBlock, endNumber, interval, rescan) {
if (endNumber < 0)
endNumber = 0;
if (blockNumber <= endNumber) {
if (rescan) {
process.exit(9);
}
return;
}

if(web3.isConnected()) {

Expand All @@ -35,9 +50,9 @@ var getStats = function(web3, blockNumber, nextBlock, endBlock) {
}
else {
if (nextBlock)
checkBlockDBExistsThenWrite(web3, blockData, nextBlock.timestamp);
checkBlockDBExistsThenWrite(web3, blockData, nextBlock, endNumber, interval, rescan);
else
checkBlockDBExistsThenWrite(web3, blockData, parseInt(Date.now()/1000));
checkBlockDBExistsThenWrite(web3, blockData, null, endNumber, interval, rescan);
}
});
} else {
Expand All @@ -52,9 +67,9 @@ var getStats = function(web3, blockNumber, nextBlock, endBlock) {
* if record exists: abort
* if record DNE: write a file for the block
*/
var checkBlockDBExistsThenWrite = function(web3, blockData, nextTime) {
var checkBlockDBExistsThenWrite = function(web3, blockData, nextBlock, endNumber, interval, rescan) {
BlockStat.find({number: blockData.number}, function (err, b) {
if (!b.length) {
if (!b.length && nextBlock) {
// calc hashrate, txCount, blocktime, uncleCount
var stat = {
"number": blockData.number,
Expand All @@ -64,7 +79,7 @@ var checkBlockDBExistsThenWrite = function(web3, blockData, nextTime) {
"gasUsed": blockData.gasUsed,
"gasLimit": blockData.gasLimit,
"miner": blockData.miner,
"blockTime": nextTime - blockData.timestamp,
"blockTime": (nextBlock.timestamp - blockData.timestamp) / (nextBlock.number - blockData.number),
"uncleCount": blockData.uncles.length
}
new BlockStat(stat).save( function( err, s, count ){
Expand All @@ -77,13 +92,20 @@ var checkBlockDBExistsThenWrite = function(web3, blockData, nextTime) {
} else {
console.log('DB successfully written for block number ' +
blockData.number.toString() );
getStats(web3, blockData.number - 1, blockData);
getStats(web3, blockData.number - interval, blockData, endNumber, interval, rescan);
}
});
} else {
console.log('Aborting because block number: ' + blockData.number.toString() +
' already exists in DB.');
return;
if (rescan || !nextBlock) {
getStats(web3, blockData.number - interval, blockData, endNumber, interval, rescan);
if (nextBlock) {
console.log('WARN: block number: ' + blockData.number.toString() + ' already exists in DB.');
}
} else {
console.error('Aborting because block number: ' + blockData.number.toString() +
' already exists in DB.');
return;
}
}

})
Expand All @@ -95,6 +117,40 @@ var checkBlockDBExistsThenWrite = function(web3, blockData, nextTime) {
var minutes = 1;
statInterval = minutes * 60 * 1000;

setInterval(function() {
updateStats();
}, statInterval);
var rescan = false; /* rescan: true - rescan range */
var range = 1000;
var interval = 100;

/**
* RESCAN=1000:100000 means interval;range
*
* Usage:
* RESCAN=1000:100000 node tools/stats.js
*/
if (process.env.RESCAN) {
var tmp = process.env.RESCAN.split(/:/);
if (tmp.length > 1) {
interval = Math.abs(parseInt(tmp[0]));
if (tmp[1]) {
range = Math.abs(parseInt(tmp[1]));
}
}
var i = interval;
var j = 0;
for (var j = 0; i >= 10; j++) {
i = parseInt(i / 10);
}
interval = Math.pow(10, j);
console.log('Selected interval = ' + interval);

rescan = true;
}

// run
updateStats(range, interval, rescan);

if (!rescan) {
setInterval(function() {
updateStats(range, interval);
}, statInterval);
}

0 comments on commit 2603e78

Please sign in to comment.