using System;
|
using System.Collections.Generic;
|
using System.Diagnostics;
|
using System.IO;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
using WIDESEAWCS_Core.Helper;
|
|
namespace WIDESEAWCS_Core.LogHelper
|
{
|
public class LoggerHelper
|
{
|
// 读写锁,确保多线程环境下日志写入的线程安全
|
static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim();
|
|
// 日志文件夹路径
|
static string folderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"Log");
|
|
// 记录日志的队列
|
static Queue<string> logQueue = new Queue<string>();
|
|
static LoggerHelper()
|
{
|
try
|
{
|
if (!Directory.Exists(folderPath))
|
{
|
Directory.CreateDirectory(folderPath);
|
}
|
}
|
catch (Exception ex)
|
{
|
Debug.WriteLine(ex.Message);
|
}
|
}
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="ex"></param>
|
/// <param name="filePath"></param>
|
public static void WriteError(Exception ex, string filePath = "")
|
{
|
StringBuilder builder = new StringBuilder();
|
builder.Append("错误信息:");
|
builder.Append(ex.Message);
|
builder.Append(Environment.NewLine);
|
builder.Append("错误源:");
|
builder.Append(ex.Source);
|
builder.Append(Environment.NewLine);
|
builder.Append("错误堆栈:");
|
builder.Append(ex.StackTrace);
|
builder.Append(Environment.NewLine);
|
builder.Append("错误类型:");
|
builder.Append(ex.GetType().ToString());
|
builder.Append(Environment.NewLine);
|
builder.Append("错误方法:");
|
builder.Append(ex.TargetSite?.ToString());
|
builder.Append(Environment.NewLine);
|
builder.Append(Environment.NewLine);
|
|
WriteLogToFile($"Error_", builder.ToString(), filePath);
|
}
|
|
/// <summary>
|
/// 将日志内容写入指定文件
|
/// </summary>
|
/// <param name="fileName">日志文件名</param>
|
/// <param name="log">要记录的日志内容</param>
|
/// <remarks>
|
/// 该方法会确保线程安全地写入日志,若目录不存在会自动创建,
|
/// 日志内容会自动添加时间戳并追加到文件末尾
|
/// </remarks>
|
public static void WriteLogToFile(string fileName, string log, string filePath = "")
|
{
|
try
|
{
|
// 进入写锁
|
LogWriteLock.EnterWriteLock();
|
|
string path = string.IsNullOrEmpty(filePath) ? folderPath : filePath;
|
|
// 如果文件夹不存在,则创建文件夹
|
if (!Directory.Exists(path))
|
{
|
Directory.CreateDirectory(path);
|
}
|
// 获取日志文件路径
|
string logFilePath = Path.Combine(path, GetLastAccessFileName(fileName, path));
|
// 获取当前时间
|
DateTime now = DateTime.Now;
|
// 构造日志内容
|
string logContent = $"【{now}】{Environment.NewLine}{log}";
|
|
// 将日志内容追加到日志文件中
|
File.AppendAllText(logFilePath, logContent);
|
|
WriteCompleted();
|
}
|
catch { }
|
finally
|
{
|
// 退出写锁
|
LogWriteLock.ExitWriteLock();
|
}
|
}
|
static int size = 10 * 1024 * 1024;
|
|
/// <summary>
|
/// 获取最后一个可用的日志文件名
|
/// </summary>
|
/// <param name="fileName">日志文件基础名称</param>
|
/// <returns>如果存在未达到大小限制的日志文件则返回该文件名,否则返回基于当前时间的新日志文件名</returns>
|
/// <remarks>
|
/// 该方法会遍历所有已存在的日志文件,返回第一个文件大小未超过限制的文件名。
|
/// 如果没有符合条件的文件,则生成一个以当前时间命名的新日志文件名。
|
/// </remarks>
|
private static string GetLastAccessFileName(string fileName, string path)
|
{
|
foreach (var m in GetExistLogFileNames(fileName, path))
|
{
|
FileInfo fileInfo = new FileInfo(m);
|
if (fileInfo.Length < size)
|
{
|
return m;
|
}
|
}
|
|
// 返回一个新的默认当前时间的日志名称
|
return $@"{fileName}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.log";
|
}
|
|
/// <summary>
|
/// 获取指定文件名模式的所有日志文件
|
/// </summary>
|
/// <param name="fileName">日志文件名前缀</param>
|
/// <returns>匹配文件名模式的所有日志文件路径数组</returns>
|
private static string[] GetExistLogFileNames(string fileName, string path)
|
{
|
string[] fileNames = Directory.GetFiles(path, fileName + "*.log");
|
return fileNames;
|
}
|
|
private static string[] GetExistLogFileNames()
|
{
|
if (!string.IsNullOrEmpty(folderPath))
|
return Directory.GetFiles(folderPath, "Error_*.log");
|
else
|
return new string[] { };
|
}
|
|
private static int controlFileQuantity = 100;
|
|
protected static void WriteCompleted()
|
{
|
if (controlFileQuantity > 1)
|
{
|
try
|
{
|
string[] files = GetExistLogFileNames();
|
if (files.Length > controlFileQuantity)
|
{
|
List<FileInfo> fileInfos = new List<FileInfo>();
|
for (int i = 0; i < files.Length; i++)
|
{
|
fileInfos.Add(new FileInfo(files[i]));
|
}
|
|
fileInfos.Sort(new Comparison<FileInfo>((m, n) =>
|
{
|
return m.CreationTime.CompareTo(n.CreationTime);
|
}));
|
|
for (int i = 0; i < fileInfos.Count - controlFileQuantity; i++)
|
{
|
File.Delete(fileInfos[i].FullName);
|
}
|
}
|
}
|
catch
|
{
|
|
}
|
}
|
}
|
}
|
}
|