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

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

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

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

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

 /// <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;
                }
            }
        }
    }


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值