httpd: add country pie chart to dashboard
This commit is contained in:
61
httpd.py
61
httpd.py
@@ -598,9 +598,30 @@ function update(d) {
|
||||
$('failLegend').innerHTML = fhtml;
|
||||
|
||||
// Leaderboards (session data)
|
||||
renderLeaderboard('topCountries', d.top_countries_session, 'code', 'count');
|
||||
renderLeaderboard('topAsns', d.top_asns_session, 'asn', 'count');
|
||||
|
||||
// Country pie chart (database data)
|
||||
var countryColors = ['#58a6ff','#3fb950','#d29922','#f85149','#a371f7','#39c5cf','#db61a2','#db6d28','#7ee787','#7d8590'];
|
||||
if (d.db && d.db.top_countries && d.db.top_countries.length > 0) {
|
||||
var countries = d.db.top_countries.slice(0, 8);
|
||||
var countryTotal = countries.reduce(function(s, c) { return s + (c.count || c[1] || 0); }, 0);
|
||||
var segs = [], chtml = '';
|
||||
countries.forEach(function(c, i) {
|
||||
var code = c.code || c[0], cnt = c.count || c[1] || 0;
|
||||
var col = countryColors[i % countryColors.length];
|
||||
var pctVal = countryTotal > 0 ? ((cnt / countryTotal) * 100).toFixed(1) : '0';
|
||||
segs.push({c: col, d: (cnt / countryTotal) * 360});
|
||||
chtml += '<div class="legend-item"><div class="legend-dot" style="background:' + col + '"></div>';
|
||||
chtml += '<span class="legend-name">' + code + '</span><span class="legend-val">' + fmt(cnt) + '</span>';
|
||||
chtml += '<span class="sub" style="margin-left:4px">' + pctVal + '%</span></div>';
|
||||
});
|
||||
$('countryPie').style.background = conicGrad(segs);
|
||||
$('countryLegend').innerHTML = chtml;
|
||||
} else {
|
||||
$('countryPie').style.background = 'var(--border)';
|
||||
$('countryLegend').innerHTML = '<div style="color:var(--dim);font-size:11px">No data</div>';
|
||||
}
|
||||
|
||||
// Tor pool
|
||||
var thtml = '';
|
||||
if (d.tor_pool && d.tor_pool.hosts) {
|
||||
@@ -639,15 +660,6 @@ function update(d) {
|
||||
return '<div class="stat-row"><span class="stat-lbl">' + p.toUpperCase() + '</span><span class="stat-val">' + fmt(c) + '</span></div>';
|
||||
}).join('');
|
||||
|
||||
var chtml = '';
|
||||
if (dbs.top_countries) {
|
||||
dbs.top_countries.slice(0, 5).forEach(function(c, i) {
|
||||
var name = c.code || c[0], cnt = c.count || c[1];
|
||||
chtml += '<div class="lb-item"><div class="lb-rank' + (i === 0 ? ' top' : '') + '">' + (i + 1) + '</div>';
|
||||
chtml += '<span class="lb-name">' + name + '</span><span class="lb-val blu">' + fmt(cnt) + '</span></div>';
|
||||
});
|
||||
}
|
||||
$('dbCountries').innerHTML = chtml || '<div style="color:var(--dim)">No data</div>';
|
||||
}
|
||||
|
||||
// Scraper/Engine stats
|
||||
@@ -705,6 +717,11 @@ function update(d) {
|
||||
$('dbTestedHour').textContent = fmt(dbh.tested_last_hour);
|
||||
$('dbAddedDay').textContent = fmt(dbh.added_last_day);
|
||||
$('dbDead').textContent = fmt(dbh.dead_count);
|
||||
$('dbFailing').textContent = fmt(dbh.failing_count);
|
||||
$('dbFreelist').textContent = fmt(dbh.freelist_count);
|
||||
$('dbAvgLat').textContent = fmtMs(dbh.db_avg_latency);
|
||||
$('dbMinLat').textContent = fmtMs(dbh.db_min_latency);
|
||||
$('dbMaxLat').textContent = fmtMs(dbh.db_max_latency);
|
||||
}
|
||||
|
||||
// Tor pool enhanced stats
|
||||
@@ -933,14 +950,17 @@ DASHBOARD_HTML = '''<!DOCTYPE html>
|
||||
|
||||
<!-- Geographic Distribution -->
|
||||
<div class="sec">
|
||||
<div class="sec-hdr">Geographic Distribution (Session)</div>
|
||||
<div class="sec-hdr">Geographic Distribution <a href="/map" style="font-size:10px;font-weight:normal;margin-left:8px">View Map →</a></div>
|
||||
<div class="g g2">
|
||||
<div class="c">
|
||||
<div class="lbl">Top Countries</div>
|
||||
<div class="lb" id="topCountries"></div>
|
||||
<div class="lbl">Proxies by Country (Database)</div>
|
||||
<div class="pie-wrap">
|
||||
<div class="pie" id="countryPie"></div>
|
||||
<div class="legend" id="countryLegend"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="c">
|
||||
<div class="lbl">Top ASNs</div>
|
||||
<div class="lbl">Top ASNs (Session)</div>
|
||||
<div class="lb" id="topAsns"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1023,14 +1043,21 @@ DASHBOARD_HTML = '''<!DOCTYPE html>
|
||||
<div class="val-sm red" id="dbDead">-</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="g g2">
|
||||
<div class="g g3">
|
||||
<div class="c">
|
||||
<div class="lbl">Working by Protocol</div>
|
||||
<div id="dbByProto"></div>
|
||||
</div>
|
||||
<div class="c">
|
||||
<div class="lbl">Top Countries (All Time)</div>
|
||||
<div class="lb" id="dbCountries"></div>
|
||||
<div class="lbl">Latency Stats</div>
|
||||
<div class="stat-row"><span class="stat-lbl">Average</span><span class="stat-val cyn" id="dbAvgLat">-</span></div>
|
||||
<div class="stat-row"><span class="stat-lbl">Min</span><span class="stat-val grn" id="dbMinLat">-</span></div>
|
||||
<div class="stat-row"><span class="stat-lbl">Max</span><span class="stat-val red" id="dbMaxLat">-</span></div>
|
||||
</div>
|
||||
<div class="c">
|
||||
<div class="lbl">Activity</div>
|
||||
<div class="stat-row"><span class="stat-lbl">Failing</span><span class="stat-val yel" id="dbFailing">-</span></div>
|
||||
<div class="stat-row"><span class="stat-lbl">Freelist</span><span class="stat-val" id="dbFreelist">-</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user