Skip to content

feat(observers): per-observer activity endpoint - #135

Merged
MrAlders0n merged 1 commit into
devfrom
observer-activity
Sep 10, 2026
Merged

MrAlders0n merged 1 commit into
devfrom
observer-activity

Conversation

@MrAlders0n

Copy link
Copy Markdown
Member

Summary

GET /api/v1/observers/{observerId}/activity?range=24h&interval=15m — a per-observer, time-bucketed view of what an observer heard: observation counts, LoRa airtime, SNR/RSSI aggregates and a whole-range payload-type breakdown. Feeds four new charts on the Stats → Observer tab.

Design

  • Airtime is computed at ingest and stored on packet_observations.airtime_ms (RadioLib getTimeOnAir, MeshCore preamble rule, internal/lora). Ingest has the raw frame so the length is exact. Rows without radio params stay NULL.
  • No request path joins back to packets — the same join that overran /dev/shm for the payload breakdown before migration 015.
  • Intervals ≥ 1h read an hourly matview mv_observer_activity_hourly (observer, payload type, hour) over 30 days, refreshed with the other views. 5m/15m read packet_observations over idx_observations_observer, capped at a 48h window.
  • Cached 60 s per observer/range/interval.

Migrations

  • 030 adds the column (ALTER only, so the lock is released immediately).
  • 031 backfills the last 7 days with a throwaway SQL copy of the formula, like 015.
  • 032 creates the matview + unique index.

Verify before merging

These have only been reviewed, not executed — there is no Postgres on the dev box:

  1. Apply 030–032 on a prod-sized copy; time the backfill UPDATE and the matview build, and time one REFRESH … CONCURRENTLY (this view is keyed by observer, so it is larger than the IATA-keyed ones).
  2. EXPLAIN ANALYZE the raw 24h/15m and hourly 720h/6h queries on a busy observer; both should use idx_observations_observer and never touch packets.
  3. Spot-check a few backfilled airtime_ms values against lora.TimeOnAirMs.

Tests

Formula spot checks (SF7/62.5/CR5/50 B → 244.224 ms; SF10 trips LDRO), end-to-end frame-length reconstruction for flood, transport and 2-byte-hash paths, gomock store tests for both paths and all null gating, handler tests for every validation rule. Swagger regenerated. Docs in beacon-docs api_contract.md.

GET /observers/{id}/activity returns bucketed observation counts, LoRa
airtime, SNR/RSSI aggregates and a payload-type breakdown for one
observer. Airtime is computed at ingest from the raw frame length and
stored on the observation; intervals of 1h and up are served from an
hourly matview so no request path joins back to packets.
@MrAlders0n
MrAlders0n requested a review from 446564 as a code owner September 10, 2026 10:44
@MrAlders0n
MrAlders0n merged commit b66573b into dev Sep 10, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant