西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁編程開發(fā)C#.NET → 軟件日志分析工具LogAnalysise詳細(xì)介紹

軟件日志分析工具LogAnalysise詳細(xì)介紹

相關(guān)軟件相關(guān)文章發(fā)表評論 來源:西西整理時間:2012/6/28 10:36:52字體大。A-A+

作者:佚名點擊:529次評論:0次標(biāo)簽: 日志分析

  • 類型:站長工具大。46.6M語言:中文 評分:10.0
  • 標(biāo)簽:
立即下載

萬惡的加班還在延續(xù)著,分析軟件日志分析的頭疼還是沒有能夠找到問題的癥結(jié)所在。 五十多兆的日志文件中,很多都是沒用的,有用的信息都被這些無用的信息給推攘到了不知名的角落里。我愣是找了一個小時,找到的有用的信息寥寥無幾,抬頭望望遠(yuǎn)處,已經(jīng)感覺到有些眼暈了。 考慮到每天都要進(jìn)行這樣的診斷工作,于是決定寫一個日志分析的小軟件,要求能夠過濾掉帶有指定關(guān)鍵字的行,并且能夠高亮某些關(guān)鍵字。于是,LogAnalysiser這個小工具誕生了。

程序運行效果截圖:

啟動界面(采用了Slash窗體,在程序啟動時會自動檢測缺失的配置文件或者程序集):  

然后啟動到主界面(主界面包含了配置窗體,著色窗體,更新窗體):  

這個是配置窗體,多個關(guān)鍵字或者子句,利用豎線分隔開,程序會自動過濾掉含有這些關(guān)鍵字的文本行:

下面的這個是著色窗體,輸入關(guān)鍵字,以數(shù)顯隔開,點擊確定按鈕可以實時實現(xiàn)關(guān)鍵字高亮:  

下面這個是更新窗體,主要負(fù)責(zé)軟件更新工作:  

然后這里是幫助文檔:  

這就是這個軟件的大概,雖然很小,但是算是比較的全面。

下面來說下在制作過程中使用到的技術(shù):

技術(shù)一: 異步操作(采用APM模式)

      關(guān)于這個模式的具體講解,可以參見我之前的博客文章:我所知道的.net異步

      在軟件Slash窗體加載,關(guān)鍵字過濾以及軟件更新的時候,由于這三個操作比較耗時,所以采用了異步方式來進(jìn)行,即使用BeginInvoek和與之配對的EndInvoke方式來達(dá)到目的。 比如說軟件中的LoadAppendingText()函數(shù)主要是用來循環(huán)過濾關(guān)鍵字來達(dá)到簡化日志的目的,一旦日志文件體積非常大的情況下,這個函數(shù)將會阻塞主界面,導(dǎo)致假死狀況。針對這種情況,我利用異步方式來處理,也就是利用下面代碼進(jìn)行了封裝,從而產(chǎn)生異步效果:

#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>
        /// 異步結(jié)束
        /// </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

      這樣,當(dāng)軟件運行的時候,界面不會卡死,一切都很流暢:

     所以,從上面的異步方式看來,這種模式下,我們只需要對耗時函數(shù)利用BeginInvoke和EndInvoke進(jìn)行一下簡單的封裝即可,省時也省力。

    需要說明的是,利用異步和界面交互,不得不遇到一個跨線程的問題,不過我們可以通過Form控件的Invoke方式來進(jìn)行,也就是類似如下的操作:

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

技術(shù)二: 委托事件傳值。

      關(guān)于委托的更多詳細(xì)情況,請參見我之前的博客:淺談C#中常見的委托

      在制作本軟件的過程中,著色的字體需要實時的顯示;Slash窗體檢測完畢,也需要傳值給主窗體,然后自己關(guān)閉掉。 這兩個地方都使用了委托事件來進(jìn)行,具體怎么用呢,請看下面的步驟:

首先,聲明全局委托:

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

然后再DaemonFrm窗體中(也就是進(jìn)行著色配置的窗體中),聲明一個OnColorDaemonEventHandler事件,用于拋出通知:

public event ColorDaemonDelegate OnColorDaemonEventHandler;

那么,這個通知如何拋出呢?

當(dāng)然是在點擊著色按鈕的時候拋出去,它向外界宣布:我現(xiàn)在要著色啦,于是它在以下的代碼中將著色事件拋了出去:

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

