[原文源碼下載]
[譯者改後源碼下載]
原文發佈日期:2007.03.14
作者:Scott Mitchell
翻譯:webabcd
介紹
在程序部署之前,要經歷許多軟件工程中定義的重要階段,如需求分析、設計、編碼和測試等。 但是,並不是說一旦程序部署並使用之後就脫離軟件工程的各個階段了。 不管一個web程序有多好的設計、多好的編碼、多好的測試,它總是會有掉鏈子的時候。 如數據庫服務器掉線,web站點比你憑經驗預期的有更大的負載,或者你的web服務器本身的硬件出現問題等。 除非你的程序是很輕量級的或者是上帝給你寫的,否則它總是會時不時地蹦出一些問題。
爲了發現和診斷這些問題,非常重要的一步就是監視web程序並記錄日誌。 有很多開源的軟件和微軟開發的類庫可以幫助你記錄未處理的異常並通知給開發人員。 如何記錄未處理的異常可以參看人性化地響應未處理異常 – 處理未經處理的異常。
ASP.NET 1.x不包括任何內嵌的日誌和通知系統,所以需要開發人員寫一些代碼或者做一些配置。 然而,ASP.NET 2.0提供了內嵌的“健康監測”工具,你可以方便快捷地通過配置來把web站點的一些事件記錄到事件日誌、數據庫、WMI、email或ASP.NET頁面跟蹤系統。 另外,健康監測系統是使用Provider設計模式(譯者注:可以看一下我寫的ASP.NET 2.0中實現Provider設計模式的文章)開發的,這樣我們就可以實現自己的記錄日誌的邏輯了。
本文是研究ASP.NET 2.0的健康監測系統的系列文章的第一篇。 我們將在此學一學健康監測系統的基礎知識,以及如何建立一個健康監測系統,從而將日誌記錄到SQL Server數據庫。 繼續往下看,你會知道得更多!
健康監測系統概述
ASP.NET 2.0的健康監測系統是用來監測運營環境中ASP.NET程序的運行狀況的。 它可以記錄事件信息到一個指定的日誌源中。 例如,它可以記錄像程序開始和停止、登錄的成功和失敗、未處理的異常信息等到一個像Windows事件日誌或SQL Server數據庫這樣的日誌源。 配置健康監測系統是非常容易的,只用在Web.config中增加一些配置信息從而指定事件監測者和要發往的日誌源即可。
雖然.NET 2.0框架提供了一些內嵌的健康監測事件和日誌源,但是當你需要增加自定義事件或換成另一個日誌源的時候並不需要更改這些東西。 你可以通過擴展WebBaseEvent類來創建新的事件,通過擴展WebEventProvider類來創建自定義的日誌源。 健康監測系統可以在設計模式中使用,並且允許你通過對配置信息的一些改變,從而在程序裏添加自定義事件和自定義日誌源。
在這個系列文章的未來的內容裏,我們將會探討一下如何創建自定義事件和自定義日誌源。 而本文中,我們將只使用內嵌的事件和日誌源來做示例。
配置健康監測系統
通過Web.config的<healthMonitoring>元素可以配置健康監測系統,該元素用於指定事件映射、事件訂閱規則和日誌源。 它們中的每一項都是作爲<healthMonitoring>元素的子元素被定義的。 讓我們來分別看看這些子元素:
·Event Mappings (<eventMappings>) – 顧名思義,就是一套事件。 它的name會在其它節點中被引用。
·Log Sources (<providers>) - 顧名思義,就是能作爲日誌源的類型。
·Event Subscription Rules (<rules>) – 與定義在<eventMappings>節點的事件和定義在<providers>節點的日誌源相關聯。
接下來的這個示例演示瞭如何將這三個節點結合起來使用。 首先我們定義了一個名爲“All Errors”的事件影射,它表示的是所有從WebBaseErrorEvent類繼承的事件類。 接下來,定義了一個名爲“EventLogProvider”的日誌源,它會映射到EventLogWebEventProvider類,其意味着事件信息要被記錄到Windows的事件日誌中。 最後的名爲“All Errors Default”的事件規則描述用來關聯“All Errors”事件,並把相關日誌記錄到“EventLogProvider”日誌源中。 像這樣定義完Web.config後,如果發生任何未處理異常或明顯的錯誤事件,都將記錄到Windows的事件日誌中。
<system.web>
<healthMonitoring enabled="true">
<eventMappings>
<clear />
<add name="All Errors" type="System.Web.Management.WebBaseErrorEvent"
startEventCode="0" endEventCode="2147483647" />
</eventMappings>
<providers>
<clear />
<add name="EventLogProvider" type="System.Web.Management.EventLogWebEventProvider" />
</providers>
<rules>
<clear />
<add name="All Errors Default" eventName="All Errors" provider="EventLogProvider"
profile="Default" minInstances="1" maxLimit="Infinite" minInterval="00:00:00" />
</rules>
</healthMonitoring>
</system.web>
</configuration>
在你的Web.config中做了如上配置後,一旦遇到未處理異常,健康監測系統就會自動地將錯誤的詳細信息記錄到Windows的事件日誌中。 請注意<rules>節點中設置的minInterval屬性。 該屬性的值用於指定相同的事件在多長時間的間隔後才能被再次記錄。 在上面的示例中,我把minInterval的值設置爲_00:00:00,其意味着即使發生了相同的事件也都會被記錄,打個比方說,如果10秒內某一事件發生了5次,那麼這5個事件都會被記錄。 當然,你也可以修改這個值。 如果你把minInterval的值設爲“00:00:30”,那麼首次被觸發的事件會被記錄。 如果相同的事件在10秒後再次被觸發,那麼該事件是不會被記錄的,因爲還沒有到我們設置的30秒的間隔時間。 如果要求一旦有事件發生就需要記錄的話,那麼就要確保minInterval的值爲“00:00:00”, 否則可以給minInterval設置成一個較高的合適的值。
本文結束後會有一個web示例程序提供下載,其內有一個網頁,網頁中有一個按鈕,當你單擊這個按鈕的時候就會觸發ApplicationException。 當你訪問了這個網頁並單擊了這個按鈕後,就會出現著名的“黃頁”,其意味着發生了一個未處理的異常。 之後,該異常信息就會記錄到Windows的事件日誌中。
發生了未處理異常後所顯示的“黃頁”
未處理異常的詳細信息被記錄到了Windows的事件日誌中。
健康監測系統的默認配置
默認情況下,ASP.NET 2.0程序已經啓用了健康監測系統,並且會記錄所有的錯誤事件和失敗的請求到Windows的事件日誌中。 所有web程序都需要讀取machine級別的Web.config,你可以在該文件中查看或修改健康監測系統的默認功能,此文件的具體位置在“%WINDOWS%\Microsoft.NET\Framework\版本號\CONFIG\”文件夾內。 在上面的示例中,我使用了<clear />,它的作用是在指定我自己的配置之前移除默認設置。
除了指定的“EventLogProvider”日誌源外,默認配置中還包括其他兩個Provider,如下所示:
·“SqlWebEventProvider” – 使用SqlWebEventProvider類把事件信息記錄到SQL Server數據庫中。 其默認連接使用的是“LocalSqlServer”所指的連接字符串,它會映射到“App_Data”文件夾內的㩵SPNETDB.MDF數據庫。 默認情況下,Membership使用的也是這個數據庫。 (關於Membership的更多信息請參看Examining ASP.NET 2.0's Membership, Roles, and Profile)
·“WmiWebEventProvider” – 使用WmiWebEventProvider類把事件信息記錄到Windows Management Instrumentation(WMI)
雖然在.NET框架中附加了這3個日誌源的Provider,但是默認情況下它們並沒有包含在<providers>節點內。 如果你想添加這些Provider或是自定義的Provider,那麼你需要像我們上面的示例那樣在Web.config裏添加<prviders>元素。
另外,在<eventMappings>節點下還有一些預定義事件可以讓你設置。 我們查看一下machine級別的Web.config文件。
本文接下來的部分將研究一下如何使用“SqlWebEventProvider”日誌源,它可以把錯誤日誌記錄到SQL Server數據庫中。
·配置web程序的健康監測系統,使其記錄日誌到SQL Server數據庫。
·爲數據庫添加必需的結構信息,使其可以作爲日誌源而被使用。
如果你給“SqlWebEventProvider”日誌源使用的是默認數據存儲的話(App_Data文件夾內的ASPNETDB.MDF數據庫),那麼該數據庫會在健康監測系統首次記錄事件的時候被自動地創建。 如果你想使用其它數據庫,那麼就需要用到ASP.NET SQL Server註冊工具(aspnet_regsql.exe)了。 你可以在命令行中運行它,如下所示:
aspnet_regsql.exe -E -S serverName -d database -A w
aspnet_regsql.exe -U userID -P password -S serverName -d database -A w
aspnet_regsql.exe程序放置在“%WINDOWS%\Microsoft.NET\Framework\版本號\”文件夾內。 同樣在這個文件夾內,你也會發現一個名爲“InstallWebEventSqlProvider.sql”的文件,該文件就是創建健康監測系統的數據庫結構的T-SQL腳本。
它的結構非常地簡單易懂,就是一個表 – aspnet_WebEvent_Events和一個存儲過程 – aspnet_WebEvent_LogEvent。 就是這些東西,很簡單吧。 當健康監測系統監測到發生了某一事件,並且你已經配置了記錄日誌到“SqlWebEventProvder”日誌源,那麼存儲過程aspnet_WebEvent_LogEvent將會被執行,從而在aspnet_WebEvent_Events表中添加一條新記錄。
當把數據庫建完後(如果你使用的是App_Data文件夾內的ASPNETDB.MDF數據庫,那麼你就不需要做這件事了),你就可以在Web.config中添加<healthMonitoring>節點了。 通過下面示例那樣的配置,就可以指示健康監測系統使用“SqlWebEventProvider”日誌源記錄所有的錯誤事件和所有的程序事件。 你應該在<providers>節點內重新設置“SqlWebEventProvider”。 我使用的是默認的連接字符串(“LocalSqlServer”),如果你不想使用ASPNETDB.MDF作爲你的日誌數據庫,那麼也可以修改這個名字,改爲在Web.config的<connectionStrings>節點中註冊的連接字符串的名字。
<system.web>
<healthMonitoring enabled="true">
<eventMappings>
<clear />
<!--記錄所有錯誤事件-->
<add name="All Errors" type="System.Web.Management.WebBaseErrorEvent"
startEventCode="0" endEventCode="2147483647" />
<!--記錄程序開始和結束事件-->
<add name="Application Events" type="System.Web.Management.WebApplicationLifetimeEvent"
startEventCode="0" endEventCode="2147483647"/>
</eventMappings>
<providers>
<clear />
<add connectionStringName="SqlConnectionString" maxEventDetailsLength="1073741823"
buffer="false" name="SqlWebEventProvider" type="System.Web.Management.SqlWebEventProvider" />
</providers>
<rules>
<clear />
<add name="All Errors Default" eventName="All Errors" provider="SqlWebEventProvider"
profile="Default" minInstances="1" maxLimit="Infinite" minInterval="00:00:00" custom="" />
<add name="Application Events Default" eventName="Application Events"
provider="SqlWebEventProvider" profile="Default" minInstances="1"
maxLimit="Infinite" minInterval="00:00:00" custom="" />
</rules>
</healthMonitoring>
</system.web>
</configuration>
像上面這樣配置完後,無論程序的開始或是停止,又或是發生了錯誤事件,其事件信息都會被記錄到App_Data文件夾下的ASPNETDB.MDF數據庫。(如果這個數據庫不存在,則它會被自動地創建。)
在本文的結尾處你可以下載到一個簡單的web站點程序,它演示了這個功能。 該程序包括兩個網頁,Default.aspx和Log.aspx。Default.aspx內有一個按鈕,當點擊了這個按鈕後就會觸發ApplicationException。 Log.aspx中使用的是GridView,DetailsView和兩個SqlDataSource控件,用於顯示aspnet_WebEvent_Events表中的事件信息。
注意,每一個事件都有與其相關聯的EventCode值。 參考Erik Reitan的BLOG文章 - FAQ - Health Monitoring in ASP.NET 2.0,它裏面有一個表格列出了事件代碼和事件類型(當然文中還有其它有用的信息)。 (譯者注:我把它轉載過來,如下表所示)
InvalidEventCode |
-1 |
UndefinedEventCode |
0 |
UndefinedEventDetailCode |
0 |
ApplicationCodeBase |
1000 |
ApplicationStart |
1001 |
ApplicationShutdown |
1002 |
ApplicationCompilationStart |
1003 |
ApplicationCompilationEnd |
1004 |
ApplicationHeartbeat |
1005 |
RequestCodeBase |
2000 |
RequestTransactionComplete |
2001 |
RequestTransactionAbort |
2002 |
ErrorCodeBase |
3000 |
RuntimeErrorRequestAbort |
3001 |
RuntimeErrorViewStateFailure |
3002 |
RuntimeErrorValidationFailure |
3003 |
RuntimeErrorPostTooLarge |
3004 |
RuntimeErrorUnhandledException |
3005 |
WebErrorParserError |
3006 |
WebErrorCompilationError |
3007 |
WebErrorConfigurationError |
3008 |
WebErrorOtherError |
3009 |
WebErrorPropertyDeserializationError |
3010 |
WebErrorObjectStateFormatterDeserializationError |
3011 |
AuditCodeBase |
4000 |
AuditFormsAuthenticationSuccess |
4001 |
AuditMembershipAuthenticationSuccess |
4002 |
AuditUrlAuthorizationSuccess |
4003 |
AuditFileAuthorizationSuccess |
4004 |
AuditFormsAuthenticationFailure |
4005 |
AuditMembershipAuthenticationFailure |
4006 |
AuditUrlAuthorizationFailure |
4007 |
AuditFileAuthorizationFailure |
4008 |
AuditInvalidViewStateFailure |
4009 |
AuditUnhandledSecurityException |
4010 |
AuditUnhandledAccessException |
4011 |
MiscCodeBase |
6000 |
WebEventProviderInformation |
6001 |
ApplicationDetailCodeBase |
50000 |
ApplicationShutdownUnknown |
50001 |
ApplicationShutdownHostingEnvironment |
50002 |
ApplicationShutdownChangeInGlobalAsax |
50003 |
ApplicationShutdownConfigurationChange |
50004 |
ApplicationShutdownUnloadAppDomainCalled |
50005 |
ApplicationShutdownChangeInSecurityPolicyFile |
50006 |
ApplicationShutdownBinDirChangeOrDirectoryRename |
50007 |
ApplicationShutdownBrowsersDirChangeOrDirectoryRename |
50008 |
ApplicationShutdownCodeDirChangeOrDirectoryRename |
50009 |
ApplicationShutdownResourcesDirChangeOrDirectoryRename |
50010 |
ApplicationShutdownIdleTimeout |
50011 |
ApplicationShutdownPhysicalApplicationPathChanged |
50012 |
ApplicationShutdownHttpRuntimeClose |
50013 |
ApplicationShutdownInitializationError |
50014 |
ApplicationShutdownMaxRecompilationsReached |
50015 |
StateServerConnectionError |
50016 |
AuditDetailCodeBase |
50200 |
InvalidTicketFailure |
50201 |
ExpiredTicketFailure |
50202 |
InvalidViewStateMac |
50203 |
InvalidViewState |
50204 |
WebEventDetailCodeBase |
50300 |
SqlProviderEventsDropped |
50301 |
WebExtendedBase |
100000 |
結論
ASP.NET 2.0內置的健康監測系統可以非常容易地使指定的事件自動地記錄到指定的日誌源。 本文中,我們研究了兩種內置日誌源:“EventLogProvider”和“SqlWebEventProvider”,它們會分別記錄事件信息到Windows的事件日誌中和SQL Server數據庫的一個表裏。 健康監測系統可以捕獲自定義事件,也可以使用其它日誌源。 在後面的文章中,我們將會看到更多的日誌源,甚至是創建我們自己的日誌源。 我們也會知道如何創建自己的事件,以及如何自動地觸發一個事件。
到這裏本文結束。祝編程愉快!