You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
haoliang-net/src/CncSimulator/Core/LogRecorder.cs

154 lines
4.8 KiB
C#

using System;
using System.Collections.Generic;
namespace CncSimulator.Core
{
/// <summary>日志条目</summary>
public class LogEntry
{
/// <summary>时间戳</summary>
public DateTime Timestamp { get; set; }
/// <summary>地址端口</summary>
public int AddressPort { get; set; }
/// <summary>设备数量</summary>
public int DeviceCount { get; set; }
/// <summary>关键数据摘要</summary>
public string KeyData { get; set; }
/// <summary>完整JSON</summary>
public string FullJson { get; set; }
/// <summary>响应耗时(毫秒)</summary>
public long Duration { get; set; }
}
/// <summary>异常记录条目</summary>
public class ErrorRecord
{
/// <summary>时间戳</summary>
public DateTime Timestamp { get; set; }
/// <summary>异常类型: http500, timeout, empty, malformed, refuse</summary>
public string ErrorType { get; set; }
/// <summary>异常描述</summary>
public string Description { get; set; }
/// <summary>影响设备数</summary>
public int AffectedDevices { get; set; }
}
/// <summary>
/// 日志记录器。同时写入内存环形缓冲和log4net文件。
/// </summary>
public class LogRecorder
{
private readonly int _capacity;
private readonly LogEntry[] _buffer;
private int _writeIndex;
private int _count;
private readonly object _lock = new object();
private readonly log4net.ILog _log;
// 异常记录列表(独立于请求日志)
private readonly List<ErrorRecord> _errors = new List<ErrorRecord>();
private readonly object _errorLock = new object();
public LogRecorder(int capacity = 200)
{
_capacity = capacity;
_buffer = new LogEntry[capacity];
_writeIndex = 0;
_count = 0;
_log = log4net.LogManager.GetLogger(typeof(LogRecorder));
}
/// <summary>记录一次返回</summary>
public void Record(int addressPort, int deviceCount, string keyData, string fullJson, long durationMs)
{
var entry = new LogEntry
{
Timestamp = DateTime.Now,
AddressPort = addressPort,
DeviceCount = deviceCount,
KeyData = keyData,
FullJson = fullJson,
Duration = durationMs
};
lock (_lock)
{
_buffer[_writeIndex] = entry;
_writeIndex = (_writeIndex + 1) % _capacity;
if (_count < _capacity) _count++;
}
// 写文件日志
_log.Info($"[{addressPort}] 返回{deviceCount}台设备, 耗时{durationMs}ms");
_log.Info($"[{addressPort}] 关键数据: {keyData}");
}
/// <summary>记录一次异常</summary>
public void RecordError(string errorType, string description, int affectedDevices)
{
var record = new ErrorRecord
{
Timestamp = DateTime.Now,
ErrorType = errorType,
Description = description,
AffectedDevices = affectedDevices
};
lock (_errorLock)
{
_errors.Add(record);
// 限制数量
if (_errors.Count > 1000) _errors.RemoveAt(0);
}
_log.Warn($"[异常] 类型={errorType}, 影响{affectedDevices}台设备: {description}");
}
/// <summary>获取所有异常记录</summary>
public List<ErrorRecord> GetErrors()
{
lock (_errorLock)
{
return new List<ErrorRecord>(_errors);
}
}
/// <summary>获取异常次数统计</summary>
public int GetErrorCount()
{
lock (_errorLock) { return _errors.Count; }
}
/// <summary>获取最近的日志</summary>
public List<LogEntry> GetRecentLogs(int count)
{
var result = new List<LogEntry>();
lock (_lock)
{
int toRead = Math.Min(count, _count);
// 从最新到最旧
for (int i = 0; i < toRead; i++)
{
int idx = (_writeIndex - 1 - i + _capacity) % _capacity;
result.Add(_buffer[idx]);
}
}
return result;
}
/// <summary>获取最新一条日志</summary>
public LogEntry GetLatest()
{
lock (_lock)
{
if (_count == 0) return null;
int idx = (_writeIndex - 1 + _capacity) % _capacity;
return _buffer[idx];
}
}
}
}