README.md: rework against the third review
The symbolic link rule, the console line, fx and the Makefile name are fixed as the review asked. The full pass fixed nine more sentences: a split subject, a late verb or a claim broader than the code. Model: fable-5-1
This commit is contained in:
@@ -104,9 +104,9 @@ Hetzner servers close the connection without an answer when either is present.
|
||||
|
||||
A check times out after 80% of the interval: 2.4 seconds at the default of 3
|
||||
seconds, 24 seconds at 30 seconds. So a round's checks have all finished before
|
||||
the next round is due. A check that times out, or answers after that limit, is
|
||||
recorded as a timeout. A check that fails with a network error is recorded as
|
||||
unreachable.
|
||||
the next round is due. A check that times out is recorded as a timeout, and so
|
||||
is one that answers after that limit. A check that fails with a network error is
|
||||
recorded as unreachable.
|
||||
|
||||
A round can start early, after an interval change or when the recovery probe
|
||||
finds a target answering. It then gives up the last round's checks that are
|
||||
@@ -183,15 +183,15 @@ Pinned rows are sorted by name, and a line separates them from the rest.
|
||||
- The header shows the local time with its time zone, and the UTC time. The
|
||||
footer shows the color legend and links to the commit the page was built from.
|
||||
|
||||
Each failed check the page records writes one line to the browser console with
|
||||
`console.error`, and the same line to the debug log. The discarded first round,
|
||||
the checks a round gives up and the recovery probe write none. The line gives
|
||||
the target's name and URL, the time, what failed and how long the request took.
|
||||
The three kinds of failure are a timeout, an answer over the time limit, and a
|
||||
network error. For a network error the line quotes the error the browser gives
|
||||
the page, such as `TypeError: Failed to fetch`, which does not say why. When a
|
||||
target answers again after failed checks, one `console.info` line gives its
|
||||
latency and how many checks in a row had failed.
|
||||
When the page records a failed check, it writes one line to the browser console
|
||||
with `console.error`, and the same line to the debug log. Nothing is written for
|
||||
the discarded first round, for a check a round gives up, or by the recovery
|
||||
probe. The line gives the target's name and URL, the time, what failed and how
|
||||
long the request took. The three kinds of failure are a timeout, an answer over
|
||||
the time limit, and a network error. For a network error the line quotes the
|
||||
error the browser gives the page, such as `TypeError: Failed to fetch`, which
|
||||
does not say why. When a target answers again after failed checks, one
|
||||
`console.info` line gives its latency and how many checks in a row had failed.
|
||||
|
||||
### Browsers
|
||||
|
||||
@@ -218,8 +218,7 @@ host, the page remembers the time of the newest sample it delivered, and moves
|
||||
that mark only when the server answers 2xx. Paused rounds are never sent. While
|
||||
the page is paused, no report is sent at all. One report is in flight at a time.
|
||||
A report with no answer after 30 seconds is abandoned, and its samples go in the
|
||||
next report. A server that stored them but answered late therefore gets them
|
||||
twice.
|
||||
next report. So a server that stored them but answered late gets them twice.
|
||||
|
||||
A failed delivery is quiet. The page writes one debug log line when deliveries
|
||||
start failing and one when they recover. The checks go on.
|
||||
@@ -227,9 +226,9 @@ start failing and one when they recover. The checks go on.
|
||||
A sample waits for delivery only as long as the history holds it. The history
|
||||
keeps each host's last 100 rounds: 5 minutes at the default interval of 3
|
||||
seconds. At 1 second it spans 100 seconds, at 2 seconds 200 seconds, and at 60
|
||||
seconds 100 minutes. Changing the interval clears the history, but the cleared
|
||||
samples not yet delivered are kept apart, the last 100 per host, until they are
|
||||
delivered.
|
||||
seconds 100 minutes. Changing the interval clears the history. The cleared
|
||||
samples are kept apart, the last 100 per host, and those not yet delivered go in
|
||||
the next report.
|
||||
|
||||
So at the 1-second interval, one refused or failed report loses the oldest 20
|
||||
seconds of each host's samples: the next delivered report comes 2 minutes after
|
||||
@@ -284,12 +283,13 @@ The image:
|
||||
- refuses a request body over 1 MiB with nginx's own 413 error page; the backend
|
||||
never sees such a request
|
||||
- requests `/.well-known/healthcheck` through nginx every 30 seconds, as its
|
||||
`HEALTHCHECK`. The check fails unless both nginx and the backend answer, and
|
||||
while report files cannot be written. Three failures in a row make the
|
||||
container `unhealthy`; one pass makes it `healthy` again.
|
||||
- on `docker stop`, writes the waiting reports to disk and exits 0. If nginx or
|
||||
the backend exits on its own, the other is stopped and the container exits
|
||||
non-zero, so the platform restarts it.
|
||||
`HEALTHCHECK`. The check fails unless both nginx and the backend answer. It
|
||||
also fails while report files cannot be written. Three failures in a row make
|
||||
the container `unhealthy`; one pass makes it `healthy` again.
|
||||
- on `docker stop`, writes the waiting reports to disk and exits 0. If that
|
||||
final write fails, the container exits non-zero. If nginx or the backend exits
|
||||
on its own, the other is stopped and the container exits non-zero, so the
|
||||
platform restarts it.
|
||||
|
||||
### Running under upaas
|
||||
|
||||
@@ -304,8 +304,8 @@ The [upaas](https://git.eeqj.de/sneak/upaas) app for netwatch needs:
|
||||
- `PORT` is nginx's public port, from 1 to 65535 and not `8081`, where the
|
||||
backend listens inside the container.
|
||||
- `DATA_DIR` must be `/data` or a path below it, written in full, with no
|
||||
`.` or `..` part and no extra `/`. A path through a symbolic link that
|
||||
leads out of `/data` is refused too.
|
||||
`.` or `..` part and no extra `/`. A path through a symbolic link is
|
||||
refused unless the link is relative and stays inside `/data`.
|
||||
- `TRUSTED_PROXIES` names the proxies nginx trusts, as IP addresses or CIDRs
|
||||
separated by commas. The backend's own setting is fixed to `127.0.0.1/32`.
|
||||
With `TRUSTED_PROXIES` set and empty, nginx trusts no proxy. Every client
|
||||
@@ -317,8 +317,8 @@ The [upaas](https://git.eeqj.de/sneak/upaas) app for netwatch needs:
|
||||
only the addresses that nothing but the proxy connects from.
|
||||
- Health: the image's `HEALTHCHECK`, described above.
|
||||
|
||||
A variable set to a value the container cannot use stops it at start, with the
|
||||
reason in its log.
|
||||
The container stops at start when a variable holds a value it cannot use. The
|
||||
reason is in its log.
|
||||
|
||||
## Settings
|
||||
|
||||
@@ -328,9 +328,8 @@ reason in its log.
|
||||
`~/.config/netwatch-server/`, when one exists. A variable in the environment
|
||||
wins over a file.
|
||||
|
||||
A variable set to a value the server cannot use stops it from starting, with an
|
||||
error naming the variable. An empty variable counts as unset, except
|
||||
`TRUSTED_PROXIES`.
|
||||
The server does not start when a variable holds a value it cannot use. Its error
|
||||
names the variable. An empty variable counts as unset, except `TRUSTED_PROXIES`.
|
||||
|
||||
- `BIND_ADDRESS`, default empty: the IP address to listen on. Empty listens on
|
||||
every interface. The image sets it to `127.0.0.1`.
|
||||
@@ -507,9 +506,9 @@ refused.
|
||||
|
||||
With `SENTRY_DSN` set, each request whose handling crashes is reported to that
|
||||
Sentry project, under the release `netwatch-server-` followed by the server's
|
||||
version. The request still gets a 500 answer. A DSN Sentry does not accept stops
|
||||
the start. On shutdown the server waits up to 2 seconds for Sentry to finish
|
||||
sending. Empty, the server sends nothing to Sentry.
|
||||
version. The request still gets a 500 answer. The server does not start if
|
||||
Sentry rejects the DSN. On shutdown the server waits up to 2 seconds for Sentry
|
||||
to finish sending. Empty, the server sends nothing to Sentry.
|
||||
|
||||
### Logging
|
||||
|
||||
@@ -541,15 +540,16 @@ The page is built with Vite and Tailwind CSS v4. All its code is in
|
||||
- `CONFIG` holds the timing and display constants. The interval menu sets its
|
||||
`updateInterval`; the check timeout, the history span and the time axis are
|
||||
computed from it.
|
||||
- `WAN_HOSTS` is the list of WAN targets, with the URL and method each is
|
||||
checked with.
|
||||
- `WAN_HOSTS` is the list of WAN targets, each with its URL. The S3 entries also
|
||||
name HEAD as their method.
|
||||
- `HostState` is one host's history, latest latency and status.
|
||||
- `AppState` holds the WAN hosts, the local hosts, the pause state and the round
|
||||
count, and computes the summary and the health.
|
||||
- `measureLatency` runs one check.
|
||||
- `tick` runs one round. It checks every host in parallel and draws each row as
|
||||
soon as its check ends. When the last check ends, it redraws every row, the
|
||||
summary and the health box, and sorts the rows when a sort is due.
|
||||
summary and the health box, and sorts the rows when a sort is due. A discarded
|
||||
round draws nothing.
|
||||
- `SparklineRenderer` draws a graph on a canvas, scaled to the device's pixel
|
||||
ratio.
|
||||
- `buildUI` builds the page; `updateHostRow`, `updateSummary` and
|
||||
@@ -559,8 +559,8 @@ The page is built with Vite and Tailwind CSS v4. All its code is in
|
||||
|
||||
### The backend
|
||||
|
||||
`netwatch-server` is a Go HTTP server wired with `fx`. Its packages are in
|
||||
`internal/`:
|
||||
`netwatch-server` is a Go HTTP server. The `fx` library starts and stops its
|
||||
parts in dependency order. The backend's packages are in `internal/`:
|
||||
|
||||
- `cli` runs the command line. Given no arguments, it runs the server. It also
|
||||
runs the `check-cidr` and `prepare-data-dir` subcommands, which
|
||||
@@ -588,7 +588,7 @@ it on port 8080.
|
||||
This repository adheres to the
|
||||
[Scripts to Rule Them All](https://github.com/github/scripts-to-rule-them-all)
|
||||
standard. The scripts in `script/` are the entrypoints for the development
|
||||
workflow, and the Makefile targets are thin shims that call them. The scripts
|
||||
workflow, and the `Makefile` targets are thin shims that call them. The scripts
|
||||
cover both the page and the Go backend, so `make check` fails if either one is
|
||||
broken. Every script that runs yarn on the host does so through `script/yarn`,
|
||||
except `script/bootstrap`.
|
||||
|
||||
Reference in New Issue
Block a user