写日志的功能

最近在做一个asp.net的项目要求实现一个记录日志的功能,本来极力推荐使用Log4net的,开源的配置又方便实现又多样,但领导考虑到将来这个项目要做成产品,担心它的开放政策,找了一大堆理由不同意使用,无奈自己来一个吧

要求:1,服务器不重启的前提下随时更改记录日志的级别

2.考虑并发的情况

 
 直接上代码吧
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Configuration;
using System.Web;
using System.Text.RegularExpressions;
using System.Data;
using System.Threading;

namespace WebApplication1
{
    //日志信息级别类
    public enum Level { 
        /// <summary>
        /// 调试信息
        /// </summary>
        Debug = 3, 
        /// <summary>
        ///  警告信息
        /// </summary>
        Warn = 2, 
        /// <summary>
        /// 错误信息
        /// </summary>
        Error = 1
    };

    //日志信息类
    public class Logs
    {
        #region 字段
        private Level level;         //错误级别
        private string datetime;    //发生时间
        private string source;         //发生地址
        private string message;          //错误内容
        #endregion

        #region 构造函数
        /// <summary>
        /// 对象有参构造函数
        /// </summary>
        /// <param name="lvl">错误级别(枚举值)</param>
        /// <param name="datetime">发生时间</param>
        /// <param name="source">发生地址</param>
        /// <param name="message">错误内容</param>
        public Logs(Level level, string datetime, string source, string message)
        {
            this.level = level;
            this.datetime = datetime;
            this.source = source;
            this.message = message;
        }
        #endregion

        #region 属性
        public Level Level
        {
            get { return level; }
            set { level = value; }
        }

        public string Datetime
        {
            get { return datetime; }
            set { datetime = value; }
        }

        public string Source
        {
            get { return source; }
            set { source = value; }
        }

        public string Message
        {
            get { return message; }
            set { message = value; }
        }
        #endregion
    }

    //日志相关配置类
    public static class ConstDeclare
    {
        /// <summary>
        /// 写日志间隔时间
        /// </summary>
        private static int witeTime = 10000;
        
        /// <summary>
        /// 日志错误级别
        /// </summary>
        private static string logLevel = Level.Debug.ToString();
       
        /// <summary>
        /// 保留日志文件数
        /// </summary>
        private static int logsCount = 10;
        /// <summary>
        ///日志文件大小 
        /// </summary>

        private static int logSize = 1024*1024;
        /// <summary>
        /// 日志文件主目录
        /// </summary>
        public static string filePath = "SystemLog";

        /// <summary>
        /// 错误数
        /// </summary>
        private static int excptionCount = 0;

        

        public static int WiteTime
        {
            get { return witeTime; }
            set { if (value > 0) witeTime = value * 60000; }
        }
        public static string LogLevel
        {
            get { return logLevel; }
            set
            {
                if (value.Equals(Level.Debug.ToString()) || value.Equals(Level.Error.ToString()) || value.Equals(Level.Warn.ToString()))
                {
                    logLevel = value;
                }
            }
        }
        public static int LogsCount
        {
            get { return logsCount; }
            set { if (value > 0) logsCount = value; }
        }
        public static int LogSize
        {
            get { return logSize; }
            set { if (value > 0) logSize = value*1024; }
        }
        public static string FilePath
        {
            get { return filePath; }
            set { filePath = value; }
        }
        public static int ExcptionCount
        {
            get { return excptionCount; }
            set { excptionCount = value; }
        }
    }

    //文档处理类
    public class ExceptionManager
    {
        //定义队列集合 
        private static readonly Queue<Logs> docQueue = new Queue<Logs>();

        //添加文档              
        /// <summary>
        /// 添加异常信息
        /// </summary>
        /// <param name="level">错误级别(枚举值)</param>
        /// <param name="dataTime">出错时间</param>
        /// <param name="source">发生地址</param>
        /// <param name="message">错误内容</param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]
        public static void AddException(Level level, string dataTime, string source, string message)
        {
            Logs logs = new Logs(level, dataTime, source, message);

            if ((int)level <= (int)(Level)Enum.Parse(typeof(Level), ConstDeclare.LogLevel))
            {
                //从队列一端插入内容 
                docQueue.Enqueue(logs);
                ConstDeclare.ExcptionCount++;    //错误数
                if (IsDocumentAvailable)
                {
                    GetException();
                }
            }
        }

        //只读属性,确定队列中是不是还有元素 
        public static bool IsDocumentAvailable
        {
            get
            {
                return docQueue.Count > 0;
            }
        }

