using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; namespace CoreAgent.ProtocolClient.ProtocolEngineCore { /// /// 管理所有与统计信息相关的操作 /// 职责: /// 1. 定时轮询获取统计信息 (stats)。 /// 2. 管理统计信息的配置 (samples, rf)。 /// 3. 管理轮询的定时器 (_statsTimer)。 /// 4. 触发统计信息相关的事件。 /// public class StatsManager : IDisposable { private readonly ILogger _logger; private readonly Func?, bool, long> _sendMessage; private readonly string _clientName; private bool _enableSamples = false; private bool _enableRf = false; private int _statsPollDelay = 1000; private Timer? _statsTimer; private bool _isFirstStatsUpdate = true; private bool _disposed = false; private bool _isConnected = false; public event EventHandler? StatsReceived; public StatsManager(string clientName, ILogger logger, Func?, bool, long> sendMessage) { _clientName = clientName; _logger = logger; _sendMessage = sendMessage; } public void HandleMessage(JObject message) { // The "stats" response is handled via callback in UpdateStats, // but a generic handler could be placed here if needed in the future. var messageType = message["message"]?.ToString(); if (messageType == "stats") { StatsReceived?.Invoke(this, message); } } public void SetConnectionState(bool isConnected) { _isConnected = isConnected; if (!_isConnected) { StopStatsTimer(); } } public void TriggerStatsUpdate() { UpdateStats(); } public void ResetStatistics() { var resetStats = new JObject { ["cpu"] = new JObject { ["global"] = 0 } }; _logger.LogDebug($"[{_clientName}] 重置统计信息"); // This was a local-only operation in the original code. // If it needs to send a message, it should be done here. } public void SetStatisticsConfig(bool enableSamples, bool enableRf) { _enableSamples = enableSamples; _enableRf = enableRf; _logger.LogInformation($"[{_clientName}] 设置统计配置: samples={enableSamples}, rf={enableRf}"); } public (bool samples, bool rf) GetStatisticsConfig() { return (_enableSamples, _enableRf); } public void SetRefreshDelay(int delay) { _statsPollDelay = delay; } public void Start(bool first = false) { if (first) { _isFirstStatsUpdate = true; } UpdateStats(first); } private void UpdateStats(bool first = false) { if (_disposed || !_isConnected) return; var msg = new JObject { ["message"] = "stats", ["samples"] = _enableSamples, ["rf"] = _enableRf }; _sendMessage(msg, response => { if (_disposed) return; if (first || _isFirstStatsUpdate) { ResetStatistics(); _isFirstStatsUpdate = false; StartStatsTimer(); // In the original, the first response is not propagated. return; } StatsReceived?.Invoke(this, response); StartStatsTimer(); // Schedule next update }, false); } private void StartStatsTimer() { if (_statsTimer != null) { _statsTimer.Dispose(); } _statsTimer = new Timer(_ => UpdateStats(), null, _statsPollDelay, Timeout.Infinite); } public void StopStatsTimer() { _statsTimer?.Dispose(); _statsTimer = null; } public void Dispose() { if (_disposed) return; _disposed = true; StopStatsTimer(); } } }