Merged
Conversation
ReleaseMutex() throws ApplicationException if called by a thread that doesn't own the mutex. This happens when the app exits after detecting a second instance, or when shutdown is triggered from a non-owning thread. Track ownership and only release if we own it. Fixed in both Dashboard and Lite. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix mutex crash on app exit (fixes #89)
- Add checkpoint_threshold=1GB to connection string to prevent auto-checkpoint stalls - Add manual CHECKPOINT after each collection cycle during idle time - Change collector execution from parallel Task.WhenAll to sequential per-server - Fix using var timing bug across all 16 collector files: change to explicit using blocks so appender Dispose (flush + connection close) is captured inside the DuckDB stopwatch, giving accurate timing in collection_log Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…t-optimization DuckDB checkpoint optimization and timing fix
) Display queries now read from views that UNION hot DuckDB tables with archived parquet files, so users can see the full 90-day retention window instead of only the 7-day hot data window. Views are created at startup and refreshed after each archive cycle. Adds daily database compaction to prevent file bloat from DuckDB's append-only storage. Compaction exports all tables to a fresh database via ATTACH/CREATE TABLE AS, swaps files, and recreates indexes/views. Includes a 1GB size watchdog that logs warnings between compaction cycles. Tested: 24/24 — archive round-trip (export to parquet, delete hot rows, verify view still returns all rows) and compaction (19MB → 5MB, all 1055 rows preserved across 25 tables). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…queries Parquet archive visibility and scheduled compaction
…) (#163) Collector now reports state, collation, RCSI, snapshot isolation, stats settings, encryption, security, CDC, broker, and three version-gated columns (ADR 2019+, memory optimized 2019+, optimized locking 2025+). Dynamic SQL builds the SELECT list based on SQL Server version; Azure SQL DB always gets 2019+ columns. Schema version bumped to v11 (drop/recreate database_config table). Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Three fixes for "DuckDBOpen failed: Cannot open file" errors introduced by PR #159 (checkpoint) and PR #162 (compaction): 1. Timer initialization: DateTime.MinValue → DateTime.UtcNow prevents compaction/archival from firing on the very first collection cycle 2. Inline checkpoint: moved CHECKPOINT to end of RunDueCollectorsAsync using the existing connection pool instead of opening a separate DuckDB instance that conflicts via OS file locks 3. Atomic file swap: replaced two-step File.Move in CompactAsync with File.Replace (single OS operation, no window where the database file is missing) plus retry logic for locked files and WAL cleanup Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…ed (#139) (#172) SQL view TOP (20) → TOP (50) ensures low-volume poison waits like THREADPOOL reach the client. UI default selection cap raised from 20 to 30 across both Dashboard and Lite, giving enough room for poison waits + usual suspects + top 10 without squeezing. Closes #139 Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
DeadlockSeverity was only checking the perfmon counter delta between poll cycles, so deadlocks that occurred before Dashboard startup or between the first two polls showed green. Now also checks LastDeadlockMinutesAgo from extended events: <=10 min = Critical, <=60 min = Warning. Added missing OnPropertyChanged notification so the severity dot updates when the timestamp arrives. Closes #170 Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…) (#175) Default Trace Events and Trace Analysis tabs belong under Overview, not Resource Metrics. Extracted into new DefaultTraceContent UserControl following the same pattern as DailySummaryContent and CriticalIssuesContent. Removed dead column filter popup infrastructure from ResourceMetricsContent. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…176) The view report.long_running_query_patterns aggregates ALL time then takes TOP 50 by avg_duration_ms. When recent patterns are shorter than old load test patterns, the dashboard's time filter eliminates all 50 rows. Fix by inlining the query with time filter inside the CTE so aggregation only considers data within the selected time range. The second part of #168 (Trace Analysis in wrong location) was already fixed in PR #175. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Tooltips used Euclidean pixel distance requiring the mouse to be within 50px of a data point marker. With sparse time-series data (points every 15 mins), large gaps between markers made tooltips unreliable or absent. Fix: use X-axis (time) proximity as primary filter (80px horizontal), Y-axis distance as tiebreaker for multi-series charts. Tooltips now appear reliably when hovering at any Y position near a data point's time. Added try-catch for robustness, reduced throttle to 30ms. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Charts in query/procedure drill-down windows were fixed at 250px height, making them hard to read especially on larger monitors. Changed from fixed height to proportional layout (2* chart / 3* grid) with MinHeight 250 so charts scale with window size while maintaining a minimum. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
All three drill-down windows (Query Store, Query Stats, Procedure Stats) fetched ALL historical data with no time limit — up to 3776 rows per query, each carrying ~10KB of plan XML. Added 7-day time filter to collection_time on all three queries to keep result sets manageable. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
New "Current Configuration" tab in Overview shows the latest state of server settings, database settings, and trace flags using ROW_NUMBER windowing over the change history tables. Three sub-tabs with inline column filters for quick searching. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…iew (#140) (#181) Adds total_physical_memory_mb and committed_target_memory_mb columns to collect.memory_stats table, collected from sys.dm_os_sys_memory and sys.dm_os_sys_info. Memory Overview summary panel now shows absolute GB values for Physical Memory, SQL Server Memory, Target Memory, Buffer Pool, and Plan Cache alongside percentages. Includes ALTER TABLE migration for existing installs. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Red badge on the Alerts sidebar button shows the count of active alerts from the last 24 hours. Updates on each alert check cycle and on startup. Shows "99+" when count exceeds 99, collapses when no alerts. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…ing, aggregate by collection_time (#189) - Remove query_plan_text/query_plan from drill-down SELECT queries (was loading 122 MB inline, hanging the app) - Add on-demand plan fetch methods for all three drill-down types - Pass parent view's time range (hoursBack/fromDate/toDate) through to drill-down queries - Aggregate query_stats drill-down by collection_time with MAX for cumulative counters (matches report.query_stats_summary pattern) - Aggregate query_store drill-down by collection_time + plan_id with weighted averages - Remove broken 7-day DATEADD filter from PR #179 that prevented drill-downs from returning data - Fix Download button: increase RowHeight 30->35, remove stale IsEnabled binding, async on-demand fetch - Fix DefaultTraceContent/CurrentConfigContent StaticResource -> DynamicResource for theme support - Add upgrade script for memory_stats columns (1.2.0 -> 1.3.0) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AcknowledgeServerAlerts_Click only updated AlertStateService (tab badges) but never hid alerts in EmailAlertService, so the sidebar Alerts button badge count stayed unchanged. Now also hides alerts for the acknowledged server and refreshes the badge. Alert History dismiss actions also immediately update the sidebar badge via an AlertsDismissed event. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix sidebar alert badge not clearing on acknowledge (fixes #186)
…187) Extended Events timestamps are UTC but the NOC queries used SYSDATETIME() (local time). On a UTC-8 server, DATEDIFF returned -480 for recent events, which FormatMinutesAgo treated as "just now". Changed to SYSUTCDATETIME(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…mp-187 Fix NOC deadlock/blocking timestamps showing 'just now' for stale events (fixes #187)
RESOURCE_SEMAPHORE and RESOURCE_SEMAPHORE_QUERY_COMPILE were missing from the wait type picker because they had no collected data. Poison waits are now always injected into the picker list so they appear and get pre-selected by default, ready to show data if/when those waits occur. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…-188 Add missing poison wait defaults to wait stats picker (fixes #188)
…#199) LandingPage created its own ServerManager instance, so its in-memory server list was stale after MainWindow added a server. Now MainWindow passes its ServerManager to LandingPage so they share the same instance. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…sync-199 Fix newly added servers not appearing on Overview until restart (fixes #199)
Added IsDoubleClickOnRow() helper that walks the visual tree to distinguish DataGridRow clicks from DataGridColumnHeader clicks. Applied the guard to all five MouseDoubleClick handlers across QueryPerformanceContent, ServerTab, and ManageServersWindow. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix double-click on column header triggering row drill-down (fixes #195)
…xpress (fixes #192) All GetBoolean() and Convert.ToInt32() calls now check IsDBNull first, defaulting to false/0. Prevents "Object cannot be cast from DBNull to other types" on editions where certain sys.databases columns return NULL. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…-192 Fix DBNull cast error in Lite database_config collector (fixes #192)
…ixes #194) Plan cache execution_count is a cumulative counter — MAX is the correct aggregation, matching the main grid. The "Total Executions" label implied a sum, confusing users. Renamed to "Executions" in QueryStatsHistory and ProcedureHistory windows. Query Store window keeps "Total Executions" since it correctly sums interval deltas. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename misleading Total Executions label in drill-down summaries (fixes #194)
NumericFilterHelper: Replace naive Split('-') range parsing with TryParseRange
that finds the separator dash by looking for a '-' preceded by a digit. Correctly
handles -100-200, -100--50, and .. syntax. Previously, negative-start ranges were
silently ignored due to the StartsWith('-') guard.
MainWindow: Wrap MCP StopAsync in Task.Run to avoid sync-over-async deadlock on
the WPF UI thread during app close.
Addresses items from #113 and #112.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CDC capture agents use `waitfor delay @waittime` and run indefinitely by design. Service Broker listeners use `waitfor receive`. Neither should trigger long-running query alerts. Adds NOT LIKE filters for both patterns in Dashboard (live DMV query) and Lite (DuckDB alert query). Fixes #151. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Migrates 5 DataGrids from the old TextBox-in-header filter style to the standard popup filter pattern used by the rest of the Dashboard: - DefaultTraceContent: DefaultTraceEventsDataGrid (7 cols), TraceAnalysisDataGrid (9 cols) - CurrentConfigContent: ServerConfigDataGrid (9 cols), DatabaseConfigDataGrid (5 cols), TraceFlagsDataGrid (5 cols — previously had no filters at all) All columns now have consistent popup filter buttons with operator support and gold active-filter indicators. Fixes #200. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix numeric filter negative range parsing and MCP shutdown deadlock risk
…ning-151 Exclude WAITFOR sessions from long-running query alerts
Replace TextBox-in-header filters with popup filter buttons
…210) Settings dropdown had 1h/6h/24h/7d but dashboard buttons offer 1h/4h/8h/12h/24h/7d/30d. Aligned the dropdown to match exactly. Fixed fallback index for 24-hour default. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix settings time range dropdown to match dashboard buttons
…ows (#206) All three drill-down windows (QueryStatsHistory, QueryExecutionHistory, ProcedureHistory) now have popup filter buttons on every column and right-click context menus for copy cell/row/all rows and CSV export, matching the behavior of all other DataGrids in the application. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rs-206 Add column filters and context menus to drill-down history windows
When dismissing alerts from inside a server tab (right-clicking Locking, Memory, etc.), the sidebar Alerts badge count was not updated because ServerTab only called AlertStateService.AcknowledgeAlert (tab badges) without touching the EmailAlertService alert log (sidebar badge source). Added AlertAcknowledged event on ServerTab, fired after sub-tab dismiss. MainWindow subscribes and hides email alerts + refreshes sidebar badge, matching the landing page dismiss flow. Note: the sidebar badge re-notification follows a 5-minute cooldown per alert type per server — this is by design to avoid notification spam. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix sidebar alert badge not syncing with sub-tab dismissals
- 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 <noreply@anthropic.com>
Release prep: v1.3.0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Highlights
collect.memory_statsgainstotal_physical_memory_mbandcommitted_target_memory_mb(automatic via installer, idempotent)Test plan
🤖 Generated with Claude Code