        //读取文档 并 写入 
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]
        public static void GetException()
        {
            Logs ex = null;
            if (docQueue.Count > 0)
            {
                ex = docQueue.Dequeue();
                SaveException(ex);
            }
        }

        //间隔时间执行某动作 (写文件)
        public static void SaveException(Logs e)
        {
            //指定日志文件的目录 
            string fileLogPath = AppDomain.CurrentDomain.BaseDirectory + ConstDeclare.FilePath;
            //错误日志的记录地址(每天产生一个日志文件)
            string fileLogName = DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ".log";

            try
            {
                if (!Directory.Exists(fileLogPath))
                {
                    Directory.CreateDirectory(fileLogPath);
                }

                DirectoryInfo info = new DirectoryInfo(fileLogPath);
                //FileInfo[] existingFiles = info.GetFiles(string.Format("{0}*{1}", fileNameWithoutExtension, extension));
                FileInfo[] existingFiles = info.GetFiles();

                List<FileInfo> deleteFiles = new List<FileInfo>();
                FileInfo finfo;
                //Regex regex = new Regex(string.Format(@"{0}\.(.+).{1}", fileNameWithoutExtension, extension));
                if (existingFiles.Length > 0)
                {
                    for (int index = 0; index < existingFiles.Length; index++)
                    {
                        //Match sequenceMatch = regex.Match(existingFiles[index].FullName);
                        //if (sequenceMatch.Success)
                        {
                            deleteFiles.Add(existingFiles[index]);
                        }
                    }

                    deleteFiles.Sort((x, y) => x.CreationTime < y.CreationTime ? 1 : x.CreationTime > y.CreationTime ? -1 : 0);

                    //最近创建的日志文件
                    finfo = deleteFiles[0];

                    if (finfo.Length >= ConstDeclare.LogSize)
                    {
                        for (int index = ConstDeclare.LogsCount; index < deleteFiles.Count; index++)
                        {
                            try
                            {
                                deleteFiles[index].Delete();
                            }
                            catch
                            {
                            }
                        }
                        finfo = new FileInfo(string.Format("{0}\\{1}", fileLogPath, fileLogName));
                    }
                }
                else
                {
                    finfo = new FileInfo(string.Format("{0}\\{1}", fileLogPath, fileLogName));
                }

                //string directory = Path.GetDirectoryName(finfo.FullName);
                //string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(finfo.FullName);
                //string extension = Path.GetExtension(finfo.FullName);
              
                //创建只写文件流  
                using (FileStream fs = finfo.OpenWrite())
                {
                    //根据上面创建的文件流创建写数据流  
                    StreamWriter strwriter = new StreamWriter(fs);

                    //设置写数据流的起始位置为文件流的末尾  
                    strwriter.BaseStream.Seek(0, SeekOrigin.End);
 
                    strwriter.WriteLine("[发生时间]:" + e.Datetime.ToString());
                    strwriter.WriteLine("[错误级别]:" + e.Level.ToString());
                    strwriter.WriteLine("[发生地址]:" + e.Source);
                    //strwriter.WriteLine("[目标网站]:" + e.TargetSite);  
                    strwriter.WriteLine("[错误内容]:" + e.Message);
                    //strwriter.WriteLine("[帮助链接]:" + e.HelpLink);
                    //strwriter.WriteLine("[堆栈跟踪]:" + e.StackTrace);
                    //strwriter.WriteLine("[内部异常]:" + e.InnerException);
                    strwriter.WriteLine("[记录时间]:" + DateTime.Now.ToString());

                    //写入间隔符  
                    strwriter.WriteLine("************************************************************************");
                    strwriter.WriteLine("\n");

                    //清空缓冲区内容,并把缓冲区内容写入基础流  
                    strwriter.Flush();

                    //关闭写数据流  
                    strwriter.Close();
                    fs.Close();
                }
            }
            catch (Exception ex)
            {
                AddException(Level.Debug, DateTime.Now.ToString(), ex.TargetSite.ToString()+ex.Source+ex.StackTrace, ex.Message);
            }
        }

        #region 写日志的线程操作
        public static void Start()
        {
            // 参数 : public delegate void ThreadStart(); 
            //Thread thread = new Thread(DoThreadFunc);
            //thread.Start();
            System.Timers.Timer tm = new System.Timers.Timer();
            tm.Elapsed += new System.Timers.ElapsedEventHandler(tm_Elapsed);
            tm.Interval = 10000;
            tm.Enabled = true;
        }

