西西软件园多重安全检测下载网站、值得信赖的软件下载站!
软件
软件
文章
搜索

首页编程开发C#.NET → 软件日志分析工具LogAnalysise详细介绍

软件日志分析工具LogAnalysise详细介绍

相关软件相关文章发表评论 来源:西西整理时间:2012/6/28 10:36:52字体大小:A-A+

作者:佚名点击:529次评论:0次标签: 日志分析

360星图日志分析系统0.6.2 官方完整版
  • 类型:站长工具大小:46.6M语言:中文 评分:10.0
  • 标签:
立即下载

万恶的加班还在延续着,分析软件日志分析的头疼还是没有能够找到问题的症结所在。 五十多兆的日志文件中,很多都是没用的,有用的信息都被这些无用的信息给推攘到了不知名的角落里。我愣是找了一个小时,找到的有用的信息寥寥无几,抬头望望远处,已经感觉到有些眼晕了。 考虑到每天都要进行这样的诊断工作,于是决定写一个日志分析的小软件,要求能够过滤掉带有指定关键字的行,并且能够高亮某些关键字。于是,LogAnalysiser这个小工具诞生了。

程序运行效果截图:

启动界面(采用了Slash窗体,在程序启动时会自动检测缺失的配置文件或者程序集):  

然后启动到主界面(主界面包含了配置窗体,着色窗体,更新窗体):  

这个是配置窗体,多个关键字或者子句,利用竖线分隔开,程序会自动过滤掉含有这些关键字的文本行:

下面的这个是着色窗体,输入关键字,以数显隔开,点击确定按钮可以实时实现关键字高亮:  

下面这个是更新窗体,主要负责软件更新工作:  

然后这里是帮助文档:  

这就是这个软件的大概,虽然很小,但是算是比较的全面。

下面来说下在制作过程中使用到的技术:

技术一: 异步操作(采用APM模式)

      关于这个模式的具体讲解,可以参见我之前的博客文章:我所知道的.net异步

      在软件Slash窗体加载,关键字过滤以及软件更新的时候,由于这三个操作比较耗时,所以采用了异步方式来进行,即使用BeginInvoek和与之配对的EndInvoke方式来达到目的。 比如说软件中的LoadAppendingText()函数主要是用来循环过滤关键字来达到简化日志的目的,一旦日志文件体积非常大的情况下,这个函数将会阻塞主界面,导致假死状况。针对这种情况,我利用异步方式来处理,也就是利用下面代码进行了封装,从而产生异步效果:

#region Begin and End Invoke of Async mode
        /// <summary>
        /// 异步开始
        /// </summary>
        private void BeginInvokeAppending()
        {
            Action action = new Action(LoadAppendingText);
            IAsyncResult result = action.BeginInvoke(new AsyncCallback(EndInvokeAppending),action);
            pPrograss.Maximum = GetTotalCounts();
            tTick.Enabled = true;
        }

        /// <summary>
        /// 异步结束
        /// </summary>
        /// <param name="iar"></param>
        private void EndInvokeAppending(IAsyncResult iar)
        {
            btnAnalysis.Invoke(new Action(delegate
                {
                    btnAnalysis.Enabled = false;
                }));
            tTick.Enabled = false;
            notificationIcon.Image = (Image)WinRes.Complete;
            Action action = (Action)iar.AsyncState;
            action.EndInvoke(iar);
        }
        #endregion

      这样,当软件运行的时候,界面不会卡死,一切都很流畅:

     所以,从上面的异步方式看来,这种模式下,我们只需要对耗时函数利用BeginInvoke和EndInvoke进行一下简单的封装即可,省时也省力。

    需要说明的是,利用异步和界面交互,不得不遇到一个跨线程的问题,不过我们可以通过Form控件的Invoke方式来进行,也就是类似如下的操作:

lblStatus.Invoke(new Action(delegate
            {
                lblStatus.Text = "更新完毕。";
            }));

技术二: 委托事件传值。

      关于委托的更多详细情况,请参见我之前的博客:浅谈C#中常见的委托

      在制作本软件的过程中,着色的字体需要实时的显示;Slash窗体检测完毕,也需要传值给主窗体,然后自己关闭掉。 这两个地方都使用了委托事件来进行,具体怎么用呢,请看下面的步骤:

首先,声明全局委托:

 /// <summary>
    /// 全局委托,用于着色
    /// </summary>
    /// <param name="text">待着色文本</param>
    public delegate void ColorDaemonDelegate(string text);

然后再DaemonFrm窗体中(也就是进行着色配置的窗体中),声明一个OnColorDaemonEventHandler事件,用于抛出通知:

public event ColorDaemonDelegate OnColorDaemonEventHandler;

那么,这个通知如何抛出呢?

当然是在点击着色按钮的时候抛出去,它向外界宣布:我现在要着色啦,于是它在以下的代码中将着色事件抛了出去:

 private void btnColor_Click(object sender, EventArgs e)
        {
            string text = txtWordDaemon.Text;
            OnColorDaemonEventHandler(text);  //抛出事件
        }

