From fe6c6bdac4f5d947d16f7889de5dfde4cd8adec0 Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Fri, 20 Feb 2026 14:53:42 -0500 Subject: [PATCH] Bump version to 1.3.0, fix deadlock XML timezone bug, add changelog - Version bump all 4 csproj files from 1.2.0 to 1.3.0 - Fix UTC timezone mismatch in process_deadlock_xml: sp_BlitzLock expects local time dates but was receiving UTC, causing 0 parsed results on any server not in UTC. Convert dates to local time before passing to sp_BlitzLock. - Add CHANGELOG entries for both 1.2.0 (previously missing) and 1.3.0 - 1.3.0 includes schema upgrade warning for large memory_stats tables Tested: deployed fix to sql2016/2017/2019/2022, verified 192 stuck unprocessed deadlock XML events parsed successfully on sql2022. Co-Authored-By: Claude Opus 4.6 --- CHANGELOG.md | 131 +++++++++++++++++++ Dashboard/Dashboard.csproj | 2 +- Installer/PerformanceMonitorInstaller.csproj | 8 +- InstallerGui/InstallerGui.csproj | 2 +- Lite/PerformanceMonitorLite.csproj | 2 +- install/25_process_deadlock_xml.sql | 41 ++++-- 6 files changed, 169 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 715e3f9b..1f999e77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,83 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.3.0] - 2026-02-20 + +### Important + +- **Schema upgrade**: The `collect.memory_stats` table gains two new columns (`total_physical_memory_mb`, `committed_target_memory_mb`). The upgrade script runs automatically via the CLI/GUI installer and uses `IF NOT EXISTS` checks, so it is safe to re-run. On servers with very large `memory_stats` tables this ALTER may take a moment. + +### Added + +- Physical Memory, SQL Server Memory, and Target Memory columns in Memory Overview ([#140]) +- Current Configuration view (Server Config, Database Config, Trace Flags) in Dashboard Overview ([#143]) +- Popup column filters and right-click context menus in all drill-down history windows ([#206]) +- Consistent popup column filters across all Dashboard grids — replaced remaining TextBox-in-header filters and added filters to Trace Flags ([#200]) +- 7-day time filter option in drill-down queries ([#165]) +- Alert badge/count on sidebar Alerts button ([#109]) +- Missing poison wait defaults in wait stats picker ([#188]) + +### Changed + +- Default Trace tabs moved from Resource Metrics to Overview section ([#169]) +- Trends tab shown first in Locking section ([#171]) +- Wait stats cap raised from 20 to 30 (Dashboard) / 50 (Lite) so poison waits are never dropped ([#139]) +- Settings time range dropdown now matches dashboard button options ([#210]) +- "Total Executions" label in drill-down summaries renamed to clarify meaning ([#194]) +- WAITFOR sessions excluded from long-running query alerts ([#151]) + +### Fixed + +- Deadlock XML processor timezone mismatch — sp_BlitzLock returning 0 results because UTC dates were passed instead of local time +- Sidebar alert badge not updating when alerts dismissed from server sub-tabs ([#214]) +- Sidebar alert badge not clearing on acknowledge ([#186]) +- NOC deadlock/blocking showing "just now" for stale events instead of actual timestamp ([#187]) +- NOC deadlock severity using extended events timestamp ([#170]) +- Newly added servers not appearing on Overview until app restart ([#199]) +- Double-click on column header incorrectly triggering row drill-down ([#195]) +- Squished drill-down charts — now use proportional sizing ([#166]) +- Unreliable chart tooltips — now use X-axis proximity matching ([#167]) +- Query Trace Patterns showing empty despite data existing ([#168]) +- Drill-down windows: removed inline plan XML, added time range filtering, aggregated by collection_time ([#189]) +- Row clipping in Default Trace and Current Configuration grids ([#183], [#184]) +- Numeric filter negative range parsing ([#113]) +- MCP shutdown deadlock risk ([#112]) +- Lite DBNull cast error in database_config collector on SQL 2016 Express ([#192]) +- DuckDB concurrent file access IO errors ([#164]) + +## [1.2.0] - 2026-02-15 + +### Added + +- Alert types, alerts history view, column filtering, and dismiss/hide for alerts ([#52], [#56]) +- Average ms per wait chart toggle in both apps ([#22]) +- Collection Health tab in Lite UI ([#39]) +- Collector performance diagnostics in Lite UI ([#40]) +- Hover tooltips on all Dashboard charts ([#70]) +- Minimize-to-tray setting added to Lite ([#53]) +- Persist dismissed alerts across app restarts ([#44]) +- Locale-aware date/time formatting throughout UI ([#41]) +- 24-hour format in time range picker ([#41]) +- CI pipelines for build validation, SQL install testing, and DuckDB schema tests +- Expanded Lite database config collector to 28 sys.databases columns ([#142]) +- Parquet archive visibility and scheduled DuckDB database compaction ([#160], [#161]) +- DuckDB checkpoint optimization and collection timing accuracy +- Installer `--reset-schedule` flag to reset collection schedule on re-install + +### Fixed + +- Deadlock charts not populating data ([#73]) +- Chart X-axis double-converting custom range to server time ([#49]) +- query_cost overflow in memory grant collector ([#47]) +- XE ring buffer query timeouts on large buffers ([#37]) +- Dashboard sub-tab badge state and DuckDB migration for dismissed column +- Lite duplicate blocking/deadlock events from missing WHERE clause ([#61]) +- Procedure_stats_collector truncation on DDL triggers ([#69]) +- DataGrid row height increased from 25 to 28 to fix text clipping +- Skip offline servers during Lite collection and reduce connection timeout ([#90]) +- Mutex crash on Lite app exit ([#89]) +- Permission denied errors handled gracefully in collector health ([#150]) + ## [1.1.0] - 2026-02-13 ### Added @@ -42,6 +119,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Delta normalization for per-second rate calculations - Dark theme UI +[1.3.0]: https://github.com/erikdarlingdata/PerformanceMonitor/compare/v1.2.0...v1.3.0 +[1.2.0]: https://github.com/erikdarlingdata/PerformanceMonitor/compare/v1.1.0...v1.2.0 [1.1.0]: https://github.com/erikdarlingdata/PerformanceMonitor/compare/v1.0.0...v1.1.0 [1.0.0]: https://github.com/erikdarlingdata/PerformanceMonitor/releases/tag/v1.0.0 [#1]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/1 @@ -54,5 +133,57 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#18]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/18 [#20]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/20 [#21]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/21 +[#22]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/22 [#23]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/23 [#25]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/25 +[#37]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/37 +[#39]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/39 +[#40]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/40 +[#41]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/41 +[#44]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/44 +[#47]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/47 +[#49]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/49 +[#52]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/52 +[#53]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/53 +[#56]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/56 +[#61]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/61 +[#69]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/69 +[#70]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/70 +[#73]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/73 +[#85]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/85 +[#86]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/86 +[#89]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/89 +[#90]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/90 +[#109]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/109 +[#112]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/112 +[#113]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/113 +[#139]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/139 +[#140]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/140 +[#142]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/142 +[#143]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/143 +[#150]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/150 +[#151]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/151 +[#160]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/160 +[#161]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/161 +[#164]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/164 +[#165]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/165 +[#166]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/166 +[#167]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/167 +[#168]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/168 +[#169]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/169 +[#170]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/170 +[#171]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/171 +[#183]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/183 +[#184]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/184 +[#186]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/186 +[#187]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/187 +[#188]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/188 +[#189]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/189 +[#192]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/192 +[#194]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/194 +[#195]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/195 +[#199]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/199 +[#200]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/200 +[#206]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/206 +[#210]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/210 +[#214]: https://github.com/erikdarlingdata/PerformanceMonitor/issues/214 diff --git a/Dashboard/Dashboard.csproj b/Dashboard/Dashboard.csproj index 8de16fa1..4f568c24 100644 --- a/Dashboard/Dashboard.csproj +++ b/Dashboard/Dashboard.csproj @@ -6,7 +6,7 @@ true PerformanceMonitorDashboard SQL Server Performance Monitor Dashboard - 1.2.0 + 1.3.0 Darling Data, LLC Copyright © 2026 Darling Data, LLC EDD.ico diff --git a/Installer/PerformanceMonitorInstaller.csproj b/Installer/PerformanceMonitorInstaller.csproj index 07e9c964..a5091055 100644 --- a/Installer/PerformanceMonitorInstaller.csproj +++ b/Installer/PerformanceMonitorInstaller.csproj @@ -20,10 +20,10 @@ PerformanceMonitorInstaller SQL Server Performance Monitor Installer - 1.2.0 - 1.2.0.0 - 1.2.0.0 - 1.2.0 + 1.3.0 + 1.3.0.0 + 1.3.0.0 + 1.3.0 Darling Data, LLC Copyright © 2026 Darling Data, LLC Installation utility for SQL Server Performance Monitor - Supports SQL Server 2016-2025 diff --git a/InstallerGui/InstallerGui.csproj b/InstallerGui/InstallerGui.csproj index 2e41cf44..c9d3797a 100644 --- a/InstallerGui/InstallerGui.csproj +++ b/InstallerGui/InstallerGui.csproj @@ -8,7 +8,7 @@ PerformanceMonitorInstallerGui PerformanceMonitorInstallerGui SQL Server Performance Monitor Installer - 1.2.0 + 1.3.0 Darling Data, LLC Copyright © 2026 Darling Data, LLC EDD.ico diff --git a/Lite/PerformanceMonitorLite.csproj b/Lite/PerformanceMonitorLite.csproj index 6b51c5fa..5bc6031c 100644 --- a/Lite/PerformanceMonitorLite.csproj +++ b/Lite/PerformanceMonitorLite.csproj @@ -7,7 +7,7 @@ PerformanceMonitorLite PerformanceMonitorLite SQL Server Performance Monitor Lite - 1.2.0 + 1.3.0 Darling Data, LLC Copyright © 2026 Darling Data, LLC Lightweight SQL Server performance monitoring - no installation required on target servers diff --git a/install/25_process_deadlock_xml.sql b/install/25_process_deadlock_xml.sql index b7e75850..74067fdf 100644 --- a/install/25_process_deadlock_xml.sql +++ b/install/25_process_deadlock_xml.sql @@ -55,7 +55,10 @@ BEGIN @error_number integer, @blitzlock_database sysname = NULL, @sql nvarchar(max) = N'', - @debug_msg nvarchar(500) = N''; + @debug_msg nvarchar(500) = N'', + @utc_offset_minutes integer = DATEDIFF(MINUTE, SYSUTCDATETIME(), SYSDATETIME()), + @start_date_local datetime2(7) = NULL, + @end_date_local datetime2(7) = NULL; BEGIN TRY BEGIN TRANSACTION; @@ -142,16 +145,33 @@ BEGIN END; END; + /* + Convert UTC dates to local time for sp_BlitzLock and comparison + with collect.deadlocks.event_date (which sp_BlitzLock stores in local time). + event_time in collect.deadlock_xml stores UTC (from XE timestamps). + sp_BlitzLock converts @StartDate/@EndDate from local time to UTC internally. + */ + SELECT + @start_date_local = DATEADD(MINUTE, @utc_offset_minutes, @start_date), + @end_date_local = DATEADD(MINUTE, @utc_offset_minutes, @end_date); + + IF @debug = 1 + BEGIN + SET @debug_msg = N'UTC offset: ' + CAST(@utc_offset_minutes AS nvarchar(10)) + N' minutes. Local dates: ' + ISNULL(CONVERT(nvarchar(30), @start_date_local, 121), N'NULL') + N' to ' + ISNULL(CONVERT(nvarchar(30), @end_date_local, 121), N'NULL'); + RAISERROR(@debug_msg, 0, 1) WITH NOWAIT; + END; + /* Delete existing parsed deadlocks for the time range to prevent duplicates sp_BlitzLock will re-insert fresh parsed data + Uses local-time dates because sp_BlitzLock stores event_date in local time */ IF @start_date IS NOT NULL AND @end_date IS NOT NULL BEGIN DELETE d FROM collect.deadlocks AS d - WHERE d.event_date >= @start_date - AND d.event_date <= @end_date; + WHERE d.event_date >= @start_date_local + AND d.event_date <= @end_date_local; SELECT @rows_deleted = ROWCOUNT_BIG(); @@ -175,8 +195,8 @@ BEGIN @TargetTableName = N''deadlock_xml'', @TargetColumnName = N''deadlock_xml'', @TargetTimestampColumnName = N''event_time'', - @StartDate = @start_date, - @EndDate = @end_date, + @StartDate = @start_date_local, + @EndDate = @end_date_local, @OutputDatabaseName = N''PerformanceMonitor'', @OutputSchemaName = N''collect'', @OutputTableName = N''deadlocks'', @@ -184,20 +204,21 @@ BEGIN EXECUTE sys.sp_executesql @sql, - N'@start_date datetime2(7), @end_date datetime2(7), @debug bit', - @start_date = @start_date, - @end_date = @end_date, + N'@start_date_local datetime2(7), @end_date_local datetime2(7), @debug bit', + @start_date_local = @start_date_local, + @end_date_local = @end_date_local, @debug = @debug; /* Verify sp_BlitzLock produced parsed results before marking rows as processed If no results were inserted, leave rows unprocessed so they are retried next run + Uses local-time dates because sp_BlitzLock stores event_date in local time */ SELECT @rows_parsed = COUNT_BIG(*) FROM collect.deadlocks AS d - WHERE d.event_date >= @start_date - AND d.event_date <= @end_date + WHERE d.event_date >= @start_date_local + AND d.event_date <= @end_date_local OPTION(RECOMPILE); IF @rows_parsed > 0