fix(rf-health): add region filter support to metrics summary

Frontend passes RegionFilter query string to summary API.
Backend filters results by observer IATA region.
Added iata field to MetricsSummaryRow.
This commit is contained in:
you
2026-04-05 06:00:42 +00:00
parent 968c104e14
commit 747aea37b7
3 changed files with 16 additions and 3 deletions

View File

@@ -1781,6 +1781,7 @@ func (db *DB) GetObserverMetrics(observerID, since, until string) ([]MetricsSamp
type MetricsSummaryRow struct {
ObserverID string `json:"observer_id"`
ObserverName *string `json:"observer_name"`
IATA string `json:"iata,omitempty"`
CurrentNF *float64 `json:"current_noise_floor"`
AvgNF *float64 `json:"avg_noise_floor_24h"`
MaxNF *float64 `json:"max_noise_floor_24h"`
@@ -1800,7 +1801,7 @@ func (db *DB) GetMetricsSummary(since string) ([]MetricsSummaryRow, error) {
FROM observer_metrics
WHERE timestamp >= ?
)
SELECT m.observer_id, o.name,
SELECT m.observer_id, o.name, COALESCE(o.iata, '') as iata,
r.noise_floor as current_nf,
AVG(m.noise_floor) as avg_nf,
MAX(m.noise_floor) as max_nf,
@@ -1822,7 +1823,7 @@ func (db *DB) GetMetricsSummary(since string) ([]MetricsSummaryRow, error) {
var result []MetricsSummaryRow
for rows.Next() {
var s MetricsSummaryRow
if err := rows.Scan(&s.ObserverID, &s.ObserverName, &s.CurrentNF, &s.AvgNF, &s.MaxNF, &s.CurrentBattMv, &s.SampleCount); err != nil {
if err := rows.Scan(&s.ObserverID, &s.ObserverName, &s.IATA, &s.CurrentNF, &s.AvgNF, &s.MaxNF, &s.CurrentBattMv, &s.SampleCount); err != nil {
return nil, err
}
result = append(result, s)

View File

@@ -2193,6 +2193,7 @@ func (s *Server) handleMetricsSummary(w http.ResponseWriter, r *http.Request) {
if window == "" {
window = "24h"
}
region := r.URL.Query().Get("region")
// Parse window duration
dur, err := parseWindowDuration(window)
@@ -2211,6 +2212,17 @@ func (s *Server) handleMetricsSummary(w http.ResponseWriter, r *http.Request) {
summary = []MetricsSummaryRow{}
}
// Filter by region if specified
if region != "" {
filtered := make([]MetricsSummaryRow, 0)
for _, row := range summary {
if strings.EqualFold(row.IATA, region) {
filtered = append(filtered, row)
}
}
summary = filtered
}
writeJSON(w, map[string]interface{}{
"observers": summary,
})

View File

@@ -2700,7 +2700,7 @@ function destroy() { _analyticsData = {}; _channelData = null; if (_ngState && _
// Compute window string for summary endpoint
const windowMap = { '1h':'1h', '3h':'3h', '6h':'6h', '12h':'12h', '24h':'24h', '3d':'3d', '7d':'7d', '30d':'30d' };
const window = windowMap[_rfHealthState.range] || '24h';
const summaryData = await api('/observers/metrics/summary?window=' + window);
const summaryData = await api('/observers/metrics/summary?window=' + window + (RegionFilter.regionQueryString() || ''));
const observers = summaryData.observers || [];
// Filter to observers with sufficient sparkline data (≥2 non-null noise_floor values)