Browse Source

Add blocks stats

pool
Sammy Libre 7 years ago
parent
commit
919248ee12
  1. 28
      go-pool/stratum/api.go
  2. 2
      go-pool/stratum/miner.go
  3. 10
      go-pool/stratum/stratum.go
  4. 45
      www/index.html
  5. 57
      www/script.js
  6. 4
      www/style.css

28
go-pool/stratum/api.go

@ -36,6 +36,7 @@ func (s *StratumServer) StatsIndex(w http.ResponseWriter, r *http.Request) { @@ -36,6 +36,7 @@ func (s *StratumServer) StatsIndex(w http.ResponseWriter, r *http.Request) {
stats["upstreams"] = upstreams
stats["current"] = convertUpstream(s.rpc())
stats["luck"] = s.getLuckStats()
stats["blocks"] = s.getBlocksStats()
if t := s.currentBlockTemplate(); t != nil {
stats["height"] = t.height
@ -115,11 +116,11 @@ func (s *StratumServer) getLuckStats() map[string]interface{} { @@ -115,11 +116,11 @@ func (s *StratumServer) getLuckStats() map[string]interface{} {
for k, v := range s.blockStats {
if k >= now-int64(s.luckWindow) {
blocksCount++
variance += v
variance += v.variance
}
if k >= now-int64(s.luckLargeWindow) {
totalBlocksCount++
totalVariance += v
totalVariance += v.variance
} else {
delete(s.blockStats, k)
}
@ -139,3 +140,26 @@ func (s *StratumServer) getLuckStats() map[string]interface{} { @@ -139,3 +140,26 @@ func (s *StratumServer) getLuckStats() map[string]interface{} {
result["largeWindow"] = s.config.LargeLuckWindow
return result
}
func (s *StratumServer) getBlocksStats() []interface{} {
now := util.MakeTimestamp()
var result []interface{}
s.blocksMu.Lock()
defer s.blocksMu.Unlock()
for k, v := range s.blockStats {
if k >= now-int64(s.luckLargeWindow) {
block := map[string]interface{}{
"height": v.height,
"hash": v.hash,
"variance": v.variance,
"timestamp": k,
}
result = append(result, block)
} else {
delete(s.blockStats, k)
}
}
return result
}

2
go-pool/stratum/miner.go

@ -183,7 +183,7 @@ func (m *Miner) processShare(s *StratumServer, cs *Session, job *Job, t *BlockTe @@ -183,7 +183,7 @@ func (m *Miner) processShare(s *StratumServer, cs *Session, job *Job, t *BlockTe
roundShares := atomic.SwapInt64(&s.roundShares, 0)
ratio := float64(roundShares) / float64(t.difficulty)
s.blocksMu.Lock()
s.blockStats[now] = ratio
s.blockStats[now] = blockEntry{height: t.height, hash: blockFastHash, variance: ratio}
s.blocksMu.Unlock()
atomic.AddUint64(&m.accepts, 1)
atomic.AddUint64(&r.Accepts, 1)

10
go-pool/stratum/stratum.go

@ -26,7 +26,7 @@ type StratumServer struct { @@ -26,7 +26,7 @@ type StratumServer struct {
timeout time.Duration
estimationWindow time.Duration
blocksMu sync.RWMutex
blockStats map[int64]float64
blockStats map[int64]blockEntry
luckWindow int64
luckLargeWindow int64
roundShares int64
@ -34,6 +34,12 @@ type StratumServer struct { @@ -34,6 +34,12 @@ type StratumServer struct {
sessions map[*Session]struct{}
}
type blockEntry struct {
height int64
hash string
variance float64
}
type Endpoint struct {
config *pool.Port
instanceId []byte
@ -57,7 +63,7 @@ const ( @@ -57,7 +63,7 @@ const (
)
func NewStratum(cfg *pool.Config) *StratumServer {
stratum := &StratumServer{config: cfg, blockStats: make(map[int64]float64)}
stratum := &StratumServer{config: cfg, blockStats: make(map[int64]blockEntry)}
stratum.upstreams = make([]*rpc.RPCClient, len(cfg.Upstream))
for i, v := range cfg.Upstream {

45
www/index.html

@ -146,9 +146,54 @@ @@ -146,9 +146,54 @@
</div>
</div>
</script>
<script id="blocks-template" type="text/x-handlebars-template">
<div class="row marketing">
<div class="col-xs-12">
<p>
<strong>Blocks {{luck.window}}:</strong> <span class="label label-primary">{{formatNumber luck.blocksCount}}</span>
<strong>Shares/Diff {{luck.window}}:</strong>
<span class="label label-primary">{{formatNumber luck.variance style="percent" minimumFractionDigits=2 maximumFractionDigits=2}}</span>
<strong>Blocks {{luck.largeWindow}}:</strong> <span class="label label-primary">{{formatNumber luck.totalBlocksCount}}</span>
<strong>Shares/Diff {{luck.largeWindow}}:</strong>
<span class="label label-primary">{{formatNumber luck.totalVariance style="percent" minimumFractionDigits=2 maximumFractionDigits=2}}</span>
{{#if template}}
<strong>Round Progress:</strong>
<span class="label label-primary">{{formatNumber variance style="percent" minimumFractionDigits=2 maximumFractionDigits=2}}</span>
{{/if}}
</p>
</div>
<div id="blocks" class="col-xs-12">
<h4>Blocks</h4>
<div class="table-responsive">
<table class="table table-condensed table-striped">
<tr>
<th>Height</th>
<th>Time</th>
<th>Hash</th>
<th>Shares/Diff</th>
</tr>
{{#each blocks}}
<tr>
<td>{{formatNumber height}}</td>
<td>{{formatDate timestamp year="numeric" month="numeric" day="numeric" hour="numeric" minute="numeric"}}</td>
<td class="hash">{{hash}}</td>
<td>{{formatNumber variance style="percent" minimumFractionDigits=2 maximumFractionDigits=2}}</td>
</tr>
{{/each}}
</table>
</div>
</div>
</div>
</script>
<div class="container">
<div class="header clearfix">
<nav>
<ul class="nav nav-pills pull-right">
<li role="presentation"><a href="#" id="homeTab">Home</a></li>
<li role="presentation"><a href="#blocks" id="blocksTab">Blocks</a></li>
</ul>
</nav>
<h3 class="text-muted">MoneroProxy</h3>
</div>
<div id="alert" class="alert alert-danger hide" role="alert">

57
www/script.js

@ -1,38 +1,75 @@ @@ -1,38 +1,75 @@
HandlebarsIntl.registerWith(Handlebars);
$(function() {
window.state = {};
switch (location.hash) {
case '#blocks':
window.homeTab = false;
break;
default:
window.homeTab = true;
}
var userLang = (navigator.language || navigator.userLanguage) || 'en-US';
window.intlData = { locales: userLang };
var source = $("#stats-template").html();
var template = Handlebars.compile(source);
refreshStats(template);
var statsSource = $("#stats-template").html();
var statsTemplate = Handlebars.compile(statsSource);
var blocksSource = $("#blocks-template").html();
var blocksTemplate = Handlebars.compile(blocksSource);
refreshStats(statsTemplate, blocksTemplate);
$('#homeTab').on('click', function() {
window.homeTab = true;
refreshStats(statsTemplate, blocksTemplate);
});
$('#blocksTab').on('click', function() {
window.homeTab = false;
refreshStats(statsTemplate, blocksTemplate);
});
setInterval(function() {
refreshStats(template);
refreshStats(statsTemplate, blocksTemplate);
}, 5000)
});
function refreshStats(template) {
function refreshStats(statsTemplate, blocksTemplate) {
$.getJSON("/stats", function(stats) {
$("#alert").addClass('hide');
// Sort miners by ID
if (stats.miners) {
stats.miners = stats.miners.sort(compare)
stats.miners = stats.miners.sort(compareMiners);
}
// Reverse sort blocks by height
if (stats.blocks) {
stats.blocks = stats.blocks.sort(compareBlocks);
}
var html = null;
$('.nav-pills > li').removeClass('active');
if (window.homeTab) {
html = statsTemplate(stats, { data: { intl: window.intlData } });
$('.nav-pills > li > #homeTab').parent().addClass('active');
} else {
html = blocksTemplate(stats, { data: { intl: window.intlData } });
$('.nav-pills > li > #blocksTab').parent().addClass('active');
}
// Repaint stats
var html = template(stats, { data: { intl: window.intlData } });
$('#stats').html(html);
}).fail(function() {
$("#alert").removeClass('hide');
});
}
function compare(a, b) {
function compareMiners(a, b) {
if (a.name < b.name)
return -1;
if (a.name > b.name)
return 1;
return 0;
}
function compareBlocks(a, b) {
if (a.height > b.height)
return -1;
if (a.height < b.height)
return 1;
return 0;
}

4
www/style.css

@ -42,6 +42,10 @@ span.logo-3 { @@ -42,6 +42,10 @@ span.logo-3 {
font-weight: 100;
}
.hash {
font-family: 'Inconsolata', monospace;
}
/* Custom page footer */
.footer {
padding-top: 15px;

Loading…
Cancel
Save