diff --git a/Dashboard/Controls/FinOpsContent.xaml b/Dashboard/Controls/FinOpsContent.xaml index 14ae05c..858096c 100644 --- a/Dashboard/Controls/FinOpsContent.xaml +++ b/Dashboard/Controls/FinOpsContent.xaml @@ -431,10 +431,11 @@ diff --git a/Dashboard/Controls/FinOpsContent.xaml.cs b/Dashboard/Controls/FinOpsContent.xaml.cs index 4d34b20..79ea1a1 100644 --- a/Dashboard/Controls/FinOpsContent.xaml.cs +++ b/Dashboard/Controls/FinOpsContent.xaml.cs @@ -102,7 +102,13 @@ await Task.WhenAll( LoadDatabaseResourcesAsync(), LoadDatabaseSizesAsync(), LoadApplicationConnectionsAsync(), - LoadServerInventoryAsync() + LoadServerInventoryAsync(), + LoadStorageGrowthAsync(), + LoadIdleDatabasesAsync(), + LoadTempdbSummaryAsync(), + LoadWaitCategorySummaryAsync(), + LoadExpensiveQueriesAsync(), + LoadMemoryGrantEfficiencyAsync() ); } catch (Exception ex) @@ -133,6 +139,13 @@ private async Task LoadUtilizationAsync() DbSizeChart.ItemsSource = await _databaseService.GetFinOpsDatabaseSizeSummaryAsync(); ProvisioningTrendGrid.ItemsSource = await _databaseService.GetFinOpsProvisioningTrendAsync(); } + else + { + TopTotalGrid.ItemsSource = null; + TopAvgGrid.ItemsSource = null; + DbSizeChart.ItemsSource = null; + ProvisioningTrendGrid.ItemsSource = null; + } } catch (Exception ex) { diff --git a/Lite/Controls/FinOpsTab.xaml b/Lite/Controls/FinOpsTab.xaml index b431d94..11c7ca1 100644 --- a/Lite/Controls/FinOpsTab.xaml +++ b/Lite/Controls/FinOpsTab.xaml @@ -430,10 +430,11 @@ diff --git a/Lite/Controls/FinOpsTab.xaml.cs b/Lite/Controls/FinOpsTab.xaml.cs index d0f529f..c8c59fe 100644 --- a/Lite/Controls/FinOpsTab.xaml.cs +++ b/Lite/Controls/FinOpsTab.xaml.cs @@ -108,10 +108,18 @@ private async System.Threading.Tasks.Task LoadPerServerDataAsync() var serverId = GetSelectedServerId(); if (serverId == 0 || _dataService == null) return; - await LoadUtilizationAsync(serverId); - await LoadDatabaseResourcesAsync(serverId); - await LoadApplicationConnectionsAsync(serverId); - await LoadDatabaseSizesAsync(serverId); + await System.Threading.Tasks.Task.WhenAll( + LoadUtilizationAsync(serverId), + LoadDatabaseResourcesAsync(serverId), + LoadApplicationConnectionsAsync(serverId), + LoadDatabaseSizesAsync(serverId), + LoadStorageGrowthAsync(serverId), + LoadIdleDatabasesAsync(serverId), + LoadTempdbSummaryAsync(serverId), + LoadWaitCategorySummaryAsync(serverId), + LoadExpensiveQueriesAsync(serverId), + LoadMemoryGrantEfficiencyAsync(serverId) + ); } private async System.Threading.Tasks.Task LoadUtilizationAsync(int serverId) @@ -132,6 +140,13 @@ private async System.Threading.Tasks.Task LoadUtilizationAsync(int serverId) DbSizeChart.ItemsSource = await _dataService.GetDatabaseSizeSummaryAsync(serverId); ProvisioningTrendGrid.ItemsSource = await _dataService.GetProvisioningTrendAsync(serverId); } + else + { + TopTotalGrid.ItemsSource = null; + TopAvgGrid.ItemsSource = null; + DbSizeChart.ItemsSource = null; + ProvisioningTrendGrid.ItemsSource = null; + } } catch (Exception ex) { diff --git a/Lite/Services/LocalDataService.FinOps.cs b/Lite/Services/LocalDataService.FinOps.cs index 68aacea..fb0091d 100644 --- a/Lite/Services/LocalDataService.FinOps.cs +++ b/Lite/Services/LocalDataService.FinOps.cs @@ -476,7 +476,7 @@ LIMIT 1 s.cpu_count FROM cpu_stats c CROSS JOIN mem_latest m -CROSS JOIN server_info s"; +LEFT JOIN server_info s ON true"; command.Parameters.Add(new DuckDBParameter { Value = serverId }); command.Parameters.Add(new DuckDBParameter { Value = cutoff }); diff --git a/collection_schedule.json b/collection_schedule.json deleted file mode 100644 index ab6b3d8..0000000 --- a/collection_schedule.json +++ /dev/null @@ -1,144 +0,0 @@ -{ - "collectors": [ - { - "name": "wait_stats", - "enabled": true, - "frequency_minutes": 1, - "retention_days": 30, - "description": "Wait statistics from sys.dm_os_wait_stats" - }, - { - "name": "query_stats", - "enabled": true, - "frequency_minutes": 1, - "retention_days": 30, - "description": "Query statistics from sys.dm_exec_query_stats" - }, - { - "name": "procedure_stats", - "enabled": true, - "frequency_minutes": 1, - "retention_days": 30, - "description": "Stored procedure statistics from sys.dm_exec_procedure_stats" - }, - { - "name": "query_store", - "enabled": true, - "frequency_minutes": 5, - "retention_days": 30, - "description": "Query Store data (top 100 queries per database)" - }, - { - "name": "query_snapshots", - "enabled": true, - "frequency_minutes": 1, - "retention_days": 7, - "description": "Currently running queries snapshot" - }, - { - "name": "cpu_utilization", - "enabled": true, - "frequency_minutes": 1, - "retention_days": 30, - "description": "CPU utilization from ring buffer" - }, - { - "name": "file_io_stats", - "enabled": true, - "frequency_minutes": 1, - "retention_days": 30, - "description": "File I/O statistics from sys.dm_io_virtual_file_stats" - }, - { - "name": "memory_stats", - "enabled": true, - "frequency_minutes": 1, - "retention_days": 30, - "description": "Memory statistics from sys.dm_os_sys_memory and performance counters" - }, - { - "name": "memory_clerks", - "enabled": true, - "frequency_minutes": 5, - "retention_days": 30, - "description": "Memory clerk allocations from sys.dm_os_memory_clerks" - }, - { - "name": "tempdb_stats", - "enabled": true, - "frequency_minutes": 1, - "retention_days": 30, - "description": "TempDB space usage from sys.dm_db_file_space_usage" - }, - { - "name": "perfmon_stats", - "enabled": true, - "frequency_minutes": 1, - "retention_days": 30, - "description": "Key performance counters from sys.dm_os_performance_counters" - }, - { - "name": "deadlocks", - "enabled": true, - "frequency_minutes": 1, - "retention_days": 30, - "description": "Deadlocks from system_health extended event session" - }, - { - "name": "server_config", - "enabled": true, - "frequency_minutes": 0, - "retention_days": 30, - "description": "Server configuration (on-load only)" - }, - { - "name": "database_config", - "enabled": true, - "frequency_minutes": 0, - "retention_days": 30, - "description": "Database configuration (on-load only)" - }, - { - "name": "memory_grant_stats", - "enabled": true, - "frequency_minutes": 1, - "retention_days": 30, - "description": "Memory grant statistics from sys.dm_exec_query_memory_grants" - }, - { - "name": "waiting_tasks", - "enabled": true, - "frequency_minutes": 1, - "retention_days": 7, - "description": "Point-in-time waiting tasks from sys.dm_os_waiting_tasks" - }, - { - "name": "blocked_process_report", - "enabled": true, - "frequency_minutes": 1, - "retention_days": 30, - "description": "Blocked process reports from XE ring buffer session (opt-out)" - }, - { - "name": "database_scoped_config", - "enabled": true, - "frequency_minutes": 0, - "retention_days": 30, - "description": "Database-scoped configurations (on-load only)" - }, - { - "name": "trace_flags", - "enabled": true, - "frequency_minutes": 0, - "retention_days": 30, - "description": "Active trace flags via DBCC TRACESTATUS (on-load only)" - }, - { - "name": "running_jobs", - "enabled": true, - "frequency_minutes": 5, - "retention_days": 7, - "description": "Currently running SQL Agent jobs with duration comparison" - } - ] -} \ No newline at end of file diff --git a/install/04_create_schedule_table.sql b/install/04_create_schedule_table.sql index fa4e639..fbae51e 100644 --- a/install/04_create_schedule_table.sql +++ b/install/04_create_schedule_table.sql @@ -74,7 +74,9 @@ FROM (N'plan_cache_stats_collector', 1, 5, 5, 30, N'Plan cache composition statistics - single-use plans and plan cache bloat detection'), (N'session_stats_collector', 1, 1, 2, 30, N'Session and connection statistics - connection leaks and application patterns'), (N'waiting_tasks_collector', 1, 1, 2, 30, N'Currently waiting tasks - blocking chains and wait analysis'), - (N'running_jobs_collector', 1, 1, 2, 7, N'Currently running SQL Agent jobs with historical duration comparison') + (N'running_jobs_collector', 1, 1, 2, 7, N'Currently running SQL Agent jobs with historical duration comparison'), + (N'database_size_stats_collector', 1, 60, 10, 90, N'Database file sizes for growth trending and capacity planning'), + (N'server_properties_collector', 1, 1440, 5, 365, N'Server edition, licensing, CPU/memory hardware metadata for license audit') ) AS v (collector_name, enabled, frequency_minutes, max_duration_minutes, retention_days, description) WHERE NOT EXISTS ( diff --git a/servers.json b/servers.json deleted file mode 100644 index 6dc91e0..0000000 --- a/servers.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "Servers": [] -} \ No newline at end of file