Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Lite's portable ZIP is self-contained, which HALVED it** ([#2501]) - `Publish Lite` is now `-r win-x64 --self-contained` in both `build.yml` and `nightly.yml`, so neither Lite artifact has a .NET prerequisite any more and the failure [#2489] documented stops existing: a tester who unzips onto a stock Windows Server no longer meets the .NET host's bare `You must install .NET to run this application` before a line of our code runs. **The size went the opposite way from what bundling a runtime suggests.** The old publish was RID-agnostic, so it copied every platform its packages ship - **537 MB of `runtimes\` on a 565 MB tree** (osx 130, linux-x64 116, linux-arm64 70, win-arm64 56, then win-x86, musl, loongarch64 and riscv64), of which only the **52 MB `win-x64`** folder could ever load on Windows. `DuckDB.NET.Bindings.Full` is most of it, SkiaSharp and SqlClient behind it. Dropping ~485 MB of unloadable native payload beats the cost of bundling .NET, WPF and ASP.NET Core by roughly two to one: measured on one commit and one SDK, **565 MB tree / 212.7 MB zipped becomes 277 MB / 114.2 MB**. It matters most for the **nightly** ZIP, which is the UAT download and is not offered as a `Setup.exe` at all. **A RID-specific publish needed two more files than the flag.** `Lite/packages.lock.json` had only a `net10.0-windows7.0` target, and a RID restore adds `net10.0-windows7.0/win-x64` to it - after which the `dotnet restore --locked-mode` that BOTH workflows run before the publish fails `NU1004: the project's runtime identifiers have changed`, because locked mode compares the PROJECT's RID set (empty) against the lock file's (win-x64). Reproduced locally; that is a red CI run on every PR, not the future `--no-restore` trap it was filed as. The fix is `<RuntimeIdentifiers>win-x64</RuntimeIdentifiers>` in `PerformanceMonitorLite.csproj`, so the project itself asks for that graph and one committed lock file satisfies the RID-less locked-mode restore and the RID publish alike; `RuntimeIdentifiers` (plural) sets no RID on the build, so a plain `dotnet build` stays RID-agnostic and `Lite.Tests` is untouched. **SignPath needed nothing** - the `Lite` artifact-configuration slug already receives both shapes today, and the signed re-zip reads `signed/Lite/*`, inheriting whatever shape `publish/Lite` has. Auto-update is unaffected; the ZIP is not a Velopack channel. `LiteRuntimePrerequisiteDocsTests` went red on the flag alone (3 of its 7 facts) and was rewritten to state every claim BOTH ways round: [#2499]'s version asserted only that the docs DID name the runtimes, so two of its facts stayed green while the prose went stale. It now also derives the lock file's RID coverage from the `-r` flags in the workflows, and every new assertion was proven red with its fix reverted.