可以看出,这个事件抛出的时候,带有一个参数,这个参数就是需要高亮的关键字。 那么事件抛出来了,抛给谁了?谁接收到了呢? 之后的内容估计就是我们非常常见的了,即事件注册:

  /// <summary>
        /// 点击主窗体中的着色按钮,可以对当前文档进行关键字高亮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsBtnColor_Click(object sender, EventArgs e)
        {
            if (daemonFrm == null || daemonFrm.IsDisposed == true)
            {
                daemonFrm = new DaemonFrm();
            }
            daemonFrm.OnColorDaemonEventHandler += new ColorDaemonDelegate(daemonFrm_OnColorDaemonEventHandler);
            daemonFrm.Show();
        }

利用上面的+=号,就把刚才抛出的事件给接住了,并且这个抛出的事件被主窗体给接住了。

下面是针对这个抛出的事件进行处理:       

/// <summary>
        /// 着色委托事件,可以实时高亮关键字
        /// </summary>
        /// <param name="text"></param>
        private void daemonFrm_OnColorDaemonEventHandler(string text)
        {
            RichTextBoxEx.SetColorBox(richTextBox1,richTextBox1.Text, text, Color.Red);
        }

上面的RichTextBoxEx.SetColorBox是一个利用扩展方法实现的函数,就可以实现关键字的实时高亮,看看效果:  

这样就可以非常方便的分析日志了。

技术三:更新组件的编写。

       更新组件是软件最常用的组件之一,本软件的更新组件主要采用HttpWebRequest和HttpWebResponse进行数据获取并结合异步机制完成。

      首先,来看看下载数据的函数:

private void DownLoadVersion(string url,string filename,ProgressBar progress,Label label)
        {
            int percent = 0;
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            request.ContentType = @"application/octet-stream";
            request.Credentials = CredentialCache.DefaultCredentials;

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            long totalBytes = response.ContentLength;  //获取文件字节数

            progress.Invoke(new Action(delegate
            {
                progress.Maximum = (int)totalBytes;
            }));

            Stream responseStream = response.GetResponseStream(); //保存到内存
            Stream fileStream = new FileStream(filename, FileMode.Create);

            long totalDownloadBytes = 0;
            byte[] bytes = new byte[1024];
            int paragraphByteSize = responseStream.Read(bytes, 0, (int)bytes.Length); //一次性读取1024个字节
            while (paragraphByteSize > 0)
            {
                totalDownloadBytes += paragraphByteSize;  //当前已经读取的字节数
                fileStream.Write(bytes, 0, paragraphByteSize); //写入到文件
                progress.Invoke(new Action(delegate
                {
                    progress.Value = (int)totalDownloadBytes;
                }));
               
                paragraphByteSize = responseStream.Read(bytes, 0, (int)bytes.Length); //继续读取下一段

                percent = (int)((float)totalDownloadBytes / (float)totalBytes * 100);  //进度百分比

                label.Invoke(new Action(delegate
                {
                    label.Text = "当前已经更新:" + percent.ToString() + "%";
                }));
            }
            responseStream.Close();
            fileStream.Close();
        }

这里我已经做了不少的注释了,其主体的逻辑就是得到请求数据,然后1字节1字节的写入,直到下载完毕为止。

如果直接运行这个函数进行更新的话,会造成界面假死,所以在这里我采用了和之前一样的异步处理方式,即利用BeginInvoke和EndInvoke方式来进行。这样就保证了界面的流畅性。

/// <summary>
        /// 开始进行异步更新
        /// </summary>
        /// <param name="url">软件地址</param>
        /// <param name="filename">软件名称</param>
        /// <param name="progress">PrograssBar进度条</param>
        /// <param name="label">Label状态标签</param>
        private void BeginDownload(string url,string filename,ProgressBar progress,Label label)
        {
            //利用Action委托进行代理
            Action<string, string, ProgressBar, Label> action = new Action<string, string, ProgressBar, Label>(DownLoadVersion);
            //开始进行异步
            action.BeginInvoke(url, filename, progress, label, new AsyncCallback(EndDownload), action);
        }

        /// <summary>
        /// 异步更新结束
        /// </summary>
        /// <param name="iar">异步状态</param>
        private void EndDownload(IAsyncResult iar)
        {
            //还原对象
            Action<string, string, ProgressBar, Label> action = (Action<string, string, ProgressBar, Label>)iar.AsyncState;
            //得到异步结果
            action.EndInvoke(iar);
            //更新异步操作状态
            lblStatus.Invoke(new Action(delegate
            {
                lblStatus.Text = "更新完毕。";
            }));
            //暂停
            System.Threading.Thread.Sleep(1000);
           
            string fileName = Application.StartupPath + "\\LogAnalysiser.exe";
            //异步更新结束,启动主程序
            Process.Start(fileName);
            //退出异步更新程序
            Application.Exit();
        }

其次,需要说明的是,既然我们是更新软件,那么肯定需要一个网络地址存储更高版本的文件,这里我专门创建了一个WebService用来处理更新程序所发出的请求。

