91 lines
3.4 KiB
C#
91 lines
3.4 KiB
C#
using IpcLibrary.Core;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace IpcLibrary.Server {
|
|
/// <summary>
|
|
/// 服务器状态监控器
|
|
/// </summary>
|
|
public class ServerMonitor : IDisposable {
|
|
private readonly IPCServer _server;
|
|
private readonly System.Timers.Timer _monitorTimer;
|
|
private readonly Dictionary<string, DateTime> _processLastSeen;
|
|
private bool _disposed;
|
|
|
|
public event EventHandler<ServerStatistics> StatisticsUpdated;
|
|
|
|
public ServerMonitor(IPCServer server, TimeSpan monitorInterval) {
|
|
_server = server ?? throw new ArgumentNullException(nameof(server));
|
|
_processLastSeen = new Dictionary<string, DateTime>();
|
|
|
|
_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<ProcessInfo> 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();
|
|
}
|
|
}
|
|
}
|