diff --git a/Lite/Controls/FinOpsTab.xaml.cs b/Lite/Controls/FinOpsTab.xaml.cs
index 03e41fdc..d0f529fb 100644
--- a/Lite/Controls/FinOpsTab.xaml.cs
+++ b/Lite/Controls/FinOpsTab.xaml.cs
@@ -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;
}
@@ -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;
diff --git a/Lite/Controls/ServerTab.xaml.cs b/Lite/Controls/ServerTab.xaml.cs
index 5e9a6148..b49c0766 100644
--- a/Lite/Controls/ServerTab.xaml.cs
+++ b/Lite/Controls/ServerTab.xaml.cs
@@ -36,6 +36,7 @@ public partial class ServerTab : UserControl
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;
@@ -117,13 +118,13 @@ public ServerTab(ServerConnection server, DuckDbInitializer duckDb, CredentialSe
_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
@@ -582,7 +583,7 @@ private async System.Threading.Tasks.Task RefreshAllDataAsync(bool fullRefresh =
}
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})";
}
catch (Exception ex)
{
diff --git a/Lite/MainWindow.xaml b/Lite/MainWindow.xaml
index b5aee93c..72b1b361 100644
--- a/Lite/MainWindow.xaml
+++ b/Lite/MainWindow.xaml
@@ -121,14 +121,14 @@
diff --git a/Lite/MainWindow.xaml.cs b/Lite/MainWindow.xaml.cs
index 328c020c..0b1881cc 100644
--- a/Lite/MainWindow.xaml.cs
+++ b/Lite/MainWindow.xaml.cs
@@ -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 */
@@ -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;
@@ -563,23 +564,23 @@ 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}";
}
}
@@ -587,9 +588,10 @@ 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)
});
@@ -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}";
}
}
@@ -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);
@@ -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}";
}
}
@@ -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);
}
}
diff --git a/Lite/Mcp/McpDiscoveryTools.cs b/Lite/Mcp/McpDiscoveryTools.cs
index c9fc54b8..a11b815c 100644
--- a/Lite/Mcp/McpDiscoveryTools.cs
+++ b/Lite/Mcp/McpDiscoveryTools.cs
@@ -19,9 +19,10 @@ public static async Task ListServers(ServerManager serverManager, LocalD
var lines = new List { $"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
@@ -31,8 +32,8 @@ public static async Task 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})");
diff --git a/Lite/Mcp/ServerResolver.cs b/Lite/Mcp/ServerResolver.cs
index ae66b719..8cdf9ec8 100644
--- a/Lite/Mcp/ServerResolver.cs
+++ b/Lite/Mcp/ServerResolver.cs
@@ -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;
@@ -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 */
@@ -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;
@@ -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);
}
diff --git a/Lite/Models/ServerConnection.cs b/Lite/Models/ServerConnection.cs
index a07c227f..24ca11c5 100644
--- a/Lite/Models/ServerConnection.cs
+++ b/Lite/Models/ServerConnection.cs
@@ -77,6 +77,20 @@ public bool UseWindowsAuth
///
public bool ReadOnlyIntent { get; set; } = false;
+ ///
+ /// Server name with "(Read-Only)" suffix when ReadOnlyIntent is enabled.
+ /// Used for sidebar subtitle and status text.
+ ///
+ [JsonIgnore]
+ public string ServerNameDisplay => ReadOnlyIntent ? $"{ServerName} (Read-Only)" : ServerName;
+
+ ///
+ /// Display name with "(Read-Only)" suffix when ReadOnlyIntent is enabled.
+ /// Used for alerts, tray notifications, status bar, and overview cards.
+ ///
+ [JsonIgnore]
+ public string DisplayNameWithIntent => ReadOnlyIntent ? $"{DisplayName} (Read-Only)" : DisplayName;
+
///
/// Display-only property for showing authentication type in UI.
///
diff --git a/Lite/Services/RemoteCollectorService.BlockedProcessReport.cs b/Lite/Services/RemoteCollectorService.BlockedProcessReport.cs
index b47a9284..cd5c90a7 100644
--- a/Lite/Services/RemoteCollectorService.BlockedProcessReport.cs
+++ b/Lite/Services/RemoteCollectorService.BlockedProcessReport.cs
@@ -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)
diff --git a/Lite/Services/RemoteCollectorService.Cpu.cs b/Lite/Services/RemoteCollectorService.Cpu.cs
index 800fb01c..a46c0681 100644
--- a/Lite/Services/RemoteCollectorService.Cpu.cs
+++ b/Lite/Services/RemoteCollectorService.Cpu.cs
@@ -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))
diff --git a/Lite/Services/RemoteCollectorService.DatabaseSize.cs b/Lite/Services/RemoteCollectorService.DatabaseSize.cs
index 96583975..7005819f 100644
--- a/Lite/Services/RemoteCollectorService.DatabaseSize.cs
+++ b/Lite/Services/RemoteCollectorService.DatabaseSize.cs
@@ -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)
diff --git a/Lite/Services/RemoteCollectorService.Deadlocks.cs b/Lite/Services/RemoteCollectorService.Deadlocks.cs
index 883341b7..22c8e4df 100644
--- a/Lite/Services/RemoteCollectorService.Deadlocks.cs
+++ b/Lite/Services/RemoteCollectorService.Deadlocks.cs
@@ -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)
diff --git a/Lite/Services/RemoteCollectorService.FileIo.cs b/Lite/Services/RemoteCollectorService.FileIo.cs
index b9d280aa..5ce5540b 100644
--- a/Lite/Services/RemoteCollectorService.FileIo.cs
+++ b/Lite/Services/RemoteCollectorService.FileIo.cs
@@ -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)
diff --git a/Lite/Services/RemoteCollectorService.Memory.cs b/Lite/Services/RemoteCollectorService.Memory.cs
index 55e36219..4af53786 100644
--- a/Lite/Services/RemoteCollectorService.Memory.cs
+++ b/Lite/Services/RemoteCollectorService.Memory.cs
@@ -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)
@@ -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();
diff --git a/Lite/Services/RemoteCollectorService.MemoryGrants.cs b/Lite/Services/RemoteCollectorService.MemoryGrants.cs
index a8db4a6e..244e08b2 100644
--- a/Lite/Services/RemoteCollectorService.MemoryGrants.cs
+++ b/Lite/Services/RemoteCollectorService.MemoryGrants.cs
@@ -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)
diff --git a/Lite/Services/RemoteCollectorService.Perfmon.cs b/Lite/Services/RemoteCollectorService.Perfmon.cs
index 9bfe972f..8e0b1ecb 100644
--- a/Lite/Services/RemoteCollectorService.Perfmon.cs
+++ b/Lite/Services/RemoteCollectorService.Perfmon.cs
@@ -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)
diff --git a/Lite/Services/RemoteCollectorService.ProcedureStats.cs b/Lite/Services/RemoteCollectorService.ProcedureStats.cs
index 0b93c483..e46b71ab 100644
--- a/Lite/Services/RemoteCollectorService.ProcedureStats.cs
+++ b/Lite/Services/RemoteCollectorService.ProcedureStats.cs
@@ -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 */
diff --git a/Lite/Services/RemoteCollectorService.QuerySnapshots.cs b/Lite/Services/RemoteCollectorService.QuerySnapshots.cs
index 93f5e363..da031295 100644
--- a/Lite/Services/RemoteCollectorService.QuerySnapshots.cs
+++ b/Lite/Services/RemoteCollectorService.QuerySnapshots.cs
@@ -137,7 +137,7 @@ private async Task 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 */
diff --git a/Lite/Services/RemoteCollectorService.QueryStats.cs b/Lite/Services/RemoteCollectorService.QueryStats.cs
index 810e5ca6..cb0f535c 100644
--- a/Lite/Services/RemoteCollectorService.QueryStats.cs
+++ b/Lite/Services/RemoteCollectorService.QueryStats.cs
@@ -253,7 +253,7 @@ qs.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(reader.IsDBNull(0) ? (string?)null : reader.GetString(0)) /* database_name */
.AppendValue(queryHash) /* query_hash */
.AppendValue(reader.IsDBNull(2) ? (string?)null : reader.GetString(2)) /* query_plan_hash */
diff --git a/Lite/Services/RemoteCollectorService.QueryStore.cs b/Lite/Services/RemoteCollectorService.QueryStore.cs
index f8d916a6..612653c3 100644
--- a/Lite/Services/RemoteCollectorService.QueryStore.cs
+++ b/Lite/Services/RemoteCollectorService.QueryStore.cs
@@ -376,7 +376,7 @@ AND qst.query_sql_text NOT LIKE N''%PerformanceMonitorLite%''
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(reader.GetInt64(0)) /* query_id */
.AppendValue(reader.GetInt64(1)) /* plan_id */
diff --git a/Lite/Services/RemoteCollectorService.RunningJobs.cs b/Lite/Services/RemoteCollectorService.RunningJobs.cs
index 00d26b87..9b56ca75 100644
--- a/Lite/Services/RemoteCollectorService.RunningJobs.cs
+++ b/Lite/Services/RemoteCollectorService.RunningJobs.cs
@@ -165,7 +165,7 @@ rj.current_duration_seconds DESC
var row = appender.CreateRow();
row.AppendValue(collectionTime)
.AppendValue(serverId)
- .AppendValue(server.ServerName)
+ .AppendValue(GetServerNameForStorage(server))
.AppendValue(r.JobName)
.AppendValue(r.JobId)
.AppendValue(r.JobEnabled)
diff --git a/Lite/Services/RemoteCollectorService.ServerConfig.cs b/Lite/Services/RemoteCollectorService.ServerConfig.cs
index 6a7ba535..66f4b604 100644
--- a/Lite/Services/RemoteCollectorService.ServerConfig.cs
+++ b/Lite/Services/RemoteCollectorService.ServerConfig.cs
@@ -76,7 +76,7 @@ ORDER BY c.name
row.AppendValue(GenerateCollectionId())
.AppendValue(captureTime)
.AppendValue(serverId)
- .AppendValue(server.ServerName)
+ .AppendValue(GetServerNameForStorage(server))
.AppendValue(r.Name)
.AppendValue(r.ValueConfigured)
.AppendValue(r.ValueInUse)
@@ -233,7 +233,7 @@ ORDER BY d.name
row.AppendValue(GenerateCollectionId())
.AppendValue(captureTime)
.AppendValue(serverId)
- .AppendValue(server.ServerName)
+ .AppendValue(GetServerNameForStorage(server))
.AppendValue(r.DbName)
.AppendValue(r.StateDesc)
.AppendValue(r.CompatLevel)
@@ -443,7 +443,7 @@ ORDER BY dsc.name
row.AppendValue(GenerateCollectionId())
.AppendValue(captureTime)
.AppendValue(serverId)
- .AppendValue(server.ServerName)
+ .AppendValue(GetServerNameForStorage(server))
.AppendValue(dbName)
.AppendValue(configName)
.AppendValue(value)
@@ -535,7 +535,7 @@ ORDER BY tf.trace_flag
row.AppendValue(GenerateCollectionId())
.AppendValue(captureTime)
.AppendValue(serverId)
- .AppendValue(server.ServerName)
+ .AppendValue(GetServerNameForStorage(server))
.AppendValue(r.TraceFlag)
.AppendValue(r.Status)
.AppendValue(r.IsGlobal)
diff --git a/Lite/Services/RemoteCollectorService.ServerProperties.cs b/Lite/Services/RemoteCollectorService.ServerProperties.cs
index 519f4deb..40bfd944 100644
--- a/Lite/Services/RemoteCollectorService.ServerProperties.cs
+++ b/Lite/Services/RemoteCollectorService.ServerProperties.cs
@@ -110,7 +110,7 @@ FROM sys.dm_os_sys_info AS osi
row.AppendValue(GenerateCollectionId())
.AppendValue(collectionTime)
.AppendValue(serverId)
- .AppendValue(serverName)
+ .AppendValue(GetServerNameForStorage(server))
.AppendValue(edition)
.AppendValue(productVersion)
.AppendValue(productLevel)
diff --git a/Lite/Services/RemoteCollectorService.SessionStats.cs b/Lite/Services/RemoteCollectorService.SessionStats.cs
index a8281434..3eade6ec 100644
--- a/Lite/Services/RemoteCollectorService.SessionStats.cs
+++ b/Lite/Services/RemoteCollectorService.SessionStats.cs
@@ -120,7 +120,7 @@ ORDER BY
row.AppendValue(GenerateCollectionId())
.AppendValue(collectionTime)
.AppendValue(serverId)
- .AppendValue(server.ServerName)
+ .AppendValue(GetServerNameForStorage(server))
.AppendValue(programName)
.AppendValue(connectionCount)
.AppendValue(runningCount)
diff --git a/Lite/Services/RemoteCollectorService.TempDb.cs b/Lite/Services/RemoteCollectorService.TempDb.cs
index 1f600121..d36c8da1 100644
--- a/Lite/Services/RemoteCollectorService.TempDb.cs
+++ b/Lite/Services/RemoteCollectorService.TempDb.cs
@@ -90,7 +90,7 @@ ORDER BY (ssu.user_objects_alloc_page_count + ssu.internal_objects_alloc_page_co
row.AppendValue(GenerateCollectionId())
.AppendValue(collectionTime)
.AppendValue(serverId)
- .AppendValue(server.ServerName)
+ .AppendValue(GetServerNameForStorage(server))
.AppendValue(userObjMb)
.AppendValue(internalObjMb)
.AppendValue(versionStoreMb)
diff --git a/Lite/Services/RemoteCollectorService.WaitStats.cs b/Lite/Services/RemoteCollectorService.WaitStats.cs
index 0b5dcfbe..35ade9ab 100644
--- a/Lite/Services/RemoteCollectorService.WaitStats.cs
+++ b/Lite/Services/RemoteCollectorService.WaitStats.cs
@@ -135,7 +135,7 @@ WHERE ws.wait_time_ms > 0
row.AppendValue(GenerateCollectionId()) /* collection_id BIGINT */
.AppendValue(collectionTime) /* collection_time TIMESTAMP */
.AppendValue(serverId) /* server_id INTEGER */
- .AppendValue(server.ServerName) /* server_name VARCHAR */
+ .AppendValue(GetServerNameForStorage(server)) /* server_name VARCHAR */
.AppendValue(stat.WaitType) /* wait_type VARCHAR */
.AppendValue(stat.WaitingTasks) /* waiting_tasks_count BIGINT */
.AppendValue(stat.WaitTimeMs) /* wait_time_ms BIGINT */
diff --git a/Lite/Services/RemoteCollectorService.WaitingTasks.cs b/Lite/Services/RemoteCollectorService.WaitingTasks.cs
index d68fc1ee..bd9373b1 100644
--- a/Lite/Services/RemoteCollectorService.WaitingTasks.cs
+++ b/Lite/Services/RemoteCollectorService.WaitingTasks.cs
@@ -80,7 +80,7 @@ AND wt.wait_type IS NOT NULL
row.AppendValue(GenerateCollectionId())
.AppendValue(collectionTime)
.AppendValue(serverId)
- .AppendValue(server.ServerName)
+ .AppendValue(GetServerNameForStorage(server))
.AppendValue((int)sessionId)
.AppendValue(waitType)
.AppendValue(waitDurationMs)
diff --git a/Lite/Services/RemoteCollectorService.cs b/Lite/Services/RemoteCollectorService.cs
index 53fec1c8..3a10c56d 100644
--- a/Lite/Services/RemoteCollectorService.cs
+++ b/Lite/Services/RemoteCollectorService.cs
@@ -568,12 +568,22 @@ protected static long GenerateCollectionId()
return Interlocked.Increment(ref s_idCounter);
}
+ ///
+ /// Gets the server name used for DuckDB storage and hashing.
+ /// Appends ":RO" for ReadOnlyIntent connections so they get a
+ /// different server_id than read-write connections to the same host.
+ ///
+ internal static string GetServerNameForStorage(ServerConnection server)
+ {
+ return server.ReadOnlyIntent ? server.ServerName + ":RO" : server.ServerName;
+ }
+
///
/// Gets the numeric server ID from the server connection.
///
protected static int GetServerId(ServerConnection server)
{
- return GetDeterministicHashCode(server.ServerName);
+ return GetDeterministicHashCode(GetServerNameForStorage(server));
}
///
diff --git a/Lite/Windows/ManageServersWindow.xaml b/Lite/Windows/ManageServersWindow.xaml
index 0060bd7f..63ad4208 100644
--- a/Lite/Windows/ManageServersWindow.xaml
+++ b/Lite/Windows/ManageServersWindow.xaml
@@ -47,8 +47,8 @@
MouseDoubleClick="ServersGrid_MouseDoubleClick"
ContextMenu="{StaticResource DataGridContextMenu}">
-
-
+
+
diff --git a/Lite/Windows/ManageServersWindow.xaml.cs b/Lite/Windows/ManageServersWindow.xaml.cs
index 8ef3447c..03b6b8e8 100644
--- a/Lite/Windows/ManageServersWindow.xaml.cs
+++ b/Lite/Windows/ManageServersWindow.xaml.cs
@@ -78,7 +78,7 @@ private void DeleteButton_Click(object sender, RoutedEventArgs e)
}
var result = MessageBox.Show(
- $"Delete server '{selected.DisplayName}'?\n\nThis will remove the server and its stored credentials.",
+ $"Delete server '{selected.DisplayNameWithIntent}'?\n\nThis will remove the server and its stored credentials.",
"Delete Server",
MessageBoxButton.YesNo,
MessageBoxImage.Warning);