### Fixed
- **Eight PostgreSQL reads told a SQL Server target its vacuum was healthy, and stock PostgreSQL was told to go and check a collector that will never run** ([#2532]) - [#2530] taught the miss vocabulary the engine-KIND axis but wired only the *engine half* of the dispatch gate into it, so the PostgreSQL collectors' own `AppliesTo` gates were still invisible to it, and none of the eight `get_pg_*` reads asked the question at all. A SQL Server target asked `get_pg_xmin_horizon` got `no_holder` - "nothing is holding back the xmin horizon", a confident all-clear about a mechanism that engine does not have - and `get_pg_autovacuum_health` reported `no_pending_maintenance`, which is a fabricated clean bill of health rather than a weak one. `CollectorEngineCapability.TargetsWithEngineKind` now sweeps every target shape an engine kind permits, fixing `IsAurora` (nothing turns a stock PostgreSQL server into an Aurora one) and varying `PostgresMajorVersion`, `PostgresVersionNum` and `IsInRecovery`, all three of which an upgrade or a writer connection moves. So `pg_wait_stats` and `pg_statement_stats`, which read `aurora_stat_system_waits()` and `aurora_stat_statements()`, are permanent gaps on stock PostgreSQL and say so - while `pg_stat_io`'s PG16 floor and the writer-only autovacuum read keep the `unavailable` vocabulary that correctly sends an operator to look. The message names the real reason: a foreign DIALECT is stopped by the dispatch gate's engine half, a same-dialect gap is the collector's own gate, and one sentence for both would have told a PostgreSQL operator that a PostgreSQL collector is not written for PostgreSQL. Shipped with the guard [#2532] made its prerequisite: `EveryFactAPostgresGateReads_IsVariedBySweepOrFixedByKind` decodes the IL of every PostgreSQL `AppliesTo` and fails the build if the sweep leaves a fact it reads at its CLR default - the twin of [#2518]'s edition-axis guard, and the reason a sweep can be trusted not to over-claim silently.
- **The Overview lanes skewed apart when one lane's numbers got long** ([#2533]) - the five lanes are five SEPARATE plots, and `SyncXAxes` only ever gave them the same X-axis LIMITS. Nothing gave them the same pixel geometry: each plot sizes its own left gutter from its own Y tick labels, so on a server whose wait time runs into six figures the Wait ms/sec lane began its data area ~27 px right of the I/O latency lane reading `0.4`, and the lanes stopped lining up on the time axis. Every value stayed correct throughout - which is why the tooltips still read true, and what identified this as layout rather than data. **Not a regression**, and the reporter's "I think this worked before" is right for his machine: `MinimumSize`, `Layout.Fixed` and `PixelPadding` have never appeared in any SKU on any branch, so nothing was removed - alignment was always incidental, holding only while the five lanes happened to need labels of similar width, and five- or six-digit wait ms/sec is what breaks the coincidence. The same build therefore looks right on one server and skewed on another. The lanes now share ONE gutter, sized to the widest lane's own natural gutter and re-derived on every refresh - a frozen constant would have to cover six-digit wait times and would then steal that width from every server whose lanes read in single digits, and it ratchets back down when the big values go away. The mechanism is `Axes.Left.MinimumSize` rather than a fixed layout, because a fixed layout pins all four sides and the bottom lane legitimately needs more bottom room than the other four - it alone draws the time labels. This is the second alignment defect in these lanes and the first one shipped with nothing that could have caught it, so the fix comes with headless render tests: ScottPlot draws without a window, so CI now builds lanes with deliberately mismatched magnitudes, renders them, and compares their data rectangles - shown failing at 20.02 px on the unfixed control before it passed. **Darling viewer only.** Lite's Overview control is the same five separate plots and carries the same latent defect, but nobody has reported hitting it there; the aligner lives in the shared `PerformanceMonitor.Ui`, so picking Lite up later is one call site. Reported by @ghauan.
- **A SQL Server read aimed at a PostgreSQL target says so, instead of telling you to check collection** ([#2530]) - [#2511] taught the miss vocabulary the engine-EDITION axis, so a read served by a collector gated off on Azure SQL Database answers `not_collected` naming the engine. A PostgreSQL target got `unavailable` - "never collected, check that collection is running" - which is true and points at the wrong cause: those collectors do not apply to that engine at all. That was the honest answer while nothing in the store distinguished a PostgreSQL target from an unconnected one; now something does. The answer is derived the same way the edition axis is, from the collectors' own dispatch gate rather than from a list, so flipping a definition's target engine moves it. **Unknown targets keep making no claim** - a pre-v82 row, a server that has not connected since the rung landed, and a token a newer build wrote all stay silent, because the distinction added is "known to be PostgreSQL" and never "not known to be SQL Server". It runs both ways: a `get_pg_*` read aimed at a known SQL Server target now says the same thing in reverse. Limit worth knowing: only the reads [#2511] wired to the capability helper can answer on either axis, so a read like `get_database_config` - whose collector runs on every SQL Server, so the edition axis gave it nothing to say - still reports `unavailable` on a PostgreSQL target.
- **A fresh store never seeded, so the control plane silently overrode `darling.json`** ([#2524]) - the seed INSERT named sixteen columns and supplied fifteen: a bound parameter was never written into the VALUES list, so every value after it shifted one column left and PostgreSQL refused the whole statement with `42601`. The failure was caught and logged and the service carried on with the file config, which is why it shipped - the damage came next, because the control plane is authoritative after first contact and was answering from a row that had never been written, where every toggle is false. So `web.enabled` and `mcp.enabled` were **true** in `darling.json`, **false** in the store, the store won as designed, and neither endpoint ever listened. That was the entire first-run experience of a container deployment, and the only clue was one line saying the config would seed on a later start - it would not, because the statement was malformed rather than racing. Found by running the shipped nightly image against a live target rather than by reading it, since no test drove the seed against an empty store.
Expand Down Expand Up @@ -2877,6 +2878,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#2520]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/2520
[#2525]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/2525
[#2530]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/2530
[#2532]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/2532
[#2518]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/2518
[#2533]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/2533
[#2480]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/2480
[#2489]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/2489
Expand Down
Loading
Loading