利用队列和定时器构造的一种日志记录模型实现

来源:互联网 发布:淘宝买家钻石等级 编辑:程序博客网 时间:2024/06/16 12:20

    软件系统在运行过程中,会产生大量的运行时中间数据,中间数据是整个数据流向和异常后的回溯,一个好的日志记录系统,能记录下整个软件运行周期内的所有相关中间数据流。

   日志记录系统首先要保证的是与软件的正常运行无关性,他不会随着软件异常的抛出,而崩溃或阻塞正常的系统运行,日志系统还要高效性,不能因为记录日志影响系统的整体资源调度。

    此模型的设计思路是,异常消息记录队列+周期性处理定时器+消息关闭回调消息中心,所有的日志,统一先压入异常消息记录队列,周期性处理定时器触发后,负责将消息队列整体锁定,更换队列的处理引用地址,在定时器处理线程栈上,进行数据的写入处理,因为是通过定时器周期性的写入数据到存储介质,在软件关闭时刻可能存在还未写入存储介质的数据,因此需要消息中心的回调处理,进行数据的收尾保存。

   此模型的设计,简单易于实现,但是也存在很大的弊端是,在高并发场合的写入会存在很高的锁争用。定时器控制写入到存储介质,吞吐和效率不好调整。如果存在日志保存到比较慢速的介质中,缓存不够。

 /// <summary>    ///SQL操作日志记录服务    /// </summary>    internal static class SQLLogService    {        /// <summary>        /// 线程互斥锁        /// </summary>        private static object syncObj = new object();        /// <summary>        /// 写入锁        /// </summary>        private static object writeLock = new object();        /// <summary>        /// 日志记录消息队列        /// </summary>        private static Queue<SQLLogMessage> logMessageQueue = new Queue<SQLLogMessage>();        /// <summary>        /// 处理定时器        /// </summary>        private static System.Timers.Timer timer = null;        /// <summary>        /// 消息中心停止通知        /// </summary>        private static MessageCenterStopCallBack stopCallBack = null;        /// <summary>        /// 启动日志记录服务        /// </summary>        public static void Start()        {            if (timer == null)            {                timer = new System.Timers.Timer();                timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);                timer.Interval = SQLLogFactory.Config.LogPeriod;//日志保存周期,三分钟                timer.Start();                if (stopCallBack == null)                {                    stopCallBack = new MessageCenterStopCallBack(stopNotify);                    MessageCenterManage.Register(typeof(SQLLogService).FullName, stopCallBack);                }            }        }        /// <summary>        /// 回调处理函数        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)        {            List<SQLLogMessage> tempList = null;            lock (syncObj)            {                try                {                    Int32 count = logMessageQueue.Count;                    if (count > 0)                    {                        tempList = new List<SQLLogMessage>();                        for (int i = 0; i < count; i++)                        {                            tempList.Add(logMessageQueue.Dequeue());                        }                    }                }                catch                {                                 }            }            if (tempList != null && tempList.Count > 0)            {                lock (writeLock)                {                    try                    {                        Dictionary<string, StreamWriter> dic = new Dictionary<string, StreamWriter>();                        string filePath = string.Format("{0}\\SQLLog\\{1}\\",SQLLogFactory.Config.LogPath, DateTime.Now.ToString("yyyyMMdd"));                        if (!Directory.Exists(filePath))                        {                            Directory.CreateDirectory(filePath);                        }                        //开始记录日志数据                        for (int i = 0; i < tempList.Count; i++)                        {                            SQLLogMessage logMessage = tempList[i];                            string fileFullName = string.Format("{0}{1}", filePath, logMessage.FileName);                            if (dic.ContainsKey(fileFullName))                            {                                StreamWriter sw = dic[fileFullName];                                sw.WriteLine(logMessage.Message);                            }                            else                            {                                StreamWriter sw = new StreamWriter(fileFullName, true);                                dic[fileFullName] = sw;                                sw.WriteLine(logMessage.Message);                            }                        }                        foreach (var item in dic.Keys)                        {                            StreamWriter sw = dic[item];                            sw.Flush();                            sw.Close();                        }                        dic.Clear();                    }                    catch                     {                                        }                }            }        }                /// <summary>        /// 停止日志记录服务        /// </summary>        public static void Stop()        {            List<SQLLogMessage> tempList = null;            lock (syncObj)            {                Int32 count = logMessageQueue.Count;                if (count > 0)                {                    tempList = new List<SQLLogMessage>();                    for (int i = 0; i < count; i++)                    {                        tempList.Add(logMessageQueue.Dequeue());                    }                }            }            if (tempList != null && tempList.Count > 0)            {                lock (writeLock)                {                    try                    {                        Dictionary<string, StreamWriter> dic = new Dictionary<string, StreamWriter>();                        string filePath = string.Format("{0}\\SQLLog\\{1}\\", SQLLogFactory.Config.LogPath, DateTime.Now.ToString("yyyyMMdd"));                        if (!Directory.Exists(filePath))                        {                            Directory.CreateDirectory(filePath);                        }                        //开始记录日志数据                        for (int i = 0; i < tempList.Count; i++)                        {                            SQLLogMessage logMessage = tempList[i];                            string fileFullName = string.Format("{0}{1}", filePath, logMessage.FileName);                            if (dic.ContainsKey(fileFullName))                            {                                StreamWriter sw = dic[fileFullName];                                sw.WriteLine(logMessage.Message);                            }                            else                            {                                StreamWriter sw = new StreamWriter(fileFullName, true);                                dic[fileFullName] = sw;                                sw.WriteLine(logMessage.Message);                            }                        }                        foreach (var item in dic.Keys)                        {                            StreamWriter sw = dic[item];                            sw.WriteLine("停止日志记录");                            sw.Flush();                            sw.Close();                        }                        dic.Clear();                    }                    catch                    {                    }                }            }            if (timer != null)            {                if (timer.Enabled == true)                {                    timer.Stop();                }                timer = null;            }        }        /// <summary>        /// 要记录的日志数据压队队列        /// </summary>        /// <param name="logType"></param>        /// <param name="message"></param>        public static void LogSystem(string header,string message)        {            try            {                SQLLogMessage logMessage = new SQLLogMessage();                logMessage.FileName = string.Format("{0}.Log", header);                logMessage.Message = string.Format("{0}  {1}", DateTime.Now.ToString(), message);                lock (syncObj)                {                    logMessageQueue.Enqueue(logMessage);                }                if (timer == null)                {                    timer = new System.Timers.Timer();                    timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);                    timer.Interval = SQLLogFactory.Config.LogPeriod;//日志保存周期,三分钟                    timer.Start();                    if (stopCallBack == null)                    {                        stopCallBack = new MessageCenterStopCallBack(stopNotify);                        MessageCenterManage.Register(typeof(SQLLogService).FullName, stopCallBack);                    }                }                else if (timer.Enabled == false)                {                    timer.Start();                    if (stopCallBack == null)                    {                        stopCallBack = new MessageCenterStopCallBack(stopNotify);                        MessageCenterManage.Register(typeof(SQLLogService).FullName, stopCallBack);                    }                }            }            catch            {                         }        }        /// <summary>        /// 获取消息中心的通知        /// </summary>        /// <param name="signal"></param>        private static void stopNotify(bool signal)        {            if (signal == true)            {                Stop();            }        }        /// <summary>        /// 获取日志记录服务的状态        /// </summary>        /// <returns></returns>        public static bool GetLogServiceStatus()        {            if (timer == null)            {                return false;            }            else            {                if (timer.Enabled == true)                {                    return true;                }                else                {                    return false;                }            }        }    }


 

0 0