Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions Dashboard/Controls/CurrentConfigContent.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<UserControl x:Class="PerformanceMonitorDashboard.Controls.CurrentConfigContent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Loaded="OnLoaded">
<TabControl>
<!-- Current Server Configuration Sub-Tab -->
<TabItem Header="Server Configuration">
<Grid>
<DataGrid x:Name="ServerConfigDataGrid" AutoGenerateColumns="False" IsReadOnly="True"
RowHeight="25" GridLinesVisibility="Horizontal" CanUserResizeColumns="True" ContextMenu="{StaticResource DataGridContextMenu}"
ScrollViewer.CanContentScroll="True" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding ConfigurationName}" Width="220">
<DataGridTextColumn.Header>
<StackPanel>
<TextBlock Text="Setting" FontWeight="Bold" Margin="0,0,0,2"/>
<TextBox Width="210" Height="22" FontSize="11" TextChanged="ServerConfigFilterTextBox_TextChanged" Tag="ConfigurationName"/>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding ValueConfigured}" Width="100">
<DataGridTextColumn.Header>
<StackPanel>
<TextBlock Text="Configured" FontWeight="Bold" Margin="0,0,0,2"/>
<TextBox Width="90" Height="22" FontSize="11" TextChanged="ServerConfigFilterTextBox_TextChanged" Tag="ValueConfigured"/>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding ValueInUse}" Width="100">
<DataGridTextColumn.Header>
<StackPanel>
<TextBlock Text="In Use" FontWeight="Bold" Margin="0,0,0,2"/>
<TextBox Width="90" Height="22" FontSize="11" TextChanged="ServerConfigFilterTextBox_TextChanged" Tag="ValueInUse"/>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding ValueMinimum}" Width="80" Header="Minimum"/>
<DataGridTextColumn Binding="{Binding ValueMaximum}" Width="80" Header="Maximum"/>
<DataGridCheckBoxColumn Binding="{Binding IsDynamic}" Width="65" Header="Dynamic"/>
<DataGridCheckBoxColumn Binding="{Binding IsAdvanced}" Width="70" Header="Advanced"/>
<DataGridTextColumn Binding="{Binding LastChanged, StringFormat='{}{0:yyyy-MM-dd HH:mm:ss}'}" Width="150" Header="Last Changed"/>
<DataGridTextColumn Binding="{Binding Description}" Width="*" MinWidth="200" Header="Description"/>
</DataGrid.Columns>
</DataGrid>
<TextBlock x:Name="ServerConfigNoDataMessage" Style="{StaticResource NoDataMessage}"/>
</Grid>
</TabItem>

<!-- Current Database Configuration Sub-Tab -->
<TabItem Header="Database Configuration">
<Grid>
<DataGrid x:Name="DatabaseConfigDataGrid" AutoGenerateColumns="False" IsReadOnly="True"
RowHeight="25" GridLinesVisibility="Horizontal" CanUserResizeColumns="True" ContextMenu="{StaticResource DataGridContextMenu}"
ScrollViewer.CanContentScroll="True" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding DatabaseName}" Width="150">
<DataGridTextColumn.Header>
<StackPanel>
<TextBlock Text="Database" FontWeight="Bold" Margin="0,0,0,2"/>
<TextBox Width="140" Height="22" FontSize="11" TextChanged="DatabaseConfigFilterTextBox_TextChanged" Tag="DatabaseName"/>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding SettingType}" Width="160">
<DataGridTextColumn.Header>
<StackPanel>
<TextBlock Text="Setting Type" FontWeight="Bold" Margin="0,0,0,2"/>
<TextBox Width="150" Height="22" FontSize="11" TextChanged="DatabaseConfigFilterTextBox_TextChanged" Tag="SettingType"/>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding SettingName}" Width="220">
<DataGridTextColumn.Header>
<StackPanel>
<TextBlock Text="Setting Name" FontWeight="Bold" Margin="0,0,0,2"/>
<TextBox Width="210" Height="22" FontSize="11" TextChanged="DatabaseConfigFilterTextBox_TextChanged" Tag="SettingName"/>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding SettingValue}" Width="200">
<DataGridTextColumn.Header>
<StackPanel>
<TextBlock Text="Value" FontWeight="Bold" Margin="0,0,0,2"/>
<TextBox Width="190" Height="22" FontSize="11" TextChanged="DatabaseConfigFilterTextBox_TextChanged" Tag="SettingValue"/>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding LastChanged, StringFormat='{}{0:yyyy-MM-dd HH:mm:ss}'}" Width="150" Header="Last Changed"/>
</DataGrid.Columns>
</DataGrid>
<TextBlock x:Name="DatabaseConfigNoDataMessage" Style="{StaticResource NoDataMessage}"/>
</Grid>
</TabItem>

