Skip to content

Commit 0afc74d

Browse files
cansofgreaseclaude
andcommitted
Correct the readme, and picture the settings panel
Some of what the readme said had drifted from what the program does. It named the reason a server wins a Best-of round as `fastest`, which nothing reports - it is `fastest_ranked`. It put the power switch in the row of tabs, when it sits beside them in the top bar. It listed some of the columns the exported spreadsheet ends with and not others, so anyone opening a file found five columns the readme never mentioned. It explained the export's version number without saying that turning Discard losers off is what moves it. And it never named the server the bufferbloat test pings - one.one.one.one - a call the "who does Pingularity talk to" table was missing as well. One more address the dashboard uses, /api/speedtest/candidates, was absent from the list of calls that carry no body. The pictures were behind in two ways. The themes picture showed six themes when there are nine, leaving out Parchment, Solarized and Ember; it now shows all nine. And nothing pictured the settings panel, which is where most of the readme's second half happens, so there is a shot of it now, open on the Ookla tab with the server list, the Best-of controls and the saved servers. The descriptions attached to each picture for people who cannot see them were written for older versions of those pictures and now match what is in them. The dashboard picture also stops describing itself as the live demo, which it is not. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 0412179 commit 0afc74d

3 files changed

Lines changed: 29 additions & 19 deletions

File tree

README.md

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ by majority vote (a *quorum* across multiple *anchors*), with anti-flapping
1010
latency, uptime, and speed to SQLite and shows it all in a live UI - no runtime
1111
to install.
1212

