Merged
Conversation
Auto-refresh timer was firing all sub-tab queries (~32 SQL queries) every 30 seconds regardless of which sub-tab was visible. Now only the active sub-tab refreshes on timer ticks (1-2 queries). Full refresh preserved for initial load, manual refresh, and Apply-to-All time range changes. Controls updated: ResourceMetricsContent (8 sub-tabs), QueryPerformanceContent (8 sub-tabs), SystemEventsContent (9 sub-tabs), MemoryContent (5 sub-tabs). Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Add database_size_stats_collector and server_properties_collector to install seed data so fresh installs get FinOps collectors (fixes #531) - Load all per-server FinOps sub-tabs on server switch (fixes #530) - Clear stale utilization grids when switching servers (fixes #532) - Fix NoUtilizationMessage layout (RowSpan, alignment, margin) - Change CROSS JOIN to LEFT JOIN for server_info in Lite utilization query so data shows even without v_server_properties (fixes #533) - Remove stale debug JSON files Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…-ui-fixes Fix FinOps collector scheduling and UI bugs
RetrievedFromCache is an attribute on the StmtSimple XML element, but the parser was reading it from the child QueryPlan element where it never exists. Changed to read from stmtEl instead of queryPlanEl in both Dashboard and Lite copies. Ported from PerformanceStudio#88 / PerformanceStudio#89. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The database_size_stats and server_properties collectors iterate databases with cursor-based dynamic SQL. On mirroring passive servers, RESTORING databases must be excluded to prevent severity 22 engine crashes (same root cause as #384 and #430). - database_size_stats: Change state_desc filter to d.state = 0 - server_properties: Change state_desc filter to d.state = 0, add HAS_DBACCESS() check (was missing entirely) Fixes #535 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e-crash Fix SQL dumps on mirroring passive servers from FinOps collectors
00_uninstall.sql (added in #431 for standalone uninstall) was placed in install/ and picked up by the file glob, making it the first script executed on every install — including upgrades. This silently dropped the PerformanceMonitor database before recreating it empty. Four fixes: 1. Exclude 00_* from the install file list (both CLI and GUI), matching the existing 97_/99_ exclusion pattern. 2. Abort installation when any upgrade script fails instead of falling through to the full install path over a partially-upgraded database. New CLI exit code 8 (UpgradesFailed). 3. Version detection fallback: when the database exists but installation_history has no SUCCESS rows (prior GUI bug), return "1.0.0" so all idempotent upgrades are attempted rather than treating it as a fresh install. 4. Increase upgrade script timeout from 5 minutes to 1 hour for data migrations on large tables (compress_query_stats on 240GB+ DBs). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix installer dropping database on every upgrade
Rule-based inference engine for automated SQL Server diagnostics: - FactCollector gathers wait stats, blocking, deadlocks, config, memory - FactScorer applies threshold formulas + contextual amplifiers - RelationshipGraph encodes diagnostic reasoning as conditional edges - InferenceEngine does greedy traversal to build evidence-backed stories - FindingStore persists/retrieves/mutes findings in DuckDB MCP tools (6 total): - analyze_server: full pipeline with next_tools recommendations per finding - get_analysis_facts: raw scored facts with amplifier details - compare_analysis: two-period comparison with severity deltas - audit_config: edition-aware CTFP/MAXDOP/memory/threads evaluation - get_analysis_findings: retrieve persisted findings - mute_analysis_finding: suppress known patterns Stripped UI (Narrator, AnalysisTab) — AI clients consume via MCP, not prose. 83 tests passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New fact categories with scoring, amplifiers, and graph edges: - CPU_SQL_PERCENT: avg SQL CPU % (thresholds 75/95%), cross-refs SOS_SCHEDULER_YIELD - IO_READ_LATENCY_MS / IO_WRITE_LATENCY_MS: avg latency from file_io_stats deltas - TEMPDB_USAGE: usage fraction from tempdb_stats (thresholds 75/90%) - MEMORY_GRANT_PENDING: max waiters from resource semaphore (thresholds 1/5) - QUERY_SPILLS / QUERY_HIGH_DOP: aggregate query stats (spill counts, DOP > 8) Amplifier cross-references connect the new facts: - SOS_SCHEDULER_YIELD boosted by CPU > 80% - PAGEIOLATCH boosted by read latency > 20ms and grant waiters - CXPACKET boosted by high-DOP query count - MEMORY_GRANT_PENDING boosted by RESOURCE_SEMAPHORE and spills - QUERY_SPILLS boosted by grant waiters Relationship graph edges for full diagnostic chains: - CPU: CPU_SQL_PERCENT ↔ SOS_SCHEDULER_YIELD ↔ CXPACKET - I/O: IO_READ_LATENCY ↔ PAGEIOLATCH, IO_WRITE_LATENCY ↔ WRITELOG - Memory: RESOURCE_SEMAPHORE ↔ MEMORY_GRANT_PENDING ↔ QUERY_SPILLS - TempDB: TEMPDB_USAGE → PAGEIOLATCH, TEMPDB_USAGE → QUERY_SPILLS - Query: QUERY_HIGH_DOP → CXPACKET/SOS, QUERY_SPILLS ↔ TEMPDB/grants Tool recommendations added for all new fact keys. MinimumDataHours raised from 0.5 to 72 (production threshold). Cleaned up stale narrator references in comments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
10 new collectors covering all non-plumbing DuckDB tables: - perfmon_stats: PLE (scored, <300 concerning), Batch Req/sec, compilations - memory_clerks: top 10 by size with breakdown - database_config: aggregated RCSI/auto_shrink/auto_close/page_verify counts - procedure_stats: aggregate proc execution stats (CPU, reads, elapsed) - query_snapshots: active query counts (long-running, blocked, parallel) - running_jobs: long-running job detection (scored, is_running_long count) - session_stats: connection counts by state and per-app max - trace_flags: active global trace flags list - server_properties: CPU count, cores, sockets, memory, HADR status - database_size_stats: disk volume free space (scored, <10% concerning) Scoring rules for PLE (inverted threshold), DB config (auto_shrink/close), running jobs, and disk space. Amplifiers cross-reference: - PLE boosted by PAGEIOLATCH and RESOURCE_SEMAPHORE - Deadlocks boosted by RCSI-off databases - DB_CONFIG boosted by I/O latency (auto_shrink fragmentation) - Disk space boosted by TempDB pressure and query spills Tool recommendations for PLE, DB_CONFIG, RUNNING_JOBS, DISK_SPACE. 83 tests passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ports the 5 plan analysis tools from PerformanceStudio to both apps: - analyze_query_plan: Analyze cached plan by query_hash - analyze_procedure_plan: Analyze procedure plan by sql_handle/plan_handle - analyze_query_store_plan: Analyze Query Store plan (fetched on-demand from SQL Server) - analyze_plan_xml: Analyze raw showplan XML directly - get_plan_xml: Retrieve raw showplan XML by query_hash Uses ShowPlanParser + PlanAnalyzer (31 anti-pattern rules) to return structured JSON with warnings, missing indexes, parameters, memory grants, and top operators. Dashboard fetches plans from SQL Server PerformanceMonitor database. Lite fetches from DuckDB cache, with Query Store as on-demand SQL Server fallback. Tested end-to-end on both apps against SQL2022. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add execution plan analysis MCP tools to Dashboard and Lite
- Add 24 adversarial tests (FactCollectorMiseryTests) covering division by zero, empty tables, reversed time ranges, DMV corruption, overflow, boundary conditions, and full-pipeline zero-period resilience - Add 15 new seed methods to TestDataSeeder for all remaining collectors (CPU, IO, TempDB, memory grants, query stats, perfmon, memory clerks, database config, procedure stats, active queries, running jobs, session stats, trace flags, server properties, disk space) - Enrich all 6 test scenarios with new seed data for integration coverage - Add 24 new happy-path collector tests in FactCollectorTests - Fix FactScorer bug: PLE=0 scored as severity 0.0 instead of 1.0 (zero page life expectancy = worst memory pressure, not harmless) - Widen CXPACKET amplifier test range to accommodate new CPU amplifier 131/131 tests passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
, #545) Lite perfmon fixes (#544): - Aggregate chart query by collection_time (SUM across instance_name) so multi-instance counters show one clean line instead of jagged duplicates - Add gap detection to DeltaCalculator — if >5min since last cached value, return 0 delta instead of inflated value spanning the entire gap - Seed timestamps from DuckDB so gap detection works after app restarts - Fix sample_interval_seconds from hardcoded 600 to 60 (actual interval) Dashboard fix (#545): - Wrap ServerTab construction in try-catch with user-friendly error message pointing to VC++ Redistributable download for SkiaSharp failures Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…n-and-scottplot Fix Lite perfmon chart bugs and Dashboard ScottPlot crash handling
DMV sys.dm_exec_query_stats returns min_dop, max_dop, and thread columns as bigint, but our temp table and permanent table used smallint/integer — causing overflow on INSERT. Widened to match actual DMV types: - min_dop, max_dop: smallint -> bigint - min/max_reserved_threads, min/max_used_threads: integer -> bigint Includes upgrade script for existing 2.2.0 installations. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The publish/ directory is gitignored; the type fix was already applied to install/02_create_tables.sql (the source of truth). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…verflow Fix arithmetic overflow in query_stats collector
Schema.cs: min_dop, max_dop changed from INTEGER to BIGINT Collector: Convert.ToInt32 changed to Convert.ToInt64 for dop reads Mirrors the Dashboard fix — same root cause, different codebase. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix Lite query_stats dop columns to match DMV bigint type
Missed the third copy of the query_stats schema in 06_ensure_collection_table.sql — same smallint/integer -> bigint fix for min_dop, max_dop, and thread columns. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix ensure_collection_table query_stats column types
Full audit of all collector tables against Microsoft DMV docs found 6 SQL Server columns and 2 Lite columns narrower than documented types: SQL Server: - cpu_scheduler_stats: total_work_queue_count, total_active_parallel_thread_count (int -> bigint) - cpu_scheduler_stats: system_memory_state_desc (nvarchar(120) -> nvarchar(256)) - waiting_tasks: resource_description (nvarchar(1000) -> nvarchar(3072)) - database_size_stats: recovery_model_desc (nvarchar(12) -> nvarchar(60)) - database_size_stats: volume_mount_point (nvarchar(256) -> nvarchar(512)) Lite (DuckDB): - tempdb_stats: total_sessions_using_tempdb (INTEGER -> BIGINT, removed narrowing cast) - session_stats: connection_count (INTEGER -> BIGINT, COUNT_BIG result) Also fixes Azure SQL DB collector CONVERT(nvarchar(12),...) -> nvarchar(60) for recovery_model_desc. Idempotent upgrade script tested on sql2022. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…smatches Widen collector columns to match DMV documentation
The summary DataGrid was in a RowDefinition Height="Auto" row, which lets it grow unbounded to fit all content. With enough rows the grid extends past the window and the detail grid gets pushed off-screen. Changed both grids to proportional heights (* and 2*) so they share the available space and scroll internally. Fix applied to both Lite and Dashboard. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…l-554 Fix Index Analysis scroll not working with many results (#554)
The existing NotifyOnConnectionLost/Restored settings only sent tray notifications. Now also sends an email (if SMTP is configured) on the online→offline transition and a "Server Restored" email when it comes back. Fires exactly once per transition — no repeated alerts while the server stays down. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…le-email-529 Email alerts when monitored servers go offline (#529)
Azure SQL DB isolates each database — you can't cross-database query. The collector was running sys.database_files against the connection's default database (usually master), so only master's files appeared in Storage Growth and Database Sizes. Now enumerates databases via sys.databases on master, then connects to each individually to collect file sizes. Extracted ReadSizeRow helper to deduplicate the reader parsing for both paths. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add missing "Optional" case to encryption switch — previously fell through to default (Mandatory), making the dropdown option non-functional - Remove bare catch in LogInstallationHistoryAsync — exceptions now propagate to the caller which already logs them as warnings. Prevents silent history write failures that cause version detection fallback. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
57 tests covering CpuScore, MemoryScore, StorageScore, Overall, ScoreColor, PercentRank, and HighImpactScorer with adversarial inputs. Found and fixed: PercentRank returned 1.5 when value exceeded all list entries (rank/count-1 exceeded 1.0). Clamped with Math.Min(1.0m, ...). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add HealthCalculator tests + fix PercentRank >1.0 bug
Lite: Add column-level filtering to all 5 Optimization sub-tab grids (IdleDatabases, TempdbPressure, WaitCategorySummary, ExpensiveQueries, MemoryGrantEfficiency) using the existing shared filter infrastructure. Dashboard: Add column-level filtering to all 10 FinOps DataGrids (Recommendations, DatabaseResources, StorageGrowth, DatabaseSizes, WaitCategorySummary, ExpensiveQueries, MemoryGrantEfficiency, ApplicationConnections, ServerInventory, HighImpact). Uses a single FinOpsFilter_Click handler that finds the parent DataGrid via visual tree walk, with per-grid filter state dictionaries. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add column filters to FinOps grids
Full SQL Server port of the Lite analysis engine. Dashboard now has the same inference engine, scoring, anomaly detection, drill-downs, and 6 MCP analysis tools as Lite. Portable files (copied from Lite, namespace updated): - AnalysisModels.cs, IFactCollector.cs, IPlanFetcher.cs - InferenceEngine.cs, RelationshipGraph.cs, FactScorer.cs SQL Server implementations (new): - SqlServerFactCollector.cs — 23 fact collectors querying collect.* tables - SqlServerFindingStore.cs — persists findings, auto-creates config.analysis_* tables - SqlServerAnomalyDetector.cs — CPU/wait/blocking/IO anomaly detection - SqlServerDrillDownCollector.cs — 11 drill-down categories - SqlServerPlanFetcher.cs — on-demand plan fetch via sys.dm_exec_query_plan - AnalysisService.cs — orchestrates pipeline with SQL Server backend MCP tools (6 new): - analyze_server, get_analysis_facts, compare_analysis - audit_config, get_analysis_findings, mute_analysis_finding Dashboard now has 63 total MCP tools (was 57). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…-port-590 Port ErikAI analysis engine to Dashboard (#590)
Add column filter buttons (FinOpsFilter_Click + ColumnFilterButtonStyle) to the remaining 4 FinOps DataGrids that were missing them: IdleDatabasesDataGrid (4 cols), TempdbPressureDataGrid (4 cols), IndexAnalysisSummaryGrid (28 cols), and IndexAnalysisDetailGrid (15 cols). All existing ElementStyle properties preserved. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…filters Add filters to remaining Dashboard FinOps grids
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hide IdleDatabases grid when empty to fix scrollbar artifact
SqlServerDrillDownCollector was splitting on ASCII ' -> ' but story
paths use Unicode ' → '. The split produced the entire path as one
key, so pathKeys.Contains("DEADLOCKS") always returned false.
Single character fix: ' -> ' → ' → '. All 8 applicable findings
now have populated drill-down data.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…arrow Fix Dashboard drill-down: Unicode arrow in story path split
TempDB grid showed white scrollbar when empty (same fix as IdleDatabases). Warning column was changed from Width=* to Width=200 during filter button addition, causing horizontal scrollbar with data present. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ning-width Fix TempDB grid scrollbar and Warning column width
Collapse DataGrid.Visibility when data count is 0 for all FinOps grids: Recommendations, DatabaseResources, StorageGrowth, WaitCategorySummary, ExpensiveQueries, MemoryGrantEfficiency, HighImpact. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hide all empty FinOps DataGrids to prevent scrollbar artifacts
Add ScrollViewer.HorizontalScrollBarVisibility=Disabled to all 12 FinOps DataGrids. Revert the visibility-collapse workarounds that hid grids entirely when empty. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…crollbar Fix FinOps grid scrollbars — disable horizontal scroll
MaxHeight was 700px which wasn't enough to fit the Username/Password fields plus Connection Options plus buttons. Bumped to 850px. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ight Fix Add Server dialog buttons hidden with SQL auth
- Bump Version/AssemblyVersion/FileVersion/InformationalVersion to 2.3.0 in all 4 csproj files - Fix GUI installer: set _installedVersion after successful install so the Uninstall button is enabled Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Version bump to 2.3.0 + fix GUI uninstall button
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
….3.0 Add 2.3.0 changelog
* Implement #567 for dashboard * Implement #567 for lite * Fix columns "order by" for dashboard * Fix columns "order by" for Lite * Fix upgrade script * Add filters to "Database Size" columns (matching Lite) * Do not swallow v22 migration failures. Update Lite/Database/DuckDbInitializer.cs Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Add upgrade script to the upgrade.txt * Remove the IF OBJECT_ID … ALTER TABLE block * Tidy up duplicate code * Fix collection health overflow and query stats DOP type mismatch - collection_health view: cast duration_ms and rows_collected to bigint before AVG/SUM to prevent arithmetic overflow after 7 days of data - collection_health C# reader: use Convert.ToInt64 for avg_duration_ms, update model property from int to long - query_stats reader: min_dop/max_dop columns are bigint in the table but reader called GetInt16() — changed to Convert.ToInt16(GetValue()) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Clamp negative duration_ms to 0 in master collector DST clock-backward adjustments cause DATEDIFF(MILLISECOND, @start, SYSDATETIME()) to return negative values when the wall clock jumps back. This pollutes avg_duration_ms in report.collection_health. Clamp to 0 with IIF rather than switching to UTC, which would break consistency with existing data. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix Database Sizes grid: scrollbar, filter handlers, per-file VLF count - Enable horizontal scrollbar (was Disabled, clipping new columns) - Unify all column filter buttons to DatabaseSizesFilter_Click (existing columns used FinOpsFilter_Click, causing split filter state) - VLF count: filter sys.dm_db_log_info by file_id so each log file gets its own count instead of the whole-database total (Dashboard + Lite) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix uninitialized @error_message in database size collector CATCH The per-database inner CATCH referenced @error_message which was never set — debug output always showed NULL. Use ERROR_MESSAGE() directly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: ClaudioESSilva <claudiosil100@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Cláudio Silva <ClaudioESSilva@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ServerSelector used DisplayName instead of DisplayNameWithIntent, so read-only intent connections were indistinguishable from normal ones. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix FinOps server dropdown missing (Read-Only) suffix
Contributor
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (142)
📝 WalkthroughWalkthroughIntroduces version 2.3.0 featuring a comprehensive Analysis engine for diagnostic fact collection, anomaly detection, two-layer scoring, and relationship graph-based story inference. Adds extensive MCP tools for query/plan analysis, health metrics, and diagnostics. Implements FinOps enhancements with monthly cost tracking, health scoring, and recommendations. Updates installers with SQL version validation, upgrade timeout handling, and new test coverage. Expands UI with cost inputs and partial refresh capabilities. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
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.
Release v2.3.0
See CHANGELOG.md for full details.
Highlights
Testing completed
Summary by CodeRabbit
New Features
Bug Fixes
Documentation