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
4 changes: 2 additions & 2 deletions Lite/Controls/FinOpsTab.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ private void PopulateServerSelector()
private int GetSelectedServerId()
{
if (ServerSelector.SelectedItem is ServerConnection server)
return RemoteCollectorService.GetDeterministicHashCode(server.ServerName);
return RemoteCollectorService.GetDeterministicHashCode(RemoteCollectorService.GetServerNameForStorage(server));
return 0;
}

Expand Down Expand Up @@ -347,7 +347,7 @@ private async System.Threading.Tasks.Task LoadServerInventoryAsync(bool forceRef
// Step 2: Get collected metrics from DuckDB
try
{
var serverId = RemoteCollectorService.GetDeterministicHashCode(server.ServerName);
var serverId = RemoteCollectorService.GetDeterministicHashCode(RemoteCollectorService.GetServerNameForStorage(server));
var (avgCpu, storageGb, idleDbs, status) = await _dataService!.GetServerMetricsAsync(serverId);
if (avgCpu.HasValue) item.AvgCpuPct = avgCpu;
if (storageGb.HasValue) item.StorageTotalGb = storageGb;
Expand Down
9 changes: 5 additions & 4 deletions Lite/Controls/ServerTab.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
private readonly LocalDataService _dataService;
private readonly int _serverId;
public int ServerId => _serverId;
public ServerConnection Server => _server;
private readonly CredentialService _credentialService;
private readonly DispatcherTimer _refreshTimer;
private bool _isRefreshing;
Expand Down Expand Up @@ -117,13 +118,13 @@

_server = server;
_dataService = new LocalDataService(duckDb);
_serverId = RemoteCollectorService.GetDeterministicHashCode(server.ServerName);
_serverId = RemoteCollectorService.GetDeterministicHashCode(RemoteCollectorService.GetServerNameForStorage(server));
_credentialService = credentialService;
UtcOffsetMinutes = utcOffsetMinutes;
ServerTimeHelper.UtcOffsetMinutes = utcOffsetMinutes;

ServerNameText.Text = server.DisplayName;
ConnectionStatusText.Text = server.ServerName;
ServerNameText.Text = server.ReadOnlyIntent ? $"{server.DisplayName} (Read-Only)" : server.DisplayName;
ConnectionStatusText.Text = server.ServerNameDisplay;

/* Apply default time range from settings */
TimeRangeCombo.SelectedIndex = App.DefaultTimeRangeHours switch
Expand Down Expand Up @@ -582,7 +583,7 @@
}

var tz = ServerTimeHelper.GetTimezoneLabel(ServerTimeHelper.CurrentDisplayMode);
ConnectionStatusText.Text = $"{_server.ServerName} - Last refresh: {DateTime.Now:HH:mm:ss} ({tz})";
ConnectionStatusText.Text = $"{_server.ServerNameDisplay} - Last refresh: {DateTime.Now:HH:mm:ss} ({tz})";

Check warning on line 586 in Lite/Controls/ServerTab.xaml.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.

Check warning on line 586 in Lite/Controls/ServerTab.xaml.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
}
catch (Exception ex)
{
Expand Down
4 changes: 2 additions & 2 deletions Lite/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,14 @@

<!-- Server Name -->
<TextBlock Grid.Column="1" Grid.Row="0"
Text="{Binding DisplayName}"
Text="{Binding DisplayNameWithIntent}"
FontSize="13"
FontWeight="SemiBold"
Foreground="{DynamicResource ForegroundBrush}"/>

<!-- Server Details -->
<TextBlock Grid.Column="1" Grid.Row="1"
Text="{Binding ServerName}"
Text="{Binding ServerNameDisplay}"
FontSize="11"
Foreground="{DynamicResource ForegroundMutedBrush}"/>

Expand Down
26 changes: 14 additions & 12 deletions Lite/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ private void ServerTabControl_SelectionChanged(object sender, SelectionChangedEv
if (ServerTabControl.SelectedItem is TabItem { Content: ServerTab serverTab })
{
ServerTimeHelper.UtcOffsetMinutes = serverTab.UtcOffsetMinutes;
StatusText.Text = $"Connected to {serverTab.Server.DisplayNameWithIntent}";
}

/* Refresh alerts tab when selected */
Expand Down Expand Up @@ -416,8 +417,8 @@ private async Task RefreshOverviewAsync()
{
try
{
var serverId = RemoteCollectorService.GetDeterministicHashCode(server.ServerName);
var summary = await _dataService.GetServerSummaryAsync(serverId, server.DisplayName);
var serverId = RemoteCollectorService.GetDeterministicHashCode(RemoteCollectorService.GetServerNameForStorage(server));
var summary = await _dataService.GetServerSummaryAsync(serverId, server.DisplayNameWithIntent);
if (summary != null)
{
summary.ServerName = server.ServerName;
Expand Down Expand Up @@ -563,33 +564,34 @@ private async void ConnectToServer(ServerConnection server)
// Then collect fresh data and refresh again
if (_collectorService != null)
{
StatusText.Text = $"Collecting data from {server.DisplayName}...";
StatusText.Text = $"Collecting data from {server.DisplayNameWithIntent}...";
try
{
await _collectorService.RunAllCollectorsForServerAsync(server);
StatusText.Text = $"Connected to {server.DisplayName} - Data loaded";
StatusText.Text = $"Connected to {server.DisplayNameWithIntent} - Data loaded";
serverTab.RefreshData();
UpdateCollectorHealth();
_ = RefreshOverviewAsync();
}
catch (Exception ex)
{
StatusText.Text = $"Connected to {server.DisplayName} - Collection error: {ex.Message}";
StatusText.Text = $"Connected to {server.DisplayNameWithIntent} - Collection error: {ex.Message}";
}
}
else
{
StatusText.Text = $"Connected to {server.DisplayName}";
StatusText.Text = $"Connected to {server.DisplayNameWithIntent}";
}
}

private StackPanel CreateTabHeader(ServerConnection server)
{
var panel = new StackPanel { Orientation = Orientation.Horizontal };

var tabLabel = server.ReadOnlyIntent ? $"{server.DisplayName} (RO)" : server.DisplayName;
panel.Children.Add(new TextBlock
{
Text = server.DisplayName,
Text = tabLabel,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0, 0, 4, 0)
});
Expand Down Expand Up @@ -795,7 +797,7 @@ private void AddServerButton_Click(object sender, RoutedEventArgs e)
if (dialog.ShowDialog() == true && dialog.AddedServer != null)
{
RefreshServerList();
StatusText.Text = $"Added server: {dialog.AddedServer.DisplayName}";
StatusText.Text = $"Added server: {dialog.AddedServer.DisplayNameWithIntent}";
}
}

Expand Down Expand Up @@ -880,7 +882,7 @@ private void ServerContextMenu_Remove_Click(object sender, RoutedEventArgs e)
if (server == null) return;

var result = MessageBox.Show(
$"Remove server '{server.DisplayName}'?",
$"Remove server '{server.DisplayNameWithIntent}'?",
"Remove Server",
MessageBoxButton.YesNo,
MessageBoxImage.Question);
Expand All @@ -890,7 +892,7 @@ private void ServerContextMenu_Remove_Click(object sender, RoutedEventArgs e)
CloseServerTab(server.Id);
_serverManager.DeleteServer(server.Id);
RefreshServerList();
StatusText.Text = $"Removed server: {server.DisplayName}";
StatusText.Text = $"Removed server: {server.DisplayNameWithIntent}";
}
}

Expand Down Expand Up @@ -961,14 +963,14 @@ private void CheckConnectionsAndNotify()
{
_trayService?.ShowNotification(
"Server Offline",
$"{server.DisplayName} is unreachable: {status.ErrorMessage ?? "unknown error"}",
$"{server.DisplayNameWithIntent} is unreachable: {status.ErrorMessage ?? "unknown error"}",
Hardcodet.Wpf.TaskbarNotification.BalloonIcon.Error);
}
else if (!wasOnline && isOnline)
{
_trayService?.ShowNotification(
"Server Online",
$"{server.DisplayName} is back online",
$"{server.DisplayNameWithIntent} is back online",
Hardcodet.Wpf.TaskbarNotification.BalloonIcon.Info);
}
}
Expand Down
9 changes: 5 additions & 4 deletions Lite/Mcp/McpDiscoveryTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ public static async Task<string> ListServers(ServerManager serverManager, LocalD
var lines = new List<string> { $"Monitored servers ({servers.Count}):\n" };
foreach (var s in servers)
{
var roTag = s.ReadOnlyIntent ? " [Read-Only]" : "";
var display = string.IsNullOrEmpty(s.DisplayName) || s.DisplayName == s.ServerName
? s.ServerName
: $"{s.DisplayName} ({s.ServerName})";
? $"{s.ServerName}{roTag}"
: $"{s.DisplayName} ({s.ServerName}){roTag}";

var status = serverManager.GetConnectionStatus(s.Id);
var statusText = status.IsOnline switch
Expand All @@ -31,8 +32,8 @@ public static async Task<string> ListServers(ServerManager serverManager, LocalD
null => "Status not checked"
};

var serverId = RemoteCollectorService.GetDeterministicHashCode(s.ServerName);
var summary = await dataService.GetServerSummaryAsync(serverId, s.DisplayName ?? s.ServerName);
var serverId = RemoteCollectorService.GetDeterministicHashCode(RemoteCollectorService.GetServerNameForStorage(s));
var summary = await dataService.GetServerSummaryAsync(serverId, s.DisplayNameWithIntent);
var lastCollection = summary?.LastCollectionTime?.ToString("o") ?? "No data collected";

lines.Add($"- {display} [{statusText}] (last collection: {lastCollection})");
Expand Down
18 changes: 12 additions & 6 deletions Lite/Mcp/ServerResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public static (int ServerId, string ServerName)? Resolve(
if (servers.Count == 1)
{
var s = servers[0];
return (RemoteCollectorService.GetDeterministicHashCode(s.ServerName), s.ServerName);
var storageName = RemoteCollectorService.GetServerNameForStorage(s);
return (RemoteCollectorService.GetDeterministicHashCode(storageName), storageName);
}

return null;
Expand All @@ -37,7 +38,8 @@ public static (int ServerId, string ServerName)? Resolve(

if (exact != null)
{
return (RemoteCollectorService.GetDeterministicHashCode(exact.ServerName), exact.ServerName);
var exactName = RemoteCollectorService.GetServerNameForStorage(exact);
return (RemoteCollectorService.GetDeterministicHashCode(exactName), exactName);
}

/* Partial match */
Expand All @@ -47,7 +49,8 @@ public static (int ServerId, string ServerName)? Resolve(

if (partial != null)
{
return (RemoteCollectorService.GetDeterministicHashCode(partial.ServerName), partial.ServerName);
var partialName = RemoteCollectorService.GetServerNameForStorage(partial);
return (RemoteCollectorService.GetDeterministicHashCode(partialName), partialName);
}

return null;
Expand All @@ -62,9 +65,12 @@ public static string ListAvailableServers(ServerManager serverManager)
}

var lines = servers.Select(s =>
string.IsNullOrEmpty(s.DisplayName) || s.DisplayName == s.ServerName
? s.ServerName
: $"{s.DisplayName} ({s.ServerName})");
{
var roTag = s.ReadOnlyIntent ? " [Read-Only]" : "";
return string.IsNullOrEmpty(s.DisplayName) || s.DisplayName == s.ServerName
? $"{s.ServerName}{roTag}"
: $"{s.DisplayName} ({s.ServerName}){roTag}";
});

return string.Join("\n", lines);
}
Expand Down
14 changes: 14 additions & 0 deletions Lite/Models/ServerConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,20 @@ public bool UseWindowsAuth
/// </summary>
public bool ReadOnlyIntent { get; set; } = false;

/// <summary>
/// Server name with "(Read-Only)" suffix when ReadOnlyIntent is enabled.
/// Used for sidebar subtitle and status text.
/// </summary>
[JsonIgnore]
public string ServerNameDisplay => ReadOnlyIntent ? $"{ServerName} (Read-Only)" : ServerName;

/// <summary>
/// Display name with "(Read-Only)" suffix when ReadOnlyIntent is enabled.
/// Used for alerts, tray notifications, status bar, and overview cards.
/// </summary>
[JsonIgnore]
public string DisplayNameWithIntent => ReadOnlyIntent ? $"{DisplayName} (Read-Only)" : DisplayName;

/// <summary>
/// Display-only property for showing authentication type in UI.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ as it lingers in the ring buffer across collection cycles. */
row.AppendValue(GenerateCollectionId())
.AppendValue(collectionTime)
.AppendValue(serverId)
.AppendValue(server.ServerName)
.AppendValue(GetServerNameForStorage(server))
.AppendValue(parsed.EventTime)
.AppendValue(parsed.DatabaseName)
.AppendValue(parsed.BlockedSpid)
Expand Down
2 changes: 1 addition & 1 deletion Lite/Services/RemoteCollectorService.Cpu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ drs.end_time DESC
row.AppendValue(GenerateCollectionId())
.AppendValue(collectionTime)
.AppendValue(serverId)
.AppendValue(server.ServerName)
.AppendValue(GetServerNameForStorage(server))
.AppendValue(sampleTime)
.AppendValue(reader.IsDBNull(1) ? 0 : reader.GetInt32(1))
.AppendValue(reader.IsDBNull(2) ? 0 : reader.GetInt32(2))
Expand Down
2 changes: 1 addition & 1 deletion Lite/Services/RemoteCollectorService.DatabaseSize.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ ORDER BY
row.AppendValue(GenerateCollectionId())
.AppendValue(collectionTime)
.AppendValue(serverId)
.AppendValue(server.ServerName)
.AppendValue(GetServerNameForStorage(server))
.AppendValue(r.DatabaseName)
.AppendValue(r.DatabaseId)
.AppendValue(r.FileId)
Expand Down
2 changes: 1 addition & 1 deletion Lite/Services/RemoteCollectorService.Deadlocks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ and was previously misattributed as DuckDB time. */
row.AppendValue(GenerateCollectionId())
.AppendValue(collectionTime)
.AppendValue(serverId)
.AppendValue(server.ServerName)
.AppendValue(GetServerNameForStorage(server))
.AppendValue(deadlockTime)
.AppendValue(victimProcessId)
.AppendValue(victimSqlText)
Expand Down
2 changes: 1 addition & 1 deletion Lite/Services/RemoteCollectorService.FileIo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ AND vfs.database_id < 32761
row.AppendValue(GenerateCollectionId())
.AppendValue(collectionTime)
.AppendValue(serverId)
.AppendValue(server.ServerName)
.AppendValue(GetServerNameForStorage(server))
.AppendValue(stat.DatabaseName)
.AppendValue(stat.FileName)
.AppendValue(stat.FileType)
Expand Down
4 changes: 2 additions & 2 deletions Lite/Services/RemoteCollectorService.Memory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ FROM sys.dm_os_schedulers
row.AppendValue(GenerateCollectionId())
.AppendValue(collectionTime)
.AppendValue(serverId)
.AppendValue(server.ServerName)
.AppendValue(GetServerNameForStorage(server))
.AppendValue(totalPhysicalMb)
.AppendValue(availablePhysicalMb)
.AppendValue(totalPageFileMb)
Expand Down Expand Up @@ -249,7 +249,7 @@ ORDER BY
row.AppendValue(GenerateCollectionId())
.AppendValue(collectionTime)
.AppendValue(serverId)
.AppendValue(server.ServerName)
.AppendValue(GetServerNameForStorage(server))
.AppendValue(reader.GetString(0))
.AppendValue(reader.GetDecimal(1))
.EndRow();
Expand Down
2 changes: 1 addition & 1 deletion Lite/Services/RemoteCollectorService.MemoryGrants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ WHERE deqrs.max_target_memory_kb IS NOT NULL
row.AppendValue(GenerateCollectionId())
.AppendValue(collectionTime)
.AppendValue(serverId)
.AppendValue(server.ServerName)
.AppendValue(GetServerNameForStorage(server))
.AppendValue(r.ResourceSemaphoreId)
.AppendValue(r.PoolId)
.AppendValue(r.TargetMb)
Expand Down
2 changes: 1 addition & 1 deletion Lite/Services/RemoteCollectorService.Perfmon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ WHERE pc.counter_name IN (
row.AppendValue(GenerateCollectionId())
.AppendValue(collectionTime)
.AppendValue(serverId)
.AppendValue(server.ServerName)
.AppendValue(GetServerNameForStorage(server))
.AppendValue(objectName)
.AppendValue(counterName)
.AppendValue(instanceName)
Expand Down
2 changes: 1 addition & 1 deletion Lite/Services/RemoteCollectorService.ProcedureStats.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ ORDER BY s.total_elapsed_time DESC
row.AppendValue(GenerateCollectionId()) /* collection_id */
.AppendValue(collectionTime) /* collection_time */
.AppendValue(serverId) /* server_id */
.AppendValue(server.ServerName) /* server_name */
.AppendValue(GetServerNameForStorage(server)) /* server_name */
.AppendValue(dbName) /* database_name */
.AppendValue(schemaName) /* schema_name */
.AppendValue(objectName) /* object_name */
Expand Down
2 changes: 1 addition & 1 deletion Lite/Services/RemoteCollectorService.QuerySnapshots.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ private async Task<int> CollectQuerySnapshotsAsync(ServerConnection server, Canc
row.AppendValue(GenerateCollectionId())
.AppendValue(collectionTime)
.AppendValue(serverId)
.AppendValue(server.ServerName)
.AppendValue(GetServerNameForStorage(server))
.AppendValue(Convert.ToInt32(reader.GetValue(0))) /* session_id */
.AppendValue(reader.IsDBNull(1) ? (string?)null : reader.GetString(1)) /* database_name */
.AppendValue(reader.IsDBNull(2) ? (string?)null : reader.GetString(2)) /* elapsed_time_formatted */
Expand Down
Loading
Loading