        static void tm_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            //无限循环读取,只要队列中有内容,这条线程就读出来 
            //while (true)
            {
                while(IsDocumentAvailable)
                {
                    GetException();
                }
                //Thread.CurrentThread.Join(1000);
                //Thread.Sleep(ConstDeclare.WiteTime);
            }
        }

        public static void DoThreadFunc()
        {
            //无限循环读取,只要队列中有内容,这条线程就读出来 
            while (true)
            {
                while (IsDocumentAvailable)
                {
                    GetException();
                    Thread.Sleep(10000);
                }
                //Thread.CurrentThread.Join(1000);
                //Thread.Sleep(ConstDeclare.WiteTime);
            }
        }
        #endregion

        #region 获取日志信息

        public static DataSet GetLogs()
        {
            DataSet ds = new DataSet();
            DataTable dt = new DataTable();
            dt.Columns.Add("id", typeof(System.Int32));
            dt.Columns.Add("logdate", typeof(System.DateTime));
            dt.Columns.Add("level", typeof(System.String));
            dt.Columns.Add("address", typeof(System.String));
            dt.Columns.Add("message", typeof(System.String));

            string filepath = AppDomain.CurrentDomain.BaseDirectory + ConstDeclare.FilePath;

            try
            {
                if (Directory.Exists(filepath))
                {
                    DirectoryInfo dinfo = new DirectoryInfo(filepath);
                    FileInfo[] finfo = dinfo.GetFiles();
                    List<FileInfo> linfo = new List<FileInfo>();
                    int rowid = 0;
                    for (int index = 0; index < finfo.Length; index++)
                    {
                        linfo.Add(finfo[index]);
                    }
                    linfo.Sort((x, y) => x.CreationTime < y.CreationTime ? 1 : x.CreationTime > y.CreationTime ? -1 : 0);

                    for (int i = 0; i < linfo.Count; i++)
                    {
                        StreamReader sr = new StreamReader(string.Format("{0}\\{1}", filepath, Path.GetFileName(linfo[i].FullName)), Encoding.UTF8);
                        DataRow dr = null;
                        while (!sr.EndOfStream)
                        {

                            string logline = sr.ReadLine();
                            string[] str = logline.Split(new string[] { "]:" }, StringSplitOptions.RemoveEmptyEntries);

                            if (!string.IsNullOrEmpty(logline) && str.Length > 0)
                            {
                                if (logline.Substring(1, 4).Equals("发生时间"))
                                {
                                    //创建一个空行
                                    rowid++;
                                    dr = dt.NewRow();
                                    dr["id"] = rowid;
                                    dr["logdate"] = str.Length > 1 ? str[1] : "";
                                }
                                if (logline != null && logline.Substring(1, 4).Equals("错误级别") && dr != null)
                                {
                                    dr["level"] = str.Length > 1 ? ConvertLevel(str[1]) : "";
                                }
                                if (logline != null && logline.Substring(1, 4).Equals("发生地址") && dr != null)
                                {
                                    dr["address"] = str.Length > 1 ? str[1] : "";
                                }
                                if (logline != null && logline.Substring(1, 4).Equals("错误内容") && dr != null)
                                {
                                    dr["message"] = str.Length > 1 ? str[1] : "";
                                    //添加一行数据
                                    dt.Rows.Add(dr);
                                }
                            }
                        }
                        sr.Close();
                    }
                    ds.Tables.Add(dt);
                }
            }
            catch (Exception ex)
            {
                ExceptionManager.AddException(Level.Debug, DateTime.Now.ToString(), ex.TargetSite.ToString()+ex.Source+ex.StackTrace, ex.Message);
            }
            return ds;
        }
        public static string ConvertLevel(string level)
        {
            string leveldesc;
            if (level.Equals(Level.Debug.ToString()))
            {
                leveldesc = "调试";
            }
            else if (level.Equals(Level.Error.ToString()))
            {
                leveldesc = "错误";
            }
            else
            {
                leveldesc = "警告";
            }
            return leveldesc;
        }
        #endregion
    }
}

 

在Global.asax.cs页面调用

    public class Global : System.Web.HttpApplication
    {

 	void Application_Start(object sender, EventArgs e)
        {
	    // Code that runs on application startup
	    ExceptionManager.AddException(Level.Debug, DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss fff"), "Global.asax void A			pplication_Start(object sender, EventArgs e)", "当应用程序开始时,启动一个定时器,用来定时执行任务AddException方				法记录错误");
                        ExceptionManager.Start();

	}

 	void Application_Error(object sender, EventArgs e)
        {
            // Code that runs when an unhandled error occurs
            Exception ex = Server.GetLastError().GetBaseException();
            ExceptionManager.AddException(Level.Debug, DateTime.Now.ToString(), ex.Source, ex.Message);
            Server.ClearError();
        }
     }


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值