捉蟲記 - 善用Trace Object來加速尋找ASP.NET應用程序里的runtime error根源。

(華版)

我想作為一個编冩ASP.NET應用程序的程序員;最怕也應該是面對和解决突然而來的runtime error。因為没有人能够预測它會幾時會發生,在怎样的情况下在發生。而一般的程序員都是根据本身的經驗和技術知識來做事前的预防,一個脑袋能够聨想,幻想到多遠去?更何况每一位用户都有不同的知識水平(電脑和應用程序),這样就產生了很多不可思异的效果。。。最终就出現了漏網之鱼。如果不赶緊去補救,那久而久之這些漏網之鱼就慢慢長大變成可怕又令人討厭的蟲蟲了!所以大公司就常常設立“脑震荡”(brainstorming)之纇的會議來商討對策來殺出重圍。可是有没有想過再多幾個脑袋也敵不勝一個有效的debuger或tracer工具。

有人會説VS.NET不就是一個很好的debugger嗎?對,但是一般deployed的ASP.NET應用程序都不會附带任何源代碼(這里是指Code Behind Page的源代碼);也証明了在這種情形下,VS.NET不會有很大的贡献。如果能够符合以上重重條件,那也不能只在VS.NET debugger環境里空等runetime error的發生;那是很没有效率的工作態度!説明是runtim error。。。就是随時随地也可以發生,也可以等了好幾個白晝黑夜也不發生。

所以今次就跟大家來講解一下如何在ASP.NET應用程序里捉蟲。VS.NET的debugger為程序員提供两種debugging object:
  1. Debug Object
  2. Trace Object

在此我不多加討論Debug Object,因為它只能把所有的debugging信息生產去VS.NET里的Output窗口;而且也只能用于debug mode版本和执行于VS.NET debugger環境里。但Trace Object就不一样,应為Trace Object依然可以在release build里操作,并且能随時enabled或disabled而不需要從新compile任何一份源代碼或删除所有的tracing語句!

至于Trace Object就有两種不同的level tracing:
  1. Page-level tracing
  2. Application-level tracing

Page-level Tracing
只限用在個别的WebForm文件里。比如説WebForm1.aspx有tracing enabled而WebForm2.aspx没有;當IIS执行WebForm1.aspx和WebForm2.aspx時,只有WebForm1.aspx會显示所有在WebForm1.aspx文件里定制的trace信息。

要在WebForm文件里enable tracing是非常容易,只需要在WebForm文件里的@Page directive加添以下的特性(attribute)就可以了。
VB.NET
   <@ Page Language="vb" Trace="True" %>
C#
   <@ Page Language="c#" Trace="True" %>

或者在property page里更改也可以。

 

然後在code behind page(WebForm1.aspx.vb或WebForm1.aspx.cs)里引用:
VB.NET
   Imports System.Diagnostics
C#
   using System.Diagnostics;

之後就可以開始用Trace Object來生產你想要的trace信息。而這些信息會附加在.aspx文件的底部或背後。
此Trace Object提供了,
  两個方法(Method):
    1. Trace.Write
    2. Trace.Warn
  两個屬性(Property):
    1. Trace.IsEnabled
    2. Trace.TraceMode

Trace.Write和Trace.Warn都是生產trace信息的唯一方法;两者不同之處是Trace.Warn生產的trace信息字軆颜色為红色(Warn就是Warning的簡冩)而Trace.Write是黑色。

Private Sub Button1_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles Button1.Click

    
If Trace.IsEnabled Then
        Trace.
Write("種纇""調試信息,Write方法。")
        Trace.Warn(
"種纇""調試信息,Warn方法。")
    
End If

End Sub

private void Button1_Click(object sender, System.EventArgs e)
{
    
if (Trace.IsEnabled)
    
{
        Trace.Write(
"種纇""調試信息,Write方法。");
        Trace.Warn(
"種纇""調試信息,Warn方法。");
    }

}


因為當WebForm文件enabled了tracing mode,全部用Trace Object生產的trace信息都會显示在aspx文件里。所以Trace.IsEnabled是给程序員一點空間去用程序代碼來决定在某種情况下要還是不要生產trace信息。

Trace.TraceMode屬性是用來控制生產trace信息的次序,基本上有三種不同的次序:
  1. TraceMode.Default
  2. TraceMode.SortByCategory
  3. TraceMode.SortByTime

