C# 写日志,高性能批量处理 -- Logger

当然了,可以使用:log4net 库;

但目前该功能需求不需要用到这么强大的日志管理;直接写文件记录;所以就写了一个简单的;


这是半成品,还可以用,还有地方可以优化;

但再优化前,可读性比较好,我就上传了:


using System;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Threading;
using System.Runtime.InteropServices;


namespace Testing
{
    public delegate bool ConsoleCtrlDelegate(int dwCtrlType);


    /// <summary>  
    /// @author Jave.Lin  
    /// @date 2013-12-11  
    /// </summary>  
    public partial class Logger
    {
        [DllImport("kernel32.dll")]
        private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate handlerRoutine, bool add);


        private const int CtrlCEvent = 0;//CTRL_C_EVENT = 0;//一个Ctrl+C的信号被接收,该信号或来自键盘,或来自GenerateConsoleCtrlEvent    函数   


        private const int CtrlBreakEvent = 1;//CTRL_BREAK_EVENT = 1;//一个Ctrl+Break信号被接收,该信号或来自键盘,或来自GenerateConsoleCtrlEvent    函数  


        private const int CtrlCloseEvent = 2;//CTRL_CLOSE_EVENT = 2;//当用户系统关闭Console时,系统会发送此信号到此   


        private const int CtrlLogoffEvent = 5;//CTRL_LOGOFF_EVENT = 5;//当用户退出系统时系统会发送这个信号给所有的Console程序。该信号不能显示是哪个用户退出。   


        private const int CtrlShutdownEvent = 6;//CTRL_SHUTDOWN_EVENT = 6;//当系统将要关闭时会发送此信号到所有Console程序   


        public static readonly object Locker = new object();
        private static StreamWriter WRITER;


        // TODO : caches 可改用 StringBuilder 来优化
        private static string ContinueWriteCaches;
        private static readonly Stopwatch Continue_WriteSw;
        private static int ContinueTime = 300; // 300毫秒以后,连续写操作,都统一到一块操作  
        private static int ContinueCountMax = 100; // 当连续写操作次数上限到指定的数值后,都写一次操作,之后的重新再计算  
        private static int ContinueCount = 0;
        private static string LoggerFileName;


        public static int AllWriteCount = 0;


        static Logger()
        {
            var nowDateTime = DateTime.Now;
            var dateTimeStr =
                nowDateTime.Year + "_" +
                nowDateTime.Month + "_" +
                nowDateTime.Day + "_" +
                nowDateTime.Hour + "_" +
                nowDateTime.Minute + "_" +
                nowDateTime.Second + "_" +
                nowDateTime.Millisecond;
            LoggerFileName = "Log/Logs_" + dateTimeStr + ".txt";
            Continue_WriteSw = new Stopwatch();


            if (SetConsoleCtrlHandler(new ConsoleCtrlDelegate(HandlerRoutine), true))
            {
                Info("Set SetConsoleCtrlHandler success.");
            }
            else
            {
                Error("Set SetConsoleCtrlHandler Error.");
            }
        }


        private static bool HandlerRoutine(int ctrlType)
        {
            switch (ctrlType)
            {
                // src:
                //case CtrlCEvent: System.Console.WriteLine("Ctrl+C keydown"); break;


                //case CtrlBreakEvent: System.Console.WriteLine("Ctrl+Break keydown"); break;


                //case CtrlCloseEvent: System.Console.WriteLine("window closed"); break;


                //case CtrlLogoffEvent: System.Console.WriteLine("log off or shut down"); break;


                //case CtrlShutdownEvent: System.Console.WriteLine("system shut down"); break;


                //default: System.Console.WriteLine(ctrlType.ToString()); break;


                // new:
                //case CtrlCEvent: System.Console.WriteLine("Ctrl+C keydown"); break;
                //case CtrlBreakEvent: System.Console.WriteLine("Ctrl+Break keydown"); break;
                case CtrlCloseEvent:
                    _WriteBuffer();
                    break;
                //case CtrlLogoffEvent: System.Console.WriteLine("log off or shut down"); break;
                //case CtrlShutdownEvent: System.Console.WriteLine("system shut down"); break;
                default: System.Console.WriteLine(ctrlType.ToString()); break;
            }
            return false;
        }


