/// <summary>
/// 日志文件模块,使用多线程来进行写日志文件
/// </summary>
public class LoggerTool
{
private static LoggerTool sLogFileModule;
/// <summary>
/// 开启写日志
/// </summary>
public static void Open()
{
if (sLogFileModule == null)
{
sLogFileModule = new LoggerTool();
}
}
public static void Close()
{
if (sLogFileModule != null)
{
sLogFileModule.Dispose();
sLogFileModule = null;
}
}
#region 私有
private class LogData
{
public string log { get; set; }
public string trace { get; set; }
public LogType level { get; set; }
}
private StreamWriter m_StreamWriter;
private ManualResetEvent m_ManualResetEvent;
private ConcurrentQueue<LogData> m_ConcurrentQueue; // 安全队列
private bool m_ThreadRunning;
private string logDirectoryPath = string.Empty;
private string logFilePath = string.Empty;
private const string LOG_FILE_NAME = "MyopiaCHomeEditionA_log.log";
private readonly int MAX_FILE_SIZE = 1024 * 1024 * 5;
private LoggerTool()
{
#if UNITY_EDITOR
logDirectoryPath = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "Logs/");
#else
logDirectoryPath = Path.Combine(Application.persistentDataPath, "Logs/");
#endif
logFilePath = Path.Combine(logDirectoryPath, LOG_FILE_NAME);
logFilePath = logFilePath.Replace("\\", "/");
if (!Directory.Exists(logDirectoryPath))
{
Directory.CreateDirectory(logDirectoryPath);
}
Debug.Log($"logFilePath:{logFilePath}");
Start();
Application.logMessageReceivedThreaded += OnLogMessageReceivedThreaded;
}
private void Start()
{
if (File.Exists(logFilePath))
{
m_StreamWriter = new StreamWriter(logFilePath, true);
}
else
{
m_StreamWriter = new StreamWriter(logFilePath);
}
m_StreamWriter.Write($"\n\n\n --------======{DateTime.Now.ToString("yyyy年MM月dd日HH时mm分ss秒")}======--------\n");
m_StreamWriter.Flush();
m_ManualResetEvent = new ManualResetEvent(false);
m_ConcurrentQueue = new ConcurrentQueue<LogData>();
m_ThreadRunning = true;
var fileThread = new Thread(FileLogThread);
fileThread.Start();
}
private void Stop()
{
try
{
m_ThreadRunning = false;
m_ManualResetEvent.Set();
m_StreamWriter.Close();
m_StreamWriter.Dispose();
m_StreamWriter = null;
}
catch (Exception e)
{
//这里异常了。
Debug.Log(e.ToString());
}
}
private void Dispose()
{
Stop();
}
private void OnLogMessageReceivedThreaded(string logString, string stackTrace, LogType type)
{
if (m_ConcurrentQueue == null) return;
m_ConcurrentQueue.Enqueue(new LogData() { log = logString, trace = stackTrace, level = type });
m_ManualResetEvent.Set();
}
private void FileLogThread()
{
while (m_ThreadRunning)
{
m_ManualResetEvent.WaitOne();
if (m_StreamWriter == null)
{
break;
}
//判断文件大小,如果文件超过大小,则备份文件并重新开始写文件
FileInfo fileInfo = new FileInfo(logFilePath);
if (fileInfo.Length >= MAX_FILE_SIZE)
{
//备份文件
Stop();
//检测文件夹中有多少文件,超过十个就删掉之前的。
DirectoryInfo dirInfo = new DirectoryInfo(logDirectoryPath);
FileInfo[] dirFiles = dirInfo.GetFiles();
string fn = Path.GetFileNameWithoutExtension(LOG_FILE_NAME);
if (dirFiles.Length >= 5)
{
foreach (var dirf in dirFiles)
{
if (dirf.Name.Equals(LOG_FILE_NAME) || !dirf.FullName.Contains(fn))
{
continue;
}
File.Delete(dirf.FullName);
}
}
string targetLogFilePath = Path.Combine(logDirectoryPath, string.Format("MyopiaCHomeEditionA_log_{0}.log.bak", DateTime.Now.ToString("yyyyMMddHHmmss")));
File.Move(logFilePath, targetLogFilePath);
//重新开始写文件
Start();
m_ManualResetEvent.WaitOne();
return;
}
LogData msg;
while (m_ConcurrentQueue.Count > 0 && m_ConcurrentQueue.TryDequeue(out msg))
{
if (!m_ThreadRunning)
{
break;
}
if (msg.level == LogType.Log)
{
m_StreamWriter.Write($"[Log][{DateTime.Now.ToString("yyyyMMddHHmmss")}]{msg.log}");
}
else if (msg.level == LogType.Warning)
{
m_StreamWriter.Write('\n');
m_StreamWriter.Write($"[Warning][{DateTime.Now.ToString("yyyyMMddHHmmss")}]{msg.log}");
m_StreamWriter.Write('\n');
m_StreamWriter.Write(msg.trace);
}
else
{
m_StreamWriter.Write('\n');
m_StreamWriter.Write($"[Error][{DateTime.Now.ToString("yyyyMMddHHmmss")}]{msg.log}");
m_StreamWriter.Write('\n');
m_StreamWriter.Write(msg.trace);
}
m_StreamWriter.Write("\r\n");
}
if (m_ThreadRunning)
{
m_StreamWriter?.Flush();
m_ManualResetEvent?.Reset();
}
Thread.Sleep(1);
}
}
#endregion
}