<!-- Current Trace Flags Sub-Tab -->
<TabItem Header="Trace Flags">
<Grid>
<DataGrid x:Name="TraceFlagsDataGrid" AutoGenerateColumns="False" IsReadOnly="True"
RowHeight="25" GridLinesVisibility="Horizontal" CanUserResizeColumns="True" ContextMenu="{StaticResource DataGridContextMenu}"
ScrollViewer.CanContentScroll="True" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding TraceFlag}" Width="100" Header="Trace Flag"/>
<DataGridCheckBoxColumn Binding="{Binding Status}" Width="70" Header="Enabled"/>
<DataGridCheckBoxColumn Binding="{Binding IsGlobal}" Width="70" Header="Global"/>
<DataGridCheckBoxColumn Binding="{Binding IsSession}" Width="70" Header="Session"/>
<DataGridTextColumn Binding="{Binding LastChanged, StringFormat='{}{0:yyyy-MM-dd HH:mm:ss}'}" Width="150" Header="Last Changed"/>
</DataGrid.Columns>
</DataGrid>
<TextBlock x:Name="TraceFlagsNoDataMessage" Style="{StaticResource NoDataMessage}"/>
</Grid>
</TabItem>
</TabControl>
</UserControl>
122 changes: 122 additions & 0 deletions Dashboard/Controls/CurrentConfigContent.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Copyright (c) 2026 Erik Darling, Darling Data LLC
*
* This file is part of the SQL Server Performance Monitor.
*
* Licensed under the MIT License. See LICENSE file in the project root for full license information.
*/

using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using PerformanceMonitorDashboard.Helpers;
using PerformanceMonitorDashboard.Services;

namespace PerformanceMonitorDashboard.Controls
{
public partial class CurrentConfigContent : UserControl
{
private DatabaseService? _databaseService;

public CurrentConfigContent()
{
InitializeComponent();
}

public void Initialize(DatabaseService databaseService)
{
_databaseService = databaseService;
}

public async Task RefreshAllDataAsync()
{
if (_databaseService == null) return;

await Task.WhenAll(
RefreshServerConfigAsync(),
RefreshDatabaseConfigAsync(),
RefreshTraceFlagsAsync()
);
}

private void OnLoaded(object sender, RoutedEventArgs e)
{
TabHelpers.AutoSizeColumnMinWidths(ServerConfigDataGrid);
TabHelpers.AutoSizeColumnMinWidths(DatabaseConfigDataGrid);
TabHelpers.AutoSizeColumnMinWidths(TraceFlagsDataGrid);
TabHelpers.FreezeColumns(ServerConfigDataGrid, 1);
TabHelpers.FreezeColumns(DatabaseConfigDataGrid, 1);
}

#region Server Configuration

private async Task RefreshServerConfigAsync()
{
if (_databaseService == null) return;

try
{
var data = await _databaseService.GetCurrentServerConfigAsync();
ServerConfigDataGrid.ItemsSource = data;
ServerConfigNoDataMessage.Visibility = data.Count == 0 ? Visibility.Visible : Visibility.Collapsed;
}
catch (Exception ex)
{
Logger.Error($"Error loading server configuration: {ex.Message}");
}
}

private void ServerConfigFilterTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
DataGridFilterService.ApplyFilter(ServerConfigDataGrid, sender as TextBox);
}

#endregion

#region Database Configuration

private async Task RefreshDatabaseConfigAsync()
{
if (_databaseService == null) return;

try
{
var data = await _databaseService.GetCurrentDatabaseConfigAsync();
DatabaseConfigDataGrid.ItemsSource = data;
DatabaseConfigNoDataMessage.Visibility = data.Count == 0 ? Visibility.Visible : Visibility.Collapsed;
}
catch (Exception ex)
{
Logger.Error($"Error loading database configuration: {ex.Message}");
}
}

private void DatabaseConfigFilterTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
DataGridFilterService.ApplyFilter(DatabaseConfigDataGrid, sender as TextBox);
}

#endregion

#region Trace Flags

