Measurements, bearings and positions
Three kinds of reading, kept apart on purpose. A bearing is averaged around the circle rather than through the 0°/360° seam, where the plain average of 350° and 10° would come out as due south.
Live data
Readings arrive from whatever you already run, are checked before they are kept, and show up in every module pointed at them. The two Monitor modules are there so you never have to take that on trust.
From your message brokers, from a plain HTTP call, or from the log exporter you already use.
Into a measurement, a bearing or a position — and a value aimed at the wrong kind of sensor is refused rather than stored as something it is not.
Timestamps are held to a window you configure, so a mis-clocked sender cannot write into next year.
A reading delivered twice is recognised as the same reading, instead of quietly pulling an average off course.
On a chart, a tile, a map marker or a floor plan — wherever you pointed something at it.
Three kinds of reading, kept apart on purpose. A bearing is averaged around the circle rather than through the 0°/360° seam, where the plain average of 350° and 10° would come out as due south.
Every chart and tile picks its own per-interval summary: average, minimum, maximum, sum, count, median and percentiles, spike envelopes, standard deviation, meter deltas or data coverage — the percentiles precomputed as each day and month is compacted, so asking for a P95 costs what asking for an average does. Directions get proper circular statistics — a compass heading, a wind rose's sector distribution — and positions draw as tracks over time rather than being averaged into a point that was never visited.
Application logs and custom text payloads arrive the same way and land in Log Explorer — searchable by identifier, source and time, and marked with your highlight groups.
Anything that does go missing is reported as such rather than quietly forgotten. That is the number worth alerting on, and it is on the Monitor pages rather than buried.
Every transport accepts a batch of readings per message — a gateway flushing a second of its sensors' samples at once — as well as one reading at a time. The batch shape is what lets a single ingestion instance take hundreds of thousands of readings a second.
A broker consumer that stalls on a dead connection is noticed, reported on the health endpoint and restarted — on every transport, the same way — rather than sitting silently while readings pile up unseen.
For the engineers
If your team thinks in data-engineering terms, the ingestion path is ETL — extract, transform, load — running continuously rather than on a nightly schedule. The transform is finished before anything reaches long-term storage, so what is stored is already the clean, canonical shape every module reads.
Readings arrive from the message brokers you already run, or over plain HTTP. The producer's own field names are mapped onto one canonical shape at the door — nothing downstream ever sees a source-specific format, and adding a source never changes what is stored.
Before storage, every reading is validated, its timestamp normalised and held to the accepted window, a redelivery recognised as the same reading, and its kind — measurement, bearing or position — decided. Readings are then reduced into per-minute summaries, computed correctly across every receiving instance, not per machine.
A separate sweep writes finished minutes into the database, decoupled from arrival — slow storage delays storage, never ingestion, and the Monitor pages show exactly how far behind the load stage is. At month close, sealed months are folded into compact query form inside the database itself.
The same three stages carry text and logs — extracted from the same brokers, the standard telemetry log protocol and plain HTTP, and loaded as compressed files rather than database rows, so log volume never weighs on the database.