admin: add connected Mount Clients page and dashboard section (#9968)

* admin: add connected mount clients page and dashboard section

The filer is the authority on who is subscribed to its metadata stream
(FUSE/VFS mounts, S3, peer filers, ...), but its in-memory listener
registry only tracked clientId->epoch and was not exposed.

- Enrich the filer subscriber registry with name/type/address/path/
  connected-time, populated in addClient and cleared in deleteClient so
  it reflects currently-connected clients only.
- Add a ListMetadataSubscribers filer gRPC (optional client-type filter).
- Admin server fans out to every filer, filters to mount types
  ("mount" Go weed mount, "sw-vfs" Rust VFS), and renders a new
  Cluster > Mount Clients page plus a Mount Clients dashboard section.

Read-only; no behavior change to the subscribe hot path.

* admin: address review — parallelize filer fan-out, guard nil map, robust CSV

- GetMountClients now queries filers concurrently, each under a 5s
  timeout, so a slow/unreachable filer can't stall the admin dashboard.
- Defensively initialize fs.subscribers before first write.
- Mount Clients CSV export uses a Blob with quote-escaping instead of a
  data: URI, so special characters in paths export correctly.
This commit is contained in:
Chris Lu authored and GitHub committed 2026-06-14 21:44:10 -07:00
1 parent a736ba1c21
commit 7df43ad9b5
18 files changed
+1616 -724

No files matched your search

+10
View File
@@ -38,6 +38,9 @@ type AdminData struct {
TotalEcVolumes int `json:"total_ec_volumes"` // Total number of EC volumes across all servers
TotalEcShards int `json:"total_ec_shards"` // Total number of EC shards across all servers
// TotalMountClients is the number of connected FUSE/VFS mount clients across filers.
TotalMountClients int `json:"total_mount_clients"`
// Trends holds at-a-glance sparklines built from the admin's own recent
// cluster snapshots (no Prometheus required).
Trends DashboardTrends `json:"trends"`
@@ -186,6 +189,12 @@ func (s *AdminServer) GetAdminData(username string) (AdminData, error) {
}
totalEcVolumes = len(ecVolumeSet)
// Count connected FUSE/VFS mount clients (best-effort; don't fail the dashboard)
totalMountClients := 0
if mountData, mountErr := s.GetMountClients(); mountErr == nil {
totalMountClients = mountData.TotalMountClients
}
// Prepare admin data
adminData := AdminData{
Username: username,
@@ -202,6 +211,7 @@ func (s *AdminServer) GetAdminData(username string) (AdminData, error) {
LastUpdated: topology.UpdatedAt,
TotalEcVolumes: totalEcVolumes,
TotalEcShards: totalEcShards,
TotalMountClients: totalMountClients,
Trends: s.GetDashboardTrends(),
}