如果你WebForm的Page layout值數是FlowLayout,那所有的trace信息就附加在.aspx文件的底部。

 

<%@ Page trace="true" Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="TraceObjVB.WebForm1" traceMode="SortByTime"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
    
<HEAD>
        
<title>Trace Object - VB</title>
        
<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
        
<meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
        
<meta name="vs_defaultClientScript" content="JavaScript">
        
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
    
</HEAD>
    
<body ms_positioning="GridLayout">
        
<form id="Form1" method="post" runat="server">
            
<asp:Button id="Button2" runat="server" Text="Trace In Component"></asp:Button>
            
<asp:Button id="Button1" runat="server" Text="Trace In Page"></asp:Button>
            
<asp:TextBox id="TextBox1" runat="server"></asp:TextBox>
        
</form>
    
</body>
</HTML>


如果你WebForm.aspx的Page layout值數是GridLayout,所有的trace信息就附加在.aspx文件的背後。

 

<%@ Page trace="true" Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="TraceObjVB.WebForm1" traceMode="SortByTime"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
    
<HEAD>
        
<title>Trace Object - VB</title>
        
<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
        
<meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
        
<meta name="vs_defaultClientScript" content="JavaScript">
        
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
    
</HEAD>
    
<body ms_positioning="GridLayout">
        
<form id="Form1" method="post" runat="server">
            
<asp:Button id="Button2" style="Z-INDEX: 102; LEFT: 496px; POSITION: absolute; TOP: 8px" runat="server"
                Text
="Trace In Component"></asp:Button>
            
<asp:Button id="Button1" style="Z-INDEX: 101; LEFT: 312px; POSITION: absolute; TOP: 8px" runat="server"
                Text
="Trace In Page" Width="176px"></asp:Button>
            
<asp:TextBox id="TextBox1" style="Z-INDEX: 103; LEFT: 8px; POSITION: absolute; TOP: 8px" runat="server"
                Width
="296px"></asp:TextBox>
        
</form>
    
</body>
</HTML>


至于FlowLayout和GridLayout的详细分别解释請閲讀相關的文章或查詢http://msdn.microsoft.com


Application-level Tracing
因為显示在.aspx文件底部里的trace信息有太多了,雖然是最快閲讀方法之一。而每當此.aspx文件一刷新(refresh),旧trace信息就没了!所以就要用Application-level tracing來補救此缺點。如果enabled了Application-level tracing,個别的WebForm文件里的Page-level tracing依然有效。

所有關于Application-level tracing的設定都可以在Web.Config文件里找的到:
  <trace enabled="true" requestLimit="15" pageOutput="false" traceMode="SortByTime" localOnly="true" />

Application-level tracing只有5個特性(attribute):
  1. enabled
  2. requestLimit
  3. pageOutput
  4. traceMode
  5. localOnly