        private static void Write(string msg)
        {
            if (string.IsNullOrEmpty(msg))
            {
                return;
            }


            lock (Locker)
            {
                if (ContinueWriteCaches == null) ContinueWriteCaches = msg + "\r\n";
                else ContinueWriteCaches += msg + "\r\n";


                if (Continue_WriteSw.IsRunning)
                {
                    if (Continue_WriteSw.ElapsedMilliseconds > ContinueTime)
                    {
                        _WriteBuffer();
                        return;
                    }
                }


                ++ContinueCount;
                if (ContinueCount > ContinueCountMax)
                {
                    _WriteBuffer();
                    return;
                }


                if (!Continue_WriteSw.IsRunning)
                {
                    Continue_WriteSw.Start();
                }
            }
        }


        private static void _WriteBuffer()
        {
            if (ContinueWriteCaches != null)
            {
                if (!File.Exists(LoggerFileName))
                {
                    var dir = Directory.GetParent(LoggerFileName).FullName;
                    if (!Directory.Exists(dir))
                    {
                        Directory.CreateDirectory(dir);
                    }
                }


                WRITER = new StreamWriter(LoggerFileName, true, Encoding.UTF8);
                WRITER.WriteLine(ContinueWriteCaches);
                WRITER.Flush();
                WRITER.Close();
            }
            Continue_WriteSw.Stop();
            Continue_WriteSw.Reset();
            ContinueWriteCaches = null;
            ContinueCount = 0;


            Interlocked.Increment(ref AllWriteCount);
        }
    }
    public partial class Logger
    {
        public static ConsoleColor S_InfoColor = ConsoleColor.White;
        public static ConsoleColor S_DebugColor = ConsoleColor.Green;
        public static ConsoleColor S_WarningColor = ConsoleColor.Yellow;
        public static ConsoleColor S_ErrorColor = ConsoleColor.Red;


        private static object _s_pLocker = new object();
        // alwasy log
        public static void Info(string msg, params object[] ps)
        {
            if (ps != null && ps.Length > 0 )
            {
                msg = string.Format(msg, ps);
            }
            _Write(S_InfoColor, "[Info]" + msg);
        }
        // remove log when debug complete.
        public static void Debug(string msg, params object[] ps)
        {
            if (ps != null && ps.Length > 0)
            {
                msg = string.Format(msg, ps);
            }
            _Write(S_DebugColor, "[Debug]" + msg);
        }
        // remove log when bug fixed.
        public static void Warning(string msg, params object[] ps)
        {
            if (ps != null && ps.Length > 0)
            {
                msg = string.Format(msg, ps);
            }
            _Write(S_WarningColor, "[Warning]" + msg);
        }
        // remove log when error fixed.
        public static void Error(string msg, params object[] ps)
        {
            if (ps != null && ps.Length > 0)
            {
                msg = string.Format(msg, ps);
            }
            _Write(S_ErrorColor, "[Error]" + msg);
        }


        private static void _Write(ConsoleColor color, string msg)
        {
            lock (_s_pLocker)
            {
                msg = DateTime.Now.ToString() + " " + msg;
                var srcColor = Console.ForegroundColor;
                Console.ForegroundColor = color;
                Console.WriteLine(msg);
                Console.ForegroundColor = srcColor;
                Write(msg);
            }
        }
    }
}



测试调用:

            for (int i = 0; i < 300; i++)
            {
                Logger.Debug("testsadfasdfasdf" + i);
            }

            Logger.Debug("Write Count : " + Logger.AllWriteCount); // 总调用IO写的次数为:2次。。。但写的内容次数就超过300


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值