using IpcLibrary.Core; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace IpcLibrary.Server { /// /// 服务器状态监控器 /// public class ServerMonitor : IDisposable { private readonly IPCServer _server; private readonly System.Timers.Timer _monitorTimer; private readonly Dictionary _processLastSeen; private bool _disposed; public event EventHandler StatisticsUpdated; public ServerMonitor(IPCServer server, TimeSpan monitorInterval) { _server = server ?? throw new ArgumentNullException(nameof(server)); _processLastSeen = new Dictionary(); _monitorTimer = new System.Timers.Timer(monitorInterval.TotalMilliseconds); _monitorTimer.Elapsed += OnMonitorTimer; _monitorTimer.Start(); _server.ProcessConnected += OnProcessConnected; _server.ProcessDisconnected += OnProcessDisconnected; } private void OnProcessConnected(object sender, ProcessInfo processInfo) { lock (_processLastSeen) { _processLastSeen[processInfo.ProcessId] = DateTime.UtcNow; } } private void OnProcessDisconnected(object sender, ProcessInfo processInfo) { lock (_processLastSeen) { _processLastSeen.Remove(processInfo.ProcessId); } } private void OnMonitorTimer(object sender, System.Timers.ElapsedEventArgs e) { try { var statistics = GatherStatistics(); StatisticsUpdated?.Invoke(this, statistics); } catch (Exception ex) { Console.WriteLine($"收集统计信息时发生错误: {ex.Message}"); } } private ServerStatistics GatherStatistics() { var connectedProcesses = _server.ConnectedProcesses; var now = DateTime.UtcNow; return new ServerStatistics { Timestamp = now, TotalConnectedProcesses = connectedProcesses.Count, OnlineProcesses = connectedProcesses.Count(p => p.Status == ProcessStatus.Connected), DisconnectedProcesses = connectedProcesses.Count(p => p.Status == ProcessStatus.Disconnected), ReconnectingProcesses = connectedProcesses.Count(p => p.Status == ProcessStatus.Reconnecting), AverageHeartbeatDelay = CalculateAverageHeartbeatDelay(connectedProcesses, now), ServerUptime = now - _server.StartTime // 需要在IPCServer中添加StartTime属性 }; } private TimeSpan CalculateAverageHeartbeatDelay(IReadOnlyList processes, DateTime now) { var delays = processes .Where(p => p.Status == ProcessStatus.Connected) .Select(p => now - p.LastHeartbeat) .Where(delay => delay.TotalSeconds >= 0); if (!delays.Any()) return TimeSpan.Zero; var averageTicks = delays.Select(d => d.Ticks).Average(); return new TimeSpan((long)averageTicks); } public void Dispose() { if (_disposed) return; _disposed = true; _monitorTimer?.Stop(); _monitorTimer?.Dispose(); } } }