C#日志记录工具 MicroLog

Posted Thomas会写字

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#日志记录工具 MicroLog相关的知识,希望对你有一定的参考价值。

一个简单的日志记录工具,性能高效,常用功能都有,结构简单。 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;
using System.IO;

namespace MicroLog

    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 LinkItem<LogItem> linkLog = new LinkItem<LogItem>();
        public int logSize = 0;
        public object objLog = new object();

        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);

            // addLink
            lock (objLog)
            
                linkLog.AddEnd(log);
                logSize += log.logSize;
            
        
    
    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 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 = true;
        public bool IsStableName = false;

        byte[] logHead = null;
        String logName = "";
        String logNameExt = "";
        String logMark = "";
        String logLayout = "";
        String pathLayout = "";
        List<String> listLogLayout = new List<String>();
        List<String> listPathLayout = new List<String>();
        Dictionary<String, int> dictLog;
        Dictionary<int, String> dictPath;

        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 => logLayout;
            set
            
                logLayout = value;
                String format = value;
                int n1 = format.IndexOf("");
                int n2 = format.IndexOf("");
                dictLog = new Dictionary<string, int>();
                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>();
                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;

            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();
        static int maxLogSize = 1024 * 1024 * 10;
        static int maxLogCount = 20;
        static int logWriteTime = 100;

        public static int MaxLogSize
        
            get
            
                return maxLogSize;
            
            set
            
                maxLogSize = value;
                if (maxLogSize < 1024 * 1024) maxLogSize = 1024 * 1024;
            
        
        public static int MaxLogCount
        
            get
            
                return maxLogCount;
            
            set
            
                maxLogCount = value;
                if (maxLogCount < 1) maxLogCount = 1;
            
        
        public static int LogWriteTime
        
            get
            
                return logWriteTime;
            
            set
            
                logWriteTime = value;
                if (logWriteTime < 10) logWriteTime = 10;
                if (logWriteTime > 1000) logWriteTime = 1000;
            
        


        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)
        
            lock (objLockLog)
            
                if (dictLog.ContainsKey(Name))
                    dictLog.Remove(Name);
                if (dictWrite.ContainsKey(Name))
                    dictWrite.Remove(Name);
                MWriter w = new MWriter(log);
                dictLog.Add(Name, log);
                dictWrite.Add(Name, w);
            
        
        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);
                    log.filter.IsEnable = true;
                    log.filter.EnableAllLog(false);
                    w.bExit = true;
                
            
        
        public static MLog GetLog(String Name)
        
            MLog log = null;
            lock (objLockLog)
            
                if (dictLog.ContainsKey(Name))
                    dictLog.TryGetValue(Name, out log);
            
            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
    
        MLog microLog;
        Thread thr;
        List<String> listFiles;
        int nameIdx = -1;
        public bool bFlush = false;
        public bool bExit = false;
        byte[] buf = null;
        int nExtraSize = 1024 * 1024;
        object objCF = new object();
        public MWriter(MLog microLog)
        
            buf = new byte[Manager.MaxLogSize + nExtraSize];
            this.microLog = microLog;
            listFiles = new List<String>();
            thr = new Thread(FuncWriteLog);
            thr.IsBackground = true;
            thr.Start();
        
        void FuncWriteLog()
        
            Stopwatch sw = new Stopwatch();
            sw.Restart();
            while (bExit == false)
            
                Thread.Sleep(10);
                if (sw.ElapsedMilliseconds < Manager.LogWriteTime && bFlush == false)
                    continue;

                if (buf.Length != Manager.MaxLogSize + nExtraSize)
                    buf = new byte[Manager.MaxLogSize + nExtraSize];
                LinkItem<LogItem> linkLog = null;
                lock (microLog.objLog)
                
                    if (microLog.logSize > 0)
                    
                        linkLog = microLog.linkLog;
                        microLog.linkLog = new LinkItem<LogItem>();
                        microLog.logSize = 0;
                    
                
                if (linkLog == null || linkLog.Count() == 0)
                    continue;

                SubItem<LogItem> itm = linkLog.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, microLog.convert.IsStableName, ref remainSize);
                int writedSize = 0;

                while (itm != null)
                
                    if (itm.t.filePath == basePath)
                    
                        if (remainSize == Manager.MaxLogSize && writedSize == 0 &&
                           microLog.convert.IsEnableLogHead == true && 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, microLog.convert.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, microLog.convert.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();
            
        
        void Flush()
        
            bFlush = true;
        
        String CheckFile(String basePath, String baseName, String baseNameExt, bool bStableName, ref int remainSize)
        
            lock (objCF)
            
                String s = "";
                int nFileSize = 0;
                if (bStableName)   // 如果是固定名字
                
                    s = basePath + baseName + "." + baseNameExt;
                    if (File.Exists(s))
                        nFileSize = (int)(new FileInfo(s)).Length;
                    remainSize = Manager.MaxLogSize - nFileSize;
                    if (remainSize < 0)
                    
                        File.Delete(s);
                        remainSize = Manager.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 > Manager.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 = Manager.MaxLogSize - nFileSize;
                if (remainSize <= 0)
                
                    nameIdx++;
                    s = basePath + baseName + "#" + nameIdx.ToString("D3") + "." + baseNameExt;
                    listFiles.Add(s);
                    remainSize = Manager.MaxLogSize;
                
                return s;
            
        
    
    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 void Clear()
        
            lock (obj)
            
                pZero = null;
                pEnd = null;
                nCount = 0;
            
        
        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";

            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);

            Manager.AddLog("log1", log1);
            Manager.AddLog("log2", log2);
            Manager.MaxLogCount = 100;
            Manager.MaxLogSize = 1024 * 1024 * 10;
        

        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的主要内容,如果未能解决你的问题,请参考以下文章

C#日志记录工具 MicroLog

microlog4android如何将Android Log日志写到SD

c#中使用log4net工具记录日志

C# 使用ILogger接口编写日志

C# - NLog 为同一个调用记录多行

C# 如何设计一个好用的日志库?架构篇