在这个WebService中,我在web.cong文件中的configurations节点下新添加了一个子节点(这个涉及到在Web.config中进行自定义节点的设置方面的知识,可以参见我的文章:Asp.net配置文件中自定义节点详解):

<section name="MySection" type="UpgradeServer.MySection,UpgradeServer"/>

然后在CONFIGSECTIONS节点外面加入如下配置的节点:  

 <MySection>
    <add version ="1.2.0.0" fileName="http://localhost:2187/DownLoadVersion/LogAnalysiser.exe"></add>
  </MySection>

其中 version代表版本号,fileName代表待更新的文件的网络地址。

这样配置完成之后,在代码中,我们就可以使用两个函数暴露出待更新的软件的版本号和更新地址: 

        [WebMethod]
        public string GetUpgradeVersion()
        {
            MySection section = (MySection)ConfigurationManager.GetSection("MySection");
            MySectionItem item = section.Item;

            return item.Version;
        }


        [WebMethod]
        public string GetUpgradeFileName()
        {
            MySection section = (MySection)ConfigurationManager.GetSection("MySection");
            MySectionItem item = section.Item;

            return item.FileName;
        }

 

      那么当程序检测到目前版本号和WEBSERVER暴露出来的版本号一样的时候,表明服务器上面没有最新版本,当二者不一致的时候,则证明服务器上面有最新的版本,于是启动更新组件,进行更新。    

代码如下:

  public bool CheckVersionAndUpgrade()
        {
            try
            {
                if (client == null)
                {
                    client = new UpgradeFormApplication.UpgradeWebService.Service1SoapClient();
                }

                string upgradeVersion = client.GetUpgradeVersion(); //获取版本号
                string upgradeFileName = client.GetUpgradeFileName(); //获取更新文件的网络路径

                string currentVersion = CommonUntil.GetApplicationVersionFromExeFile(); //获取当前主程序的版本号

                if (String.IsNullOrEmpty(upgradeVersion))
                {
                    lblStatus.Invoke(new Action(delegate
                    {
                        lblStatus.Text = "当前没有最新版本。";
                    }));
                    btnUpgrade.Invoke(new Action(delegate
                    {
                        btnUpgrade.Enabled = false;
                    }));
                    return false;
                }
                if (String.IsNullOrEmpty(currentVersion))
                {
                    return false;
                }

                if (currentVersion.Equals(upgradeVersion)) //如果没有更高的版本号
                {
                    lblStatus.Invoke(new Action(delegate
                    {
                        lblStatus.Text = "当前没有最新版本。";
                    }));
                    btnUpgrade.Invoke(new Action(delegate
                    {
                        btnUpgrade.Enabled = false;
                    }));
                    return false;
                }

                lblStatus.Invoke(new Action(delegate
                {
                    lblStatus.Text = "当前存在最新版本" + upgradeVersion + ",点击更新。。。";
                }));

                return true;
            }
            catch
            {
                lblStatus.Invoke(new Action(delegate{lblStatus.Text = "不能连接远程主机获取更新,请检查网络连接!";}));
                btnUpgrade.Invoke(new Action(delegate { btnUpgrade.Enabled = false; }));
                return false;
            }
        }

那么一旦我们有新的版本需要更新的时候,我们只需要在把这个新的版本放到IIS的形如 http://*******/DownLoadVersion/的路径下,并且修改web.config文件中的version的值为新版本号即可。当软件更新组件运行的时候,一旦发现version值改变,就会立即启动更新程序进行更新。

技术之四:帮助文档自动生成。

      其实这个并不能称为技术,应为我们应用的是自动生成软件,但是这个帮助文档也确实是必不可少的,它可以让开发人员对软件的功能一目了然。 说到自动文档生成,这里我推荐使用.NET文档生成工具ADB,作者博客为:HTTP://WWW.CNBLOGS.COM/LUCC/ARCHIVE/2008/09/01/1281085.HTML

      这个软件支持多种注释的智能识别模式,并且支持多程序集合并功能。在使用本软件之前,强烈建议为程序集生成XML文档,具体做法是在项目上右击,选择“生成标签”,然后勾选上”XML文档文件”选项。  

      当我用ADB加载我的LOGANALYSISER.EXE文件的时候,我们可以看到软件界面列出了如下的各种公共方法,公共属性等等。   当我们最后点击创建文档按钮的时候,就得到了一个看上去非常专业的帮助文档:  

好了,这个软件的介绍就到了这里.

点击这里下载源码

    相关评论

    阅读本文后您有什么感想? 已有人给出评价!

    • 8 喜欢喜欢
    • 3 顶
    • 1 难过难过
    • 5 囧
    • 3 围观围观
    • 2 无聊无聊

    热门评论

    最新评论

    发表评论 查看所有评论(0)

    昵称:
    表情: 高兴 可 汗 我不要 害羞 好 下下下 送花 屎 亲亲
    字数: 0/500 (您的评论需要经过审核才能显示)