应用程序系统日志在.net中的处理探讨

应用程序系统日志在.net中的处理探讨

作者:xueS.net   关键字:日志、StackTrace

       本人编写程序没几年,经验不丰富,总是下载别人的代码学习,也没有为兄弟们做什么贡献,最近参考网上关于系统日志的处理方法,想出这么一个东西,来处理在我们的应用程序中记录系统日志。

       即然是日志,对于程序开发人员来说,更关心是哪个类、哪个方法、哪一行出现了问题或者是有价值的信息。还好,.net为我们提供了StackTrace类,可以获取程序中的这些信息(具体请参见帮助文档),这样一来,我们解决了日志中最核心的问题,既然核心已经找到了答案,下一步就是对日志信息的分类了,我认为将日志信息分为三类更为妥当:错误(Error)、警告(Warning)、信息(Message,错误是用来记录系统中出现的错误信息,导致系统无法运行或对系统运行正确与否产生重大影响的信息,如“数据库连接失败!”,警告是对系统运行无重大影响,但也会对系统正常运行产生影响的信息,如“数据源格式不正确!”,信息就很好理解了,就是对系统正确运行无任何影响的信息,但却能看出系统运行情况的一些信息;这样看来,我们需要三个方法来实现信息的记录了,分别是:Error()Warning()Message();信息是可以记录了,但是有些时候,我们并不一定需要将日志信息全部记录,怎样才能实现有选择性的记录日志信息呢?我想用枚举是最好不过的方法了,通过枚举异或,来实现日志信息记录类型的定义,枚举值包括:MessageWarningError,如果只想记录错误和警告信息,可以这样实现“ Error | Warning ”,这样一来,就可实现保存不同类型的信息了。好来,到现在看来,日志信息已经实现保存了,可是日志信息都包括什么呢?日志信息又该怎么处理呢?为了在以后的时候能够对其进行扩展,我将日志信息定义成一个类,包括一些属性来存储日志的日志信息内容,包括:说明、类名、方法、文件、行号、日期等,对了,不要忘了最重要的一项,日志信息类型(Message/Warning/Erro),没有它,我们将无法判断信息到底是哪一种形式的。

到现在看来,日志信息真的已经完成了,日志到是已经保存了,可是我们怎么查看日志信息呢,下面就要做一个展示日志信息的控件了,首先得能够根据信息类别分别查看,日志要是能够另存到其它文件,发给我们开发人员,就能更快的找到错误的原因了,还得有一个另存,要是日志信息不能及时更新到控件里怎么办,还需要刷新功能,日志文件总是在不断在变大,太大就占硬盘了,这可不好,删除过时的日志是应该的,清空全部日志信息也是必要的,这样,控件的功能就全部出现了,可是怎么才能与日志的处理同步呢?最好是在增加日志信息时,有一个事件,就可以在事件中对控件添加数据,实现同步了,这应该是个好方法了吧。现在看来,日志可以处理了,日志查看视图也有了,下面就是应该开始动手了。

    本文程序是用VS 2005 C#写的,对于日志部分,可以稍加修改在VS2003中运行。

    我们还是选看看类结构吧!我们要感谢微软,提供这么好的方法,通过画这些类图就能够实现编写代码的目的,我要告诉大家的事,我是先画的这些图,然后才写的代码,给我的感觉是真的太方便了。至于类的作用,前面有所描述,在这里就不在详细说明了,希望读者通过代码可以明白。

    我们先看看Demo吧,这张图中,日志视图就是我们要对日志显示的结果,怎么样,对于日志来说,应该这些信息已经够了吧,在看看工具按钮中,有一个“日志级别:高”的按钮,它是来设置日志保存类型的,高级表示记录全部(错误、警告、信息)信息,这个可以在你的应用程序中随意设置。这个Demo实现了一个简单的功能就是打开图片文件,虽然简单,但可以说明我们作的日志程序就可以了。

       先看看日志信息该怎么用吧?

// 日志处理的类

    Log log = null;

    // 实例化 参数表示 日志文件名 宿主

    this.log = new Log(string.Format(@"{0}/Logs.xml",   

Application.StartupPath), this);

     // 设置保存级别

     this.log.Style = LogStyle.Error | LogStyle.Warning | LogStyle.Message;

     // 定义改变事件,以便对日志视图控件添加记录

     this.log.Changed += new LogChangedHandle(log_Changed);

     // 绑定到日志视图控件的文件名

     this.logView1.FileName = this.log.FileName;

     // 向日志写入信息

     this.log.Message("系统已经开始运行");

     // 向日志写入警告

     this.log.Warning("测试警告!!!");

     // 向日志写入错误

     this.log.Error("测试错误!!!");

怎么样,很简单吧,有了它,我想我们应用程序的日志就是如此的简单了!

怎么样,很简单吧,有了它,我想我们应用程序的日志就是如此的简单了!

下面访说Log的代码了,这可是关键,同志们,要仔细的看呀!属性什么的,我就不说了,说关键的吧,Log.Message()Log.Warning()Log.Error()都在同一个方法中处理他们的数据:

        /// <summary>

        /// 保存系统日志信息

        /// </summary>

        /// <param name="style">日志类型</param>

        /// <param name="info">信息内容</param>

        private void SaveInfo(LogStyle style, string info)

        {

            //验证文件

            if (this.strFileName.Trim() == string.Empty) return;

            //判断保存类型

            switch (style)

            {

                case LogStyle.Error:

                    if (this.enmStyle == LogStyle.Warning |

                        this.enmStyle == LogStyle.Message |

                        this.enmStyle == (LogStyle.Warning | LogStyle.Message)) return;

                    break;

                case LogStyle.Warning:

                    if (this.enmStyle == LogStyle.Error |

                        this.enmStyle == LogStyle.Message |

                        this.enmStyle == (LogStyle.Error | LogStyle.Message)) return;

                    break;

                case LogStyle.Message:

                    if (this.enmStyle == LogStyle.Warning |

                        this.enmStyle == LogStyle.Error |

                        this.enmStyle == (LogStyle.Warning | LogStyle.Error)) return;

                    break;

            }

            //获取日志信息

            LogInfo logInfo = new LogInfo();

            logInfo.Style = style;

            logInfo.Summary = info;

            logInfo.Class = "";

            if (this.objMaster != null) logInfo.Class = this.objMaster.GetType().FullName;

            logInfo.Date = DateTime.Now;

            //关键,这里获取方法,行号,文件等信息

            StackTrace st = new StackTrace(true);

            for(int i=0;i<st.FrameCount;i++)

            {

                StackFrame sf = st.GetFrame(i);

                //这里获取Log.Message() Log.Warning() Log.Error() 被调用时发生的真正方法

                //在这些方法的后边就是我们想要的真正的方法了

                if (sf.GetMethod().Name.ToUpper() == style.ToString().ToUpper() && i+1<st.FrameCount)

                {

                    sf = st.GetFrame(i + 1);

                    logInfo.Method = sf.GetMethod().Name;

                    logInfo.Line = sf.GetFileLineNumber();

                    logInfo.File = sf.GetFileName();

                    break;

                }

            }

            //保存日志到文件

            //验证文件

            DataSet dataSet=null;

            if (File.Exists(this.strFileName))

            {

                //文件存在,打开

                dataSet = new DataSet();

                try

                {

                    dataSet.ReadXml(this.strFileName, XmlReadMode.ReadSchema);

                }

                catch (Exception)

                {

                    //可能文件格式错误,但不做错误操作

                    //新建

                    dataSet = this.CreateLogDataSet();

                }

            }

            else

            {

                //文件不存在,新建

                dataSet = this.CreateLogDataSet();

            }

            //验证LogInfo

            DataTable table = dataSet.Tables["LogInfo"];

            if (table == null)

            {

                throw new Exception(string.Format("{0} 文件格式不正确!", this.strFileName));

            }

            try

            {

                //保存到数据源

                DataRow row = table.NewRow();

                row["Style"] = logInfo.Style.ToString();

                row["Summary"] = logInfo.Summary;

                row["Class"] = logInfo.Class;

                row["Method"] = logInfo.Method;

                row["File"] = logInfo.File;

                row["Line"] = logInfo.Line;

                row["Date"] = logInfo.Date;

                table.Rows.Add(row);

                //写回到文件

                dataSet.WriteXml(this.strFileName, XmlWriteMode.WriteSchema);

            }

            catch (Exception error)

            {

                throw error;

            }

            //触发事件

            if (this.Changed != null)

            {

                this.Changed(this, new LogChangedArgs(style, logInfo));

            }

        }

 

 

 

 

 

 

 

 

 

        /// <summary>

        /// 创建日志需要的DataSet

        /// </summary>

        private DataSet CreateLogDataSet()

        {

            DataSet dataSet = new DataSet("Log");

            DataTable table = new DataTable("LogInfo");

            table.Columns.Add("Style", typeof(string));

            table.Columns.Add("Summary", typeof(string));

            table.Columns.Add("Class", typeof(string));

            table.Columns.Add("Method", typeof(string));

            table.Columns.Add("File", typeof(string));

            table.Columns.Add("Line", typeof(int));

            table.Columns.Add("Date", typeof(DateTime));

            dataSet.Tables.Add(table);

            return dataSet;

        }

    我想兄弟们能够读懂,很简单,一点技术含量都没有,日志视图控件的制作,在这里就不详细说明了,如果朋友们感兴趣,可以留言或发email给我,我会将源码献上,与朋友共同进步。这个类里有一个我到现在也没有想出解决办法的问题,就是当日志信息数据过多时,会使应用程序运行速度变得很慢,如果有更好的办法解决,还希望朋友们赐教,万分感谢!

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值