mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-10-23 10:12:34 +00:00
Merge branch 'areas-meshguide-sync'
This commit is contained in:
commit
4090d697a1
5 files changed
+37
-10
No files matched your search
@@ -3939,13 +3939,18 @@ func (s *Server) handleScopeStats(w http.ResponseWriter, r *http.Request) {
|
||||
resp.ConfiguredRegions = len(configured)
|
||||
if matched, err := s.db.GetMatchedRegionNames(); err == nil {
|
||||
unused := make([]string, 0, len(configured))
|
||||
used := make([]string, 0, len(configured))
|
||||
for _, name := range configured {
|
||||
if !matched[name] {
|
||||
if matched[name] {
|
||||
used = append(used, name)
|
||||
} else {
|
||||
unused = append(unused, name)
|
||||
}
|
||||
}
|
||||
sort.Strings(unused)
|
||||
sort.Strings(used)
|
||||
resp.UnusedRegions = unused
|
||||
resp.UsedRegions = used
|
||||
} else {
|
||||
log.Printf("WARN GetMatchedRegionNames: %v", err)
|
||||
}
|
||||
|
||||
@@ -4605,6 +4605,17 @@ func TestHandleScopeStats_UnusedRegions(t *testing.T) {
|
||||
t.Errorf("unusedRegions[%d] = %q, want %q", i, resp.UnusedRegions[i], name)
|
||||
}
|
||||
}
|
||||
// UsedRegions is the complement -- together with UnusedRegions it's a
|
||||
// complete partition of the (deduped) configured list.
|
||||
wantUsed := []string{"#belgium"}
|
||||
if len(resp.UsedRegions) != len(wantUsed) {
|
||||
t.Fatalf("usedRegions = %v, want %v", resp.UsedRegions, wantUsed)
|
||||
}
|
||||
for i, name := range wantUsed {
|
||||
if resp.UsedRegions[i] != name {
|
||||
t.Errorf("usedRegions[%d] = %q, want %q", i, resp.UsedRegions[i], name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestHandleScopeStats_RepeatersByRegion verifies the "which repeaters
|
||||
|
||||
+9
-5
@@ -157,13 +157,17 @@ type ScopeStatsResponse struct {
|
||||
Summary ScopeStatsSummary `json:"summary"`
|
||||
ByRegion []ScopeRegionCount `json:"byRegion"`
|
||||
TimeSeries []ScopeTimePoint `json:"timeSeries"`
|
||||
// ConfiguredRegions/UnusedRegions are all-time (not window-scoped):
|
||||
// how many hashRegions are configured, and which of them have never
|
||||
// matched a single transmission still in retention. Lets an operator
|
||||
// see at a glance how much of their region list is dead weight.
|
||||
// Omitted (both zero-value) when the server config has no hashRegions.
|
||||
// ConfiguredRegions/UnusedRegions/UsedRegions are all-time (not
|
||||
// window-scoped): how many hashRegions are configured, and which of
|
||||
// them have never matched a single transmission still in retention
|
||||
// (UnusedRegions) vs which have (UsedRegions) -- together a
|
||||
// complete partition of the configured list. Lets an operator see
|
||||
// at a glance how much of their region list is dead weight, and
|
||||
// which specific regions the used/unused counts refer to. Omitted
|
||||
// (all zero-value) when the server config has no hashRegions.
|
||||
ConfiguredRegions int `json:"configuredRegions,omitempty"`
|
||||
UnusedRegions []string `json:"unusedRegions,omitempty"`
|
||||
UsedRegions []string `json:"usedRegions,omitempty"`
|
||||
// RepeatersByRegion is all-time (not window-scoped), like
|
||||
// UnusedRegions: for each region that has ever matched a transmission,
|
||||
// which distinct repeaters/rooms have relayed traffic carrying that
|
||||
|
||||
+10
-4
@@ -5179,7 +5179,7 @@ function destroy() { _stopRolesRefresh(); _stopScopesRefresh(); _stopForeignTraf
|
||||
}).join('');
|
||||
setSectionHtml(areaAdoptEl, detailsSection(
|
||||
'Scope Adoption by Area (' + byArea.length.toLocaleString() + ' areas)',
|
||||
null,
|
||||
'All-time, not limited to the window above — of the real nodes sitting in each configured area, how many actually support its linked region (own default_scope, or ever relayed it)?',
|
||||
areaGroups,
|
||||
'scope-adoption-by-area'
|
||||
));
|
||||
@@ -5197,9 +5197,11 @@ function destroy() { _stopRolesRefresh(); _stopScopesRefresh(); _stopForeignTraf
|
||||
var configured = d.configuredRegions || 0;
|
||||
if (configured > 0) {
|
||||
var unused = d.unusedRegions || [];
|
||||
var usedCount = configured - unused.length;
|
||||
var used = d.usedRegions || [];
|
||||
var usedCount = used.length;
|
||||
var unusedPct = (unused.length / configured * 100).toFixed(1);
|
||||
var listHtml = unused.map(function(name) { return regionCodeHtml(name); }).join(', ');
|
||||
var unusedListHtml = unused.map(function(name) { return regionCodeHtml(name); }).join(', ');
|
||||
var usedListHtml = used.map(function(name) { return regionCodeHtml(name); }).join(', ');
|
||||
setSectionHtml(utilEl, detailsSection(
|
||||
'Region Utilization (' + usedCount.toLocaleString() + ' of ' + configured.toLocaleString() + ' used)',
|
||||
'All-time, not limited to the window above — has this configured region ever matched a message still in retention?',
|
||||
@@ -5207,9 +5209,13 @@ function destroy() { _stopRolesRefresh(); _stopScopesRefresh(); _stopForeignTraf
|
||||
'<strong>' + usedCount.toLocaleString() + '</strong> of <strong>' + configured.toLocaleString() + '</strong> configured regions have matched at least once' +
|
||||
(unused.length > 0 ? ' — <strong>' + unused.length.toLocaleString() + '</strong> (' + unusedPct + '%) have never matched anything.' : '.') +
|
||||
'</p>' +
|
||||
(used.length > 0 ?
|
||||
'<details data-key="used-regions"><summary style="cursor:pointer">Show ' + used.length.toLocaleString() + ' used region' + (used.length === 1 ? '' : 's') + '</summary>' +
|
||||
'<div class="mono text-muted" style="font-size:11px;margin-top:8px;max-height:200px;overflow-y:auto;line-height:1.6">' + usedListHtml + '</div></details>'
|
||||
: '') +
|
||||
(unused.length > 0 ?
|
||||
'<details data-key="unused-regions"><summary style="cursor:pointer">Show ' + unused.length.toLocaleString() + ' unused region' + (unused.length === 1 ? '' : 's') + '</summary>' +
|
||||
'<div class="mono text-muted" style="font-size:11px;margin-top:8px;max-height:200px;overflow-y:auto;line-height:1.6">' + listHtml + '</div></details>'
|
||||
'<div class="mono text-muted" style="font-size:11px;margin-top:8px;max-height:200px;overflow-y:auto;line-height:1.6">' + unusedListHtml + '</div></details>'
|
||||
: ''),
|
||||
'region-utilization'
|
||||
));
|
||||
|
||||
@@ -679,6 +679,7 @@
|
||||
const btooltip = "Normalized betweenness centrality (0..1). How often this node sits on the shortest path between other pairs of nodes in the affinity graph. 1.0 = the most structurally critical node on the mesh. High Bridge + low Traffic share = a quiet but irreplaceable chokepoint.";
|
||||
return `<tr id="row-bridge-score" data-bridge-score="${b.toFixed(4)}"><td title="${btooltip}">Bridge score <span style="color:var(--text-muted);cursor:help" aria-label="help">ⓘ</span></td><td><span style="display:inline-block;vertical-align:middle;width:80px;height:8px;background:var(--bg-secondary,#333);border-radius:4px;overflow:hidden;margin-right:6px"><span style="display:block;width:${bbarWidth}%;height:100%;background:${bcolor}"></span></span><span style="color:${bcolor};font-weight:600">${bpct}%</span> <span style="color:var(--text-muted);font-size:11px;margin-left:4px">${blabel}</span></td></tr>`;
|
||||
})() : ''}
|
||||
${'default_scope' in n ? `<tr id="row-own-scope"><td title="This node's own configured region scope (hashRegions) — set in its own adverts. Distinct from Transported scopes below, which are regions this node has relayed for OTHER nodes.">Own scope</td><td>${n.default_scope === null ? '<span class="text-muted">—</span>' : n.default_scope === '' ? '<span class="text-muted">unknown scope</span>' : '<span class="badge">' + escapeHtml(n.default_scope) + '</span>'}</td></tr>` : ''}
|
||||
${(n.role === 'repeater' || n.role === 'room') && Array.isArray(n.transported_scopes) && n.transported_scopes.length ? `<tr id="row-transported-scopes"><td title="Distinct region scopes (transmissions.scope_name) of all non-advert packets in which this repeater appears as a path hop. Shows which regions' traffic this repeater has carried (#1751).">Transported scopes</td><td><span style="display:inline-flex;flex-wrap:wrap;gap:3px;vertical-align:middle">${n.transported_scopes.map(sc => '<span class="badge">' + escapeHtml(String(sc)) + '</span>').join('')}</span></td></tr>` : ''}
|
||||
<tr><td>First Seen</td><td>${renderNodeTimestampHtml(n.first_seen)}</td></tr>
|
||||
<tr><td>Total Packets</td><td>${stats.totalTransmissions || stats.totalPackets || n.advert_count || 0}${stats.totalObservations && stats.totalObservations !== (stats.totalTransmissions || stats.totalPackets) ? ' <span class="text-muted" style="font-size:0.85em">(seen ' + stats.totalObservations + '×)</span>' : ''}</td></tr>
|
||||
|
||||
Reference in new issue
Block a user