milestone 13 discrepancies: redact credentials from urls in logs, metrics and cli output
This commit is contained in:
+105
-42
@@ -23,21 +23,24 @@ Serves DNS until SIGINT or SIGTERM.
|
||||
| `--config FILE` | Seed configuration file (default `/etc/nxdns/config.zon`). Read only when the database has never been configured. |
|
||||
| `--web-dev DIR` | Serve the web interface from DIR instead of the embedded assets, with no cache headers. Development only. |
|
||||
|
||||
Seeding failures are not treated as configuration faults here: a seed file that
|
||||
is unparseable, oversized or invalid prints its diagnostics and exits 1, not 2.
|
||||
See [exit codes](#exit-codes).
|
||||
A seed file that is unparseable, oversized or invalid prints its diagnostics and
|
||||
exits 2 — the same code `check` and `import` give for the same file. See
|
||||
[exit codes](#exit-codes).
|
||||
|
||||
## `check`
|
||||
|
||||
Validates the configuration and probes the upstreams. Exit 0 when clean, 2 when
|
||||
it found problems. It always reports every problem, not just the first. What it
|
||||
checks, in order:
|
||||
Validates the configuration and probes the upstreams. Exit 0 when it found no
|
||||
failures, 2 when it found one. It always reports every problem, not just the
|
||||
first. What it checks, in order:
|
||||
|
||||
1. Which source to check (see [source selection](#source-selection)).
|
||||
2. Full validation — the same rules `import` enforces.
|
||||
3. For each enabled DoH/DoT listener: certificate and key are readable (FAIL if
|
||||
not), and the key's permissions are owner-only (WARN if any group or other
|
||||
bit is set; the WARN does not change the exit code).
|
||||
3. For each enabled DoH/DoT listener: both PEM files are read and the key is
|
||||
tested against the certificate, through the same `CertStore.init` the
|
||||
listeners boot with. A file that is missing, unreadable, too large or
|
||||
unparseable, and a key that does not belong to the certificate, are all FAIL.
|
||||
The key's permissions are a separate finding: WARN when any group or other
|
||||
bit is set, which does not change the exit code.
|
||||
4. A live probe: one real A query for `example.com` through every enabled
|
||||
upstream, driving the same pool and failover machinery the server uses, with
|
||||
`upstream.total_timeout_ms` as the per-attempt deadline. A FAIL line names
|
||||
@@ -50,13 +53,28 @@ checks, in order:
|
||||
| `--data-dir DIR` | Data directory to look for `config.db` in. |
|
||||
| `--config FILE` | Check this file instead of the database. |
|
||||
|
||||
### Failures and warnings
|
||||
|
||||
Every finding carries a severity. `FAIL` is a problem that sets exit 2. `WARN`
|
||||
is legal configuration that is almost certainly not what was meant — a blocklist
|
||||
source no group links to, a TLS key readable beyond its owner — and never
|
||||
changes an exit code, because the service starts either way.
|
||||
|
||||
The last line is a summary, and it never contradicts the lines above it:
|
||||
|
||||
| What was found | Last line | Exit |
|
||||
| --- | --- | --- |
|
||||
| Nothing | `OK: no problems found` | 0 |
|
||||
| Warnings only | `OK: no failures found, 2 warnings` — `1 warning` in the singular | 0 |
|
||||
| At least one failure | No summary line; the FAIL lines are the report | 2 |
|
||||
|
||||
### Source selection
|
||||
|
||||
- `--config FILE` given explicitly: check that file, nothing else.
|
||||
- Otherwise, if `<data-dir>/config.db` exists: check the database — the right
|
||||
default, since the database is the truth on a configured server. Pending
|
||||
schema migrations are applied first, so a `check` immediately after an upgrade
|
||||
works.
|
||||
default, since the database is the truth on a configured server. It is opened
|
||||
immutable, so `check` writes nothing to it; see
|
||||
[what `check` does not do](#what-check-does-not-do).
|
||||
- Otherwise, if the default config file path exists: check it.
|
||||
- Otherwise: "nothing to check", exit 2.
|
||||
|
||||
@@ -64,10 +82,42 @@ The first line of output always names which source was checked. A file larger
|
||||
than 4 MiB fails with `larger than 4194304 bytes`; a ZON syntax error is
|
||||
reported with its line and column.
|
||||
|
||||
A missing file is treated differently depending on how the path was reached. An
|
||||
explicit `--config FILE` that does not exist is an I/O failure: `check failed:
|
||||
FileNotFound` on stderr, exit 1. A default path that does not exist is one of
|
||||
the cases above and produces "nothing to check", exit 2.
|
||||
A named file that is missing or unreadable is a finding like any other, not an
|
||||
I/O failure that escapes the run: `FAIL <path>: no such file` or
|
||||
`FAIL <path>: not readable`, exit 2. That is the same code the implicit path
|
||||
gives when there is nothing to check, so naming the file does not change what a
|
||||
missing file costs.
|
||||
|
||||
### What `check` does not do
|
||||
|
||||
`check` never writes to `config.db`. It opens the file immutable, which means
|
||||
SQLite refuses every statement that would write and builds no write-ahead log,
|
||||
so no `config.db-wal` and no `config.db-shm` appear beside it. It does not chmod
|
||||
the file and it does not migrate the schema.
|
||||
|
||||
Two consequences are worth knowing before you read a FAIL line as damage:
|
||||
|
||||
- A database behind this binary's schema is reported, not upgraded. Start the
|
||||
service to migrate it.
|
||||
|
||||
```
|
||||
FAIL <db>: schema version <n>, this nxdns expects <m>; `nxdns run` migrates it, `check` will not
|
||||
```
|
||||
|
||||
- A database with an unapplied write-ahead log cannot be graded without writing,
|
||||
because the newest settings are in the log and the main file holds older ones.
|
||||
`check` says so rather than reading the stale values:
|
||||
|
||||
```
|
||||
FAIL <db>: uncheckpointed changes are waiting in <db>-wal, and reading without writing would answer from the older settings in the main file; `nxdns run` applies them. A running nxdns normally holds this log, which is the usual reason to see this line.
|
||||
```
|
||||
|
||||
A running nxdns is the usual holder of that log, so this is a common answer
|
||||
when checking a live server rather than a sign of damage. It depends on what
|
||||
is in the log, not on whether a server is up: a configuration write that has
|
||||
not been checkpointed puts bytes there, and a server that has only been
|
||||
answering queries leaves `config.db-wal` empty and reads normally. Check an
|
||||
`export` with `--config`, or stop the service first.
|
||||
|
||||
## `export`
|
||||
|
||||
@@ -92,17 +142,24 @@ See [back up and restore](../how-to/back-up-and-restore.md).
|
||||
## `import FILE`
|
||||
|
||||
Validates FILE and replaces the whole configuration with it in one transaction.
|
||||
Prints every validation problem on failure; a failed import leaves the database
|
||||
untouched. Refuses a database that already has content unless `--force` is
|
||||
given (`DatabaseNotEmpty`, exit 2). Creates the data directory at mode 0700 if
|
||||
it is missing.
|
||||
Prints every validation problem; a failed import leaves the database untouched.
|
||||
Refuses a database that already holds configuration unless `--force` is given
|
||||
(`DatabaseNotEmpty`, exit 2). The check measures what an operator set, not what
|
||||
the network did: client rows the DNS path materialised from traffic never
|
||||
trigger the refusal on their own. Creates the data directory at mode 0700 if it
|
||||
is missing.
|
||||
|
||||
Client history survives the replacement. An address the database already knew
|
||||
keeps its first-seen and last-seen even when FILE names it; only an address it
|
||||
has never seen takes the import's clock. A client FILE leaves out is removed,
|
||||
history included.
|
||||
|
||||
`FILE` is positional and may appear before or after the flags.
|
||||
|
||||
| Flag | Meaning |
|
||||
| --- | --- |
|
||||
| `--data-dir DIR` | Data directory holding `config.db` (created if missing). |
|
||||
| `--force` | Replace a database that already has content. |
|
||||
| `--force` | Replace a database that already holds configuration. |
|
||||
|
||||
## `version`
|
||||
|
||||
@@ -120,31 +177,37 @@ the same. A usage error prints the same text to stderr and exits 64.
|
||||
| --- | --- |
|
||||
| 0 | Success. |
|
||||
| 1 | Runtime failure — I/O, database, out of memory. A partial diagnostic report caused by an allocation failure is a runtime failure, not a verdict on the configuration. |
|
||||
| 2 | A configuration problem the operator can fix, or a `check` that found one. Which faults qualify differs per subcommand; see below. |
|
||||
| 2 | A configuration problem the operator can fix, or a `check` that found one. |
|
||||
| 64 | Usage error — unknown command or flag, a flag without its value, a missing or extra argument. |
|
||||
|
||||
Code 2 is not a single rule shared by every subcommand. `check` and `import`
|
||||
classify configuration faults; `run` maps only four errors to it and lets
|
||||
everything else out as a runtime failure.
|
||||
Code 2 means the same thing from every subcommand. `src/config/faults.zig`
|
||||
holds the one list of errors that mean "the configuration the operator supplied
|
||||
is wrong", and `run`, `check` and `import` all ask it, so a rejected file exits
|
||||
2 whichever command read it. The list is every error the validator raises, plus
|
||||
`ParseZon`, `ConfigTooLarge`, `NoUsableUpstreams` and `BadCertificate`. In
|
||||
practice that covers a seed file with a syntax error, one larger than 4 MiB, one
|
||||
with no `default` group (`MissingDefaultGroup`), one with no enabled upstream
|
||||
(`NoUpstreams`), a bad bind address, a bad rate limit, an unusable certificate,
|
||||
and `password` and `password_hash` set together.
|
||||
|
||||
`check` exits 2 when validation reported at least one problem, when a
|
||||
certificate or key named by an enabled listener is unreadable, when a probed
|
||||
upstream failed, when the file is larger than 4 MiB, when the file has a ZON
|
||||
syntax error, and when there was nothing to check. Any other error escaping the
|
||||
run — a missing explicit `--config` file, an unreadable database — prints
|
||||
`check failed: <Error>` and exits 1.
|
||||
When `run` exits 2 it points at the diagnosis on stderr, whether the fault came
|
||||
from the seed file or from the database it loaded:
|
||||
|
||||
`import` exits 2 when validation recorded at least one problem, and for
|
||||
`DatabaseNotEmpty`, `ConfigTooLarge`, `ParseZon` and `PasswordAndHashBothSet`.
|
||||
`OutOfMemory` is 1 even when problems were recorded, because the report is then
|
||||
incomplete. Every other error is 1.
|
||||
```
|
||||
run `nxdns check` to see the configuration in full
|
||||
```
|
||||
|
||||
`run` exits 2 for `NoUsableUpstreams`, `BadBindAddress`, `BadRateLimit` and
|
||||
`BadCertificate`, and points the operator at `nxdns check` on stderr when it
|
||||
does. Nothing else is remapped. In particular, seeding the database from
|
||||
`--config` on first start happens before that classification applies to it: a
|
||||
seed file that is unparseable (`ParseZon`), larger than 4 MiB
|
||||
(`ConfigTooLarge`), or rejected by validation prints its diagnostics to stderr
|
||||
and exits 1. The same file given to `check` or `import` exits 2.
|
||||
`check` exits 2 for those faults and also when a probed upstream failed, when a
|
||||
named configuration file is missing or unreadable, when the database cannot be
|
||||
read or is not at this binary's schema version, and when there was nothing to
|
||||
check. Warnings never contribute.
|
||||
|
||||
`import` exits 2 for those faults and for `DatabaseNotEmpty`. That last one is
|
||||
deliberately not a configuration fault — it reports the state of the database
|
||||
rather than the content of a file — and `import` decides it for itself; the
|
||||
answer to it is `--force`, not an edit.
|
||||
|
||||
`OutOfMemory` is exit 1 even when problems were recorded, because the report is
|
||||
then incomplete. Every other error is 1.
|
||||
|
||||
Where an exit code sends you next: [troubleshoot](../how-to/troubleshoot.md).
|
||||
|
||||
@@ -115,7 +115,7 @@ The DNS-over-HTTPS listener (server side, for clients on the LAN). See
|
||||
| `doh_server.enabled` | bool | false | — | — | gates the DoH listener (`src/server/doh_server.zig`) |
|
||||
| `doh_server.bind` | string | `"0.0.0.0"` | IP address | must parse as an IP address of either family | DoH listener bind |
|
||||
| `doh_server.port` | u16 | 443 | port | 1–65535 (0 is refused, enabled or not) | DoH listener port |
|
||||
| `doh_server.cert_path` | string | `"/etc/nxdns/cert.pem"` | path | non-empty when enabled | certificate loaded into the hot-reloading `CertStore`; readability is checked by `nxdns check`, not by the validator |
|
||||
| `doh_server.cert_path` | string | `"/etc/nxdns/cert.pem"` | path | non-empty when enabled | certificate loaded into the hot-reloading `CertStore`; the file itself is loaded and paired with the key by `nxdns check`, not by the validator |
|
||||
| `doh_server.key_path` | string | `"/etc/nxdns/key.pem"` | path | non-empty when enabled | private key for the same; `nxdns check` warns when it is readable beyond its owner |
|
||||
|
||||
### dot_server
|
||||
@@ -169,7 +169,7 @@ the client tracker and the blocklist scheduler are throttled
|
||||
| Key | Type | Default | Unit | Validation | Consumed by |
|
||||
|---|---|---|---|---|---|
|
||||
| `blocklist_update.enabled` | bool | true | — | — | blocklist refresh scheduler (`src/filter/manager.zig`); when false the scheduler stops after the startup pass and only a manual refresh runs |
|
||||
| `blocklist_update.interval_hours` | u16 | 24 | hours | at least 1 | sleep between refresh passes and the per-source staleness test |
|
||||
| `blocklist_update.interval_hours` | u16 | 24 | hours | at least 1 | sleep between refresh passes and the per-source staleness test; each pass is preceded by the [orphan sweep](files-and-directories.md#the-orphan-sweep), which runs even when the pass itself is skipped for disk space |
|
||||
|
||||
## Collections
|
||||
|
||||
@@ -329,9 +329,35 @@ authentication](../how-to/set-up-admin-authentication.md).
|
||||
|
||||
## Validation errors
|
||||
|
||||
`nxdns check` and `nxdns import` print one `path: message` line per problem and
|
||||
report every problem, not just the first. The error set is
|
||||
`validate.ValidateError` in `src/config/validate.zig`:
|
||||
`nxdns check`, `nxdns import` and the `nxdns run` that seeds a database from the
|
||||
file all print one `FAIL path: message` line per problem, and report every
|
||||
problem rather than the first. A finding that is legal but almost certainly
|
||||
unintended is prefixed `WARN` instead: it does not change the exit code, and it
|
||||
is printed by all three even when nothing failed, so an accepted configuration
|
||||
still says what is odd about it.
|
||||
|
||||
A url in a diagnostic is redacted to its scheme, host and port. The userinfo,
|
||||
the path, the query and the fragment are dropped, and control characters are
|
||||
escaped. These lines reach the journal, and every one of those parts can carry a
|
||||
credential: a NextDNS DoH upstream is `https://dns.nextdns.io/abcd12`, where the
|
||||
path segment is the whole account identifier. The field path beside the message
|
||||
names the entry, so `blocklist_sources[1].url` still says which one to go and
|
||||
fix.
|
||||
|
||||
One credential this cannot remove: a NextDNS **DoT** upstream is
|
||||
`tls://abcd12.dns.nextdns.io`, which carries the same identifier in the hostname.
|
||||
Stripping it would leave no host at all and no line worth reading. So if you use
|
||||
NextDNS over DoT, your profile id appears in the log.
|
||||
|
||||
The host is kept because a hostname is not a secret in the general case — it is
|
||||
resolved publicly and offered as SNI on every connection — and dropping it would
|
||||
cost every operator a diagnostic to cover one vendor's choice. If that trade is
|
||||
wrong for you, it is yours to make rather than ours: NextDNS also publishes a DoH
|
||||
endpoint, `https://dns.nextdns.io/abcd12`, whose identifier sits in the path and
|
||||
is redacted in full. Configure that form instead and nothing identifying reaches
|
||||
the log.
|
||||
|
||||
The error set is `validate.ValidateError` in `src/config/validate.zig`:
|
||||
|
||||
| Error | Raised by |
|
||||
| --- | --- |
|
||||
@@ -363,6 +389,13 @@ report every problem, not just the first. The error set is
|
||||
| `MissingLogPath` | `logging.output = .file` with an empty or relative `file_path` |
|
||||
| `PasswordAndHashBothSet` | both `web.password` and `web.password_hash` are set |
|
||||
|
||||
Warnings are a separate set, outside `ValidateError` because they are not
|
||||
failures. There is one:
|
||||
|
||||
| Warning | Raised by |
|
||||
| --- | --- |
|
||||
| `SourceInNoGroup` | a `blocklist_sources` entry that no `group_sources` link names; it downloads and blocks nothing until a group uses it |
|
||||
|
||||
## Minimal working example
|
||||
|
||||
The smallest file that passes validation: a `default` group and one enabled
|
||||
|
||||
@@ -16,19 +16,31 @@ never looks at the directory, and without one `check` falls back to the default
|
||||
configuration file, or prints "nothing to check" and exits 2 when neither source
|
||||
exists.
|
||||
|
||||
No subcommand opens the directory read-only. `run`, `import`, `export` and a
|
||||
`check` that resolved to the database all go through the same
|
||||
`DataDir.openConfigDb`, which opens `config.db` read/write, chmods it to 0600,
|
||||
enables WAL — creating `config.db-wal` and `config.db-shm` — and then runs any
|
||||
pending schema migrations. So `nxdns export` and `nxdns check` write to the data
|
||||
directory, and on a database one schema version behind they migrate it. `export`
|
||||
additionally creates an empty `config.db` if the directory exists without one;
|
||||
`check` reaches the database branch only when `config.db` is already there.
|
||||
`run`, `import` and `export` go through `DataDir.openConfigDb`, which opens
|
||||
`config.db` read/write, chmods it to 0600, enables WAL — creating
|
||||
`config.db-wal` and `config.db-shm` — and then runs any pending schema
|
||||
migrations. So `nxdns export` writes to the data directory, and on a database
|
||||
one schema version behind it migrates it. `export` also creates an empty
|
||||
`config.db` if the directory exists without one.
|
||||
|
||||
`nxdns check` is the exception: it does not use that path at all. It opens
|
||||
`config.db` immutable, which is `SQLITE_OPEN_READONLY` plus `immutable=1`, so
|
||||
SQLite refuses every statement that would write and builds no wal-index. No
|
||||
`config.db-wal` and no `config.db-shm` appear beside the file, the mode is left
|
||||
alone, and no migration runs — a database behind this binary's schema is
|
||||
reported as a failure naming `nxdns run` as the fix. A `check` against a data
|
||||
directory leaves it byte-identical, and `check` reaches the database branch only
|
||||
when `config.db` is already there.
|
||||
|
||||
`immutable=1` ignores any `-wal` file, so it is refused rather than used when
|
||||
one holds bytes: the newest settings would be invisible and `check` would grade
|
||||
older ones from the main file. That is the "uncheckpointed changes" failure in
|
||||
[the CLI reference](cli.md#what-check-does-not-do).
|
||||
|
||||
| Path | What it is | Mode |
|
||||
| --- | --- | --- |
|
||||
| `config.db` | The configuration database — the single source of truth, including `web.password_hash`. | 0600 |
|
||||
| `config.db-wal`, `config.db-shm` | SQLite write-ahead log and shared-memory index for `config.db`. Created when WAL is enabled, inheriting the main file's permissions. | 0600 |
|
||||
| `config.db-wal`, `config.db-shm` | SQLite write-ahead log and shared-memory index for `config.db`. Created by `run`, `import` and `export` when WAL is enabled, inheriting the main file's permissions. `check` creates neither. | 0600 |
|
||||
| `querylog.db` | The query log: every domain every client asked for. Expendable — if it is missing or unusable it is recreated empty. | 0600 |
|
||||
| `querylog.db-wal`, `querylog.db-shm` | WAL sidecars for `querylog.db`. | 0600 |
|
||||
| `querylog.db.corrupt-<unix-seconds>` | A `querylog.db` that could not be used, moved aside before an empty one was created in its place. Kept, never overwritten. | Whatever the renamed file had — no chmod reaches it |
|
||||
@@ -38,11 +50,45 @@ additionally creates an empty `config.db` if the directory exists without one;
|
||||
| `blocklists/<id>.wild` | Wildcard entries for the same source. | 0600 |
|
||||
| `blocklists/<id>.raw.tmp`, `<id>.list.tmp`, `<id>.wild.tmp` | Transient refresh state: the downloaded body and the two compile outputs before they are published by rename. | 0600 |
|
||||
|
||||
`<id>` is the `blocklist_sources` row id. A `.list` or `.wild` file whose id is
|
||||
no longer a `blocklist_sources` row is deleted by the orphan sweep; files of a
|
||||
live source are left alone whatever their state, and the sweep matches only the
|
||||
two published suffixes, so a `.tmp` file left by an interrupted refresh is not
|
||||
swept — the next refresh of that source overwrites it.
|
||||
`<id>` is the `blocklist_sources` row id.
|
||||
|
||||
### The orphan sweep
|
||||
|
||||
The sweep decides by id, not by suffix. It matches all five names above and
|
||||
deletes those whose `<id>` is no longer a `blocklist_sources` row, so the
|
||||
compiled `.list` and `.wild` of a removed source go, and so do a `.raw.tmp`,
|
||||
`.list.tmp` or `.wild.tmp` left behind by a refresh that was killed before it
|
||||
could clean up. Files belonging to a source that still has a row are never
|
||||
touched, whatever state they are in: the sweep holds the same lock every refresh
|
||||
takes, so it never reads the directory while a refresh is part-way through.
|
||||
|
||||
It runs at three moments:
|
||||
|
||||
- at startup, before the first refresh pass — this is what collects what a
|
||||
killed process left behind, and the compiled files of a source deleted while
|
||||
the server was down;
|
||||
- before each scheduled update pass, ahead of the disk-space gate: the sweep
|
||||
only unlinks, so it is the one step here that can give a critically full disk
|
||||
room back, and gating it would keep the residue that helped fill the disk;
|
||||
- immediately after `DELETE /api/blocklists/{id}`, which is when an orphan is
|
||||
actually created in normal operation. Without it a deleted list would keep its
|
||||
megabytes until the next scheduled pass.
|
||||
|
||||
With `blocklist_update.enabled = false` there are no scheduled passes, so only
|
||||
the first and the last of those three happen.
|
||||
|
||||
Each deletion is logged:
|
||||
|
||||
```
|
||||
info(blocklist_manager): pruned orphaned blocklist file 9999.list
|
||||
```
|
||||
|
||||
A failed sweep is a warning, not an outage — leftover bytes do not justify
|
||||
losing the refresh pass behind them, let alone the server.
|
||||
|
||||
The temporaries of a source that still exists are cleaned by the refresh that
|
||||
owns them rather than by the sweep: each refresh deletes its own `.raw.tmp`,
|
||||
`.list.tmp` and `.wild.tmp` as it finishes, successfully or not.
|
||||
|
||||
A `querylog.db` is moved aside when it is missing nothing but usability:
|
||||
SQLite reports it corrupt or not a database, `PRAGMA quick_check` does not
|
||||
@@ -111,7 +157,9 @@ no file; under systemd the journal captures it.
|
||||
|
||||
`doh_server.cert_path` / `key_path` and `dot_server.cert_path` / `key_path`,
|
||||
conventionally under `/etc/nxdns`. nxdns reads them, never writes or creates
|
||||
them. Both must be readable by the user nxdns runs as; the key should be
|
||||
readable by its owner only, which `nxdns check` warns about when it is not. A
|
||||
them. Both must be readable by the user nxdns runs as, and the key must belong
|
||||
to the certificate: `nxdns check` loads the pair and fails when it does not. The
|
||||
key should also be readable by its owner only, which `check` warns about when it
|
||||
is not. A
|
||||
watcher polls both files and swaps a renewed pair in without a restart. See
|
||||
[enable DoH and DoT](../how-to/enable-doh-and-dot.md).
|
||||
|
||||
@@ -12,8 +12,8 @@ see [measure performance](../how-to/measure-performance.md).
|
||||
| Sustained ≥ 100 qps on Raspberry Pi 5 | End-to-end against the real binary on the Pi; not a harness number |
|
||||
| Blocklist lookup p95 < 1 ms | `bench filter`: `matcher.normalize` + `Snapshot.evaluate` per op |
|
||||
| Cached response p95 < 5 ms | `bench cache`: `buildKey` + `DnsCache.get` + `packet.setId` per op |
|
||||
| Memory with ~1M blocked domains < 100 MB | `bench filter`: VmRSS with the 1M-domain snapshot loaded |
|
||||
| Stripped static binary < 10 MB per arch (< 15 MB with the embedded frontend) | CI size assert on the `cross` artifacts |
|
||||
| Memory with ~1M blocked domains < 100 MiB | `bench filter`: VmRSS with the 1M-domain snapshot loaded |
|
||||
| Stripped static binary < 10 MiB per arch (< 15 MiB with the embedded frontend) | CI size assert on the `cross` artifacts |
|
||||
|
||||
The harness is `tools/bench.zig`. It measures the three targets that are
|
||||
measurable in process; the qps target is end to end and the binary-size target
|
||||
@@ -61,7 +61,7 @@ VmRSS is lower because the filter suite's snapshot has been freed by then.
|
||||
| --- | --- |
|
||||
| Blocklist lookup p95 < 1 ms | to be measured on hardware |
|
||||
| Cached response p95 < 5 ms | to be measured on hardware |
|
||||
| Memory with ~1M blocked domains < 100 MB | to be measured on hardware |
|
||||
| Memory with ~1M blocked domains < 100 MiB | to be measured on hardware |
|
||||
| Sustained ≥ 100 qps | to be measured on hardware, end to end |
|
||||
|
||||
The qps target belongs to the real binary rather than the harness: it means
|
||||
|
||||
Reference in New Issue
Block a user