可以看出,這個事件拋出的時候,帶有一個參數(shù),這個參數(shù)就是需要高亮的關(guān)鍵字。 那么事件拋出來了,拋給誰了?誰接收到了呢? 之后的內(nèi)容估計就是我們非常常見的了,即事件注冊:

  /// <summary>
        /// 點擊主窗體中的著色按鈕,可以對當(dāng)前文檔進(jìn)行關(guān)鍵字高亮
        /// </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();
        }

利用上面的+=號,就把剛才拋出的事件給接住了,并且這個拋出的事件被主窗體給接住了。

下面是針對這個拋出的事件進(jìn)行處理:       

/// <summary>
        /// 著色委托事件,可以實時高亮關(guān)鍵字
        /// </summary>
        /// <param name="text"></param>
        private void daemonFrm_OnColorDaemonEventHandler(string text)
        {
            RichTextBoxEx.SetColorBox(richTextBox1,richTextBox1.Text, text, Color.Red);
        }

上面的RichTextBoxEx.SetColorBox是一個利用擴(kuò)展方法實現(xiàn)的函數(shù),就可以實現(xiàn)關(guān)鍵字的實時高亮,看看效果:  

這樣就可以非常方便的分析日志了。

技術(shù)三:更新組件的編寫。

       更新組件是軟件最常用的組件之一,本軟件的更新組件主要采用HttpWebRequest和HttpWebResponse進(jìn)行數(shù)據(jù)獲取并結(jié)合異步機(jī)制完成。

      首先,來看看下載數(shù)據(jù)的函數(shù):

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;  //獲取文件字節(jié)數(shù)

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

            Stream responseStream = response.GetResponseStream(); //保存到內(nèi)存
            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個字節(jié)
            while (paragraphByteSize > 0)
            {
                totalDownloadBytes += paragraphByteSize;  //當(dāng)前已經(jīng)讀取的字節(jié)數(shù)
                fileStream.Write(bytes, 0, paragraphByteSize); //寫入到文件
                progress.Invoke(new Action(delegate
                {
                    progress.Value = (int)totalDownloadBytes;
                }));
               
                paragraphByteSize = responseStream.Read(bytes, 0, (int)bytes.Length); //繼續(xù)讀取下一段

                percent = (int)((float)totalDownloadBytes / (float)totalBytes * 100);  //進(jìn)度百分比

                label.Invoke(new Action(delegate
                {
                    label.Text = "當(dāng)前已經(jīng)更新:" + percent.ToString() + "%";
                }));
            }
            responseStream.Close();
            fileStream.Close();
        }

這里我已經(jīng)做了不少的注釋了,其主體的邏輯就是得到請求數(shù)據(jù),然后1字節(jié)1字節(jié)的寫入,直到下載完畢為止。

如果直接運行這個函數(shù)進(jìn)行更新的話,會造成界面假死,所以在這里我采用了和之前一樣的異步處理方式,即利用BeginInvoke和EndInvoke方式來進(jìn)行。這樣就保證了界面的流暢性。

/// <summary>
        /// 開始進(jìn)行異步更新
        /// </summary>
        /// <param name="url">軟件地址</param>
        /// <param name="filename">軟件名稱</param>
        /// <param name="progress">PrograssBar進(jìn)度條</param>
        /// <param name="label">Label狀態(tài)標(biāo)簽</param>
        private void BeginDownload(string url,string filename,ProgressBar progress,Label label)
        {
            //利用Action委托進(jìn)行代理
            Action<string, string, ProgressBar, Label> action = new Action<string, string, ProgressBar, Label>(DownLoadVersion);
            //開始進(jìn)行異步
            action.BeginInvoke(url, filename, progress, label, new AsyncCallback(EndDownload), action);
        }

        /// <summary>
        /// 異步更新結(jié)束
        /// </summary>
        /// <param name="iar">異步狀態(tài)</param>
        private void EndDownload(IAsyncResult iar)
        {
            //還原對象
            Action<string, string, ProgressBar, Label> action = (Action<string, string, ProgressBar, Label>)iar.AsyncState;
            //得到異步結(jié)果
            action.EndInvoke(iar);
            //更新異步操作狀態(tài)
            lblStatus.Invoke(new Action(delegate
            {
                lblStatus.Text = "更新完畢。";
            }));
            //暫停
            System.Threading.Thread.Sleep(1000);
           
            string fileName = Application.StartupPath + "\\LogAnalysiser.exe";
            //異步更新結(jié)束,啟動主程序
            Process.Start(fileName);
            //退出異步更新程序
            Application.Exit();
        }

