相對之前發的日誌記錄來說,此類將程式記錄處理與寫磁碟操作分離,用戶代碼部分,將日誌放到隊列,並通知線程將日誌寫到文件: 1.公共類: using System;using System.IO;using System.Collections.Generic;using static System.C ...
相對之前發的日誌記錄來說,此類將程式記錄處理與寫磁碟操作分離,用戶代碼部分,將日誌放到隊列,並通知線程將日誌寫到文件:
1.公共類:
using System;
using System.IO;
using System.Collections.Generic;
using static System.Console;
using System.Text;
using System.Diagnostics;
namespace LogWriter
{
/// <summary>
/// 日誌類型
/// </summary>
public enum LogType
{
Error,
Info,
Waring,
Success,
Failure
}
/// <summary>
/// 日誌參數信息
/// </summary>
internal struct LogInfo
{
internal string FileName { get; set; }
internal string MethodName { get; set; }
internal int Line { get; set; }
internal int Column { get; set; }
internal string LogType { get; set; }
}
/// <summary>
/// 公共日之類
/// </summary>
internal class LogCommon
{
static System.Threading.ReaderWriterLockSlim Slim = new System.Threading.ReaderWriterLockSlim(System.Threading.LockRecursionPolicy.SupportsRecursion);
/// <summary>
/// 獲取日誌參數信息
/// </summary>
/// <param name="type">類型</param>
/// <returns></returns>
internal static LogInfo GetLog(LogType type)
{
StackTrace st = new StackTrace(2, true);
StackFrame sf = st.GetFrame(0);
LogInfo li = new LogInfo()
{
FileName = sf.GetFileName(),
MethodName = sf.GetMethod().Name,
Line = sf.GetFileLineNumber(),
Column = sf.GetFileColumnNumber(),
};
string logType = "-Error";
switch (type)
{
case LogType.Error:
logType = "-Error";
break;
case LogType.Info:
logType = "-Info";
break;
case LogType.Waring:
logType = "-Waring";
break;
case LogType.Success:
logType = "-Success";
break;
case LogType.Failure:
logType = "-Failure";
break;
default:
logType = "-Error";
break;
}
li.LogType = logType;
return li;
}
/// <summary>
/// 寫入以小時分割的日誌文件
/// </summary>
/// <param name="Msg">要記錄的消息</param>
/// <param name="li">日誌信息類</param>
/// <param name="LogPath">日誌所在文件夾</param>
/// <returns></returns>
internal static string WriteLineToTimeFile(string Msg, LogInfo li,string LogPath)
{
if (string.IsNullOrEmpty(Msg))
{
return "輸入參數Msg為null或者值為空不符合記錄要求!";
}
StreamWriter sw = null;
try
{
Slim.EnterWriteLock();
//string Dir = System.Windows.Forms.Application.StartupPath + @"\GLogs\" + DateTime.Now.ToString("yyyy年MM月dd日");
checkLog(LogPath);
string file = DateTime.Now.ToString("yyyy年MM月dd日HH時") + ".log";
checkfile(LogPath, file);
string fileName = LogPath + "\\" + file;
sw = File.AppendText(fileName);
sw.WriteLine("日誌時間:" + DateTime.Now.ToString() + ",文件名:" + li.FileName + ",方法名:" + li.MethodName + "行號:" + li.Line + ",列:" + li.Column + ",日誌類型:" + li.LogType);
sw.WriteLine("日誌內容:" + Msg);
return nameof(WriteLineToTimeFile) + "日誌記錄操作成功!";
}
catch (Exception ex)
{
return nameof(WriteLineToTimeFile) + "日誌記錄發生錯誤:" + ex.Message;
}
finally
{
sw.Close();
Slim.ExitWriteLock();
}
}
/// <summary>
/// 檢查日誌目錄是否存在,不存在則創建
/// </summary>
/// <param name="Path">文件夾</param>
internal static void checkLog(string Path)
{
if (!Directory.Exists(Path))
{
Directory.CreateDirectory(Path);
}
}
/// <summary>
/// 傳入路徑名稱和文件名稱,創建日誌文件
/// </summary>
/// <param name="DirName">文件夾</param>
/// <param name="FileName">文件名</param>
internal static void checkfile(string DirName, string FileName)
{
if (!File.Exists(DirName + @"\" + FileName))
{
File.Create(DirName + @"\" + FileName).Close();
}
}
}
}
2.gLog類:
using System;
using System.IO;
using System.Collections.Generic;
using static System.Console;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace LogWriter
{
/// <summary>
/// 通過隊列緩存來提高日誌記錄速度
/// </summary>
public class GLog
{
readonly object lockobj = new object();
TimerCallback tc;
Timer timer;
Queue<LogQueueStruct> LogList = new Queue<LogQueueStruct>();
public string LogPath { get; set; } = System.Windows.Forms.Application.StartupPath + @"\Logs\" + DateTime.Now.ToString("yyyy年MM月dd日");
public void RecordLog(LogType type,string msg)
{
LogQueueStruct log = new LogQueueStruct()
{
info = LogCommon.GetLog(type),
Msg=msg
};
lock (lockobj)
{
LogList.Enqueue(log);
}
timer.Change(0, Timeout.Infinite);
}
public void RegiestLog()
{
//開啟一個線程用以將隊列中的日誌記錄到文件
tc = new TimerCallback((o) =>
{
timer.Change(Timeout.Infinite, Timeout.Infinite);
lock (lockobj)
{
if (LogList.Count > 0)
{
LogQueueStruct log = LogList.Dequeue();
LogCommon.WriteLineToTimeFile(log.Msg, log.info,LogPath);
}
}
});
timer = new Timer(tc, null, Timeout.Infinite, Timeout.Infinite);
}
public int LogListCount => LogList.Count;
}
internal class LogQueueStruct
{
internal LogInfo info { get; set; }
internal string Msg { get; set; }
}
}
3.調用:
GLog log = new GLog();
log.RegiestLog();//初始化記錄線程(定時器)
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
for(int i = 0; i++ < 1000;)
{
log.RecordLog(LogType.Info, $"日誌記錄測試數據{i}");
}
stopwatch.Stop();
Console.WriteLine(stopwatch.Elapsed.TotalSeconds);
Console.WriteLine("程式部分操作完成!");
Console.ReadLine();
相比較TxtLog:
TxtLog log = TxtLog.Instance;
//初始化記錄線程(定時器)
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
for(int i = 0; i++ < 1000;)
{
log.WriteLineToFile($"日誌記錄測試數據{i}", LogType.Info);
}
stopwatch.Stop();
Console.WriteLine($"調用{nameof(TxtLog)}耗時:{stopwatch.Elapsed.TotalSeconds}");
Console.WriteLine("程式部分操作完成!");
Console.ReadLine();
程式操作時間相差數倍!這就體現了用戶調用部分和後臺寫磁碟文件部分,分離的好處!