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