C#日志记录工具 MicroLog
Posted Thomas会写字
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#日志记录工具 MicroLog相关的知识,希望对你有一定的参考价值。
一个简单的日志记录工具,性能高效,常用功能都有,结构简单。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.IO;
namespace SystemTools
public class MLog
public MFilter filter = new MFilter();
public MConvert convert = new MConvert();
public MThr thr = new MThr();
public List<MLog> transTo = new List<MLog>();
public delegate void WriteDelegate(LogItem log);
public event WriteDelegate OnWrite;
public void Write(String msg, MType type = MType.mType1, Exception e = null)
LogItem log = new LogItem(type, msg, e);
if (transTo != null)
for (int i = 0; i < transTo.Count; i++)
transTo[i].Write(msg, type, e);
// Thr
log.thrName = thr.Name;
// filter
if (filter.Filt(log) == false) return;
// convert
convert.FormatLog(log);
// write
OnWrite(log);
public class LogItem
public DateTime time;
public Exception e;
public String thrName;
public String mark;
public byte[] logHead;
public String msg;
public MType type;
public String fileName;
public String filePath;
public String fileExten;
public int thrID = -1;
public int logSize = 0;
public byte[] logBuf;
public bool IsStableName = false;
public LogItem(MType type, String msg, Exception e = null)
time = DateTime.Now;
this.type = type;
this.msg = msg;
this.e = e;
public class MConvert
public bool IsEnableLogHead = false;
public bool IsStableName = false;
byte[] logHead = null;
String logName = "";
String logNameExt = "";
String logMark = "";
String logLayout = "";
String pathLayout = "";
List<String> listLogLayout = null;
List<String> listPathLayout = null;
Dictionary<String, int> dictLog;
Dictionary<int, String> dictPath;
public MConvert()
LogName = "mlog.log";
LogLayout = "time msg";
PathLayout = ".\\\\Mlog";
public String LogHead
get
if (logHead == null || logHead.Length == 0) return "";
return Encoding.UTF8.GetString(logHead, 0, logHead.Length - 1);
set
logHead = Encoding.UTF8.GetBytes(value + "\\n");
public String LogName
get
return logName + "." + logNameExt;
set
int n = value.LastIndexOf('.');
if (n > 0)
logName = value.Substring(0, n);
logNameExt = value.Substring(n + 1, value.Length - n - 1);
else
logName = value;
logNameExt = "log";
public String LogMark
get
return logMark;
set
logMark = value;
public String LogLayout
get return logLayout;
set
logLayout = value;
String format = value;
int n1 = format.IndexOf("");
int n2 = format.IndexOf("");
dictLog = new Dictionary<String, int>();
listLogLayout = new List<String>();
while (n1 >= 0 && n2 >= 0)
if (n1 > 0)
listLogLayout.Add(format.Substring(0, n1));
String sKey = format.Substring(n1 + 1, n2 - n1 - 1);
dictLog.Add(sKey, listLogLayout.Count);
listLogLayout.Add("");
format = format.Substring(n2 + 1, format.Length - n2 - 1);
n1 = format.IndexOf("");
n2 = format.IndexOf("");
if (format.Length > 0)
listLogLayout.Add(format);
listLogLayout.Add("\\n");
public String PathLayout
get
return pathLayout;
set
pathLayout = value;
String format = value;
int n1 = format.IndexOf("");
int n2 = format.IndexOf("");
dictPath = new Dictionary<int, String>();
listPathLayout = new List<String>();
while (n1 >= 0 && n2 >= 0)
if (n1 > 0)
listPathLayout.Add(format.Substring(0, n1));
String sKey = format.Substring(n1 + 1, n2 - n1 - 1);
dictPath.Add(listPathLayout.Count, sKey);
listPathLayout.Add("");
format = format.Substring(n2 + 1, format.Length - n2 - 1);
n1 = format.IndexOf("");
n2 = format.IndexOf("");
if (format.Length > 0)
listPathLayout.Add(format);
if (listPathLayout.Count == 0 || listPathLayout[listPathLayout.Count - 1] != "\\\\")
listPathLayout.Add("\\\\");
public void FormatLog(LogItem log)
if (IsEnableLogHead)
log.logHead = logHead;
log.fileName = logName;
log.fileExten = logNameExt;
log.mark = LogMark;
log.IsStableName = IsStableName;
foreach (String sK in dictLog.Keys)
int nIdx = 0;
if (dictLog.TryGetValue(sK, out nIdx))
if (sK.ToLower() == "time")
listLogLayout[nIdx] = log.time.ToString("HH:mm:ss,fff");
else if (sK.ToLower() == "exp" && log.e != null)
listLogLayout[nIdx] = log.e.StackTrace;
else if (sK.ToLower() == "thrname")
listLogLayout[nIdx] = log.thrName;
else if (sK.ToLower() == "thrid")
listLogLayout[nIdx] = log.thrID.ToString("D3");
else if (sK.ToLower() == "type")
listLogLayout[nIdx] = Enum.GetName(log.type.GetType(), log.type);
else if (sK.ToLower() == "msg")
listLogLayout[nIdx] = log.msg;
else if (sK.ToLower() == "mark")
listLogLayout[nIdx] = log.mark;
int nS = 0;
for (int i = 0; i < listLogLayout.Count; i++)
nS += listLogLayout[i].Length * 2;// 中文字符占两个长度
log.logBuf = new byte[nS];
log.logSize = 0;
for (int i = 0; i < listLogLayout.Count; i++)
byte[] tmp = Encoding.UTF8.GetBytes(listLogLayout[i]);
Array.Copy(tmp, 0, log.logBuf, log.logSize, tmp.Length);
log.logSize += tmp.Length;
foreach (int nIdx in dictPath.Keys)
String s = "";
if (dictPath.TryGetValue(nIdx, out s))
listPathLayout[nIdx] = log.time.ToString(s);
log.filePath = "";
for (int i = 0; i < listPathLayout.Count; i++)
log.filePath += listPathLayout[i];
public String GetLogName()
String s = GetFullPath();
int n = s.LastIndexOf("\\\\");
return s.Substring(n + 1, s.Length - n - 1);
public String GetLogPath()
foreach (int nIdx in dictPath.Keys)
String s = "";
DateTime time = DateTime.Now;
if (dictPath.TryGetValue(nIdx, out s))
listPathLayout[nIdx] = time.ToString(s);
String filePath = "";
for (int i = 0; i < listPathLayout.Count; i++)
filePath += pathLayout[i];
return filePath;
public String GetFullPath()
String basePath = GetLogPath();
if (IsStableName == true)
return basePath + logName + "." + logNameExt;
String[] files = Directory.GetFiles(basePath, logName + "#*", SearchOption.AllDirectories);
if (files.Length > 0)
List<String> listFiles = new List<String>(1000);
for (int i = 0; i < files.Length; i++)
listFiles.Add(files[i]);
listFiles.Sort(new CompareRisedTime());
return listFiles[listFiles.Count - 1];
return basePath + logName + "#" + (0).ToString("D3") + "." + logNameExt;
public class MFilter
String[] excludeMsg;
String[] includeMsg;
String[] excludeThr;
String[] includeThr;
String exMsg;
String inMsg;
String exThr;
String inThr;
bool[] isEnableLog = null;
public bool IsEnable = false;
public String ExMsg
get
return exMsg;
set
exMsg = value;
excludeMsg = exMsg.Split(',');
public String InMsg
get
return inMsg;
set
inMsg = value;
includeMsg = inMsg.Split(',');
public String ExThr
get
return exThr;
set
exThr = value;
excludeThr = exThr.Split(',');
public String InThr
get
return inThr;
set
inThr = value;
includeThr = inThr.Split(',');
public MFilter()
int len = System.Enum.GetNames((new MType()).GetType()).Length;
isEnableLog = new bool[len];
for (int i = 0; i < len; i++)
isEnableLog[i] = true;
public void EnableLog(MType type, bool bEnable)
isEnableLog[(int)type] = bEnable;
public void EnableAllLog(bool bEnable)
for (int i = 0; i < isEnableLog.Length; i++)
isEnableLog[i] = bEnable;
public bool IsEnableLog(MType type)
return isEnableLog[(int)type];
public bool Filt(LogItem log)
if (IsEnable == false) return true;
if (isEnableLog[(int)log.type] == false) return false;
if (excludeMsg != null && excludeMsg.Length > 0)
foreach (String str in excludeMsg)
if (log.msg.IndexOf(str) >= 0) return false;
if (excludeThr != null && excludeThr.Length > 0)
foreach (String str in excludeThr)
if (log.thrName.IndexOf(str) >= 0) return false;
if (includeMsg != null && includeMsg.Length > 0)
foreach (String str in includeMsg)
if (log.msg.IndexOf(str) >= 0) goto next1;
return false;
next1:
if (includeThr != null && includeThr.Length > 0)
foreach (String str in includeThr)
if (log.thrName.IndexOf(str) >= 0) goto next2;
return false;
next2:
return true;
public class MThr
public bool IsEnable = false;
public int ID
get
return Manager.GetCurThrID();
public string Name
get
return Manager.GetCurThrName();
set
Manager.SetCurThrName(value);
public static class Manager
static Dictionary<String, MLog> dictLog = new Dictionary<String, MLog>();
static Dictionary<String, MWriter> dictWrite = new Dictionary<String, MWriter>();
static Dictionary<int, String> dictThr = new Dictionary<int, String>();
static Object objLockLog = new object();
static Object objLockThr = new object();
public static int SetCurThrName(String name)
int id = GetCurThrID();
lock (objLockThr)
if (dictThr.ContainsKey(id))
dictThr.Remove(id);
dictThr.Add(id, name);
return id;
public static int GetCurThrID()
return AppDomain.GetCurrentThreadId();
public static String GetCurThrName()
String name = "";
lock (objLockThr)
int id = GetCurThrID();
if (!dictThr.TryGetValue(id, out name))
name = "";
return name;
public static void AddLog(String Name, MLog log, MWriter writer)
lock (objLockLog)
if (dictLog.ContainsKey(Name))
dictLog.Remove(Name);
if (dictWrite.ContainsKey(Name))
dictWrite.Remove(Name);
writer.Init(log);
dictLog.Add(Name, log);
dictWrite.Add(Name, writer);
public static void RemoveLog(String Name)
lock (objLockLog)
MLog log = null;
MWriter w = null;
if (dictLog.TryGetValue(Name, out log) && dictWrite.TryGetValue(Name, out w))
dictLog.Remove(Name);
dictWrite.Remove(Name);
log.filter.EnableAllLog(false);
log.filter.IsEnable = true;
w.bExit = true;
public static MLog GetLog(String Name)
MLog log = null;
lock (objLockLog)
if (dictLog.ContainsKey(Name))
dictLog.TryGetValue(Name, out log);
else
log = new MLog();
AddLog(Name, log, new MFileWriter());
return log;
public static MLog[] GetLogs()
lock (objLockLog)
return dictLog.Values.ToArray();
public static String[] GetNames()
lock (objLockLog)
return dictLog.Keys.ToArray();
public static MWriter GetWriter(String name)
lock (objLockLog)
MWriter w = null;
dictWrite.TryGetValue(name, out w);
return w;
public class MWriter
public bool bExit = false;
public virtual void Init(MLog microLog)
public virtual void OnWrite(LogItem log)
public virtual void Flush()
public class MFileWriter : MWriter
Thread thr;
List<String> listFiles;
LinkItem<LogItem> linkLog = new LinkItem<LogItem>();
int nameIdx = -1;
int nExtraSize = 1024 * 1024;
int maxLogSize = 1024 * 1024 * 10;
int maxLogCount = 20;
int logWriteTime = 100;
int logSize = 0;
byte[] buf = null;
bool bFlush = false;
object objLog = new object();
public int NExtraSize
get
return nExtraSize;
set
nExtraSize = value;
if (nExtraSize < 128)
nExtraSize = 128;
if (nExtraSize > 1024 * 1024)
nExtraSize = 1024 * 1024;
public int MaxLogSize
get
return maxLogSize;
set
maxLogSize = value;
if (maxLogSize < 1024 * 1024) maxLogSize = 1024 * 1024;
public int MaxLogCount
get
return maxLogCount;
set
maxLogCount = value;
if (maxLogCount < 1) maxLogCount = 1;
public int LogWriteTime
get
return logWriteTime;
set
logWriteTime = value;
if (logWriteTime < 10) logWriteTime = 10;
if (logWriteTime > 1000) logWriteTime = 1000;
public override void Init(MLog microLog)
buf = new byte[MaxLogSize + NExtraSize];
listFiles = new List<String>();
if (microLog == null)
return;
microLog.OnWrite += OnWrite;
thr = new Thread(FuncWriteLog);
thr.IsBackground = true;
thr.Start();
public override void OnWrite(LogItem log)
lock (objLog)
linkLog.AddEnd(log);
logSize += log.logSize;
public override void Flush()
bFlush = true;
void FuncWriteLog()
Stopwatch sw = new Stopwatch();
sw.Restart();
while (true)
Thread.Sleep(10);
if (sw.ElapsedMilliseconds < LogWriteTime && bFlush == false)
continue;
sw.Restart();
if (logSize <= 0)
if (bExit == true)
break;
else
continue;
LinkItem<LogItem> tmpLinkLog = null;
lock (objLog)
tmpLinkLog = linkLog;
linkLog = new LinkItem<LogItem>();
logSize = 0;
if (buf.Length != MaxLogSize + NExtraSize)
buf = new byte[MaxLogSize + NExtraSize];
SubItem<LogItem> itm = tmpLinkLog.FromFirst();
String basePath = itm.t.filePath;
String baseName = itm.t.fileName;
String baseNameExt = itm.t.fileExten;
if (Directory.Exists(basePath) == false)
Directory.CreateDirectory(basePath);
listFiles.Clear();
nameIdx = -1;
int remainSize = 0;
String name = CheckFile(basePath, baseName, baseNameExt, itm.t.IsStableName, ref remainSize);
int writedSize = 0;
while (itm != null)
if (itm.t.filePath == basePath)
if (remainSize == MaxLogSize && writedSize == 0 &&
itm.t.logHead != null
&& itm.t.logHead.Length > 0)
Array.Copy(itm.t.logHead, 0, buf, writedSize, itm.t.logHead.Length);
writedSize += itm.t.logHead.Length;
if (writedSize < remainSize
&& baseName == itm.t.fileName
&& baseNameExt == itm.t.fileExten)
Array.Copy(itm.t.logBuf, 0, buf, writedSize, itm.t.logSize);
writedSize += itm.t.logSize;
else
WriteLog(buf, writedSize, name);
basePath = itm.t.filePath;
baseName = itm.t.fileName;
baseNameExt = itm.t.fileExten;
name = CheckFile(basePath, baseName, baseNameExt, itm.t.IsStableName, ref remainSize);
writedSize = 0;
itm = itm.pPrev;
else
basePath = itm.t.filePath;
baseName = itm.t.fileName;
baseNameExt = itm.t.fileExten;
if (Directory.Exists(basePath) == false)
Directory.CreateDirectory(basePath);
listFiles.Clear();
nameIdx = -1;
WriteLog(buf, writedSize, name);
name = CheckFile(basePath, baseName, baseNameExt, itm.t.IsStableName, ref remainSize);
writedSize = 0;
itm = itm.pPrev;
if (itm != null)
itm = itm.pNext;
if (writedSize > 0)
WriteLog(buf, writedSize, name);
bFlush = false;
GC.Collect();
void WriteLog(byte[] buf, int size, String name)
using (FileStream fs = new FileStream(name, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
fs.Write(buf, 0, size);
fs.Close();
String CheckFile(String basePath, String baseName, String baseNameExt, bool bStableName, ref int remainSize)
String s = "";
int nFileSize = 0;
if (bStableName) // 如果是固定名字
s = basePath + baseName + "." + baseNameExt;
if (File.Exists(s))
nFileSize = (int)(new FileInfo(s)).Length;
remainSize = MaxLogSize - nFileSize;
if (remainSize < 0)
File.Delete(s);
remainSize = MaxLogSize;
return s;
String[] files = Directory.GetFiles(basePath, baseName + "#*", SearchOption.AllDirectories);
if (listFiles.Count == 0 && files.Length > 0)
for (int i = 0; i < files.Length; i++)
listFiles.Add(files[i]);
listFiles.Sort(new CompareRisedTime());
while (listFiles.Count > MaxLogCount)
File.Delete(listFiles[0]);
listFiles.RemoveAt(0);
if (listFiles.Count > 0)
s = listFiles[listFiles.Count - 1];
if (nameIdx < 0)
int n = s.LastIndexOf("#");
String sub = s.Substring(n + 1, 3);
nameIdx = int.Parse(sub);
nFileSize = 0;
if (File.Exists(s))
int n1 = s.LastIndexOf("\\\\");
int n2 = s.LastIndexOf("#");
String sub = s.Substring(n1 + 1, n2 - n1 - 1);
if (sub != baseName)
nameIdx = 0;
s = basePath + baseName + "#" + nameIdx.ToString("D3") + "." + baseNameExt;
listFiles.Clear();
listFiles.Add(s);
nFileSize = 0;
else
nFileSize = (int)(new FileInfo(s)).Length;
else
nameIdx++;
s = basePath + baseName + "#" + nameIdx.ToString("D3") + "." + baseNameExt;
remainSize = MaxLogSize - nFileSize;
if (remainSize <= 0)
nameIdx++;
s = basePath + baseName + "#" + nameIdx.ToString("D3") + "." + baseNameExt;
listFiles.Add(s);
remainSize = MaxLogSize;
return s;
public class MDebugWriter : MWriter
public override void Init(MLog microLog)
if (microLog == null)
return;
microLog.OnWrite += OnWrite;
public override void OnWrite(LogItem log)
if (bExit == true)
return;
if (log.mark.Length > 0)
System.Diagnostics.Debug.Write(Encoding.UTF8.GetString(log.logBuf, 0, log.logSize), log.mark);
else
System.Diagnostics.Debug.Write(Encoding.UTF8.GetString(log.logBuf, 0, log.logSize));
public override void Flush()
System.Diagnostics.Debug.Flush();
public class MTraceWriter : MWriter
public override void Init(MLog microLog)
if (microLog == null)
return;
microLog.OnWrite += OnWrite;
public override void OnWrite(LogItem log)
if (bExit == true)
return;
if (log.mark.Length > 0)
System.Diagnostics.Trace.Write(Encoding.UTF8.GetString(log.logBuf, 0, log.logSize), log.mark);
else
System.Diagnostics.Trace.Write(Encoding.UTF8.GetString(log.logBuf, 0, log.logSize));
public override void Flush()
System.Diagnostics.Trace.Flush();
public class MConsoleWriter : MWriter
public override void Init(MLog microLog)
if (microLog == null)
return;
microLog.OnWrite += OnWrite;
public override void OnWrite(LogItem log)
if (bExit == true)
return;
Console.Write(Encoding.UTF8.GetString(log.logBuf, 0, log.logSize));
public override void Flush()
public class SubItem<T>
public T t;
public SubItem<T> pPrev;
public SubItem<T> pNext;
public SubItem(T tVal, SubItem<T> pPrev_, SubItem<T> pNext_)
t = tVal;
pPrev = pPrev_;
pNext = pNext_;
public class LinkItem<T>
SubItem<T> pZero = null;
SubItem<T> pEnd = null;
int nCount = 0;
object obj = new object();
public SubItem<T> FromFirst()
return pZero;
public void AddAt(T t_, int nPos)
if (nPos < 0 || nPos > nCount)
throw new ArgumentException("插入的位置不合适 nPos=" + nPos + " ,COunt=" + nCount);
lock (obj)
if (nPos == 0)
pZero.pPrev = new SubItem<T>(t_, null, pZero);
pZero = pZero.pPrev;
else if (nPos == nCount)
pEnd.pNext = new SubItem<T>(t_, pEnd, null); ;
pEnd = pEnd.pNext;
else
SubItem<T> pSel = pZero;
for (int i = 0; i < nCount; i++)
if (i == nPos)
pSel.pPrev.pNext = new SubItem<T>(t_, pSel.pPrev, pSel);
pSel.pPrev.pNext.pNext.pPrev = pSel.pPrev.pNext;
break;
pSel = pSel.pNext;
nCount++;
public void AddEnd(T t_)
lock (obj)
if (pEnd == null)
pEnd = new SubItem<T>(t_, null, null);
pZero = pEnd;
else if (nCount == 1)
pEnd = new SubItem<T>(t_, pZero, null);
pZero.pNext = pEnd;
else
pEnd.pNext = new SubItem<T>(t_, pEnd, null); ;
pEnd = pEnd.pNext;
//pNow.pNext = null;
nCount++;
public void AddFirst(T t_)
lock (obj)
if (pZero == null)
pZero = new SubItem<T>(t_, null, null);
pEnd = pZero;
else
pZero.pPrev = new SubItem<T>(t_, null, pZero);
pZero = pZero.pPrev;
//pZero.pPrev = null;
nCount++;
public T RemoveAt(int nPos)
if (nPos < 0 || nPos >= nCount)
throw new ArgumentException("输入参数超限 idx=" + nPos + " ,Count=" + nCount);
lock (obj)
SubItem<T> pSel = pZero;
for (int i = 0; i < nCount; i++)
if (i == nPos)
if (pSel.pPrev != null)
if (i == nCount - 1)
pEnd = pEnd.pPrev;
pSel.pPrev.pNext = pSel.pNext;
if (pSel.pNext != null)
if (i == 0)
pZero = pZero.pNext;
pSel.pNext.pPrev = pSel.pPrev;
nCount--;
if (nCount == 0) Clear();
break;
pSel = pSel.pNext;
return pSel.t;
public T RemoveEnd()
if (nCount == 0)
throw new ArgumentException("List容量为0,无法移除");
lock (obj)
T t_ = pEnd.t;
if (pEnd.pPrev != null)
pEnd = pEnd.pPrev;
pEnd.pNext = null;
nCount--;
else
Clear();
return t_;
public T RemoveFirst()
if (nCount == 0)
throw new ArgumentException("List容量为0,无法移除");
lock (obj)
T t_ = pZero.t;
if (pZero.pNext != null)
pZero = pZero.pNext;
pZero.pPrev = null;
nCount--;
else
Clear();
return t_;
public T ViewFirst()
if (nCount < 1)
throw new ArgumentException("数量为0 nCount=" + nCount);
return pZero.t;
public T ViewAt(int nPos)
if (nPos < 0 || nPos >= nCount)
throw new ArgumentException("输入参数超限 idx=" + nPos + " ,Count=" + nCount);
lock (obj)
SubItem<T> pSel = pZero;
for (int i = 0; i < nCount; i++)
if (i == nPos)
break;
pSel = pSel.pNext;
return pSel.t;
public T ViewEnd()
if (nCount < 1)
throw new ArgumentException("数量为0 nCount=" + nCount);
return pEnd.t;
// 十分耗费资源
public T this[int index]
get
lock (obj)
if (index < 0 || index >= nCount)
throw new ArgumentException("输入参数超限 idx=" + index + " ,Count=" + nCount);
SubItem<T> pSel = pZero;
T tRtn = pSel.t;
for (int i = 0; i < nCount; i++)
if (i == index)
tRtn = pSel.t;
break;
pSel = pSel.pNext;
return tRtn;
set
lock (obj)
if (index < 0 || index >= nCount)
throw new ArgumentException("输入参数超限 idx=" + index + " ,Count=" + nCount);
SubItem<T> pSel = pZero;
for (int i = 0; i < nCount; i++)
if (i == index)
pSel.t = value;
break;
pSel = pSel.pNext;
public SubItem<T> Clear()
SubItem<T> itm = null;
lock (obj)
itm = pZero;
pZero = null;
pEnd = null;
nCount = 0;
return itm;
public int Count()
return nCount;
public T[] GetElements()
if (Count() == 0)
return null;
T[] tt = null;
lock (obj)
tt = new T[Count()];
for (int i = 0; i < Count(); i++)
tt[i] = this[i];
return tt;
public enum MType
mType1 = 0,
mType2,
mType3,
mType4
class CompareRisedTime : IComparer<String>
public int Compare(String a, String b)
FileInfo f1 = new FileInfo(a);
FileInfo f2 = new FileInfo(b);
if (f1.CreationTime > f2.CreationTime) return 1;
if (f1.CreationTime < f2.CreationTime) return -1;
return 0;
调用
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MicroLog
public partial class Form1 : Form
public Form1()
InitializeComponent();
private void Form1_Load(object sender, EventArgs e)
MLog log1 = new MLog();
log1.convert.LogHead = "[Time] [Mark] -ThrID:ThrName- [Type] Msg"; // 每个日志文件第一行都会输出
log1.convert.LogName = "firstTest.log";
log1.convert.PathLayout = "D:\\\\MLog\\\\Log1_yyy.MM.dd";
log1.convert.LogLayout = "[time] [mark] -thrid:thrname- [type] msg";
log1.convert.LogMark = "mark1";
log1.convert.IsEnableLogHead = true;
log1.convert.IsStableName = false; // 是否固定文件名,固定:只有一个文件,达到最大文件大小后悔删除源文件
log1.thr.IsEnable = true;
log1.thr.Name = "main";
//log.filter.SetExcludeLog("first");
//log.filter.EnableLog(LogType.Debug, false);
MLog log2 = new MLog();
log2.convert.LogName = "secondTest.log";
log2.convert.PathLayout = "D:\\\\MLog\\\\Log2_yyy.MM.dd";
log2.convert.LogLayout = "[time] [mark] -thrid:thrname- [type] msg";
log2.convert.LogMark = "mark2";
log2.thr.IsEnable = false;
log2.thr.Name = "222";
log2.filter.IsEnable = true;
//log2.filter.ExThr = "2";
log2.filter.ExMsg = "10";
//log2.filter.EnableLog(MType.mType1, false);
//log1.transTo = log2;
MConsoleWriter w1 = new MConsoleWriter();
MDebugWriter w2 = new MDebugWriter();
Manager.AddLog("log1", log1,w1);
Manager.AddLog("log2", log2,w2);
private void button1_Click(object sender, EventArgs e)
Stopwatch sw = new Stopwatch();
MLog log = Manager.GetLog("log1");
sw.Restart();
for (int i = 0; i < 1000000; i++)
log.Write("firstLog 打两块就到啦世纪东方啦收到啦就是到了看静安寺多放辣椒撒冷的发几款 " + i.ToString("D10"));
long l = sw.ElapsedMilliseconds;
double n1 = l / 1000.0;
double n2 = l / 100.0;
MessageBox.Show("TotlaTime=" + n1.ToString() + " s\\n Ave 10000 Item = " + n2.ToString("F2") + " ms");
private void button2_Click(object sender, EventArgs e)
MLog log1 = Manager.GetLog("log1");
MLog log2 = Manager.GetLog("log2");
log1.transTo.Add(log2); // log1 的日志会流转给 log2
log1.Write("firstLog 打两块就到啦世纪东方啦收到啦就是到了看静安寺多放辣椒撒冷的发几款 10");
log1.Write("firstLog 打两块就到啦世纪东方啦收到啦就是到了看静安寺多放辣椒撒冷的发几款 11");
log1.transTo.Remove(log2);
以上是关于C#日志记录工具 MicroLog的主要内容,如果未能解决你的问题,请参考以下文章