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.
154 lines
4.8 KiB
C#
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];
|
|
}
|
|
}
|
|
}
|
|
}
|