enabled是用來固定要enabled(enabled="true")或disabled(enabled="false")Application-level tracing mode。
requestlimit是來固定記憶軆(memory)里能存储多少個trace信息。
pageOutput是用來來固要显示trace信息在個别.aspx文件的底部或背後(pageOutput="true")或不要显示(pageOutput="false")。
traceMode是用來來固trace信息的此次序。
localOnly是來固誰能通過Trace Viewer(http://servername/projectname/trace.axd)來閲讀存储在記憶軆里的trace信息;local computer(localOnly="true")或remote machine(localOnly="false")。

注意
  Web.Config文件里數据是case sensitive,也就是true不等于True

以下是不同Application-level tracing和Page-level tracing的配置值數组合所引起不同的tracing结果。 
 

Tracing

PageOutput 结果
Page-level Application-level
Trace="True" enabled="True pageOutput="true"

生產并且显示trace信息在個别.aspx文件的底部或背後和存储在記憶軆里。

Trace="True" enabled="True" pageOutput="false"

生產并且显示trace信息在個别.aspx文件的底部或背後和存储在記憶軆里。

Trace="True" enabled="False" pageOutput="true"

生產并且显示trace信息在個别.aspx文件的底部或背後和存储在記憶軆里。

Trace="True" enabled="False" pageOutput="false"

生產并且显示trace信息在個别.aspx文件的底部或背後和存储在記憶軆里。

Trace="False" enabled="True" pageOutput="true"

不生產trace信息。

Trace="False" enabled="True" pageOutput="false"

不生產trace信息。

Trace="False" enabled="False" pageOutput="true"

不生產trace信息。

Trace="False" enabled="False" pageOutput="false"

不生產trace信息。

Trace没設定义 enabled="True" pageOutput="true"

生產并且显示trace信息在個别.aspx文件的底部或背後和存储在記憶軆里。

Trace没設定义 enabled="True" pageOutput="false"

生產trace信息和存储在記憶軆里。

Trace没設定义 enablede="False" pageOutput="true"

不生產trace信息。

Trace没設定义 enabled="False" pageOutput="false"

不生產trace信息。


Application-level tracing另一好處是它能讓我們選擇要把trace信息显示在.aspx底部(背後)或存储在記憶軆(memory)里,然後用Trace Viewer去讀取相闗的trace信息。如果想將每一個WebForm的trace信息存储到記憶軆里而又不显示在.aspx文件的底部,那就先要把個别WebForm里的Trace="True"删除(Trace没設定义)和把pageOutput的值數改去true,否則就没效!以下是用Trace Viewer閲讀trace信息的界面。 

  

如果你不想给别人用Trace Viewer(http://servername/projectname/trace.axd)來閲讀種種trace信息,你可以更改machine.config(system folder\Microsoft.NET\Framework\version number\Config\machine.config)文件里的path="trace.axd"path=""(在httpHandler單元里)。
   <httpHandlers>
      <add verb="*" path="trace.axd" type="System.Web.Handlers.TraceHandler" />
   </httpHandlers>

一般我們都會開發自己的Class Object,而上面两種tracing方法都不能用來生產Class Object里的trace信息;而要改用System.Web名字空間(namespace)里的HttpContect.Current.Trace Object。

首先在Class(比如説TraceInComVB.vb或TraceInComCS.cs)代碼里引用:
VB.NET
   Imports System.Web
C#
   using System.Web;

然後在Class的構造函數(Constructor)里enabled或disable tracing功能:

Imports System.Web
Public Class TraceInComVB

    
Public Sub New()

        
' TODO - Enabled tracing 功能。
        HttpContext.Current.Trace.IsEnabled = True

    
End Sub


    
Public Function InComFunction(ByVal DataValue As StringAs String

        
' TODO - 生產trace信息 (HttpContext.Current.Trace.Write)。
        HttpContext.Current.Trace.Write("TraceInComVB""InComFunction方法,一")

        
' TODO - 生產trace信息 (HttpContext.Current.Trace.Warn)。
        HttpContext.Current.Trace.Warn("TraceInComVB""InComFunction方法,二")

        
' 設定返回值
        Return DataValue & " " & Now.ToString("hh:mm:ss")

    
End Function


End Class

using System;
using System.Web;

namespace TraceObjCS
{
    
/// <summary>
    
/// Summary description for TraceInComCS.
    
/// </summary>

    public class TraceInComCS
    
{
        
public TraceInComCS()
        
{
            
// TODO - Enabled tracing 功能。
            HttpContext.Current.Trace.IsEnabled = true;
        }


        
public string InComFunction(string DataValue)
        
{

            
// TODO - 生產trace信息 (HttpContext.Current.Trace.Write)。
            HttpContext.Current.Trace.Write("TraceInComVB""InComFunction方法,一");

            
// TODO - 生產trace信息 (HttpContext.Current.Trace.Warn)。
            HttpContext.Current.Trace.Warn("TraceInComVB""InComFunction方法,二");

            
// 設定返回值
            return DataValue + " " + DateTime.Now.ToString("hh:mm:ss");

        }

    }

}


講解了一大堆的如何用Trace Object的概念,也是時侯講解一下trace result里的信息了。Trace result里提供了好幾個種纇的信息:
  1. Request Details
  2. Trace Information
  3. Control Tree
  4. Cookies Collection
  5. Headers Collection
  6. Form Collections
  7. Server Variables

尤其是Trace Information,所有用Trace.Write或者Trace.Warn生產的trace信息就會显示在這里了。包括执行的時間(From First)和總共用了多久的時間(From Last)。

點撃下載代碼-VB
點撃下載代碼-CS

posted on 2005-03-19 21:58  克仔  阅读(3859)  评论(1编辑  收藏  举报