private async Task RefreshTraceFlagsAsync()
{
if (_databaseService == null) return;

try
{
var data = await _databaseService.GetCurrentTraceFlagsAsync();
TraceFlagsDataGrid.ItemsSource = data;
TraceFlagsNoDataMessage.Visibility = data.Count == 0 ? Visibility.Visible : Visibility.Collapsed;
}
catch (Exception ex)
{
Logger.Error($"Error loading trace flags: {ex.Message}");
}
}

#endregion
}
}
43 changes: 43 additions & 0 deletions Dashboard/Models/CurrentServerConfigItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2026 Erik Darling, Darling Data LLC
*
* This file is part of the SQL Server Performance Monitor.
*
* Licensed under the MIT License. See LICENSE file in the project root for full license information.
*/

using System;

namespace PerformanceMonitorDashboard.Models
{
public class CurrentServerConfigItem
{
public string ConfigurationName { get; set; } = string.Empty;
public string ValueConfigured { get; set; } = string.Empty;
public string ValueInUse { get; set; } = string.Empty;
public string ValueMinimum { get; set; } = string.Empty;
public string ValueMaximum { get; set; } = string.Empty;
public bool IsDynamic { get; set; }
public bool IsAdvanced { get; set; }
public string Description { get; set; } = string.Empty;
public DateTime LastChanged { get; set; }
}

public class CurrentDatabaseConfigItem
{
public string DatabaseName { get; set; } = string.Empty;
public string SettingType { get; set; } = string.Empty;
public string SettingName { get; set; } = string.Empty;
public string SettingValue { get; set; } = string.Empty;
public DateTime LastChanged { get; set; }
}

public class CurrentTraceFlagItem
{
public int TraceFlag { get; set; }
public bool Status { get; set; }
public bool IsGlobal { get; set; }
public bool IsSession { get; set; }
public DateTime LastChanged { get; set; }
}
}
5 changes: 5 additions & 0 deletions Dashboard/ServerTab.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,11 @@
<controls:DefaultTraceContent x:Name="DefaultTraceTab" />
</TabItem>

<!-- Current Configuration Sub-Tab -->
<TabItem Header="Current Configuration">
<controls:CurrentConfigContent x:Name="CurrentConfigTab" />
</TabItem>

<!-- Server Configuration Changes Sub-Tab -->
<TabItem Header="Server Config Changes">
<Grid>
Expand Down
5 changes: 4 additions & 1 deletion Dashboard/ServerTab.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ public ServerTab(ServerConnection serverConnection, int utcOffsetMinutes = 0)
DailySummaryTab.Initialize(_databaseService);
CriticalIssuesTab.Initialize(_databaseService);
DefaultTraceTab.Initialize(_databaseService);
CurrentConfigTab.Initialize(_databaseService);
MemoryTab.Initialize(_databaseService);
PerformanceTab.Initialize(_databaseService, s => StatusText.Text = s);
SystemEventsContent.Initialize(_databaseService);
Expand Down Expand Up @@ -1169,6 +1170,7 @@ private async Task ApplyAndRefreshCurrentTabAsync()
CollectionHealth_Refresh_Click(null, new RoutedEventArgs());
await CriticalIssuesTab.RefreshDataAsync();
await DefaultTraceTab.RefreshAllDataAsync();
await CurrentConfigTab.RefreshAllDataAsync();
await RefreshResourceOverviewAsync();
break;

Expand Down Expand Up @@ -1278,13 +1280,14 @@ private async Task LoadDataAsync()
var dailySummaryTask = DailySummaryTab.RefreshDataAsync();
var criticalIssuesTask = CriticalIssuesTab.RefreshDataAsync();
var defaultTraceTask = DefaultTraceTab.RefreshAllDataAsync();
var currentConfigTask = CurrentConfigTab.RefreshAllDataAsync();
var systemEventsTask = SystemEventsContent.RefreshAllDataAsync();

// Wait for everything to complete before _isRefreshing resets
await Task.WhenAll(
healthTask, blockingEventsTask, deadlocksTask, blockingStatsTask, lockWaitStatsTask,
performanceTask, memoryTask, resourceOverviewTask, runningJobsTask,
resourceMetricsTask, dailySummaryTask, criticalIssuesTask, defaultTraceTask, systemEventsTask);
resourceMetricsTask, dailySummaryTask, criticalIssuesTask, defaultTraceTask, currentConfigTask, systemEventsTask);

// Populate grids with fetched data
var healthData = await healthTask;
Expand Down
Loading
Loading