using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using Serilog.Core; using Serilog.Events; namespace XP.Common.Logging.ViewModels { /// /// Serilog 自定义 Sink,将日志事件转发到 RealTimeLogViewerViewModel,并维护环形缓冲区 /// Custom Serilog Sink that forwards log events and maintains a ring buffer for history /// public class RealTimeLogSink : ILogEventSink { private const int BufferCapacity = 500; private readonly ConcurrentQueue _buffer = new(); /// /// 全局单例实例 | Global singleton instance /// public static RealTimeLogSink Instance { get; } = new(); /// /// 日志事件到达时触发 | Fired when a log event arrives /// public event Action? LogEventReceived; public void Emit(LogEvent logEvent) { // 入队缓冲区 | Enqueue to buffer _buffer.Enqueue(logEvent); while (_buffer.Count > BufferCapacity) { _buffer.TryDequeue(out _); } LogEventReceived?.Invoke(logEvent); } /// /// 获取缓冲区中的历史日志快照 | Get a snapshot of buffered history logs /// public List GetBufferedHistory() { return _buffer.ToList(); } } }