public class LogInfo
{
public string AddTime;
public string Content;
public string Type;
public Exception Ex;
public LogInfo(string addTime, string content, string type, Exception ex = null)
{
AddTime = addTime;
Content = content;
Type = type;
Ex = ex;
}
}
interface ILogger
{
void Warn(string msg);
void Info(string msg);
void Debug(string msg);
void Error(string msg);
void Error(Exception ex, string msg);
}
/// <summary>
/// 支持多线程写日志
/// </summary>
public class SimpleLogger : ILogger
{
private BlockingCollection<LogInfo> _queue = new BlockingCollection<LogInfo>();
private readonly string _filePath = $"{AppDomain.CurrentDomain.BaseDirectory}Logs\\";
private CancellationTokenSource _cancellationTokenSource;
private CancellationToken _cancellToken;
//使用Lazy创建线程安全单例模式
//如果不用Lazy,则需要lock来判断对象是否需要实例化
private static Lazy<SimpleLogger> _instance = new Lazy<SimpleLogger>(() => new SimpleLogger());
public static SimpleLogger Instance => _instance?.Value;
private SimpleLogger()
{
_cancellationTokenSource = new CancellationTokenSource();
_cancellToken = _cancellationTokenSource.Token;
Task.Factory.StartNew(HandleLogQueue);
}
/// <summary>
/// 关闭日志队列线程
/// </summary>
public void CloseLogThread()
{
_cancellationTokenSource.Cancel();
_cancellationTokenSource.Dispose();
}
/// <summary>
/// 判断日志队列是否为空
/// </summary>
/// <returns></returns>
public bool QueueIsEmpty()
{
return _queue.IsCompleted;
}
public int Count()
{
return _queue.Count;
}
public void Debug(string msg)
{
_queue?.TryAdd(new LogInfo(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), msg, "Debug"));
}
public void Warn(string msg)
{
_queue?.TryAdd(new LogInfo(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), msg, "Warn"));
}
public void Info(string msg)
{
_queue?.TryAdd(new LogInfo(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), msg, "Info"));
}
public void Error(string msg)
{
_queue?.TryAdd(new LogInfo(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), msg, "Error"));
}
public void Error(Exception ex, string msg = "")
{
_queue?.TryAdd(new LogInfo(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), msg, "Error", ex));
}
private void HandleLogQueue()
{
try
{
foreach (var logInfo in _queue.GetConsumingEnumerable(_cancellToken))
{
WriteLine(logInfo.Content, logInfo.Type, logInfo.AddTime, logInfo.Ex);
}
}
catch
{
// ignored
}
}
private void WriteLine(string content, string category, string time, Exception ex = null)
{
var path = $"{_filePath}{DateTime.Now.ToString("yyyyMMdd")}\\";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
var filePath = $"{GetFileName(path, category)}.txt";
using (var sw = new StreamWriter(filePath, true, Encoding.UTF8))
{
sw.WriteLine(Format(content, category, time, ex));
}
}
private string Format(string content, string category, string time, Exception ex = null)
{
var builder = new StringBuilder();
builder.AppendFormat("{0} ", time);
if (!string.IsNullOrEmpty(category))
{
builder.AppendFormat("[{0}]", category);
}
if (content != "")
{
builder.Append(content + "\r\n");
}
if (ex != null)
{
builder.Append(ex.Message + "\r\n");
builder.Append(ex.StackTrace + "\r\n");
}
return builder.ToString();
}
private string GetFileName(string path, string category)
{
if (!File.Exists($"{path}Log-{category}-0.txt"))
{
return $"{path}Log-{category}-0";
}
var no = 0;
var info = new FileInfo($"{path}Log-{category}-0.txt");
while (info.Length >= 10 * 1024 * 1024)
{
no++;
if (!File.Exists($"{path}Log-{category}-{no}.txt"))
{
return $"{path}Log-{category}-{no}";
}
info = new FileInfo($"{path}Log-{category}-{no}.txt");
}
return $"{path}Log-{category}-{no}";
}
}
【C#】日志文件类
最新推荐文章于 2024-08-14 10:45:28 发布