UNIVPLMDataIntegration/Admin.NET/Admin.NET.Core/Utils/Runtime/RuntimeMonitor.cs

545 lines
16 KiB
C#
Raw Normal View History

// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
/// <summary>
/// 运行时监控器
/// </summary>
public class RuntimeMonitor : IDisposable
{
private readonly Process _currentProcess;
private readonly ConcurrentQueue<PerformanceSnapshot> _snapshots;
private readonly Timer? _monitorTimer;
private readonly object _lockObject = new();
private readonly int _maxSnapshotCount;
private volatile bool _isDisposed;
private DateTime _lastCpuTime;
private TimeSpan _lastTotalProcessorTime;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="monitorInterval">监控间隔默认5秒</param>
/// <param name="maxSnapshotCount">最大快照数量默认1000</param>
public RuntimeMonitor(TimeSpan? monitorInterval = null, int maxSnapshotCount = 1000)
{
_currentProcess = Process.GetCurrentProcess();
_snapshots = new ConcurrentQueue<PerformanceSnapshot>();
_maxSnapshotCount = maxSnapshotCount;
MonitorInterval = monitorInterval ?? TimeSpan.FromSeconds(5);
// 初始化CPU时间基准
_lastCpuTime = DateTime.UtcNow;
_lastTotalProcessorTime = _currentProcess.TotalProcessorTime;
// 创建定时器但不立即启动
_monitorTimer = new Timer(CollectSnapshot, null, Timeout.Infinite, Timeout.Infinite);
}
/// <summary>
/// 监控间隔
/// </summary>
public TimeSpan MonitorInterval { get; }
/// <summary>
/// 是否正在监控
/// </summary>
public bool IsMonitoring { get; private set; }
/// <summary>
/// 快照历史记录数量
/// </summary>
public int SnapshotCount => _snapshots.Count;
/// <summary>
/// 监控开始时间
/// </summary>
public DateTime? MonitorStartTime { get; private set; }
/// <summary>
/// 强制垃圾回收
/// </summary>
/// <param name="generation">GC代数-1表示全部代</param>
/// <param name="mode">GC模式</param>
public static void ForceGarbageCollection(int generation = -1, GCCollectionMode mode = GCCollectionMode.Default)
{
if (generation == -1)
{
GC.Collect();
}
else
{
GC.Collect(generation, mode);
}
GC.WaitForPendingFinalizers();
GC.Collect();
}
/// <summary>
/// 获取内存压力信息
/// </summary>
/// <returns>内存压力信息</returns>
public static string GetMemoryPressureInfo()
{
var info = GC.GetGCMemoryInfo();
return $"总内存: {info.TotalAvailableMemoryBytes / 1024 / 1024} MB, " +
$"高内存负载阈值: {info.HighMemoryLoadThresholdBytes / 1024 / 1024} MB, " +
$"堆大小: {info.HeapSizeBytes / 1024 / 1024} MB, " +
$"内存负载: {info.MemoryLoadBytes / 1024 / 1024} MB";
}
/// <summary>
/// 开始监控
/// </summary>
public void StartMonitoring()
{
if (IsMonitoring || _isDisposed)
{
return;
}
lock (_lockObject)
{
if (IsMonitoring || _isDisposed)
{
return;
}
IsMonitoring = true;
MonitorStartTime = DateTime.Now;
// 立即收集一次快照
CollectSnapshot(null);
// 启动定时器
_monitorTimer?.Change(MonitorInterval, MonitorInterval);
}
}
/// <summary>
/// 停止监控
/// </summary>
public void StopMonitoring()
{
if (!IsMonitoring)
{
return;
}
lock (_lockObject)
{
if (!IsMonitoring)
{
return;
}
IsMonitoring = false;
_monitorTimer?.Change(Timeout.Infinite, Timeout.Infinite);
}
}
/// <summary>
/// 获取当前性能快照
/// </summary>
/// <returns>当前性能快照</returns>
public PerformanceSnapshot GetCurrentSnapshot()
{
return CreateSnapshot();
}
/// <summary>
/// 获取最新的性能快照
/// </summary>
/// <returns>最新的性能快照如果没有则返回null</returns>
public PerformanceSnapshot? GetLatestSnapshot()
{
return _snapshots.TryPeek(out var snapshot) ? snapshot : null;
}
/// <summary>
/// 获取所有性能快照
/// </summary>
/// <returns>性能快照列表</returns>
public List<PerformanceSnapshot> GetAllSnapshots()
{
return [.. _snapshots];
}
/// <summary>
/// 获取指定时间范围内的快照
/// </summary>
/// <param name="timeRange">时间范围</param>
/// <returns>快照列表</returns>
public List<PerformanceSnapshot> GetSnapshotsInTimeRange(TimeSpan timeRange)
{
var cutoffTime = DateTime.Now - timeRange;
return [.. _snapshots.Where(s => s.Timestamp >= cutoffTime)];
}
/// <summary>
/// 分析性能趋势
/// </summary>
/// <param name="counterType">计数器类型</param>
/// <param name="timeRange">分析时间范围null表示分析所有数据</param>
/// <returns>性能趋势分析结果</returns>
public PerformanceTrend AnalyzeTrend(PerformanceCounterType counterType, TimeSpan? timeRange = null)
{
var snapshots = timeRange.HasValue
? GetSnapshotsInTimeRange(timeRange.Value)
: GetAllSnapshots();
if (snapshots.Count == 0)
{
return new PerformanceTrend
{
CounterType = counterType,
SampleCount = 0,
AnalysisTimespan = timeRange ?? TimeSpan.Zero
};
}
var values = snapshots.Select(s => GetCounterValue(s, counterType)).ToList();
var trend = new PerformanceTrend
{
CounterType = counterType,
CurrentValue = values.LastOrDefault(),
AverageValue = values.Average(),
MinValue = values.Min(),
MaxValue = values.Max(),
SampleCount = values.Count,
AnalysisTimespan = timeRange ?? (snapshots.Last().Timestamp - snapshots.First().Timestamp)
};
// 计算标准差
var variance = values.Select(v => Math.Pow(v - trend.AverageValue, 2)).Average();
trend.StandardDeviation = Math.Sqrt(variance);
// 计算趋势(简单线性回归的斜率)
if (values.Count >= 2)
{
var n = values.Count;
var sumX = Enumerable.Range(0, n).Sum();
var sumY = values.Sum();
var sumXy = values.Select((v, i) => i * v).Sum();
var sumX2 = Enumerable.Range(0, n).Select(i => i * i).Sum();
trend.Trend = ((n * sumXy) - (sumX * sumY)) / ((n * sumX2) - (sumX * sumX));
}
return trend;
}
/// <summary>
/// 清空所有快照
/// </summary>
public void ClearSnapshots()
{
while (_snapshots.TryDequeue(out _)) { }
}
/// <summary>
/// 获取性能摘要报告
/// </summary>
/// <returns>性能摘要字符串</returns>
public string GetPerformanceSummary()
{
var current = GetCurrentSnapshot();
var cpuTrend = AnalyzeTrend(PerformanceCounterType.CpuUsage, TimeSpan.FromMinutes(5));
var memoryTrend = AnalyzeTrend(PerformanceCounterType.MemoryUsage, TimeSpan.FromMinutes(5));
return $"运行时性能摘要:\n" +
$" CPU使用率: {current.CpuUsage:F1}% (5分钟平均: {cpuTrend.AverageValue:F1}%)\n" +
$" 内存使用: {current.MemoryUsage / 1024 / 1024} MB (托管内存: {current.ManagedMemory / 1024 / 1024} MB)\n" +
$" GC收集: Gen0={current.GcGen0Collections}, Gen1={current.GcGen1Collections}, Gen2={current.GcGen2Collections}\n" +
$" 线程数: {current.ThreadCount}, 句柄数: {current.HandleCount}\n" +
$" 运行时间: {current.ProcessUptime:dd\\.hh\\:mm\\:ss}\n" +
$" 监控状态: {(IsMonitoring ? "" : "")}, 快照数: {SnapshotCount}";
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
if (_isDisposed)
{
return;
}
_isDisposed = true;
StopMonitoring();
_monitorTimer?.Dispose();
_currentProcess?.Dispose();
GC.SuppressFinalize(this);
}
/// <summary>
/// 获取计数器值
/// </summary>
/// <param name="snapshot">性能快照</param>
/// <param name="counterType">计数器类型</param>
/// <returns>计数器值</returns>
private static double GetCounterValue(PerformanceSnapshot snapshot, PerformanceCounterType counterType)
{
return counterType switch
{
PerformanceCounterType.CpuUsage => snapshot.CpuUsage,
PerformanceCounterType.MemoryUsage => snapshot.MemoryUsage,
PerformanceCounterType.GcCollections => snapshot.GcGen0Collections + snapshot.GcGen1Collections + snapshot.GcGen2Collections,
PerformanceCounterType.ThreadCount => snapshot.ThreadCount,
PerformanceCounterType.HandleCount => snapshot.HandleCount,
_ => 0
};
}
/// <summary>
/// 收集性能快照
/// </summary>
/// <param name="state">定时器状态</param>
private void CollectSnapshot(object? state)
{
if (_isDisposed)
{
return;
}
try
{
var snapshot = CreateSnapshot();
_snapshots.Enqueue(snapshot);
// 限制快照数量
while (_snapshots.Count > _maxSnapshotCount)
{
_snapshots.TryDequeue(out _);
}
}
catch (Exception ex)
{
// 记录异常但继续监控
Debug.WriteLine($"Failed to collect performance snapshot: {ex.Message}");
}
}
/// <summary>
/// 创建性能快照
/// </summary>
/// <returns>性能快照</returns>
private PerformanceSnapshot CreateSnapshot()
{
_currentProcess.Refresh();
// 计算CPU使用率
var currentTime = DateTime.UtcNow;
var currentTotalProcessorTime = _currentProcess.TotalProcessorTime;
var cpuUsage = 0.0;
var timeDelta = currentTime - _lastCpuTime;
var cpuTimeDelta = currentTotalProcessorTime - _lastTotalProcessorTime;
if (timeDelta.TotalMilliseconds > 0)
{
cpuUsage = cpuTimeDelta.TotalMilliseconds / (Environment.ProcessorCount * timeDelta.TotalMilliseconds) * 100;
cpuUsage = Math.Max(0, Math.Min(100, cpuUsage)); // 限制在0-100%范围内
}
_lastCpuTime = currentTime;
_lastTotalProcessorTime = currentTotalProcessorTime;
return new PerformanceSnapshot
{
Timestamp = currentTime,
CpuUsage = cpuUsage,
MemoryUsage = _currentProcess.WorkingSet64,
PrivateMemorySize = _currentProcess.PrivateMemorySize64,
VirtualMemorySize = _currentProcess.VirtualMemorySize64,
WorkingSet = _currentProcess.WorkingSet64,
GcGen0Collections = GC.CollectionCount(0),
GcGen1Collections = GC.CollectionCount(1),
GcGen2Collections = GC.CollectionCount(2),
ManagedMemory = GC.GetTotalMemory(false),
ThreadCount = _currentProcess.Threads.Count,
HandleCount = _currentProcess.HandleCount,
UserProcessorTime = _currentProcess.UserProcessorTime,
PrivilegedProcessorTime = _currentProcess.PrivilegedProcessorTime,
TotalProcessorTime = _currentProcess.TotalProcessorTime,
ProcessUptime = DateTime.Now - _currentProcess.StartTime
};
}
}
/// <summary>
/// 性能指标快照
/// </summary>
public record PerformanceSnapshot
{
/// <summary>
/// 快照时间
/// </summary>
public DateTime Timestamp { get; set; }
/// <summary>
/// CPU使用率百分比
/// </summary>
public double CpuUsage { get; set; }
/// <summary>
/// 内存使用量(字节)
/// </summary>
public long MemoryUsage { get; set; }
/// <summary>
/// 私有内存使用量(字节)
/// </summary>
public long PrivateMemorySize { get; set; }
/// <summary>
/// 虚拟内存使用量(字节)
/// </summary>
public long VirtualMemorySize { get; set; }
/// <summary>
/// 工作集大小(字节)
/// </summary>
public long WorkingSet { get; set; }
/// <summary>
/// GC代0收集次数
/// </summary>
public int GcGen0Collections { get; set; }
/// <summary>
/// GC代1收集次数
/// </summary>
public int GcGen1Collections { get; set; }
/// <summary>
/// GC代2收集次数
/// </summary>
public int GcGen2Collections { get; set; }
/// <summary>
/// 托管内存使用量(字节)
/// </summary>
public long ManagedMemory { get; set; }
/// <summary>
/// 线程数量
/// </summary>
public int ThreadCount { get; set; }
/// <summary>
/// 句柄数量
/// </summary>
public int HandleCount { get; set; }
/// <summary>
/// 用户处理器时间
/// </summary>
public TimeSpan UserProcessorTime { get; set; }
/// <summary>
/// 特权处理器时间
/// </summary>
public TimeSpan PrivilegedProcessorTime { get; set; }
/// <summary>
/// 总处理器时间
/// </summary>
public TimeSpan TotalProcessorTime { get; set; }
/// <summary>
/// 进程运行时间
/// </summary>
public TimeSpan ProcessUptime { get; set; }
}
/// <summary>
/// 性能趋势分析结果
/// </summary>
public record PerformanceTrend
{
/// <summary>
/// 计数器类型
/// </summary>
public PerformanceCounterType CounterType { get; set; }
/// <summary>
/// 当前值
/// </summary>
public double CurrentValue { get; set; }
/// <summary>
/// 平均值
/// </summary>
public double AverageValue { get; set; }
/// <summary>
/// 最小值
/// </summary>
public double MinValue { get; set; }
/// <summary>
/// 最大值
/// </summary>
public double MaxValue { get; set; }
/// <summary>
/// 变化趋势(正数表示上升,负数表示下降)
/// </summary>
public double Trend { get; set; }
/// <summary>
/// 标准差
/// </summary>
public double StandardDeviation { get; set; }
/// <summary>
/// 样本数量
/// </summary>
public int SampleCount { get; set; }
/// <summary>
/// 分析时间范围
/// </summary>
public TimeSpan AnalysisTimespan { get; set; }
}
/// <summary>
/// 性能计数器类型枚举
/// </summary>
public enum PerformanceCounterType
{
/// <summary>
/// CPU使用率
/// </summary>
CpuUsage = 1,
/// <summary>
/// 内存使用量
/// </summary>
MemoryUsage = 2,
/// <summary>
/// GC收集次数
/// </summary>
GcCollections = 3,
/// <summary>
/// 线程数量
/// </summary>
ThreadCount = 4,
/// <summary>
/// 句柄数量
/// </summary>
HandleCount = 5
}