using Fleet.Core; using Monitor.Protocol; namespace Monitor.Backend.Application; /// monitor.event:Agent 报告的事件(Probe 连上/断开、端点变化、时钟跳变、缺口、CPU 饱和)。 public sealed class AgentEventService { private readonly AgentRuntime _runtime; private readonly IEventStore _events; private readonly TimeProvider _time; private readonly NodeInfoService _nodes; public AgentEventService(AgentRuntime runtime, IEventStore events, TimeProvider time, NodeInfoService nodes) { _runtime = runtime; _events = events; _time = time; _nodes = nodes; } public async ValueTask OnEventAsync(NodeId agent, AgentEventParams e, CancellationToken ct) { if (!AgentEventKinds.All.Contains(e.Kind)) { return; } // 节点上报的时间可能有偏差:限制在合理范围内,避免污染事件时间线 long now = _time.GetUtcNow().ToUnixTimeMilliseconds(); long at = Math.Abs(e.AtUtcMs - now) > 24L * 3600 * 1000 ? now : e.AtUtcMs; AgentRuntimeState state = _runtime.Get(agent); switch (e.Kind) { case AgentEventKinds.ProbeConnected when !string.IsNullOrEmpty(e.Detail): state.AddProbe(e.Probe is { } p ? new ConnectedProbeInfo(e.Detail, p.Version, p.Remote, p.SinceUtcMs > 0 ? p.SinceUtcMs : at) : new ConnectedProbeInfo(e.Detail, null, null, at)); _nodes.ObserveProbeInBackground(e.Detail, e.Probe?.Remote); break; case AgentEventKinds.ProbeDisconnected when !string.IsNullOrEmpty(e.Detail): state.RemoveProbe(e.Detail); break; case AgentEventKinds.EndpointChanged: state.CountEndpointChange(); break; } string? detail = e.Detail is { Length: > 512 } ? e.Detail[..512] : e.Detail; await _events.AddAsync(agent, e.Kind, at, detail, ct); } }