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();
}
}
}