diff --git a/models/collection.js b/models/collection.js index c38b5a5..7d38788 100644 --- a/models/collection.js +++ b/models/collection.js @@ -23,9 +23,7 @@ Collection.prototype.update = function(id, stats) if(!node) return false; - node.stats = stats; - - return node.getStats(); + return node.setStats(stats); } Collection.prototype.inactive = function(id) @@ -35,7 +33,7 @@ Collection.prototype.inactive = function(id) if(!node) return false; - node.stats.active = false; + node.setState(false); return node.getStats(); } diff --git a/models/node.js b/models/node.js index 5f58bd3..8f1e202 100644 --- a/models/node.js +++ b/models/node.js @@ -18,7 +18,8 @@ var Node = function Node(data) gasLimit: 0, timestamp: 0, arrival: 0, - propagation: 0 + propagation: 0, + received: 0 }, blocktimeAvg: 0, blockTimes: [], @@ -27,6 +28,15 @@ var Node = function Node(data) uptime: 0, lastUpdate: 0 }; + this.uptime = { + started: null, + history: [] + }; + + if(this.id === null) { + this.uptime.started = (new Date()).getTime(); + this.setState(true); + } if(typeof data.id !== 'undefined') this.id = data.id; @@ -65,6 +75,9 @@ Node.prototype.setInfo = function(data) if(typeof data.spark !== 'undefined') this.spark = data.spark; + + if(this.uptime.history.length > 0 && this.uptime.history[this.uptime.history.length - 1].status == 'down') + this.setState(true); } Node.prototype.getInfo = function() @@ -72,9 +85,33 @@ Node.prototype.getInfo = function() return {id: this.id, info: this.info, geo: this.geo, stats: this.stats}; } +Node.prototype.setStats = function(stats) +{ + if(typeof stats !== undefined && typeof stats.block !== undefined && typeof stats.block.number !== undefined) + { + if(stats.block.number !== this.stats.number) { + stats.block.received == (new Date()).getTime() - stats.block.arrival; + } else { + stats.block.received = this.stats.block.received; + } + + this.stats = stats; + + return this.getStats(); + } + + return false; +} + Node.prototype.getStats = function() { return {id: this.id, stats: this.stats}; } +Node.prototype.setState = function(active) +{ + this.stats.active = active; + this.uptime.history.push({status: (active ? 'up' : 'down'), time: (new Date()).getTime()}); +} + module.exports = Node; diff --git a/package.json b/package.json index cf1fbee..b76f0c2 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "private": true, "engines": { "node": "0.12.0", - "npm": "2.5.0" + "npm": "2.5.1" }, "scripts": { "start": "node ./bin/www" diff --git a/public/js/controllers.js b/public/js/controllers.js index 5c94201..2c048e8 100644 --- a/public/js/controllers.js +++ b/public/js/controllers.js @@ -69,13 +69,6 @@ function StatsCtrl($scope, $filter, socket, _, toastr) { break; case "update": - if(typeof $scope.nodes[findIndex({id: data.id})].stats !== 'undefined' && typeof $scope.nodes[findIndex({id: data.id})].stats.block !== 'undefined'){ - if($scope.nodes[findIndex({id: data.id})].stats.block.number != data.stats.block.number){ - data.stats.block.when = (new Date()).getTime() - data.stats.block.arrival; - } else { - data.stats.block.when = $scope.nodes[findIndex({id: data.id})].stats.block.when; - } - } $scope.nodes[findIndex({id: data.id})].stats = data.stats; break; diff --git a/public/js/filters.js b/public/js/filters.js index 517444b..162150b 100644 --- a/public/js/filters.js +++ b/public/js/filters.js @@ -60,14 +60,6 @@ angular.module('netStatsApp.filters', []) return (typeof gas !== 'undefined' ? parseInt(gas) : '?'); } }) -.filter('latencyFilter', function() { - return function(stats) { - if(stats.active === false) - return 'offline'; - else - return stats.latency + ' ms'; - } -}) .filter('hashFilter', function() { return function(hash) { return hash.substr(0, 6) + '...' + hash.substr(58, 6); @@ -89,12 +81,23 @@ angular.module('netStatsApp.filters', []) return 'text-danger' }; }) +.filter('latencyFilter', function() { + return function(stats) { + if(stats.active === false) + return 'offline'; + else + return stats.latency + ' ms'; + } +}) .filter('latencyClass', function() { - return function(time) { - if(time <= 100) + return function(stats) { + if(stats.active === false) + return 'text-danger'; + + if(stats.latency <= 100) return 'text-success'; - if(time <= 1000) + if(stats.latency <= 1000) return 'text-warning'; return 'text-danger' @@ -116,7 +119,6 @@ angular.module('netStatsApp.filters', []) }) .filter('blockPropagationFilter', function() { return function(ms) { - // ms = (new Date()).getTime() - ms; var result = 0; if(ms < 1000) { diff --git a/views/index.jade b/views/index.jade index 05d8a3f..17930bc 100644 --- a/views/index.jade +++ b/views/index.jade @@ -117,7 +117,7 @@ block content td div.small(ng-bind-html="node.info.node | nodeVersion") //- div.small {{node.info.os}}, {{node.info.os_v}} - td.small(class="{{ node.stats.latency | latencyClass }}") {{node.stats | latencyFilter}} + td.small(class="{{ node.stats | latencyClass }}") {{node.stats | latencyFilter}} td(class="{{ node.stats.mining | miningClass }}") i.small(class="{{ node.stats.mining | miningIconClass }}") td(class="{{ node.stats.peers | peerClass }}", style="padding-left: 18px;") {{node.stats.peers}} @@ -128,5 +128,5 @@ block content //- div.small Difficulty: {{node.stats.block.difficulty | gasFilter}} | Gas used: {{node.stats.block.gasUsed | gasFilter}} | Min gas price: {{node.stats.block.minGasPrice | gasFilter}} | Gas limit: {{node.stats.block.gasLimit | gasFilter}} td(style="padding-left: 18px;") {{node.stats.block.txCount}} td(class="{{ node.stats.block.timestamp | timeClass }}") {{node.stats.block.timestamp | blockTimeFilter }} - td(class="{{ node.stats.block.when | propagationTimeClass }}") {{node.stats.block.when | blockPropagationFilter}} + td(class="{{ node.stats.block.received | propagationTimeClass }}") {{node.stats.block.received | blockPropagationFilter}} td(class="{{ node.stats.uptime | upTimeClass }}") {{ node.stats.uptime | upTimeFilter }}