其次,需要說明的是,既然我們是更新軟件,那么肯定需要一個網(wǎng)絡(luò)地址存儲更高版本的文件,這里我專門創(chuàng)建了一個WebService用來處理更新程序所發(fā)出的請求。

在這個WebService中,我在web.cong文件中的configurations節(jié)點下新添加了一個子節(jié)點(這個涉及到在Web.config中進(jìn)行自定義節(jié)點的設(shè)置方面的知識,可以參見我的文章:Asp.net配置文件中自定義節(jié)點詳解):

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

然后在CONFIGSECTIONS節(jié)點外面加入如下配置的節(jié)點:  

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

其中 version代表版本號,fileName代表待更新的文件的網(wǎng)絡(luò)地址。

這樣配置完成之后,在代碼中,我們就可以使用兩個函數(shù)暴露出待更新的軟件的版本號和更新地址: 

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

 

      那么當(dāng)程序檢測到目前版本號和WEBSERVER暴露出來的版本號一樣的時候,表明服務(wù)器上面沒有最新版本,當(dāng)二者不一致的時候,則證明服務(wù)器上面有最新的版本,于是啟動更新組件,進(jìn)行更新。    

代碼如下:

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

                string upgradeVersion = client.GetUpgradeVersion(); //獲取版本號
                string upgradeFileName = client.GetUpgradeFileName(); //獲取更新文件的網(wǎng)絡(luò)路徑

                string currentVersion = CommonUntil.GetApplicationVersionFromExeFile(); //獲取當(dāng)前主程序的版本號

                if (String.IsNullOrEmpty(upgradeVersion))
                {
                    lblStatus.Invoke(new Action(delegate
                    {
                        lblStatus.Text = "當(dāng)前沒有最新版本。";
                    }));
                    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 = "當(dāng)前沒有最新版本。";
                    }));
                    btnUpgrade.Invoke(new Action(delegate
                    {
                        btnUpgrade.Enabled = false;
                    }));
                    return false;
                }

                lblStatus.Invoke(new Action(delegate
                {
                    lblStatus.Text = "當(dāng)前存在最新版本" + upgradeVersion + ",點擊更新。。。";
                }));

                return true;
            }
            catch
            {
                lblStatus.Invoke(new Action(delegate{lblStatus.Text = "不能連接遠(yuǎn)程主機(jī)獲取更新,請檢查網(wǎng)絡(luò)連接!";}));
                btnUpgrade.Invoke(new Action(delegate { btnUpgrade.Enabled = false; }));
                return false;
            }
        }

那么一旦我們有新的版本需要更新的時候,我們只需要在把這個新的版本放到IIS的形如 http://*******/DownLoadVersion/的路徑下,并且修改web.config文件中的version的值為新版本號即可。當(dāng)軟件更新組件運行的時候,一旦發(fā)現(xiàn)version值改變,就會立即啟動更新程序進(jìn)行更新。

技術(shù)之四:幫助文檔自動生成。

      其實這個并不能稱為技術(shù),應(yīng)為我們應(yīng)用的是自動生成軟件,但是這個幫助文檔也確實是必不可少的,它可以讓開發(fā)人員對軟件的功能一目了然。 說到自動文檔生成,這里我推薦使用.NET文檔生成工具ADB,作者博客為:HTTP://WWW.CNBLOGS.COM/LUCC/ARCHIVE/2008/09/01/1281085.HTML

      這個軟件支持多種注釋的智能識別模式,并且支持多程序集合并功能。在使用本軟件之前,強(qiáng)烈建議為程序集生成XML文檔,具體做法是在項目上右擊,選擇“生成標(biāo)簽”,然后勾選上”XML文檔文件”選項。  

      當(dāng)我用ADB加載我的LOGANALYSISER.EXE文件的時候,我們可以看到軟件界面列出了如下的各種公共方法,公共屬性等等。   當(dāng)我們最后點擊創(chuàng)建文檔按鈕的時候,就得到了一個看上去非常專業(yè)的幫助文檔:  

好了,這個軟件的介紹就到了這里.

點擊這里下載源碼

    相關(guān)評論

    閱讀本文后您有什么感想? 已有人給出評價!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過難過
    • 5 囧
    • 3 圍觀圍觀
    • 2 無聊無聊

    熱門評論

    最新評論

    發(fā)表評論 查看所有評論(0)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)