Skip to content

Commit ebd458e

Browse files
Release v2.9.0: Installed Version column, Lite-style indicators in Full, version bumps
- New Installed Version column in Manage Servers for both editions: * Full: probes config.installation_history per server in parallel * Lite: shows the running app version (mirrors Full's header for consistency) - Back-ports the Ellipse-with-DataTriggers status dot and right-aligned favorite star from Lite's server list to the Full Dashboard - Bumps Version/AssemblyVersion/FileVersion/InformationalVersion to 2.9.0 in Dashboard, Lite, Installer, and Installer.Core - Rewrites CHANGELOG: fixes the 2.8.0 date to 2026-04-22 (was TBD), moves Off preset (erikdarlingdata#888) to 2.9.0 since erikdarlingdata#891 landed after the v2.8.0 tag, and adds the full 2.9.0 entry covering the post-2.8.0 PR set - Updates README's DuckDB version reference (1.5.0 -> 1.5.2) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent dbaf19c commit ebd458e

14 files changed

Lines changed: 249 additions & 62 deletions

CHANGELOG.md

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,50 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [2.8.0] - TBD
8+
## [2.9.0] - TBD
9+
10+
### Important
11+
12+
- **Breaking change to `config.data_retention`** — the `@truncate_all` parameter has been removed. Pass `@retention_days = 0` for the same behavior. `@retention_days = NULL` (default) respects per-collector retention from `config.collection_schedule` with a 30-day fallback for unscheduled tables; `@retention_days = N > 0` overrides every table to N days. Any existing Agent jobs or scripts calling `data_retention @truncate_all = 1` need to be updated ([#900])
13+
- **New `config.collector_database_exclusions` table** for per-database collector exclusions. Eight per-database collectors filter against this table; system databases remain hard-skipped by the collectors themselves. Existing installs get the table on the next upgrade — `install/01_install_database.sql` and `config.ensure_config_tables` both create it under an `IF OBJECT_ID … IS NULL` guard ([#887])
14+
15+
### Added
16+
17+
- **Per-database collector exclusions** — exclude noisy or unimportant databases from per-database collectors. Dashboard side adds `config.collector_database_exclusions` and filters 8 collectors (`query_stats`, `query_store`, `procedure_stats`, `file_io_stats`, `waiting_tasks`, `database_configuration`, `database_size_stats`, `server_properties`). Lite side adds an `ExcludedDatabases` list per server in `servers.json` and filters 9 collectors ([#887])
18+
- **`Off` collection preset**`EXECUTE config.apply_collection_preset @preset_name = N'Off'` disables every collector in one call. Pair with a second Agent job that applies a non-`Off` preset at the start of your active window for overnight / quiet-hours scoping. Non-`Off` presets now also set `enabled = 1` across the board so the switch from `Off → Balanced` reliably resumes collection ([#888])
19+
- **Purge Now action** in Manage Servers — confirm dialog with a mode picker (Use configured / 1 / 3 / 7 / Custom / All) drives `config.data_retention`; right-click menu on the Manage Servers grid mirrors every per-row action (Edit, Toggle Favorite, Check Server Version, Purge Now, Remove) ([#900])
20+
- **Total non-idle CPU on Lite Overview** — headline value shows total CPU with the SQL-only value alongside (e.g. `64% (SQL 60%)`); new `CpuAlertMode` dropdown in Settings → Alerts (Total / SqlOnly) drives both the alert evaluator and headline color; tray notifications and email alerts label the value as "Total CPU" or "SQL CPU" ([#899])
21+
- **Resume gap detection**`query_stats`, `procedure_stats`, and `query_store` collectors skip the historical sweep on first run after an Off preset, Agent stoppage, or server reboot. When the last successful run is older than 5× the configured `frequency_minutes` (floored at 30 minutes), the cutoff clamps to `SYSDATETIME()` so only forward-going data is collected on resume — preventing the tempdb blowout that hit the original reporter ([#892])
22+
- **Right-click View Plan** on Dashboard Blocked Process Reports (View Blocked Plan + View Blocking Plan), Dashboard Deadlocks, and Lite Deadlocks grids. Plan lookup hits `sys.dm_exec_query_stats` + `sys.dm_exec_text_query_plan` on the monitored server, falling back to `executionStack/frame` entries when the process-level `sql_handle` is empty or evicted ([#880])
23+
- **Open Log Folder** sidebar button in Lite — opens `%LocalAppData%\PerformanceMonitorLite\logs\` in Explorer for grabbing historical logs to attach to bug reports. Sits below View Log, which retains its existing behavior of opening today's log file ([#873])
24+
- **Installed Version column** in the Manage Servers grid for both Dashboard and Lite. Dashboard shows the PerformanceMonitor database version on each server (probed in parallel via `GetInstalledVersionAsync`, with `Not installed` / `Unavailable` fallbacks). Lite shows the running app's own version on every row, mirroring Full's column header for consistency.
25+
- **Lite-style server card indicators in Full** — back-ported the Ellipse-with-DataTriggers status dot (Online/Offline/Warning/Unknown) and the right-aligned favorite star from Lite to the Full Dashboard's server list, matching Lite's visual treatment.
26+
- **Architecture overview** at `docs/how-collection-works.md` covering the minute loop, dispatcher, collector shape, `config.collection_schedule`, retention, and the Dashboard read path
27+
28+
### Changed
29+
30+
- **PlanIconMapper synced** with PerformanceStudio v1.9.0 improvements — columnstore storage type on scan/delete/insert/update/merge operators routes to `columnstore_index_*` icons (covers CCI and NCCI); `Parallelism` operator subtypes (Repartition Streams, Distribute Streams, Gather Streams) get their own icons
31+
- **`Microsoft.Data.SqlClient` 6.1.4 → 7.0.1** — major-version bump. Azure/Entra dependencies were split out of the core package in 7.0; `Microsoft.Data.SqlClient.Extensions.Azure 1.0.0` added to Dashboard, Lite, and Installer.Core for `ActiveDirectoryInteractive` connections
32+
- **`ModelContextProtocol` 0.7.0-preview.1 → 1.2.0** — off the preview tag and onto stable 1.x in Dashboard and Lite
33+
- **`DuckDB.NET` 1.5.0 → 1.5.2** in Lite — fixes unbounded row group growth on indexed tables under repeated load+insert cycles, memory leaks and race conditions in prepared statements, WAL checkpoint marking, and Windows UTF-8/UTF-16 handling
34+
- **`Microsoft.Extensions.*` 10.0.5 → 10.0.7**, **`System.Text.Json` 10.0.5 → 10.0.7**, **`ScottPlot.WPF` 5.1.57 → 5.1.58** — patch-level bumps with no expected behavioral change
35+
- **Theme polish** on grids and plan viewer in Dashboard and Lite — thanks [@ClaudioESSilva](https://github.com/ClaudioESSilva) ([#889])
36+
37+
### Fixed
38+
39+
- **Install loop timeout** raised from 5 minutes to 1 hour. `install/98_validate_installation.sql` runs every enabled collector with `@debug = 1` in a single batch; on large databases (reporter had 7.2M rows in `collect.query_stats`, 4.4M in `collect.query_store_data`) this took ~9 minutes and was blowing the 5-minute timeout, failing the install or upgrade ([#884])
40+
41+
[#873]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/873
42+
[#880]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/880
43+
[#884]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/884
44+
[#887]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/887
45+
[#888]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/888
46+
[#889]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/889
47+
[#892]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/892
48+
[#899]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/899
49+
[#900]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/900
50+
51+
## [2.8.0] - 2026-04-22
952

1053
### Important
1154

@@ -15,7 +58,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1558

1659
- **Memory Pressure Events in Lite** — the collector, chart, and `get_memory_pressure_events` MCP tool previously only in the Full Edition are now available in Lite ([#865])
1760
- **Grid auto-scrolling** in Lite and Dashboard ([#843]) — thanks [@ClaudioESSilva](https://github.com/ClaudioESSilva)
18-
- **`Off` collection preset**`config.apply_collection_preset @preset_name = N'Off'` disables every collector in one call. Pair it with a second Agent job that applies a non-`Off` preset at the start of your active window to get overnight / quiet-hours scoping without writing scheduler code. Non-`Off` presets now also set `enabled = 1` across the board so the switch reliably resumes collection ([#888])
1961

2062
### Changed
2163

@@ -48,7 +90,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4890
[#865]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/865
4991
[#867]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/867
5092
[#872]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/872
51-
[#888]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/888
5293

5394
## [2.7.0] - 2026-04-13
5495

Dashboard/Dashboard.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
<StartupObject>PerformanceMonitorDashboard.Program</StartupObject>
88
<AssemblyName>PerformanceMonitorDashboard</AssemblyName>
99
<Product>SQL Server Performance Monitor Dashboard</Product>
10-
<Version>2.8.0</Version>
11-
<AssemblyVersion>2.8.0.0</AssemblyVersion>
12-
<FileVersion>2.8.0.0</FileVersion>
13-
<InformationalVersion>2.8.0</InformationalVersion>
10+
<Version>2.9.0</Version>
11+
<AssemblyVersion>2.9.0.0</AssemblyVersion>
12+
<FileVersion>2.9.0.0</FileVersion>
13+
<InformationalVersion>2.9.0</InformationalVersion>
1414
<Company>Darling Data, LLC</Company>
1515
<Copyright>Copyright © 2026 Darling Data, LLC</Copyright>
1616
<ApplicationIcon>EDD.ico</ApplicationIcon>

Dashboard/MainWindow.xaml

Lines changed: 66 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -88,47 +88,75 @@
8888
BorderThickness="0">
8989
<ListView.ItemTemplate>
9090
<DataTemplate>
91-
<Border BorderBrush="{DynamicResource BorderBrush}"
92-
BorderThickness="1"
93-
CornerRadius="4"
94-
Padding="8,6"
91+
<Border BorderBrush="{DynamicResource BorderBrush}"
92+
BorderThickness="1"
93+
CornerRadius="4"
94+
Padding="8,6"
9595
Margin="2">
96-
<StackPanel>
97-
<!-- Server Name Row with Status Icon -->
98-
<StackPanel Orientation="Horizontal">
99-
<TextBlock Text="{Binding StatusIcon}"
96+
<Grid>
97+
<Grid.ColumnDefinitions>
98+
<ColumnDefinition Width="Auto"/>
99+
<ColumnDefinition Width="*"/>
100+
<ColumnDefinition Width="Auto"/>
101+
</Grid.ColumnDefinitions>
102+
103+
<!-- Status Indicator (back-ported from Lite: Ellipse + DataTriggers) -->
104+
<Ellipse Grid.Column="0"
105+
Width="10" Height="10"
106+
Margin="0,6,8,0"
107+
VerticalAlignment="Top"
108+
ToolTip="{Binding Status.ErrorMessage}">
109+
<Ellipse.Style>
110+
<Style TargetType="Ellipse">
111+
<Setter Property="Fill" Value="{DynamicResource ForegroundMutedBrush}"/>
112+
<Style.Triggers>
113+
<DataTrigger Binding="{Binding DotStatus}" Value="Online">
114+
<Setter Property="Fill" Value="{DynamicResource SuccessBrush}"/>
115+
</DataTrigger>
116+
<DataTrigger Binding="{Binding DotStatus}" Value="Offline">
117+
<Setter Property="Fill" Value="{DynamicResource ErrorBrush}"/>
118+
</DataTrigger>
119+
<DataTrigger Binding="{Binding DotStatus}" Value="Warning">
120+
<Setter Property="Fill" Value="{DynamicResource WarningBrush}"/>
121+
</DataTrigger>
122+
</Style.Triggers>
123+
</Style>
124+
</Ellipse.Style>
125+
</Ellipse>
126+
127+
<!-- Server detail stack -->
128+
<StackPanel Grid.Column="1">
129+
<TextBlock Text="{Binding DisplayName}" FontWeight="SemiBold" FontSize="13" Foreground="{DynamicResource ForegroundBrush}"/>
130+
<TextBlock Text="{Binding ServerName}" FontSize="13" Foreground="{DynamicResource AccentBrush}" Margin="0,-2,0,0" />
131+
<TextBlock Text="{Binding Description}" FontSize="10" Foreground="{DynamicResource ForegroundDimBrush}"
132+
TextWrapping="Wrap" Margin="0,-1,0,0"/>
133+
<!-- Status Duration (Online for X / Offline for X) -->
134+
<TextBlock Text="{Binding StatusDurationDisplay, Mode=OneWay}"
135+
FontSize="13"
136+
FontWeight="SemiBold"
100137
Foreground="{Binding StatusColor}"
101-
FontSize="14"
102-
FontWeight="Bold"
103-
VerticalAlignment="Center"
104-
Margin="0,0,4,0"
105-
ToolTip="{Binding Status.ErrorMessage}"/>
106-
<TextBlock Text="&#x2605;" FontSize="13" Foreground="#FFD700" Margin="0,0,4,0"
107-
VerticalAlignment="Center"
108-
Visibility="{Binding IsFavorite, Converter={StaticResource BoolToVisibilityConverter}}"/>
109-
<TextBlock Text="{Binding DisplayName}" FontWeight="SemiBold" FontSize="13" Foreground="{DynamicResource ForegroundBrush}" VerticalAlignment="Center"/>
138+
Margin="0,-1,0,0"
139+
Visibility="{Binding HasBeenChecked, Converter={StaticResource BoolToVisibilityConverter}}"/>
140+
<!-- Monitor Version -->
141+
<TextBlock Text="{Binding MonitorVersionDisplay, Mode=OneWay}"
142+
FontSize="11"
143+
Foreground="{DynamicResource ForegroundMutedBrush}"
144+
Margin="0,-1,0,0"
145+
Visibility="{Binding HasBeenChecked, Converter={StaticResource BoolToVisibilityConverter}}"/>
146+
<!-- Last Checked Timestamp -->
147+
<TextBlock FontSize="12" Foreground="{DynamicResource ForegroundDimBrush}" Margin="0,-1,0,0">
148+
<Run Text="{Binding LastCheckedDisplay, Mode=OneWay}"/>
149+
</TextBlock>
110150
</StackPanel>
111-
<TextBlock Text="{Binding ServerName}" FontSize="13" Foreground="{DynamicResource AccentBrush}" Margin="0,-2,0,0" />
112-
<TextBlock Text="{Binding Description}" FontSize="10" Foreground="{DynamicResource ForegroundDimBrush}"
113-
TextWrapping="Wrap" Margin="0,-1,0,0"/>
114-
<!-- Status Duration (Online for X / Offline for X) -->
115-
<TextBlock Text="{Binding StatusDurationDisplay, Mode=OneWay}"
116-
FontSize="13"
117-
FontWeight="SemiBold"
118-
Foreground="{Binding StatusColor}"
119-
Margin="0,-1,0,0"
120-
Visibility="{Binding HasBeenChecked, Converter={StaticResource BoolToVisibilityConverter}}"/>
121-
<!-- Monitor Version -->
122-
<TextBlock Text="{Binding MonitorVersionDisplay, Mode=OneWay}"
123-
FontSize="11"
124-
Foreground="{DynamicResource ForegroundMutedBrush}"
125-
Margin="0,-1,0,0"
126-
Visibility="{Binding HasBeenChecked, Converter={StaticResource BoolToVisibilityConverter}}"/>
127-
<!-- Last Checked Timestamp -->
128-
<TextBlock FontSize="12" Foreground="{DynamicResource ForegroundDimBrush}" Margin="0,-1,0,0">
129-
<Run Text="{Binding LastCheckedDisplay, Mode=OneWay}"/>
130-
</TextBlock>
131-
</StackPanel>
151+
152+
<!-- Favorite Star (right-aligned, back-ported from Lite) -->
153+
<TextBlock Grid.Column="2"
154+
Text="&#x2605;" FontSize="16"
155+
VerticalAlignment="Top"
156+
Foreground="#FFD700"
157+
Margin="4,2,0,0"
158+
Visibility="{Binding IsFavorite, Converter={StaticResource BoolToVisibilityConverter}}"/>
159+
</Grid>
132160
</Border>
133161
</DataTemplate>
134162
</ListView.ItemTemplate>

Dashboard/ManageServersWindow.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
<DataGridTextColumn Header="Display Name" Binding="{Binding DisplayName}" Width="150"/>
7575
<DataGridTextColumn Header="Server" Binding="{Binding ServerName}" Width="180"/>
7676
<DataGridTextColumn Header="Authentication" Binding="{Binding AuthenticationDisplay}" Width="120"/>
77+
<DataGridTextColumn Header="Installed Version" Binding="{Binding InstalledVersion}" Width="130"/>
7778
<DataGridTextColumn Header="Monthly Cost ($)" Binding="{Binding MonthlyCostUsd, StringFormat='{}{0:N0}'}" Width="120">
7879
<DataGridTextColumn.ElementStyle>
7980
<Style TargetType="TextBlock">

0 commit comments

Comments
 (0)