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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Multi-incident alerts render as labeled, self-contained units instead of one flat fact list** ([#2108], reported with the diagnosis by gotqn) - when one alert covered several deadlock fingerprints, the Teams card serialized every victim's fields first and every fingerprint's fields after, in one undifferentiated facts[] block - there was no way to tell which victim belonged to which fingerprint, and downstream automation could not split the card into per-incident work items. Two changes, one per layer where the association was lost: each fingerprinted deadlock is now ONE self-contained item (its Database, Victim SQL, Processes, Dedup Key, Involved Objects, and occurrence count together, headed "Deadlock N of M"), with the standalone victim items kept only for deadlocks the fingerprint cannot see (no parseable lock objects - they would otherwise vanish); and the Teams payload gives every fields-carrying item its OWN sections[] entry, titled by the item's heading and carrying only that item's facts, on every alert type - advice prose and remediation-T-SQL hints stay folded into the lead section, because they are commentary on the whole alert. One compatibility note for payload consumers: automation keyed specifically on sections[0].facts[] containing every fact should iterate sections[] instead.
- **Every database-scoped alert exposes a discrete Database fact** ([#2109], also gotqn) - only Blocking Detected and Long-Running Query carried { "name": "Database" } in their webhook facts; Deadlocks named databases only inside the involved-object strings, Version Store (PVS) only in the item heading, and Database State and the two AG database alerts (Suspended / Sync Fell Behind) only in prose - so routing or tagging by database meant parsing display text. Now: deadlock items and incidents carry the distinct databases parsed from the graph's own process list (comma-separated when a deadlock spans databases), PVS items lead with the database, Database State fires with a structured context (Database / Current State / Expected State), and the AG database alerts carry Database / Availability Group / Replica (plus Suspend Reason where it applies) through one shared builder in both SKUs, so the fact names cannot drift. All additive - no existing fact changes.
- **Query Store backfill yields to the live path on contended replicas** ([#2111], found validating #2102 on the prod monitor fleet) - the hour-chunked catch-up recovered most wedged databases immediately, but servers where the backfill worker ran a slice every tick alongside the live sweep stayed in a failure churn: both paths scan the same QS internal tables, the replicas are often MAXDOP-1, and the live query that normally finishes in seconds died at the command timeout behind the slice's scan - recovery-phase contention, self-inflicted, and on some servers the slices themselves timed out so their holes never drained. The backfill worker now skips a server's slice whenever that server's live query_store collection failed within the last 10 minutes (two poll cycles - "failing NOW"), in both SKUs, judged by one shared policy so the workers cannot drift. This is the class doc's own contract - backfill can be slow forever without delaying collection - enforced at the moment it matters: the hole waits, live recovers, backfill resumes. The signal is server-grain on purpose (any database's live failure vouches for the whole replica being contended) and in-memory on purpose (a restart forgetting it costs one slice racing one cycle, once).
- **Version stamps are single-sourced from `<Version>`** ([#2113], reported by SalmanRajwani) - the 3.4.0 release bumped `<Version>` in each app project but left the hand-pinned `AssemblyVersion` / `FileVersion` / `InformationalVersion` at 3.3.0, so the 3.4.0 packages installed binaries whose FILE metadata reports 3.3.0.0. The code was genuinely 3.4.0, but the lie was not cosmetic: the in-app update check compares the entry assembly's version (the stale pin) against the latest release tag, so a user already ON 3.4.0 would be told an update is available forever. Four hand-maintained copies of one fact is a release-day trap. The three derived properties are now deleted and derive from `<Version>` at build time (with the CI source-revision suffix suppressed so InformationalVersion stays a clean semver); a release bump is now ONE line per project.
- **Store Disk Pressure no longer re-notifies every cooldown while free space sits at an unchanged level** ([#2101], reported with the diagnosis by gotqn) - the self-alert re-fired on the plain cooldown, so a store volume parked at 7.3% free produced an identical CRITICAL notification every ~15 minutes for as long as the condition stood - one static condition, dozens of notifications. It now runs behind the same worsening gate the target-server volume alert has had since the #754 follow-up: fire once on entry, re-fire only when free% drops at least a full point below the last-alerted level (still cooldown-limited), one resolution row on recovery - which also clears the watermark, so a volume that oscillates around the threshold cannot go permanently silent. Deliberately NOT applied to the state-only self-alerts (Collection Stopped, Agent Not Running, Capture Down): those have no level to worsen, and their per-cooldown "still broken" reminder is wanted. The reporter's second ask - exposing the hardcoded self-alert thresholds as store-backed settings - is real but is its own design decision (control-plane knobs, Viewer rows, MCP settings groups) and stays tracked on the issue.

## [3.4.0] - 2026-08-06
Expand Down Expand Up @@ -2611,3 +2612,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#2108]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/2108
[#2109]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/2109
[#2111]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/2111
[#2113]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/2113
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@
<RootNamespace>PerformanceMonitor.Darling.Service</RootNamespace>
<AssemblyName>PerformanceMonitor.Darling.Service</AssemblyName>
<Version>3.4.0</Version>
<AssemblyVersion>3.3.0.0</AssemblyVersion>
<FileVersion>3.3.0.0</FileVersion>
<!-- #2113: <Version> is the ONE hand-set version. AssemblyVersion / FileVersion /
InformationalVersion derive from it at build time - the 3.4.0 release bumped only
<Version> and shipped binaries still STAMPED 3.3.0.0, because four hand-maintained
copies of one fact is a release-day trap. The suffix suppression keeps
InformationalVersion a clean semver instead of gaining a +sha under CI SourceLink. -->
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<Company>Darling Data, LLC</Company>
<Copyright>Copyright © 2026 Darling Data, LLC</Copyright>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@
ships inside the service zip. -->
<StartupObject>PerformanceMonitor.Darling.Viewer.Program</StartupObject>
<Version>3.4.0</Version>
<AssemblyVersion>3.3.0.0</AssemblyVersion>
<FileVersion>3.3.0.0</FileVersion>
<!-- #2113: <Version> is the ONE hand-set version. AssemblyVersion / FileVersion /
InformationalVersion derive from it at build time - the 3.4.0 release bumped only
<Version> and shipped binaries still STAMPED 3.3.0.0, because four hand-maintained
copies of one fact is a release-day trap. The suffix suppression keeps
InformationalVersion a clean semver instead of gaining a +sha under CI SourceLink. -->
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<Company>Darling Data, LLC</Company>
<Copyright>Copyright © 2026 Darling Data, LLC</Copyright>
<ApplicationIcon>EDD.ico</ApplicationIcon>
Expand Down
9 changes: 6 additions & 3 deletions Lite/PerformanceMonitorLite.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
<RootNamespace>PerformanceMonitorLite</RootNamespace>
<Product>SQL Server Performance Monitor Lite</Product>
<Version>3.4.0</Version>
<AssemblyVersion>3.3.0.0</AssemblyVersion>
<FileVersion>3.3.0.0</FileVersion>
<InformationalVersion>3.3.0</InformationalVersion>
<!-- #2113: <Version> is the ONE hand-set version. AssemblyVersion / FileVersion /
InformationalVersion derive from it at build time - the 3.4.0 release bumped only
<Version> and shipped binaries still STAMPED 3.3.0.0, because four hand-maintained
copies of one fact is a release-day trap. The suffix suppression keeps
InformationalVersion a clean semver instead of gaining a +sha under CI SourceLink. -->
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<Company>Darling Data, LLC</Company>
<Copyright>Copyright © 2026 Darling Data, LLC</Copyright>
<Description>Lightweight SQL Server performance monitoring - no installation required on target servers</Description>
Expand Down
Loading