13-
This is the [live demo](https://demo.pingularity.dev) - same dashboard, synthetic data:
13+
This is the dashboard on a real install. The [live demo](https://demo.pingularity.dev)
14+
is the same thing on synthetic data, with a badge to say so:
1415

15-
![The Pingularity dashboard: top-bar status bubbles, the Connection panel (IP / ISP / DNS / internet exit), a speedtest with bufferbloat, the latency-over-time chart, and a year-long downtime heatmap](https://raw.githubusercontent.com/pingular/pingularity/main/docs/dashboard.png)
16+
![The Pingularity dashboard: top-bar status bubbles, the Connection panel (IP / ISP / DNS / internet exit), the Speed panel - seven stat tiles over three stacked charts - the "Lowest round-trip across anchors" latency chart with its DNS line and clickable anchor pills, and a year-long downtime heatmap](https://raw.githubusercontent.com/pingular/pingularity/main/docs/dashboard.png)
1617

1718
## Quick start
1819

@@ -454,7 +455,11 @@ published.
454455
> are down: any run carrying the new columns stamps the export for the release
455456
> that introduced them - 0.70 for the failed-run marker, higher again for the
456457
> city-race verdict every Ookla run has recorded since - and an older build
457-
> refuses a newer stamp outright rather than restoring half of it.
458+
> refuses a newer stamp outright rather than restoring half of it. One rung is
459+
> yours to trigger: with **Discard losers** off a round's other servers are kept
460+
> as rows of their own, which stamps the export a rung higher again, so take the
461+
> backup before you turn it off (or turn it back on first) if the file has to
462+
> restore onto an older release.
458463
459464
## Run in the background (systemd / launchd / Windows service)
460465
@@ -670,13 +675,13 @@ transfer, reported as their **median** (if none of them land, iperf3's own
670675
`min_rtt`, and failing that the idle baseline). There is no separate fastest
671676
figure on those runs, so that median is both what is shown and what decides.
672677
673-
![The Speed panel: a row of stat tiles (download, upload, ping, jitter, packet loss, and bufferbloat both directions) above three stacked time charts for speed, ping and bufferbloat, with window averages for download, upload and ping below them, per-chart show/hide toggles, and a save-as-image button](https://raw.githubusercontent.com/pingular/pingularity/main/docs/speed-panel.png)
678+
![The Speed panel: a header row with the RUN button, the server this test used and when the next one is due, and a window picker; below it a row of stat tiles (download, upload, ping, jitter, packet loss, and bufferbloat both directions) above three stacked time charts for speed, ping and bufferbloat, with window averages for download, upload and ping below them, per-chart show/hide toggles, a Show all runs button, and a save-as-image button](https://raw.githubusercontent.com/pingular/pingularity/main/docs/speed-panel.png)
674679
675680
**Bufferbloat** is the extra lag that appears only while the line is busy - the
676681
reason a video call breaks up the moment a big download starts. Pingularity
677682
measures it by pinging before the test (idle) and during it (loaded) - both
678-
against a fixed target of its own rather than the speedtest server, so only the
679-
gap between them is meaningful, and the idle figure will not match the **ping**
683+
against a fixed target of its own (`one.one.one.one`, Cloudflare) rather than
684+
the speedtest server, so only the gap between them is meaningful, and the idle figure will not match the **ping**
680685
recorded above:
681686
682687
```mermaid
@@ -942,7 +947,7 @@ rather than by jitter: a run **keeps the server the last automatic run
942947
measured** while it is still among the servers this run pings (the winning
943948
city's list, seeded as above) and still pings within max(2 ms, 15 %) of the
944949
fastest (win reason `incumbent` when that kept it ahead of a faster server;
945-
plain `fastest` when it was the fastest anyway), and failing that prefers your
950+
plain `fastest_ranked` when it was the fastest anyway), and failing that prefers your
946951
ISP's own server inside the same band (`on_net`) - so the history compares
947952
like with like instead of flipping between equivalent servers, while a server
948953
that has gone bad loses its seat the run it goes bad, because the seat is
@@ -1154,6 +1159,7 @@ Below that:
11541159
> | **RIPE IPmap** | the two boundary router IPs the traceroute settles on, and your resolver's egress address, for geolocation | connection refresh + exit discovery |
11551160
> | **ipwho.is**, then **geojs.io** | your public IP, for the ISP/geo line | connection refresh |
11561161
> | **Cloudflare** (`/cdn-cgi/trace`) | a plain fetch, to learn the serving PoP | connection refresh |
1162+
> | **one.one.one.one:443** (Cloudflare) | bare TCP handshakes, no payload - the fixed target the bufferbloat idle and loaded samples are measured against. Resolved through your own resolver, so it reaches whichever of `1.1.1.1`/`1.0.0.1` (or their v6 pair) that answer names | every speedtest that samples bufferbloat |
11571163
> | reverse DNS | router/host IPs, for names | connection refresh |
11581164
> | **Ookla** servers | the speedtest traffic itself, plus a server-list lookup and a small probe of each listed server's upload endpoint (remembered, so a repeat does not send it again); opening the Ookla tab can also cost one by-ID lookup and one name search first, to centre the list on the server your last automatic run used; for the picker's Auto button, the same selection a run performs - one list fetch per candidate city, a round of pings at every racer, then a round at the rest of the winning city's field (up to twelve), no transfer; for a server ID typed in Find, and for a saved pin the drawer has not yet checked this page load (at most twice per server), one by-ID lookup plus one small POST at that server's upload endpoint to learn whether it can still run a test, no transfer; and for the saved list's refresh button, one by-ID lookup, one endpoint probe and a round of pings at each kept server (up to twelve), no transfer | when a speedtest runs, when the Ookla settings tab is opened or a city is searched, when a server ID is typed in Find or a saved pin is first shown, on every Auto click, and on every refresh click in the saved list |
11591165
> | your own **iperf3 server** (opt-in) | the test traffic itself - the TCP transfers, plus a short UDP pass for loss and jitter; or, for the status light in the settings drawer, one bare TCP handshake and nothing else | when an iperf3 speedtest runs, and when the drawer checks a saved server's status light - once per address while the drawer is open with iperf3 selected, plus whenever you click a server's light or change its address |
@@ -1219,9 +1225,11 @@ Below that:
12191225
> run unvetted. Full reasoning in
12201226
> [docs/security-model.md](https://github.com/pingular/pingularity/blob/main/docs/security-model.md).
12211227
1222-
The **logo** (top-right) opens a tabbed settings drawer; a **power** toggle in
1223-
the tab row starts/stops all monitoring. Changes apply **live** (no restart)
1224-
and persist across restarts:
1228+
The **logo** (top-right) opens a tabbed settings drawer; the **power** toggle
1229+
beside it, in the top bar, starts/stops all monitoring. Changes apply **live** (no restart)
1230+
and persist across restarts.
1231+
1232+
![The settings drawer, open on its Ookla tab: a row of tabs (Speedtest, Ookla, iperf3, Latency, Schedule, Data, Alerts, Access, Appearance, About) above the per-test knobs - Best of, Discard losers, Retries, Packet-loss probe, Direction and Parallel connections, each with a hover-help dot; below them the Saved pane with Auto selected, a Find box that takes a place or an Ookla server ID, and the server list with ID, ping and distance columns and a star on each row; Save and Discard sit at the bottom left, Reset to defaults and Reset tiles at the bottom right](https://raw.githubusercontent.com/pingular/pingularity/main/docs/settings-ookla.png)
12251233
12261234
- **Latency** → latency probing on/off, latency interval, probe timeout, and
12271235
sensitivity (failures→down / successes→up, IPv6 mode auto/on/off), plus the
@@ -1420,7 +1428,7 @@ and persist across restarts:
14201428
**Nine built-in themes**, every one fully recolourable (backgrounds, panels,
14211429
status colours, chart series - each picker previews live and resets to the theme):
14221430
1423-
![Six of Pingularity's built-in themes side by side: Retro, Dark, Light, Cyber, Solarized, and Amoled](https://raw.githubusercontent.com/pingular/pingularity/main/docs/themes.png)
1431+
![All nine of Pingularity's built-in themes in a three-by-three grid: Retro, Dark, Amoled across the top; Cyber, Slate, Light in the middle; Parchment, Solarized, Ember along the bottom](https://raw.githubusercontent.com/pingular/pingularity/main/docs/themes.png)
14241432
14251433
> **Notifications** post to one webhook URL, shaped per host so the common
14261434
> targets just work - JSON everywhere except ntfy. Discord → `{content}`,
@@ -1925,8 +1933,8 @@ constant memory.
19251933
19261934
Every `POST` must carry `Content-Type: application/json`, **including the ones
19271935
with no body at all** (`/api/speedtest`, `/api/speedtest/abort`, `/api/netinfo`,
1928-
`/api/iperf/check`, `/api/speedtest/servers`, `/api/auth/logout`), which answer
1929-
`415` without it. It is a CSRF guard: a cross-site form cannot set that content
1936+
`/api/iperf/check`, `/api/speedtest/servers`, `/api/speedtest/candidates`,
1937+
`/api/auth/logout`), which answer `415` without it. It is a CSRF guard: a cross-site form cannot set that content
19301938
type without a preflight this daemon never grants. So
19311939
`curl -X POST -H 'Content-Type: application/json' http://127.0.0.1:9000/api/speedtest`,
19321940
and `-d '{…}'` where a body is listed below.
@@ -1987,12 +1995,14 @@ and `-d '{…}'` where a body is listed below.
19871995
transfer actually used) and `udp_direction` (`down`/`up`, which way the
19881996
loss/jitter probe sampled); on runs that didn't establish one - and rows
19891997
predating the fields - the keys are omitted rather than sent empty
1990-
- `GET /api/speed/runs.csv` - all runs as CSV. The same two fields are the
1991-
final columns, `ip_family` and `udp_direction`, appended at the end so
1992-
consumers indexing existing columns by position keep working; blank =
1993-
unrecorded. After them, `round_of`: on a row measured in a Best-of round
1994-
that another server won (**Discard losers** off), the winner's timestamp;
1995-
blank on a test's own result
1998+
- `GET /api/speed/runs.csv` - all runs as CSV. Everything added since the
1999+
original column set is appended at the END, so consumers indexing existing
2000+
columns by position keep working. In order, the tail is `ip_family` and
2001+
`udp_direction` (blank = unrecorded); `round_of`, which on a row measured in
2002+
a Best-of round that another server won (**Discard losers** off) carries the
2003+
winner's timestamp and is blank on a test's own result; and then the same
2004+
five the runs table's **Centre** column is built from - `win_reason`,
2005+
`race_outcome`, `race_winner_label`, `race_winner_ms`, `race_racers`
19962006
- `POST /api/speed/runs/delete` - `{ts}` delete one speedtest run
19972007
- `GET /api/speed/runs/servers?ts=` - the server-selection report for one
19982008
Ookla run (`ts` = the run's unix seconds) - every automatic run, challenge

docs/settings-ookla.png

64.6 KB
Loading

docs/themes.png

-690 KB
Loading

0 commit comments

Comments
 (0)