开发过程中经常需要记录日志,虽然有很多的日志组件可以选择,但是往往需要进行了解配置和API的用法,想要修改起来也不太方便,所以就写了一个开箱即用的多线程日志工具类,使用了发布订阅的原理,实际使用非常好用。
代码如下:
/// <summary>
/// 多线程日志工具类
/// </summary>
public class LogUtils
{
/// <summary>
/// 日志队列
/// </summary>
private static ConcurrentQueue<LogModel> logQueue = new ConcurrentQueue<LogModel>();
private static CancellationToken cancellationToken = new CancellationToken();
/// <summary>
/// 启动线程循环写日志
/// </summary>
public static void Init()
{
Task.Run(() =>
{
while (!cancellationToken.IsCancellationRequested)
{
if (logQueue.Count > 0)
{
var logModel = new LogModel();
logQueue.TryDequeue(out logModel);
SaveLog(logModel);
}
else
{
Thread.Sleep(1000);
}
}
}, cancellationToken);
}
/// <summary>
/// 添加日志
/// </summary>
/// <param name="title"></param>
/// <param name="message"></param>
/// <param name="logType"></param>
public static void WriteLog(string title, string message, LogType logType)
{
logQueue.Enqueue(new LogModel
{
Title = title,
Message = message,
LogType = logType,
LogTime = DateTime.Now,
});
}
public static void LogInfo(string title, string message) => WriteLog(title, message, LogType.INFO);
public static void LogError(string title, string message) => WriteLog(title, message, LogType.ERROR);
public static void LogWarn(string title, string message) => WriteLog(title, message, LogType.WARN);
public static void LogDebug(string title, string message, bool isShowDebugLog)
{
//是否显示Debug日志
if (isShowDebugLog)
{
WriteLog(title, message, LogType.DEBUG);
}
}
/// <summary>
/// 保存日志
/// </summary>
/// <param name="model"></param>
public static void SaveLog(LogModel model)
{
//获取日志文件路径
var logPath = GetLogFilePath(model);
//追加日志信息
var template = $"[{model.LogTime.ToString("yyyy-MM-dd HH:mm:ss")}]\t{model.LogType}\t{model.Title}\t{model.Message}\r\n";
File.AppendAllText(logPath, template);
}
/// <summary>
/// 获取日志文件路径
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public static string GetLogFilePath(LogModel model)
{
var logDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
if (!Directory.Exists(logDir))
{
Directory.CreateDirectory(logDir);
}
var logPath = Path.Combine(logDir, $"{model.LogTime.ToString("yyyyMMdd")}.log");
return logPath;
}
/// <summary>
/// 滚动日志
/// </summary>
public static void RollLog()
{
var logDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
var logs = Directory.GetFiles(logDir, "*.log");
if (logs.Length > 30)
{
var date = DateTime.Now.AddMonths(-1).Date;
foreach (var item in logs)
{
var fileInfo = new FileInfo(item);
if (fileInfo.CreationTime < date)
{
fileInfo.Delete();
}
}
}
}
}
public class LogModel
{
/// <summary>
/// 日志标题
/// </summary>
public string Title { get; set; }
/// <summary>
/// 日志消息
/// </summary>
public string Message { get; set; }
/// <summary>
/// 日志类型
/// </summary>
public LogType LogType { get; set; }
/// <summary>
/// 日志时间
/// </summary>
public DateTime LogTime { get; set; }
}
public enum LogType
{
INFO,
WARN,
ERROR,
DEBUG
}
使用示例:
//全局只用执行一次
LogUtils.Init();
//直接使用
LogUtils.LogInfo("这是日志标题","这是日志内容");
LogUtils.LogError("这是异常标题", "这是异常内容");
日志效果: