using HslCommunication.LogNet;
using System.Collections.Concurrent;
using System.IO;
using WinFormsApp.Utils;
namespace guoke
{
///
/// 日志服务
///
public class LogService
{
public static LogService Log;
// 按照文件大小切割日志,指定10M,不限制日志文件数量
public ILogNet logNet { get; set; }
public LogService()
{
LogConfigModel logConfig = new LogConfigModel();
//构建配置
logConfig = ConfigReader.GetObject("Logs");
//创建日志实例
logNet = new LogNetFileSize(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, logConfig.LogFilePath), logConfig.MaxFileSize * 1024 * 1024, logConfig.MaxArchiveFiles);
logNet.SetMessageDegree(logConfig.LogLevel);
// 如果所有的日志在记录之前需要在控制台显示出来
logNet.BeforeSaveToFile += (object sender, HslEventArgs e) =>
{
Console.WriteLine(e.HslMessage.ToString());
};
Log = this;
Log.Info("日志", $"等级:{logConfig.LogLevel},大小:{logConfig.MaxFileSize * 1024 * 1024}B,数量:{logConfig.MaxArchiveFiles}");
}
#region 时间
// 使用并发字典替代普通字典+锁,提高并发性能
private static readonly ConcurrentDictionary _loggedMessages =
new ConcurrentDictionary();
// 过期时间配置为60秒
private static TimeSpan _expirationTime = TimeSpan.FromSeconds(60);
// 上次清理时间
private static DateTime _lastCleanupTime = DateTime.MinValue;
// 清理间隔设置为过期时间的一半,平衡性能和内存使用
private static TimeSpan _cleanupInterval = TimeSpan.FromSeconds(30);
///
/// 记录错误日志(带时间控制)
///
/// 日志消息
public void ErrorTime(string key, string message, bool log = true) => LogWithTimeControl(key, message, Error, log);
///
/// 记录警告日志(带时间控制)
///
/// 日志消息
public void WarnTime(string key, string message, bool log = true) => LogWithTimeControl(key, message, Warn, log);
///
/// 记录警告日志(带时间控制)
///
/// 日志消息
public void InfoTime(string key, string message, bool log = true) => LogWithTimeControl(key, message, Info, log);
// 带时间控制的通用日志记录方法
private void LogWithTimeControl(string key, string message, Action logAction, bool log)
{
if (log)
{
TryCleanupExpiredMessages();
// 检查消息是否已记录且未过期
if (_loggedMessages.TryGetValue(message, out var lastLoggedTime) &&
(DateTime.Now - lastLoggedTime) <= _expirationTime)
{
return;
}
// 记录日志并更新记录时间
logAction($"T:{key}", message);
_loggedMessages.AddOrUpdate(message, DateTime.Now, (_, __) => DateTime.Now);
}
}
// 尝试清理过期消息
private static void TryCleanupExpiredMessages()
{
var now = DateTime.Now;
// 检查是否达到清理间隔
if ((now - _lastCleanupTime) < _cleanupInterval)
{
return;
}
// 获取所有过期键
var expiredKeys = _loggedMessages
.Where(kv => (now - kv.Value) > _expirationTime)
.Select(kv => kv.Key)
.ToList();
// 移除过期键
foreach (var key in expiredKeys)
{
_loggedMessages.TryRemove(key, out _);
}
_lastCleanupTime = now;
}
#endregion
public void String(string message)
{
logNet.WriteAnyString($"mes:{message}");// 写任意的数据,不受格式化影响
}
public void Debug(string message)
{
logNet.WriteDebug(message);
}
public void Info(string message)
{
logNet.WriteInfo(message);
}
public void Warn(string message)
{
logNet.WriteWarn(message);
}
public void Error(string message)
{
logNet.WriteError(message);
}
public void Fatal(string message)
{
logNet.WriteFatal(message);
}
public void Debug(string key, string message)
{
logNet.WriteDebug(key,message);
}
public void Info(string key, string message)
{
logNet.WriteInfo(key, message);
}
public void Warn(string key, string message)
{
logNet.WriteWarn(key, message);
}
public void Error(string key, string message)
{
logNet.WriteError(key, message);
}
public void Warn(string key, string message,bool log=true)
{
if (log)
logNet.WriteWarn(key, message);
}
public void Error(string key, string message, bool log = true)
{
if (log)
logNet.WriteError(key, message);
}
public void Fatal(string key, string message, bool log = true)
{
if (log)
logNet.WriteFatal(key, message);
}
///
/// 获取日志文件列表
///
///
///
///
private List GetFileNamesWithoutExtension(string folderPath, string fileExtension)
{
List fileNames = new List();
try
{
// 检查文件夹是否存在
if (Directory.Exists(folderPath))
{
// 获取指定文件夹内指定后缀的所有文件
string[] files = Directory.GetFiles(folderPath, $"*.{fileExtension}");
foreach (string file in files)
{
// 获取不包含后缀的文件名
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
fileNames.Add(fileNameWithoutExtension);
}
}
else
{
Warn("日志","指定的文件夹不存在");
}
}
catch (Exception e)
{
Error("日志",$"发生错误:{e.Message}");
}
return fileNames;
}
///
/// 读取日志
///
///
///
private static List ParseLogFile(string filePath)
{
List logs = new List();
string currentLog = string.Empty;
foreach (var line in File.ReadLines(filePath))
{
if (line.Contains("[信息]") || line.Contains("[错误]") || line.Contains("[调试]") || line.Contains("[警告]"))
{
if (!string.IsNullOrEmpty(currentLog))
{
logs.Add(currentLog);
}
currentLog = line;
}
else
{
if (!string.IsNullOrEmpty(currentLog))
{
currentLog += Environment.NewLine + line;
}
}
}
// 添加最后一个日志条目
if (!string.IsNullOrEmpty(currentLog))
{
logs.Add(currentLog);
}
return logs;
}
}
///
/// 日志配置模型
///
public class LogConfigModel
{
// 日志文件的最大大小(以m为单位)
public int MaxFileSize { get; set; } = 1;
// 允许的最大存档文件数量
public int MaxArchiveFiles { get; set; } = 100;
///
/// 日志文件路径
///
public string LogFilePath { get; set; } = "logs";
// 日志记录的最低等级
public HslMessageDegree LogLevel { get; set; }= HslMessageDegree.DEBUG;
}
}