asp.net c# 異步日誌通用類(4)

在之前的日誌調用中用到了委託實現,現在把委託去掉,效率又有一定的提高了,說的不好聽從高大上(委託)到原始的調用,代碼如下:

/*********************************************
 * CLR 版本:       4.0.30319.42000
 * 類 名 稱:       Logger
 * 機器名稱:       MS-20170310FLQY
 * 命名空間:       Utils
 * 文 件 名:       Logger
 * 創建時間:       2017/5/12 10:16:17
 * 作    者:       Choj
 * 說    明:     
 * 修改時間:
 * 修 改 人:
 * 
*********************************************/

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Utils
{
    /// <summary>
    /// 異步日誌實現類
    /// </summary>
    public class Logger
    {
        #region 屬性
        /// <summary>
        /// 實例化
        /// </summary>
        public static Logger Instance = new Logger();
        /// <summary>
        /// 日誌保存的路徑
        /// </summary>
        string LogPath = ConfigurationManager.AppSettings["LogPath"];
        /// <summary>
        /// 文件夾路徑
        /// </summary>
        string LogDir = ConfigurationManager.AppSettings["LogDir"];
        /// <summary>
        /// 文件夾路徑
        /// </summary>
        string LogDateFormat = ConfigurationManager.AppSettings["LogDateFormat"] ?? "yyyyMMddHH";
        #endregion

        #region 構造函數
        /// <summary>
        /// 默認構造函數
        /// </summary>
        public Logger()
        { }

        /// <summary>
        /// 夠着函數
        /// </summary>
        /// <param name="LogDir">日誌的文件夾</param>
        public Logger(string LogDir)
        {
            this.LogDir = LogDir;
        }

        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="path"></param>
        /// <param name="LogDir"></param>
        public Logger(string path, string LogDir)
        {
            this.LogPath = path;
            this.LogDir = LogDir;
        }

        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="path">路徑</param>
        /// <param name="LogDir">日誌路徑</param>
        /// <param name="logDateFormat">文件格式</param>
        public Logger(string path, string logDir, string logDateFormat)
        {
            this.LogPath = path;
            this.LogDir = logDir;
            this.LogDateFormat = logDateFormat;
        }
        #endregion

        #region 錯誤日誌記錄
        /// <summary>
        /// 添加錯誤日誌
        /// </summary>
        /// <param name="ex">錯誤的信息</param>
        /// <param name="parms">其他的參數</param>
        public void Error(Exception ex, params object[] parms)
        {
            var strMsg = new StringBuilder();
            strMsg.AppendFormat("\r\n");
            strMsg.AppendFormat("Message:{0}", ex.Message);
            strMsg.AppendFormat("\r\n");
            strMsg.AppendFormat("StackTrace:{0}", ex.StackTrace);
            strMsg.AppendFormat("\r\n");
            strMsg.AppendFormat("source:{0}", ex.Source);
            strMsg.AppendFormat("\r\n");
            strMsg.AppendFormat("InnerException:{0}", ex.InnerException);
            strMsg.AppendFormat("\r\n");

            AddQueue(strMsg.ToString(), "Error", parms);
        }

        /// <summary>
        /// 調試日誌
        /// </summary>
        /// <param name="msg">信息</param>
        /// <param name="parms">其他的參數</param>
        public void Debug(string msg, params object[] parms)
        {
            AddQueue(msg, "Debug", parms);
        }

        /// <summary>
        /// 調試日誌
        /// </summary>
        /// <param name="msg">信息</param>
        /// <param name="parms">其他的參數</param>
        public void Info(string msg, params object[] parms)
        {
            AddQueue(msg, "Info", parms);
        }

        /// <summary>
        /// 警告
        /// </summary>
        /// <param name="msg">信息</param>
        /// <param name="parms">其他的參數</param>
        public void Warn(string msg, params object[] parms)
        {
            AddQueue(msg, "Warn", parms);
        }

        /// <summary>
        /// 錯誤
        /// </summary>
        /// <param name="msg">信息</param>
        /// <param name="parms">其他的參數</param>
        public void Error(string msg, params object[] parms)
        {
            AddQueue(msg, "Error", parms);
        }

        /// <summary>
        /// 致命錯誤
        /// </summary>
        /// <param name="msg">信息</param>
        /// <param name="parms">其他的參數</param>
        public void Fatal(string msg, params object[] parms)
        {
            AddQueue(msg, "Fatal", parms);
        }
        #endregion

        #region 添加日誌到隊列
        /// <summary>
        /// 添加日誌到隊列
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="level"></param>
        /// <param name="parms"></param>
        private void AddQueue(string msg, string level, params object[] parms)
        {
            QueueHelper<LogEntity>.Instance.Enqueue(new LogEntity()
            {
                Level = level,
                Msg = msg,
                Parms = parms
            });
        }
        #endregion

        #region 保存日誌信息
        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {
            ThreadPool.QueueUserWorkItem(o =>
            {
                while (true)
                {
                    var queue = QueueHelper<LogEntity>.Instance.Dequeue();

                    if (queue != null)
                    {
                        #region 基本的設置
                        var fileName = System.DateTime.Now.ToString(LogDateFormat) + ".log";
                        string path = LogPath;
                        if (string.IsNullOrEmpty(path))
                        {
                            path = System.AppDomain.CurrentDomain.BaseDirectory;
                        }
                        path = string.Format("{0}\\Log\\{1}\\{2}\\", path, queue.Level, LogDir);

                        while (path.Contains(@"\\"))
                        {
                            path = path.Replace(@"\\", @"\");
                        }
                        if (!Directory.Exists(path))
                        {
                            Directory.CreateDirectory(path);
                        }
                        string filePath = path + fileName;
                        #endregion

                        using (var sw = new StreamWriter(filePath, true))
                        {
                            var strMsg = new StringBuilder();
                            strMsg.AppendFormat(DateTime.Now.ToString());
                            strMsg.Append("\r\n");
                            strMsg.AppendFormat("{0}", queue.Msg);
                            if (queue.Parms != null)
                            {//--- 其他的參數 ---
                                foreach (var parm in queue.Parms)
                                {
                                    strMsg.Append("\r\n");
                                    strMsg.Append(parm);
                                }
                            }
                            strMsg.Append("\r\n");

                            sw.WriteLine(strMsg.ToString());
                        }
                    }
                }
            });
        }
        #endregion
    }
    /// <summary>
    /// 保存日誌
    /// </summary>
    public class LogEntity
    {
        private string msg;
        /// <summary>
        /// 日誌基本信息
        /// </summary>
        public string Msg
        {
            get { return msg; }
            set { msg = value; }
        }
        private string level;
        /// <summary>
        /// 日誌等級
        /// </summary>
        public string Level
        {
            get { return level; }
            set { level = value; }
        }
        private object[] parms;
        /// <summary>
        /// 其他的參數
        /// </summary>
        public object[] Parms
        {
            get { return parms; }
            set { parms = value; }
        }
    }
}

測試代碼:

Utils.Logger.Instance.Init();

            var sw = new Stopwatch();
            sw.Start();

            for (int i = 0; i < 10000; i++)
            {
                Utils.Logger.Instance.Debug("Logger測試");
            }

            sw.Stop();
            Console.WriteLine("Logger 日誌循環10000次,總耗時:" + sw.ElapsedMilliseconds);

            sw = new Stopwatch();
            sw.Start();

            Parallel.For(0, 100, (i) =>
            {
                for (int j = 0; j < 100; j++)
                {
                    Utils.Logger.Instance.Debug("Logger測試");
                }
            });

            sw.Stop();
            Console.WriteLine("Logger 並行循環10000次,總耗時:" + sw.ElapsedMilliseconds);

            Console.ReadKey();

這個效率感覺應該還是可以了,但是優化的還有很多,但是思想基本就是這樣了,日誌的保存根據自己的需要可以自己添加對應的功能,比如保存到mongodb(nosql),或者關係數據庫中


1000000的數據測試的代碼和結果:

Utils.Logger.Instance.Init();

            var sw = new Stopwatch();
            sw.Start();

            for (int i = 0; i < 1000000; i++)
            {
                Utils.Logger.Instance.Debug("Logger測試");
            }

            sw.Stop();
            Console.WriteLine("Logger 日誌循環1000000次,總耗時:" + sw.ElapsedMilliseconds);

            sw = new Stopwatch();
            sw.Start();

            Parallel.For(0, 100, (i) =>
            {
                for (int j = 0; j < 10000; j++)
                {
                    Utils.Logger.Instance.Debug("Logger測試");
                }
            });

            sw.Stop();
            Console.WriteLine("Logger 並行循環1000000次,總耗時:" + sw.ElapsedMilliseconds);

            Console.ReadKey();


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章