From e57938fbda9bff702004038f76d009422968bff5 Mon Sep 17 00:00:00 2001
From: alielie <alielie@git.com>
Date: 星期五, 06 十一月 2026 18:05:07 +0800
Subject: [PATCH] 提交代码

---
 DeviceService/Logging/MemoryAppender.cs |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 108 insertions(+), 0 deletions(-)

diff --git a/DeviceService/Logging/MemoryAppender.cs b/DeviceService/Logging/MemoryAppender.cs
new file mode 100644
index 0000000..2460cf4
--- /dev/null
+++ b/DeviceService/Logging/MemoryAppender.cs
@@ -0,0 +1,108 @@
+using log4net;
+using log4net.Appender;
+using log4net.Core;
+
+namespace DeviceService.Logging;
+
+/// <summary>鍐呭瓨缂撳啿涓殑涓�鏉℃棩蹇椼��</summary>
+public sealed class LogEntry
+{
+    public DateTime Time { get; set; }
+
+    public string Level { get; set; } = string.Empty;
+
+    public string Logger { get; set; } = string.Empty;
+
+    public string Message { get; set; } = string.Empty;
+
+    public string Display => $"{Time:yyyy-MM-dd HH:mm:ss.fff} [{Level}] {Logger} - {Message}";
+
+    public override string ToString() => Display;
+}
+
+/// <summary>
+/// 鑷畾涔� Appender锛氬彧鍦ㄥ唴瀛樼幆褰㈢紦鍐蹭腑淇濈暀鏈�杩� <see cref="Capacity"/> 鏉℃棩蹇楋紝
+/// 閫氳繃 <see cref="EntryAppended"/> 涓� <see cref="Snapshot"/> 渚涙棩蹇楃獥鍙f煡鐪嬨��
+/// 鏂囦欢杈撳嚭鐢� log4net.config 涓殑 RollingFileAppender 璐熻矗锛屾湰 Appender 涓嶅啓浠讳綍鏂囦欢銆�
+/// 瀹炰緥鐢� log4net 渚濇嵁 Config/log4net.config 鍒涘缓锛坅ppender name="Memory"锛夈��
+/// </summary>
+public sealed class MemoryAppender : AppenderSkeleton
+{
+    /// <summary>鍐呭瓨涓渶澶氫繚鐣欑殑鏃ュ織鏉℃暟锛屽彲鐢� log4net.config 鐨� capacity 鍙傛暟瑕嗙洊銆�</summary>
+    public int Capacity { get; set; } = 1000;
+
+    /// <summary>log4net.config 涓厤缃殑 MemoryAppender 瀹炰緥銆�</summary>
+    public static MemoryAppender Current =>
+        LogManager.GetRepository(typeof(MemoryAppender).Assembly)
+            .GetAppenders()
+            .OfType<MemoryAppender>()
+            .FirstOrDefault()
+        ?? throw new InvalidOperationException(
+            "鏈壘鍒� MemoryAppender锛岃妫�鏌� Config/log4net.config 涓槸鍚﹂厤缃簡 name=\"Memory\" 鐨� appender锛屽苟鍦� root 涓紩鐢ㄣ��");
+
+    private readonly object _sync = new object();
+    private readonly Queue<LogEntry> _entries = new Queue<LogEntry>();
+
+    /// <summary>鏂版棩蹇楀埌杈撅紙鍙兘鍦ㄥ悗鍙扮嚎绋嬭Е鍙戯紝UI 璁㈤槄鏂归渶鍒囨崲鍥� UI 绾跨▼锛夈��</summary>
+    public event Action<LogEntry>? EntryAppended;
+
+    /// <summary>褰撳墠鍐呭瓨涓棩蹇楃殑蹇収銆�</summary>
+    public IReadOnlyList<LogEntry> Snapshot
+    {
+        get
+        {
+            lock (_sync)
+            {
+                return _entries.ToList();
+            }
+        }
+    }
+
+    public MemoryAppender()
+    {
+        Name = "Memory";
+    }
+
+    /// <summary>娓呯┖鍐呭瓨缂撳啿锛堜笉褰卞搷鏂囦欢锛夈��</summary>
+    public void Clear()
+    {
+        lock (_sync)
+        {
+            _entries.Clear();
+        }
+    }
+
+    protected override void Append(LoggingEvent loggingEvent)
+    {
+        if (loggingEvent == null)
+        {
+            return;
+        }
+
+        string message = loggingEvent.RenderedMessage ?? string.Empty;
+        if (loggingEvent.ExceptionObject != null)
+        {
+            message += Environment.NewLine + loggingEvent.ExceptionObject;
+        }
+
+        var entry = new LogEntry
+        {
+            Time = loggingEvent.TimeStamp,
+            Level = loggingEvent.Level?.Name ?? string.Empty,
+            Logger = loggingEvent.LoggerName,
+            Message = message
+        };
+
+        lock (_sync)
+        {
+            _entries.Enqueue(entry);
+            while (_entries.Count > Capacity)
+            {
+                _entries.Dequeue();
+            }
+
+            // Monitor 閿佸彲閲嶅叆锛屽洖璋冨唴閮ㄨ嫢璋冪敤 Snapshot/Clear 涓嶄細姝婚攣
+            EntryAppended?.Invoke(entry);
+        }
+    }
+}

--
Gitblit v1.9.1