namespace CSharpTest.Helpers;
/// <summary>
/// 快速输出日志帮助类
/// </summary>
public static class FastLogHelper
{
static FastLogHelper()
{
logDirPath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "fast-error-log");
CreateLogFolder();
writeLogTask = Task.Run(async () =>
{
while (true)
{
if (IsLogQueueEmpty == false)
{
// 如果日志数量大于100,则以100条日志为一个批次写入
if (logQueue.Count > 100)
{
Dictionary<string, List<string>> templateDict = new();
for (int i = 0; i < 100; i++)
{
var item = logQueue.Dequeue();
if (templateDict.ContainsKey(item.prefix) == false)
{
templateDict[item.prefix] = new List<string>();
}
var time = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.FFF");
var template = $"[START][{time}][{item.content}][END]";
templateDict[item.prefix].Add(template);
}
foreach (var key in templateDict.Keys)
{
using var writer = GetLogFileWriter(key);
var content = string.Join(Environment.NewLine, templateDict[key]);
await writer.WriteLineAsync(content);
await writer.FlushAsync();
await writer.DisposeAsync();
}
}
else
{
// 否则就一条一条的写
var item = logQueue.Dequeue();
using var writer = GetLogFileWriter(item.prefix);
var time = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.FFF");
var template = $"[START][{time}][{item.content}][END]";
await writer.WriteLineAsync(template);
await writer.FlushAsync();
await writer.DisposeAsync();
}
}
else
{
await Task.Delay(50);
}
}
});
}
/// <summary>
/// 日志存储文件夹路径
/// </summary>
private static string logDirPath;
/// <summary>
/// 日志写入锁
/// </summary>
private static object writeLogLock = new();
/// <summary>
/// 日志队列
/// </summary>
private static Queue<(string content, string prefix)> logQueue = new(10000);
/// <summary>
/// 日志写入任务
/// </summary>
private static Task writeLogTask;
/// <summary>
/// 创建日志存储文件夹,当前程序目录下的 fast-error-log 文件夹
/// </summary>
private static void CreateLogFolder()
{
if (System.IO.Directory.Exists(logDirPath) == false)
{
System.IO.Directory.CreateDirectory(logDirPath);
}
}
/// <summary>
/// 是否存在 off.log 文件,如果存在,则不写日志
/// </summary>
/// <returns></returns>
private static bool IsExistOffFile()
{
var offFilePath = Path.Combine(logDirPath, "off.log");
return System.IO.File.Exists(offFilePath);
}
/// <summary>
/// 创建日志文件,默认前缀fast,格式示例:fast-2012-12-12.log,如果日志文件大小大于1m,则文件会被重命名于fast-2012-12-12-X.log,然后写入新的数据
/// </summary>
/// <param name="prefix">日志文件前缀</param>
/// <returns></returns>
private static StreamWriter GetLogFileWriter(string prefix = "fast")
{
var fileNameWithoutExtension = $"{prefix}-{DateTime.Now.ToString("yyyy-MM-dd")}";
var fileName = $"{fileNameWithoutExtension}.log";
var logFilePath = Path.Combine(logDirPath, fileName);
var file = new FileInfo(logFilePath);
if (file.Exists == true)
{
// 大于 1M,创建新的文件
if (file.Length > 1024 * 1024)
{
var files = Directory.GetFiles(logDirPath, $"{fileNameWithoutExtension}-*.log", SearchOption.TopDirectoryOnly);
var maxIndex = 0;
foreach (var f in files)
{
var indexStr = Path.GetFileNameWithoutExtension(f).Substring(fileNameWithoutExtension.Length + 1);
var index = int.Parse(indexStr);
if (index > maxIndex)
{
maxIndex = index;
}
}
maxIndex += 1;
string destFilename = Path.Combine(logDirPath, $"{fileNameWithoutExtension}-{maxIndex}.log");
file.MoveTo(destFilename);
file = new FileInfo(logFilePath);
}
}
return file.AppendText();
}
/// <summary>
/// 日志队列是否写入完毕
/// </summary>
/// <returns></returns>
public static bool IsLogQueueEmpty => logQueue.Count == 0;
/// <summary>
/// 写日志
/// </summary>
/// <param name="content">日志内容</param>
/// <param name="prefix">日志文件前缀</param>
public static void WriteLog(string content, string prefix = "fast")
{
lock (writeLogLock)
{
if (IsExistOffFile())
{
return;
}
logQueue.Enqueue((content, prefix));
}
}
}
CSharp-FastLogHelper
声明:本站所有文章除特别声明外,均采用CC BY-NC-SA 4.0许可协议。转载请注明来自
染青的博客!
相关文章
还没有评论, 告诉我们你的想法
发表评论