銷售: 1-800-867-1380

開發 Azure 應用程式的疑難排解最佳作法

更新日期: 2014年11月

作者: William Bellamy,Microsoft 首席回報工程師

參與者:

  • Bryan Lamos,Microsoft 資深程式管理員,產品品質

  • Kevin Williamson,Microsoft 資深回報工程師,Azure 開發人員支援

  • Pranay Doshi,Microsoft 資深程式管理員,Azure 生產服務

  • Tom Christian,Microsoft 資深回報工程師,Azure 開發人員支援

發行日期: 2012 年 1 月

Microsoft 的第一優先任務是協助 Azure 客戶保持應用程式正常運作。Azure 服務等級協定定義當您部署兩個以上的角色執行個體時,外部連線可達到 99.95% 的可用性。然而,外部連線是確保您能夠從 Microsoft 資料中心外部連上您的應用程式,這與「網站啟動」不同。大部分 Azure 服務都有多重相依性:SQL Azure、快取、內部傳遞網路、內部資源 (透過 Azure Connect) 等。任何相依性失效時可能導致 Azure 服務運作不如預期。

本文著重於以不同的疑難排解工作和建議的方法來設計和開發 Microsoft Azure 平台上更具支援性的應用程式。當 (而不是如果) 問題發生時,時間非常重要。適當的規劃可讓您找出並解決問題,而不必連絡 Microsoft 支援。本文提出的辦法也能加速解決需要 Microsoft 協助的問題。

本文主要是作為技術軟體對象的資源:負責設計、建立和部署 Azure 解決方案的軟體設計人員、架構設計師、IT 專業人員、系統整合者、開發人員和測試人員。

我們假設您對 Azure 應用程式的應用程式開發週期已有基本的瞭解,包括 Azure 開發和執行階段環境的術語和各種元件。

我們也假設您將遵守 Azure 的基本指導方針,例如使用最新版的 Azure SDK,以及投入正式運作之前先測試程式碼變更。

本文編排為兩個章節:

  • Azure 診斷資訊的概觀:

    • Azure 資源

    • 協力廠商資源

  • 支援性設計、開發和部署的最佳作法:

    • 部署應用程式之前。

    • 立即失敗的設計和監視。

    • 發生問題時的處理方式。

開發人員都不希望已進入生產環境的應用程式中斷運作。我們在開發期間盡最大努力測試程式碼,以期達到最健全的狀態而能正確無誤地執行,之後我們才繼續下一個專案。很遺憾,程式碼很是會發生問題。In在分散式環境中,由於應用程式元件區隔而形成的複雜性,細微的錯誤也可能演變成災難。這就是為何一開始就必須在應用程式中設計好記錄和追蹤策略的原因。基本上,此策略中可規定在元件層級上動態調整記錄的類型和數量,而不必重建/重新部署。大量的記錄不保證一定能快速解決問題。多不見得好,因為大量資料會增加解碼的時間,還可能拖垮應用程式的效能。可調整的記錄功能能夠控制記錄資料的大小和儲存成本。

就像 Azure 平台上執行的分散式應用程式一樣,當使用者與應用程式互動時,應用程式的多個元件也會彼此互動。只要一致並詳實地記錄程式碼的流程,並特別注意對外部服務的呼叫,任何人一定都能夠追蹤您應用程式的執行流程。從現在起的一兩年內,當發生問題時,這對來說極具價值。最好可從 ServiceConfiguration.cscfg 檔案來調整記錄層級,以利於變更而不必重新部署。

在開發期間可利用偵測組建以利於取得最多的錯誤資訊。開發人員通常會加入偵測陳述式,而有時是加入某種形式的錯誤記錄。請注意,在正式組建中會移除偵錯陳述式,這表示發生問題時就要自求多福。大多數客戶都不願意再以偵錯組建來解決實際執行的問題,然後重新部署。Mike Kelly 指出開發人員必須設定的四種診斷輸出:

  • 偵錯輸出 - 只在偵錯組建中,包含「判斷提示」

  • 追蹤 - 在執行期間追蹤控制流程

  • 事件記錄 - 重大事件

  • 錯誤記錄 - 例外或危險的狀況。

許多偵錯訊息也許都應該放入追蹤陳述式中,以善用不同的追蹤層級。Azure 診斷也可讓您設定診斷和停用傳輸,以控制何時將資訊寫入永續性儲存體。

下列各節說明在 Azure 上建立應用程式的開發人員可用的一些疑難排解資源。

在探討 Azure 之前,讓我們先查看 Windows Server 應用程式目前的疑難排解範例。發生實際執行的問題時,開發人員通常會檢查記錄。預設會啟用事件記錄檔和 IIS 記錄檔,且重新開機後仍然存在 (只要磁碟未故障)。

如果啟用遠端桌面,則同樣的程序也能運用在 Azure 應用程式中。開發人員可以連線至每一個執行個體來收集診斷資料。若要收集診斷資料,您可以將記錄檔複製到儲存體,或設定 RDP 將記錄檔複製到本機電腦。此程序相當耗時,如果重新製作執行個體的映像,因而啟動全新版本的 Web 或背景工作角色,此程序將會失敗。很顯然,此全新版本抹除先前所有的記錄。主體或客戶虛擬機器升級作業系統時就會重新製作映像。重新製作映像是 Azure 架構中的正常情況。

最初的 Azure SDK 1.0 能夠收集診斷資料並儲存於 Azure 儲存體,統稱為 Azure 診斷 (WAD)。此軟體以 Windows 事件追蹤 (ETW) 架構為基礎,滿足 Azure 向外延展架構提出的兩項設計需求:

  1. 將重新製作執行個體映像期間會遺失的診斷資料儲存下來。

  2. 為多個執行個體的診斷資料提供一個集中存放庫。

Microsoft.WindowsAzure.Diagnostic 命名空間延伸 System.Diagnostics 命名空間,可讓您在 Azure 應用程式內使用 ETW 架構。

Windows Azure - 診斷流程圖

在角色中加入 Azure 診斷之後 (ServiceConfiguration.cscfg 和 ServiceDefinition.csdef),WAD 就能收集該特定角色的所有執行個體的診斷資料。診斷資料可用來進行偵錯和疑難排解、測量效能、監視資源使用量、進行流量分析和容量規劃,以及稽核。可依照排程或視需要而傳輸至 Azure 儲存體帳戶來持續保存。

Azure 診斷改變伺服器架構的四大方面:

  1. 建立應用程式時必須啟用診斷。

  2. 需要特定工具/步驟才能將診斷結果視覺化。

  3. 損毀將導致遺失診斷資料,除非寫入永久儲存體 (反之,Azure 儲存體在每一個執行個體上)。

  4. 將診斷資料儲存在 Azure 儲存體會產生每月成本。

成本特別重要,因為 Azure 平台的一項主要優點就是減少成本。目前,若要排除 WAD 的使用成本,唯一的辦法就是將資料留在虛擬機器上。這在小型部署中尚且可行,但在許多情況下就不切實際。以下是將財務影響降到最低的幾個方法:

  1. 確定儲存體帳戶和您的應用程式位於相同的資料中心。如果因為某種理由而不在相同的資料中心,請明智地選擇排程傳輸的間隔。傳輸時間過短會增加資料相關性,但此利弊取捨尚不足以構成額外的頻寬和處理負荷。

  2. 定期複製和清除 Azure 儲存體中的診斷資料。診斷資料會通過 Azure 儲存體,但沒必要留在那裡。有許多工具可以這樣做:System Center Monitoring Pack for Azure、Cerebrata 的 Azure Diagnostics Manager 和 Azure PowerShell Cmdlet。

  3. 只選擇對應用程式進行疑難排解和監視時所需的診斷資料。擷取太多資料除了導致成本大幅增加,也更不容易進行疑難排解。

  4. 在應用程式實作隨需切換,以控制診斷資料的收集和範圍。

  5. 善用記錄層級 (詳細、資訊、警告、錯誤) 以取得所有資訊,再利用部署後的 WAD 組態來選擇性地收集資料。

Azure 儲存體是任何支援性應用程式的基礎。基本上,每一個應用程式都應該設定並啟用此功能。

Azure 儲存體分析可執行記錄,並提供儲存體帳戶的度量資料。您可以使用此資料追蹤儲存體要求、分析使用趨勢,以及診斷儲存體帳戶的問題。

撰寫支援性 SQL Azure 程式碼的重點在於檢查傳回碼,並確定有可靠的重試程式碼可處理失敗情形。

監視組件可讓您使用 Microsoft System Center Operations Manager 來監視 Azure 應用程式的可用性和效能:

  • 探索 Azure 應用程式。

  • 提供每一個角色執行個體的狀態。

  • 收集和監視效能資訊。

  • 收集和監視 Windows 事件。

  • 收集和監視每一個角色執行個體的 .NET Framework 追蹤訊息。

  • 清理 Azure 儲存體帳戶的效能、事件和 .NET Framework 追蹤資料。

  • 變更角色執行個體數量。

Microsoft System Center Operations Manager 2007 最適合用來監視 Azure 應用程式的健康情況。

Azure 目前未提供完整解決方案讓客戶監視和管理其託管服務。關於網路資訊,speedtest.net 有工具可測量回應時間、頻寬和整體連線品質。有許多非常實用的工具適用於 Azure。下列清單不表示對任何特定的協力廠商工具作背書或推薦使用。

Azure PowerShell Cmdlet

從遠端管理診斷資料最好的方法是使用 Azure PowerShell Cmdlet。Cmdlet 以 Azure Management and Diagnostics API 為基礎,您可以透過 CodePlex 專案取得完整的原始程式碼,以深入瞭解基礎的 API。2.0 版可讓您設定/下載/清理 Azure 診斷的各個部分。Michael Washam 的部落格提供一些很好的範例指令碼

網路視監:AlertBot、Gomez、Keynote、Pingdom

Compuware 的 Gomez Application Performance Management、KeynotePingdomAlertBot 是一些從外部監視 Azure 應用程式的解決方案。可讓您監視應用程式的可用性並最佳化效能。有些服務 (例如 Pingom) 可在偵測到錯誤時以電子郵件、簡訊或桌面通知程式來發出通知。這種監視需要模擬使用者的動作才能順利監視,因為未完全正常運作的 Web 角色有時會顯示首頁。

Azure Check

Apica 的 AzureCheck 是可「從外部」監視 Azure Web 應用程式的工具。若要使用此工具,您需要下載其程式碼,並加入至部署中當做啟動工作。此工具的優點是您不需要將記錄儲存在儲存體帳戶中,因此可減少監視成本。

Azure Diagnostics Manager

Cerebrata 的 Azure Diagnostic Manager 是可管理 Azure 診斷的 Windows 用戶端。它可顯示或下載 WAD 所收集的記錄。您也可以管理 WAD 組態,有一個儀表板可讓您監視即時效能。

Azure 儲存體總管

有許多方式可瀏覽 Azure 儲存體。Azure 儲存體團隊提供一份儲存體總管清單。其中任何一項都可讓您查看 WAD 檔案和 Azure 儲存體分析檔案。Cloudberry Lab 的 Explorer for Azure Blob Storage 提供使用者介面,只要按一下 [儲存體設定],就可直接在應用程式中進行儲存體分析。

IntelliTrace

Microsoft Visual Studio 2010 Ultimate 包含 IntelliTrace,啟用後就可以先偵錯應用程式,再部署到生產環境。IntelliTrace 支援 ASP.NET 和 WCF 應用程式。Intellitrace 在生產服務中啟用時不受支援,但在應用程式部署到 Azure 之後,可用來取得應用程式的例外狀況。Jim Nakashima 的部落格文章說明如何使用 IntelliTrace 來偵錯 Azure 雲端服務

AVIcode

Microsoft 買下 AVIcode,現在已納入成為 Microsoft System Center 的一部分。AVIcode 有一套完整的應用程式監視功能,提供 .NET 應用程式效能監視功能。

Fiddler

Fiddler 是一個 Web 偵錯 Proxy,可記錄您的電腦與網際網路之間的所有 HTTP(S) 流量。Fiddler 可讓您檢查流量、設定中斷點及「把玩」傳入或傳出的資料。Fiddler 尤其適合對 Azure 儲存體進行疑難排解。

若要對本機開發虛擬環境使用 Fiddler,請使用 ipv4.fiddler 而非 127.0.0.1:

  1. 啟動 Fiddler。

  2. 在開發虛擬環境中啟動您的服務。

  3. 瀏覽至 http://ipv4.fiddler:/。Fiddler 會追蹤要求。

若要對本機開發儲存體使用 Fiddler,您需要修改服務組態檔來指向 Fiddler:

  1. 開啟 ServiceConfiguration.cscfg 檔案,將連接字串改為:

    Value=“UseDevelopmentStorage=true;DevelopmentStorageProxyUri=http://ipv4.fiddler”

  2. 啟動 Fiddler。

  3. 啟動您的服務。Fiddler 會追蹤任何儲存體要求。

效能剖析

您可以在 Azure 應用程式執行於 Azure 時進行程式碼剖析,以找出任何效能問題。當您從 Visual Studio 發行 Azure 應用程式時,您可以選擇對應用程式進行程式碼剖析,並選取所需的程式碼剖析設定。

Azure VM 小幫手

VM Assitant 工具一個是 CodePlex 專案,當您以遠端桌面連到執行個體時,可將所有相關資料收集到一個地方,以節省診斷問題的時間。[VM Health] 按鈕提供執行個體的目前狀態。

在論及雲端架構解決方案時,相較於公司資料中心的伺服器上所部署的傳統盒裝產品軟體,更重要是軟體設計人員和開發人員在設計階段,就應該針對問題做好準備。本節著重於開發人員在雲端中負責緩和的某些特定狀況,並說明如何做好準備,以便於問題發生時迅速解決。

與傳統的伺服器型部署不同,基本差別是您無法再存取伺服器硬體。Azure SDK 1.3 多了使用遠端桌面服務來存取 Azure 角色的功能。使用最新的 SDK 可確保獲得最佳體驗。啟用遠端桌面是建立支援性 Azure 服務的首要步驟。必須在部署之前完成此步驟。

啟用遠端桌面所需的其中一個步驟是選擇使用者名稱、密碼和帳戶到期日。Azure 管理入口網站中可以變更這三個項目。如果您忘記幾個月前第一次部署服務時所設定的密碼,這會很方便解決問題。

當您在入口網站按一下 [設定] 按鈕來變更這三個參數時,通常會看到此訊息順序:正在更新...、正在等候主機...、角色已成功更新。正在等候主機…、就緒。這對應於角色接收變更事件,接著處理變更事件。客戶可以訂用帳戶 RoleEnvironment 事件,之後,當收到 RoleEnvironment.Changing 事件時:接受變更並持續執行 (預設值),或使執行個體離線、套用變更,然後重回線上 (e.Cancel = true)。

如果程式碼在變更事件上回收角色,則會回收該託管服務中所有角色中的所有執行個體。由於更新網域架構的緣故,每一角色有多個執行個體的服務不會停止運作,但因為每個網域都回收,效能可能下降。更重要的是,如果您卡在每個月才重現一次的問題上,則會失去擷取執行個體狀態的機會。因此,建議您以未過期的已知且安全的認證來啟用遠端桌面連線。

接著,您必須測試來確定連線有效。在入口網站按一下 [連接] 按鈕,即可輕鬆測試。在大部分情況下,您應該保留一份 RDP 檔案,以便於變更 Local Resources 區段來包含您的本機磁碟。這樣可讓您輕鬆地對執行個體來回複製檔案。按一下 [本機資源] 索引標籤,再按一下 [其他] 按鈕,即可複製。[一般] 索引標籤的 [連線設定值] 可讓您將設定儲存至 .RDP 檔案。

Windows Azure - 遠端桌面連接對話方塊

如何在 VM 上疑難排解

現在您已連接至執行個體,您想要尋找什麼?如果您要對無法啟動的角色進行疑難排解,請仔細閱讀這篇 MSDN 文章。Kevin Williamson 有一篇很棒的部落格文章,其中概略說明哪裡可找到記錄檔和需要偵錯什麼程序。

您也可以安裝 VM Assistant 來查看記錄檔,取得有關您的執行個體的實用資訊。您也可以安裝網路監視器或 Fiddler 等工具來了解網路情形。其中一項最簡單的測試是在執行個體上執行 Internet Explorer,並連接至您的網站,這樣會顯示例外狀況詳細資料。

偵錯裝載的 Web 核心

如果您執行裝載的 Web 核心角色,則虛擬機器中只會有一個命令視窗可用,所以,您應該從命令提示字元中執行 start 來開啟新的 Cmd 視窗,否則會經歷完整的 Windows Server 體驗。以下是一些基本命令的清單:

  • Start – 開啟新的 Cmd 視窗

  • explorer – 開啟 Windows 檔案總管

  • eventvwr – 開啟事件記錄檢視器

  • taskmgr – 開啟工作管理員

  • start iexplore – 執行 Internet Explorer

  • services.msc – 開啟服務管理員

  • control – 開啟控制台

  • certmgr.msc – 開啟憑證管理員嵌入式管理單元

  • regedit – 開啟登錄編輯程式

  • shutdown /r /t 0 – 重新啟動虛擬機器執行個體

  • 啟動工作管理員 – 適用於遺失命令提示字元且需要啟動新的命令提示字元時 (從工作管理員,移至 [檔案 -> 執行 -> Cmd])

遠端桌面是支援性 Azure 服務的基礎,但在角色和執行個體的數量增加時有其限制。例如,有 100 個以上的執行個體時,您怎麼知道需要連接至哪一個執行個體?如果您不知道查看何處和尋找什麼,則使用此疑難排解方法實際上會增加備份網站所需的時間。

重點如下:

  • 在部署期間,在每一個角色上啟用遠端桌面。

  • 設定強式的已知密碼,並確定認證未過期。

  • 在問題發生之前,進行測試以確定存取有效。

  • 儲存連線的 RDP 檔案。

使用 Azure 診斷時有四個主要工作:

  1. 設定 WAD

  2. 設定資料收集

  3. 檢測程式碼

  4. 檢視資料

設定 WAD

Azure 診斷的架構是先在執行個體上收集資料,然後將資料保存到 Azure 儲存體。因此,您必須先到 Azure 管理入口網站建立儲存體帳戶,例如 mylogs。最佳作法是在 Azure 應用程式所在的相同地理位置中尋找您的儲存體帳戶,以避免支付外部頻寬成本,並降低延遲。

在 Azure Tools for Visual Studio 1.4 版 (2011 年 8 月) 和更新版本中,很棒的一項開發功能就是本機和雲端可以有不同的組態檔 (ServiceConfiguration.cscfg)。多個服務組態可在診斷時派上用場,有助於利用儲存體模擬器來免費進行本機測試,同時為生產環境保留個別的組態檔。將應用程式發行至 Azure 時,應用程式未啟動的主要原因之一是忘了將含有 UseDevelopmentStorage=true 的連接字串改為 false

Visual Studio 可讓您輕鬆地在測試期間啟用診斷,只要按一下 [使用 Azure 儲存體模擬器] 按鈕即可:

Windows Azure - 儲存體帳戶連接對話方塊

測試過應用程式並準備發行時,您需要有儲存體帳戶來設定雲端 (ServiceConfiguration.Cloug.cscfg)。David Makogon 在部落格中提出三個理由,表示有別於應用程式資料儲存,應該要有診斷專用的儲存體帳戶:

  1. 為診斷準備個別的存取金鑰,存取記錄時就不會對應用程式資料造成風險。

  2. 多個儲存體帳戶不會產生成本,因為成本是根據資料大小而定。

  3. 具有個別帳戶可以增強效能。

接下來設定連接字串:

<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="DefaultEndpointsProtocol=https;AccountName=<name>;AccountKey=<key>" />

AccountNameAccountKey 值在管理入口網站的儲存體帳戶區段中。AccountName 是資料表和 Blob 儲存體端點 URL 的最前面部分 (“.table.core.windows.net” 之前的部分)。AccountKey 是儲存體帳戶的 Base-64 編碼主要存取金鑰。

依預設,只會啟用 Azure 記錄,但不會保存,因此,您接下來必須決定要收集多少資料,以及何時傳輸記錄。因為會影響您應用程式的效能,並決定您每個月要支付多少儲存費用,請勿草率決定。

首先,您必須判斷 Azure 診斷所收集的資料總共需要多少儲存體。此值取決於執行個體/虛擬機器大小的磁碟大小及 DiagnosticMonitorConfiguration 類別的 OverallQuotaInMB 屬性。例如,如果您設定服務模型來使用 ExtraSmall 虛擬機器大小,則可用的本機儲存體數量上限為 20 GB。依預設,OverallQuotaInMB 設為 4 GB,這表示您總共只有 16 GB 的本機儲存體,可能不夠應用程式和暫存檔使用。OverallQuotaInMB 設定可重複寫入的回繞緩衝區大小。另一方面,如果網站的流量很大,且您已設定許多效能計數器,可能會覆寫您的診斷資料,尤其是您未定期將資料傳輸至永續性儲存體時。

設定虛擬機器大小之後,您可能想要增加到 4 GB 以上。若要這樣做,您可以將 DiagnosticStore 的 <LocalStorage> 元素 (sizeInMB 屬性設為新大小) 新增至 ServiceDefinition.csdef 檔案,並對應地變更 OverallQuotaInMB 值:

<LocalResources>
      <LocalStorage name="DiagnosticStore" sizeInMB="8192" cleanOnRoleRecycle="false" />
    </LocalResources>

cleanOnRoleRecycle 屬性值設為 false,可確保角色回收時不會刪除本機儲存體 "DiagnosticStore"。如需 ServiceDefinition.csdef 的完整程式碼,請參閱<附錄 D:ServiceDefinition.csdef>。此設定不保證移動執行個體時 (硬體問題等) 會保留資料。請記住,診斷設定為一個角色所特有,您必須為每一個角色個別地新增 DiagnosticStore。

對您已設定的診斷資料計算大小總計極為重要,因為如果總和超過 OverallQuotaInMB,Azure 診斷會失敗。查看此錯誤的唯一方法是附加偵錯工具,或在 OnStart 方法中新增 try catch。如果 catch 程式碼有撰寫事件,則應用程式事件記錄檔顯示如下:

Windows Azure - 事件記錄檔

您該如何計算「要求的子配額總和」?每一個項目收集類型 (事件記錄檔、效能計數器等) 都有相關聯的資料緩衝區,依預設為零。BufferQuotaInMB 屬性可保留為預設值零,這表示小於 OverallQuotainMB,也可以明確設定。OverallQuotaInMB 必須小於所有 BufferQuotaInMB 屬性的總和。

如果達到配額,則會在加入新資料時刪除最舊的資料。如果您已設定緩衝區的傳輸間隔,則也會套用此刪除原則。傳輸之後,資料會留在本機儲存體中,且會根據上述原則來刪除。


// Set an overall quota of 8GB.
config.OverallQuotaInMB = 8192;

// Set the sub-quotas and make sure it is less than the OverallQuotaInMB set above
config.Logs.BufferQuotaInMB = 1024;
config.Directories.BufferQuotaInMB = 0; // Use the rest of the storage here
 config.WindowsEventLog.BufferQuotaInMB = 1024;
config.PerformanceCounters.BufferQuotaInMB = 1024;
config.DiagnosticInfrastructureLogs.BufferQuotaInMB = 1024;

Directories 子配額設為零,所以會使用剩餘可用的儲存體配額。如果您設定特定的值,此值必須大於或等於其他配額,因為大小必須足夠包含 IIS 記錄檔 (Web 角色) 和損毀傾印。依預設,Directory.QuotaInMB 設為 1024 MB,這表示如果損毀傾印大於 1 GB,則無法寫入傾印。迷你傾印是減少傾印大小的一種方法。

完整傾印檔案包含損毀時處理程序的記憶體 (Virtual Bytes)。因為我們在 64 位元版本的 Windows 中執行,記憶體上限就是機器的實體記憶體。您可以查看執行個體/虛擬機器大小表格的記憶體欄位來找到此值。例如,ExtraLarge 執行個體的完整損毀傾印可能高達 14 GB。顯然,這是最差的情況,處理程序用完所有可用的記憶體,但這不也是您真的想要擷取傾印檔案的時候?

現在,您知道需要收集多少診斷資料以決定策略來保存該資料。

有一種選擇是在未確定發生問題之前不要開始收集資料。此選擇有兩個缺點:

  1. 您如何得知已發生問題?雖然可依賴客戶來回報重大問題,但對於更潛伏的問題又該如何?例如記憶體流失。

  2. 問題開始發生之前有何基準?應用程式一直以 80% 的 CPU 執行?或只是問題的徵兆?

出乎意料,此選擇最受歡迎,因為不需要任何成本、規劃或動作。毋庸置疑,這也是最差的選擇。

第二個選擇是設定所有需要的計數器,但不將資料保存到 Window Azure 儲存體。發生問題時,可檢查資料或手動開始傳輸。這似乎是很理想的解決辦法,因為在問題出現之前不會產生成本。很遺憾,第一種選擇的同樣問題也發生在第二種選擇,且復原的時間更久。

第三種選擇是將不同的 ScheduledTransferPeriod 設定得夠小,以確保不會覆寫診斷資料,但也要夠大到不會影響應用程式的效能。您可指定的最小傳輸週期是 1 分鐘,幸好,任何下位值會無條件進位到 1,所以持續性不會停用。因此,在真的需要您的診斷資料之前,請記得先檢查資料有在傳輸。

在許多範例程式碼中,一個常見的問題是 ScheduledTransferPeriod 設為 1 分鐘,因而對生產環境中的應用程式效能造成不良影響。範例採用最小值的理由是為了讓您快速看到它是否正常運作。大多數開發人員都不想等待 30 分鐘來驗證記錄已傳送。有兩種辦法可解決此難題:部署後,使用其中一個其他實用工具,有系統地修改 WAD 組態,或利用本節先前所述的多個服務組態檔功能,在 ServiceConfiguration.cscfg 檔案中加入程式碼和一項設定。ServiceConfiguration.Local.cscfg 中建立的設定如下:

<ConfigurationSettings>
      <Setting name="ScheduledTransferPeriod" value="1" />

而在 ServiceConfiguration.Cloud.cscfg 中的設定���下所示:

<ConfigurationSettings>
      <Setting name="ScheduledTransferPeriod" value="30" />

OnStart 方法和 RoleEnvironmentChanging 事件中的程式碼如下所示:

// Get ScheduledTransferPeriod setting from ServiceConfiguration.cscfg and then set it 
var myScheduledTransferPeriod = RoleEnvironment.GetConfigurationSettingValue("ScheduledTransferPeriod");
TimeSpan myTimeSpan = TimeSpan.FromMinutes(Convert.ToDouble(myScheduledTransferPeriod));
config.Logs.ScheduledTransferPeriod = myTimeSpan;
config.Directories.ScheduledTransferPeriod = myTimeSpan;
config.WindowsEventLog.ScheduledTransferPeriod = myTimeSpan;
config.PerformanceCounters.ScheduledTransferPeriod = myTimeSpan;
config.DiagnosticInfrastructureLogs.ScheduledTransferPeriod = myTimeSpan;

另一個會影響收集的資料量的變數是記錄層次。需要收集的最重要資料來源之一是應用程式事件記錄檔。應用程式事件記錄檔或系統事件記錄可能很有用。安全性事件記錄檔無法透過 WAD 取得。您可以利用下列篩選值指定記錄項目的層次,以縮小這些檔案:

  • 嚴重

  • 錯誤

  • 警告

  • 資訊

  • 詳細

記錄層次會累計,因此,如果篩選設為 Warning,則也會傳輸 ErrorCritical。您可以利用上述方法來設定本機和雲端組態的特定 LogLevelFilter 層次。ServiceConfiguration.Local.cscfg 如下所示:

<Setting name="LogLevelFilter" value="Information" />

ServiceConfiguration.Cloud.cscfg 如下所示:

      <Setting name="LogLevelFilter" value="Error" />

OnStart 方法和 RoleEnvironmentChanging 事件中的程式碼如下所示:

// Get LogLevelFilter setting from ServiceConfiguration.cscfg and then set it
var LogLevelFilter = RoleEnvironment.GetConfigurationSettingValue("LogLevelFilter");
var myLogLevel = LogLevel.Undefined;
switch (LogLevelFilter)
{
    case ("Information"):
        myLogLevel = LogLevel.Information;
        break;
    case ("Verbose"):
        myLogLevel = LogLevel.Verbose;
        break;
    case ("Warning"):
        myLogLevel = LogLevel.Warning;
        break;
    case ("Critical"):
        myLogLevel = LogLevel.Critical;
        break;
    case ("Error"):
        myLogLevel = LogLevel.Error;
        break;
    default:
        break;
} 

// Filter what will be sent to persistent storage.
config.Logs.ScheduledTransferLogLevelFilter = myLogLevel;
config.DiagnosticInfrastructureLogs.ScheduledTransferLogLevelFilter = myLogLevel;
config.WindowsEventLog.ScheduledTransferLogLevelFilter = myLogLevel;

建議的程式碼不見得符合您的需要。如果不想要增加任何程式碼,且偏好使用上次已知的組態,而非程式碼中設定的組態,則還有另一個解決方案。

使用組態檔

Azure SDK 1.3 多了在 XML 檔案中加進組態而不必撰寫程式碼的功能。David Hardin 認為這是為所有類型的 Azure 角色設定診斷最有效率的作法。此方法有比撰寫程式碼更多的優點:

  1. WAD 在 OnStart 執行之前啟動,因此可擱截到啟動工作的錯誤。

  2. 在執行階段對組態所做的所有變更都會在重新啟動之後保留下來。

  3. 自動以設定的組態來啟動診斷代理程式,而不需要可能造成例外狀況而導致角色無法啟動的額外程式碼。

  4. 這是從測試版虛擬機器角色取得診斷的唯一方法。

  5. 組態變更不需要重建程式碼

附錄 F:diagnostics.wadcfg>中有一個範例 diagnostics.wadcfg。組態檔 diagnostics.wadcfg 必須放入下列位置,請記得將 [複製到輸出目錄] 設定設為 [永遠複製]

  • 若是背景工作角色,組態檔位於角色的根目錄中。

  • 若是 Web 角色,組態檔位於角色根目錄底下的 bin 目錄中。

  • 若為測試版虛擬機器角色,組態檔必須位於您上傳至 Azure 管理入口網站的映像器映像的 %ProgramFiles%\Azure Integration Components\<VersionNumber>\Diagnostics 資料夾中。<VersionNumber> 是您使用的 Azure SDK 版本。預設檔案位於此資料夾中,您可以修改預設檔案,或以您自己的檔案來覆寫此檔案。

下列 MSDN 文件說明此檔案的格式。如果 wad-control-container Blob 儲存體容器中已有 XML 組態,則會忽略 .wadcfg 檔案。您也必須確定檔案中的所有設定都正確,否則不會收集診斷資枓。

您現在可以開始決定想要收集哪些資訊。

設定資料收集

如果您不想要使用組態檔,則最適合開始執行診斷的地方是 try/catch 區塊內的 OnStart 方法。如果發生問題,此區塊可確保您正確處理問題,以避免角色陷入不斷循環中。將程式碼放入 OnStart 方法的危險是如果未處理所有例外狀況,則角色會陷入難以偵錯的循環迴圈中。在此方法中,當角色執行個體設為 Busy 時,無法透過 Azure 負載平衡器取得執行個體。如果 OnStart 方法傳回 false 或發生例外狀況,角色執行個體會立刻停止。如果方法傳回 true,Azure 會呼叫 Run 方法來啟動角色。

您可以將 OnStart 程式碼包裝在 try/catch 區塊中,以免發生例外狀況時回收角色 (管理入口網站上的狀態從未進入「就緒」)。Catch 程式碼可以包含 Trace.WriteLine 方法呼叫 (MSDN 範例),或是將事件日誌錯誤記錄下來 (ASP.NET 偵錯部落格)。將事件記錄在事件記錄檔中,就很容易查明角色為何無法啟動。如 Tom Christian 所提議,可稍微調整此程式碼,將例外狀況記錄到應用程式事件記錄檔,如下所示:

catch (Exception e)  
    {
            string sSource;
            string sEvent;
            sSource = "WaAppAgent";
            sEvent = "WorkerRole OnStart Event: " + e.Message;
            EventLog.WriteEntry(sSource, sEvent, EventLogEntryType.Error, 0);
    }

附錄 B:Web 角色程式碼範例>中有完整的程式碼。設定診斷最強大的方法是使用組態檔和程式碼,讓您從管理入口網站動態地變更組態。

現在已設定好 Azure 診斷,您可以開始收集資料。可收集的資料有五種類型:

  • 損毀傾印

  • Windows 事件記錄檔

  • 效能計數器

  • IIS 記錄

  • FREB 記錄檔

下表概述依預設在本機收集的資料及必須明確設定的資料:

 

資料來源 預設組態 描述

DiagnosticInfrastructureLogs

已啟用、儲存在本機、不定義傳輸至永續性儲存體。傳輸至儲存體資料表 WADDiagnosticInfrastructureLogsTable

與診斷基礎結構有關的記錄。這些通常不是非常有用。

記錄

已啟用、儲存在本機、不定義傳輸至永續性儲存體。傳輸至儲存體資料表 WADLogsTable

放在應用程式碼中的 System.Diagnostics.Trace 記錄。

目錄

依預設會自動建立 wad-iis-failedreqlogfileswad-iis-logfileswad-crash-dumps Blob,且各 Blob 的 DirectoryQuotaInMB 屬性都設為 1024 MB。您也可以設定其他目錄

依照 ScheduledTransferPeriod 傳輸間隔來傳輸記錄資料。

PerformanceCounters

已停用。新增這些資料時,儲存體資料表名稱為 WADPerformanceCountersTable

必須明確地指定效能計數器。

WindowsEventLog

已停用。新增這些資料時,儲存體資料表名稱為 WADWindowsEventLogsTable

不指定 Windows 事件記錄檔的 DataSources

CrashDumps

系統會在本機收集小型損毀傾印。可啟用完整傾印。wad-crash-dumps 是 Blob 儲存體中建立的名稱。

呼叫 EnableCollection(true) 方法來取得完整損毀傾印。

IIS 7.0 失敗要求追蹤資料

已停用。新增這些資料時,Blob 儲存體名稱為 wad-iis-failedreqlogfiles

必須在 Web.config 中啟用

  • 損毀傾印

    Azure 診斷不會自動收集損毀傾印。語法容易混淆,因為若要收集迷你傾印,您必須新增此程式碼:

    // Enable crash mini dump collection.
                    CrashDumps.EnableCollection(false);
    
    收集完整傾印的程式碼如下:

                    // Enable full crash dump collection.
                    CrashDumps.EnableCollection(true);
    
    請記住,在談到設定 Directory.QuotaInMB 時,如果您有完整傾印,則需要配置足夠的本機儲存體和整體儲存體來儲存完整傾印。

  • 事件記錄檔

    事件記錄檔是找出應用程式錯誤最有用的方法。以下是如何新增應用程式和系統事件:

    // Add in configuration settings for Windows Event logs           config.WindowsEventLog.DataSources.Add("Application!*");
    config.WindowsEventLog.DataSources.Add("System!*");
    
    只會收集 Azure 診斷開始之後發生的事件,這使得事件記錄檔在診斷啟動問題���沒有幫助,除非您採用建議的方法來開始和設定診斷。

    您也可以只篩選特定事件。Steve Marx 部落格說明如何建立 XPath 查詢來只取得有用的資訊。例如,使用 XPath 查詢搭配 Add 方法只會收集 WaAppAgent 訊息:

    ("Application!*[System[Provider[@Name='WaAppAgent']]]")
    
  • 效能計數器

    必須明確加入效能計數器。設定這些計數器的困難在於如果一個計數器錯誤,則會造成該角色上的所有計數器全部失敗。在 [計算模擬器] 輸出視窗中,您會看到下列錯誤:

    [MonAgentHost] Error:  PdhExpandWildCardPath(\Process(_Total)) failed
    
    Web 和背景工作角色可以使用多種語言。對於所有類型的角色,這些是建議的基本效能計數器。下列範例的處理程序名稱 (WaWorkerHost) 需要變更為 Web 角色的 WaIISHost。<附錄 C:背景工作角色程式碼範例>中提供非執行 .NET 程式碼的背景工作角色的相關程式碼:

    • @"\Process(WaWorkerHost)\% Processor Time "

    • @"\Process(WaWorkerHost)\Private Bytes "

    • @"\Process(WaWorkerHost)\Thread Count"

    • @"\Processor(_Total)\% Processor Time"

    • @"\Memory\Available Bytes"

    對於執行 .NET 語言程式碼的 Web 角色或背景工作角色,還有其他計數器需要監視。同樣地,如果這是背景工作角色,下列範例中的處理程序名稱 (w3wp) 需要變更為 WaWorkerHost,如果在完整 IIS 模式下使用 Web 角色,則需要變更為 WaIISHost。<附錄 B:Web 角色程式碼範例>針對執行 .NET 語言程式碼的 Web 角色提供建議的計數器:

    • @"\Process(w3wp)\% Processor Time "

    • @"\Process(w3wp)\Private Bytes "

    • @"\Process(w3wp)\Thread Count "

    • @"\Processor(_Total)\% Processor Time"

    • @"\Memory\Available Bytes"

    • @"\ASP.NET\Applications Running"

    • @"\.NET CLR Interop(_Global_)\# of marshalling"

    • @"\.NET CLR Jit(_Global_)\% Time in Jit"

    • @"\.NET CLR Loading(_Global_)\% Time Loading"

    • @"\.NET CLR LocksAndThreads(_Global_)\Contention Rate / sec"

    • @"\.NET CLR Memory(_Global_)\# Bytes in all Heaps"

    • @"\.NET CLR Networking(_Global_)\Connections Established"

    • @"\.NET CLR Remoting(_Global_)\Remote Calls/sec"

    如果未使用完整 IIS 模式,則需要將字串 WaIISHost 變更為 w3wp。如同稍早所討論,ScheduledTransferPeriod 可決定計數器何時或是否保存至儲存體。

  • IIS 記錄

    Azure Web 角色在 IIS 下執行,且依預設啟用記錄,並以 UTF-8 編碼的 W3C 格式寫入應用程式的資源資料夾 (例如,C:\Resources\directory\c5c31518818e46569fa68f0809b5a6aa.fm_WebRole.DiagnosticStore\LogFiles\Web),且記錄檔轉換設為 [每小時]。每一個網站有一個記錄檔。如果您從遠端連上執行個體並開啟網際網路資訊服務管理員,您可以看到這些設定:

    Windows Azure - 記錄對話方塊

    您可以修改預設記錄選項,以符合您的特定需求。訣竅在於任何變更都需要納入啟動工作中,以便每次重新啟動執行個體時,不會遺失設定。例如,若只要記錄錯誤,您可以在啟動工作中使用 Appcmd.exe (IIS7 的一部分),包含的命令如下:

    appcmd set config /section:httpLogging /dontLog:False /selectiveLogging:LogError
    
  • 失敗的要求追蹤

    如果您有 Web 角色,您一定想要收集失敗要求追蹤 (先前稱為「失敗要求緩衝」,英文縮寫為 FREB) 記錄。如下所示,您可以在 Web.config 檔案的 <system.webServer> 區段中加入下列幾行:

    <tracing>
          <traceFailedRequests>
            <add path="*">
              <traceAreas>
                <add provider="ASP" verbosity="Verbose" />
                <add provider="ASPNET" areas="Infrastructure,Module,Page,AppServices" verbosity="Verbose" />
                <add provider="WWW Server" areas="Authentication, Security, Filter, StaticFile, CGI, Compression, Cache, RequestNotifications,Module" verbosity="Verbose" />
              </traceAreas>
              <failureDefinitions timeTaken="00:00:20" statusCodes="400-599" />
            </add>
          </traceFailedRequests>
        </tracing>
    
    這會對超過 15 秒或狀態碼介於 400 和 599 之間 (failureDefinitions 元素) 的任何要求啟用失敗記錄。FREB 記錄建立之後會自動保存至儲存體。

  • 其他目錄

    您也可能想要收集其他寫入至執行個體的檔案,尤其是客體代理程式檔案。這些檔案提供客體代理程式與 Azure 網狀架構控制器之間發生什麼情況的相關資訊。若要這麼做,您需要設定將由 Azure 診斷複製的目錄:

              // Add a custom directory transfer
              DirectoryConfiguration directoryConfiguration = new DirectoryConfiguration();
              directoryConfiguration.Container = "wad-custom-logs";
              directoryConfiguration.DirectoryQuotaInMB = 0;
              directoryConfiguration.Path = @"c:\logs\WaAppAgent.log";
              config.Directories.DataSources.Add(directoryConfiguration);
    
    同樣也要注意組態失敗時可能發生的情況。若要在計算模擬器上測試,您需要建立此資料夾,並確定沒有多個角色同時執行此程式碼,否則會發生共用違規。雲端組態中不會發生此錯誤,因為每個執行個體各自獨立。

WAD 疑難排解

現在一切已設定完成,可開始在計算模擬器中測試,並部署在 Azure 中。診斷資料沒有出現是什麼情況?可檢查的事項清單如下:

  1. 在診斷儲存體帳戶中檢查 wad-control-container Blob 容器中的 Blob。尋找以 <deploymentID>/<RoleName>/<RoleInstance> 命名的 Blob (例如,3981bcff0eb743ddb9b7574a8821e955/WebRole1/WebRole1_IN_0)。

    1. 開啟 XML 檔案,確定其設定方式符合您的預期。如果看到特定的資料來源是 <ScheduledTransferPeriodInMinutes>0</ScheduledTransferPeriodInMinutes>,表示未設定診斷來傳輸任何資料。

    2. 如果有多個執行個體,而其中有些會傳輸診斷資料,有些則不會,請比較 XML 檔案來確定全部都已正確設定。

    3. 如果在部署之後設定診斷,且診斷會隨機停止運作,可能是因為角色回收或執行個體重新啟動。當執行個體重新啟動時,客戶的部署後設定會遺失,而改成使用雲端中設定的診斷。使用 .wadcfg 檔案的主要好處之一是角色回收時不會覆寫此組態。

  2. 在診斷儲存體帳戶中檢查 WADDiagnosticInfrastructureLogsTable 資料表中的記錄。您可以根據 DeploymentId 來篩選 (例如,DeploymentId eq 'bd9e149f76e8413aba8865c77326e449')。尋找可能指出為何沒有傳輸診斷資料的任何例外狀況或錯誤訊息。

  3. 如果沒有收集 Diagnostics.Trace 資訊,請確定 web.config 或 app.config 中已設定 DiagnosticMonitorTraceListener。雲端專案中依預設會有此設定,但有時可能遭到變更,導致診斷未收集追蹤陳述式。

  4. 常見的一個問題是未正確查詢診斷儲存體,於是沒有傳回結果而認為沒有擷取診斷資料。請根據 DeploymentID 篩選來查詢診斷資料表,並驗證是否正確傳輸診斷資料。常見的一些查詢錯誤包括:未根據 DeploymentID 篩選,以及未採用接續 Token。

  5. 如果執行個體在部署之後未啟動,請確定 ServiceConfiguration.cscfg 檔案中設定的儲存體帳戶不是設為 "UseDevelopmentStorage=true"。如果您使用 2011 年 8 月之後發行的 Azure Tools for Visual Studio 2011,則會出現警告。如果不是的話,則您需要經由 RDP 連至執行個體,並檢查 C:\Config 資料夾中的角色組態檔。

  6. 連接至執行個體後,還要檢查 DiagnosticsAgent.exe 和 MonAgentHost.exe 是否在執行中。假設已在執行中,則您可以安裝和附加 WinDBG,檢查是否擲回任何例外狀況。

  7. 您也可以檢查已在本機寫入診斷資料。

    • 在開發環境中,.tsf 檔案會寫入:

      c:\Users\<username>\AppData\Local\dftmp\Resources\<deploymentID>\directory\DiagnosticStore\Monitor\Tables

    • 在執行中的執行個體上,檔案會寫入:

      c:\Resources\<deploymentID>.<role>\directory\DiagnosticStore\Monitor\Tables

    目前,若要讀取這些檔案,您需要建立支援案例,並傳送給 Microsoft。

  8. 如果您有多個執行個體,且其中少數幾個沒有正確傳輸診斷資料,請嘗試從管理入口網站重新製作角色的映像。這應該當作最後手段,因為我們將無從判斷問題發生的根本原因。

檢測程式碼

最重要的診斷資料可能是您身為開發人員加入至固有程式碼的追蹤訊息。系統資料可能會顯示例外狀況或記錄錯誤訊息。您可以向下追蹤至相依系統的特定呼叫。當呼叫相依系統可能失敗時,最佳作法是加入追蹤訊息;例如協力廠商驗證服務。

ETW 架構會將 TraceEventType 連結至每一個事件:

 

TraceEventType 等級 意義

嚴重

1

0x0001

嚴重錯誤或應用程式損毀

錯誤

2

0x0002

可復原的錯誤

警告

3

0x0004

非重大的問題 -- 可能暗示即將發生更嚴重的問題

資訊

4

0x0008

參考訊息

詳細

5

0x0010

偵測追蹤 (例如詳細的執行流程資訊、參數等)

開始

0x0100

邏輯作業開始

停止

0x0200

邏輯作業停止

制定程式碼的檢測計劃後,您可以新增 System.Diagnostics 命名空間,再新增追蹤訊息,在 C# 中如下所示:

Trace.WriteLine("LoggingWorkerRole entry point called", "Information");

因為 Azure 是在完整 IIS 中開始執行 (SDK 1.3),Web 應用程式碼會在不同的應用程式網域和程序中從 RoleEntryPoint 執行。這表示追蹤訊息不會出現在計算模擬���中,除非您在 Web.Config 的 Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener 下再多增加一個追蹤接聽程式:

<add type="Microsoft.ServiceHosting.Tools.DevelopmentFabric.Runtime.DevelopmentFabricTraceListener, Microsoft.ServiceHosting.Tools.DevelopmentFabric.Runtime, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="DevFabricListener">
    <filter type=""/>
</add>

至於更複雜的應用程式,EventId 方法可讓您更有效率地篩選記錄,也就能更快速解決問題。如果您使用 C# WriteLine,則 EventId 永遠為 0。若要指定 EventId,您需要使用 TraceEvent 方法,上表中可找到 traceType

Trace.TraceEvent(traceType, eventId, message);

追蹤訊息會保存至 WADLogsTable 資料表。Azure 會自動將下列資訊連結至每一個記錄的事件:時間戳記、滴答計數 (提供細微到 100 奈秒的詳細計時),以及部署、角色和角色執行個體的相關資訊。這可讓您縮減為特定執行個體的記錄檔。訊息以 XML 格式儲存,如下所示:


<Properties>
 <EventTickCount>634402131502204503</EventTickCount>
 <DeploymentId>deployment(28)</DeploymentId>
 <Role>WebRole1</Role>
 <RoleInstance>deployment(28).Sample.WebRole1.0</RoleInstance>
 <Level>3</Level>
 <EventId>20</EventId>
 <Pid>10796</Pid>
 <Tid>7172</Tid>
 <Message>trace message; TraceSource 'Data' event</Message> 
</Properties>

層級對應於 TraceEventType。在上表中,您可以看到層級 3 對應於 Warning。如果未指定 TraceEventType,或如果您使用 Trace.WriteLine,則層級會設為 5 (Verbose)。

標準記錄通常就足夠。如需更詳細的記錄類型,您可以建立自訂的追蹤接聽程式:

Azure Table Query 是 Web 角色的 CodePlex 專案,可讓您以 LINQ 查詢來查詢 WADLogsTable

檢視資料

收集診斷資料是為了在發生問題時隨時派上用場。這表示在發生問題之前,您必須確認一切正常,就像必須確認資料備份正常運作一樣。這表示在測試應用程式期間要檢視診斷資料,然後定期檢查以確保它仍然正常運作。這也表示要建立基準,以獲知發生異常狀況。

當 WAD 啟動時,所有 Azure 診斷資料會儲存您在指定的儲存體帳戶中。您可以使用 Visual Studio 伺服器總管或許多storage explorers,將此資料視覺化。

wad-control-container Blob 包含記錄診斷基礎結構本身。您可以在這裡看到資料是否從給定的執行個體傳輸。Blob 的身分識別格式如下:

0aef2b51ad1d49ef915dd41d3ca01f24/WorkerRole1/WorkerRole1_IN_0

此身分識別分成三部分:

  1. 一長串數字是部署 ID - 0aef2b51ad1d49ef915dd41d3ca01f24

  2. 角色名稱 - WorkerRole1

  3. 執行個體名稱 - WorkerRole1_IN_0

有多個執行個體時,以零為基底的尾碼會累加,例如 WorkerRole1_IN_1 代表第二個執行個體。

下表顯示每個記錄檔的寫入位置:

 

記錄檔類型 Azure 儲存體格式 附註

從程式碼產生的 Azure 記錄檔

資料表

必須將追蹤接聽程式新增至 web.config 或 app.config 檔案。這些檔案儲存在 WADLogsTable 中。

IIS 7.0 記錄檔

blob

僅限 Web 角色。儲存在 Blob 容器的路徑 wad-iis-logfiles\<部署 ID>\<Web 角色名稱>\<角色執行個體>\W3SVC1 下。

Windows 診斷基礎結構記錄檔

資料表

診斷服務本身的相關資訊。儲存在 WADDiagnosticInfrastructureLogsTable 中。

失敗要求記錄檔

blob

僅限 Web 角色。啟用方式是在 web.config 的 system.WebServer 設定下設定追蹤選項。儲存在 Blob 容器的路徑 wad-iis-failedreqlogfiles\<部署 ID>\<Web 角色名稱>\<角色執行個體>\W3SVC1 下。

Windows 事件記錄檔

資料表

啟用方式是在設定初始組態時變更 DiagnosticMonitor Configuration.WindowsEventLog。儲存在 WADWindowsEventLogsTable 中。

效能計數器

資料表

啟用方式是變更 DiagnosticMonitor Configuration.PerformanceCounters。儲存在 WADPerformanceCountersTable 中。範例程式碼背景工作角色會設定效能計數器。

損毀傾印

blob

���用方式是呼叫 CrashDumps.EnableCollection。儲存在 Blob 容器的路徑 wad-crash-dumps 中。由於 ASP.NET 處理了大部分的例外狀況,因此通常只對背景工作角色有用。

自訂錯誤記錄檔

blob

如需有關使用此記錄的實用範例,請參閱 Neil Mackenzie 的部落格

當損毀傾印資料傳輸至永續性儲存體時,它會儲存至 wad-crash-dumps Blob 容器。IIS 記錄檔會傳輸至 wad-iis-logfiles Blob 容器。失敗要求會儲存在 wad-iis-failedreqlogfiles Blob 容器中。

事件記錄檔會傳輸至永續性儲存體中的 WADWindowsEventLogs 資料表。效能計數器會依指定的間隔傳輸至 WADPerformanceCounters 資料表。WADDiagnosticInfrastructureLogs 包含診斷基礎結構的相關記錄。追蹤接聽程式位於 WADLogsTable 資料表中。

根據 Jason Haley 的 AzureLogsWithLINQPad 範例,檢視診斷資料的另一項工具是使用 LINQPad。

管理診斷資料

將所有這些記錄檔保存至 Azure 儲存體需要成本和時間。理想的解決辦法是在需要解決特定問題時才「即時」啟用追蹤。動態變更診斷設定時,您必須記得手動恢復到原始設定,或者,如果一定需要維持某些設定,請變更原始設定。如果您不使用 .wadcfg 檔案,則此刻意步驟特別重要,因為在執行個體重新啟動時,將會以您程式碼中設定的診斷設定來取代新的設定。

Azure PowerShell Cmdlet 可以管理執行 Azure 服務時的許多層面,包括診斷。您可以提供資訊並調整參數,從本機電腦執行這些 Cmdlet,它們會使用 Azure Management and Diagnostics API 經由網際網路連接至您的服務。

Windows PowerShell 隨著 Windows 7 一起安裝,是從隨著 Azure 管理工具 (MMC) 安裝的服務管理 CmdLet 演進而來。以下一些更實用的 Cmdlet 清單:

  • Get-DiagnosticConfiguration - 取得指定緩衝區名稱的緩衝區組態 (Logs、Directories、PerformanceCounters、WindowsEventLogs 或 DiagnosticInfrastructureLogs)。

  • 若要變更角色的組態,請使用 Set-DiagnosticConfiguration Cmdlet。

  • Start-OnDemandTransfer - 啟動指定資料緩衝區的隨需傳輸。這會將資料移至 Azure 儲存體 (資料表或 Blob 儲存體)。

David Aiken 的部落格有一段指令碼可清除一些記錄檔 (IIS 記錄檔和 wad-control-container XML 檔案)。可對每一個容器呼叫 Clear-Container Cmdlet。您也需要確定排程的傳輸沒有與刪除作業重疊。您也需要對儲存在資料表中的記錄 (效能計數器、事件記錄檔…) 制訂策略。有些使用者會從 Azure 儲存體下載所有資料,然後放入 SQL Server 資料庫中,所以不必支援儲存體費用,且能夠對資料進行更複雜的查詢。

了解 Azure 診斷資源後,開發人員可以採用以下說明的設計最佳作法,建立具有支援性的應用程式。

您需要根據基準來測量應用程式的健康情況。出現首頁不見得就表示應用程式狀況良好。建立健康情況的完整基準也需要了解商務邏輯的健康狀況和效能。

下一步了解健康情況如何向上逐步提升。準時支付 Azure 帳單是維持良好健康情況的第一層保障。未支付訂用帳戶會造成愈來愈嚴重的後果,最後導致應用程式被刪除。

對於每一個訂用帳戶,Azure 託管服務有四個層級會影響應用程式的健康情況。

Windows Azure - 健全狀況等級

例如,執行個體可能因為硬體故障而失敗,或因為軟體更新而重新啟動。除非您只設定一個執行個體,否則這不會造成角色失敗。同樣地,每一個託管服務各位於特定地區 (例如,美國中南部)。此重要資訊將決定應用程式是否受到服務中斷事件所影響 (亦即中斷運作)。如果應用程式設計中未建立備援功能,則較低層級失敗可能造成託管服務層級失敗。

大部分 Azure 應用程式需要比上圖更複雜的架構。您的應用程式可能如下:

Windows Azure - 架構範例

分散式本質潛藏許多可能的失敗點。記錄這些重要途徑可讓疑難排解更有效率。例如,在上圖中,如何測試「存取控制」是否發生失敗?

若要了解應用程式有何問題,您必須監視並記錄應用程式的狀態。一般而言,您可以記錄應用程式的四種資訊:

  • 程式設計:例外狀況、重要變數的值,以及偵錯應用程式所需的任何資訊。

  • 商務程序:安全性、變更追蹤、規範所需的稽核。

  • 系統穩定性:效能、延展性、輸送量、延遲。

  • 商務假設的驗證: 應用程式的使用方式符合您的預期嗎?

人性最基本的反應就是在面臨危險時嚇呆。訓練和練習可幫助您克服這種天性。因此我們會有消防演習,有些航空公司會推出墜機安全課程。大多數大型公司都將大量的預算投入在災害復原規劃上。關於最佳作法,請參閱<Microsoft IT 在資料中心的災害復原實作>。

我們只著重在探討發生問題時可加速疑難排解的技巧。了解您的應用程式是以可加速疑難排解的方式建置,將可降低問題發生時的緊張壓力,同時縮短讓網站恢復運作的時間。成本效益分析可決定您的系統中需要建立多少容錯功能。例如,為了減少停機時間而投入額外成本來保留 Traffic Manager 所提供的熱備份,這樣是否值得?

Azure Traffic Manager 可讓您管理連入流量並分散至 Azure 託管服務,而不論這些服務是部署在相同的資料中心或世界各地不同的資料中心。它可讓您設定容錯移轉服務,因此,如果主要服務停止運作,則流量會傳送至清單中下一個可用的服務。AkamaiLimelight 等協力廠商軟體也提供負載平衡解決方案。

以下是加速解決問題的一套五步驟計劃。

計劃的第一步是必須儘快知道有問題發生。越快知道有問題發生,就可越快實作災變防護計劃。這也是監視為何很重要的原因。

第二步是判斷問題的來源:Azure 平台或您的應用程式。第一個要查看的地方是 Azure 服務儀表板。使用此網站時,必須知道您的應用程式使用的所有服務,以及服務部署在哪一個資料中心。只要有一項服務退化,就會影響您的應用程式。

監視 Azure 平台服務事件的一種作法是訂用帳戶您應用程式的所有 RSS 摘要。例如,如果應用程式裝載於美國中北部資料中心,您可以訂用帳戶此 RSS 摘要

Azure 儲存體使用容錯網域 (機架、網路交換器、電源) 來限制硬體故障的影響力。關於 Azure 儲存體,通常都誤以為單一位置 (例如美國中南部) 外的資料複本會自動容錯移轉至某一個複本。如果儲存體在某個位置中發生問題,則會影響資料的存取。此儲存體團隊部落格針對新的地理複寫功能,提供所有詳細資料。

第三步是縮小問題的範圍。在使用多個 Azure 服務的複雜應用程式中,這可能是最複雜的步驟。建立無狀態的服務有助於隔離應用程式的不同部分。如果所有相依服務都正常執行,則您需要判斷計算服務的健康情況。作法是在管理入口網站中開啟 [託管服務、儲存體帳戶和 CDN] 區段,然後選擇您的部署。在屬性視窗中,您會看到如下的畫面:

Windows Azure - 部署屬性

在此例子中,根據 [最後一個作業] [完成時間] 和 [上次重新整理時間] 之間的時間差距所計算,我可以看到我的部署在過去八天都正常執行。反之,如果您看到部署在最近中止或重新啟動,則這有助於您準確判斷從何處開始查看。如果這似乎是服務事件,且影響到您在指定資料中心裡的所有部署,請立即連絡 Microsoft:(866) 676-6546.

第四步是執行標準疑難排解步驟,例如檢查記錄檔、事件記錄檔、附加偵錯工具,或使用 Procmon 或網路監視器等工具,以檢查是否可以找出問題的某些徵兆。應用程式事件記錄檔是第一個可查看 Azure 託管服務部署的地方。請確定您的應用程式未擲回任何例外狀況。這可能沒有必要,因為目前所有支援都是免費。事實上,您通常可以比訓練有素的 Microsoft 支援工程師更快找出並解決問題,因為他們並不像您一樣了解整個應用程式範圍。如果讓「網站運作」刻不容緩,則優先查看是最佳替代方案。

第五步是連絡 Microsoft 支援。若要加速解決問題,您需要提供與您的訂用帳戶之帳戶擁有者相關聯的同盟 ID (Windows Live ID)。您也應該提供不同記錄檔中發現的問題和錯誤的來源分析結果。Microsoft 支援工程師可能要求將他們加入為您的訂用帳戶的共同管理員,以便他們與您可以看到完全相同的管理入口網站畫面。

效能就像是:情人眼裡出西施。什麼閾值會讓效能變得無法接受?頁面何時逾時?即使您設定最長載入時間,也不保證會為所有客戶載入頁面。DNS 路由和網路可靠性是決定頁面載入時間的兩個關鍵因素。例如,我們有個客戶在田納西州曼非斯,其 ISP 將聖安東尼奧的 TX 流量先傳送至芝加哥。

詳細的效能討論已超出本文的範圍。如需有關在 Azure 上開發的最佳作法,請參閱 TechNet 文章<SQL Azure 效能和彈性指南>。效能疑難排解首先需要有一個基準。這就是為何必須收集一段長時間的效能資料的理由。有了基準之後,就能看出趨勢和異常。

Azure 平台提供服務等級協定 (SLA),定義各種服務的可用性/連接性層級。您的 SLA 是什麼?我的 ISP 曾經表示我不應該將連線用於商務用途,因為我的套件不含 SLA。可靠性有一點兒像是效能,同樣都很仰賴客戶的基礎網路連線,也是見人見智。上述連結可協助您了解網路連線的效能。

通常都誤以為 Azure 平台 SLA 一定保證應用程式有相同的 SLA。首先,有些人都不看第二句,內容是:

在計算方面,我們保證在將兩個以上的角色執行個體部署至不同的容錯和升級網域時,您的網際網路對向角色將在至少 99.95% 的時間內具有外部連線能力。

這一句缺少一組兩個字的修飾語:「每一角色兩個以上的執行個體」。換言之,如果有 Web 角色和背景工作角色,且各有一個執行個體,則每當主機作業系統更新或進行某種系統修復時,就無法使用您的應用程式。Azure 計算使用容錯網域來確保符合 SLA。

另一個誤解是如果您選擇特定的作業系統版本,則絕對不會因為作業系統更新而中斷運作。對於在您執行個體上執行的客體作業系統而言,確實如此,但對於資料中心裡執行的實體機器上執行的主機作業系統而言,則不是如此。

為了達到最高的可靠性,必須監視您的網站,在內部是以 Window Azure 診斷資料來監視,在外部是使用 Compuware 的 GomezPingdom。您也必須確定已取得最新的安全性修補程式,也已備妥程式碼變更的驗證計劃。

使用 Visual Studio 建立新的應用程式時,預設行為是在 ServiceConfiguration.cscfg 檔案中設定客體作業系統版本,如下所示:

osFamily="1" osVersion="*"

這樣很好,因為可以啟用自動更新,而這也是 PaaS 的主要優點之一。缺點是您不是使用最新的作業系統。為了使用最新的作業系統版本 (Windows Server 2008 R2),應該改成如下的設定:

osFamily="2" osVersion="*"

可惜,許多客戶都決定固定使用特定的作業系統版���,希望能避免客體作業系統更新,以增加正常運作時間。這只有對企業客戶才是合理的策略,這些客戶有系統地在預備環境中測試每一項更新,然後對生產環境中執行的關鍵任務應用程式排定「VIP 交換」。對於未測試每個客體作業系統更新的其他人,未設定自動更新會讓 Azure 應用程式蒙受風險。

當您需要更新服務時,尤其在緊急情況下,有何規劃?應該關閉整個網站,還是處理次要的臨時問題,差別就在於這個經常被忽略的步驟。雖然在 Azure 應用程式的初始規劃和發行方面會投入許多時間和精力,但卻時常認為不需要廣泛測試更新,因為更正一項變更比在盒裝產品中解決還簡單。可迅速解決功能退化問題。很不幸,這些問題也很容易引起災難性的失敗。

在最後部署至生產環境之前,必須先測試對實際執行應用程式所做的���一項變更。值得投入更多時間來預防失敗的可能後果。如需詳細資訊,請參閱<更新 Azure 服務概觀>。

感謝您花時間閱讀本文所討論的主題。歡迎提供意見反應,讓我們了解對您有用的部分。您必須在關閉服務和收集診斷資料之間權衡兩者的成本。必須在移至生產環境之前做好估算。開發可靠的 Azure 應用程式所需的工作並不是新的、革命性或技術上的挑戰,只需要設計人員和開發人員仔細考慮應用程式中可能出現的潛在問題,並套用本文所提供的作法。

  • Christian, Tom,"Help with Azure role stuck in Initializing/Busy/Stopped state",部落格,2011 年 2 月 25 日。

  • Cross, Andy,"Tracing to Azure Compute Emulator SDK V1.3",部落格,2011 年 1 月 22 日。

  • Haley, Jason,"How To:Query Azure Log Tables with LINQPad",部落格,2010 年 1 月 28 日 15:09。

  • Hardin, David,"Configuring WAD via the diagnostics.wadcfg Config File",部落格,2011 年 3 月 29 日。

  • Kelly, Mike,"Take Control of Logging and Tracing in Azure",MSDN Magazine,2010 年 6 月。

  • Mackenzie, Neil,"Custom Diagnostics in Azure",部落格,2009 年 12 月 8 日。

  • Makogon, David,"Azure Tip of the Day:Separate Diagnostic Storage Account",部落格,2010 年 8 月 15 日。

  • Marx, Steve,"Capturing Filtered Events with Windows Azure Diagnostics",部落格,2010 年 4 月 21 日。

  • Mladenov, Toddy,"Collecting Event Logs in Azure",部落格,2010 年 5 月 2 日。

  • Myers, Walter,"Setting Up Performance Counters In Your Azure Web and Worker Roles",Blog,2011 年 1 月 31 日。

  • Nakashima, Jim,"Using IntelliTrace to debug Azure Cloud Services",部落格,2010 年 6 月 7 日。

  • O’Neil, Jim,"500 and Other Errors in Azure Deployments Blog",部落格,2011 年 4 月 11 日 4:47 AM。

  • Stiefel, Michael,"Why Did My Azure Application Crash?Using the Azure Diagnostics API to Find Code Problems",部落格,2011 年 9 月 8 日。

  • Washam, Michael,"Managing Log Files with Azure PowerShell Cmdlets 2.0",部落格,2011 年 9 月 20 日。

  • Williamson, Kevin,"Azure Role Architecture",部落格,2011 年 5 月 5 日。

  • Azure 管理入口網站 http://manage.windowsazure.com

  • Azure 入口網站 http://www.microsoft.com/windowsazure/

 

架構

機器的邏輯叢集,在虛擬機器內提供角色執行環境。

FREB

失敗要求追蹤 (先前稱為「失敗要求緩衝」)

管理入口網站

Azure 管理入口網站是用來管理、部署和監視 Windows Azure 服務的管理入口網站。存取管理入口網站的網址是 http://manage.windowsazure.com

REST

REpresentational State Transfer。一種軟體設計,採用無狀態的主從式架構,其中將 Web 服務視為資源,且可透過 URL 來識別。

SLA

服務等級協定

虛擬機器

在真實電腦的隔離磁碟分割中執行的電腦模擬軟體。

WAD

Azure 診斷

網路角色

Web 角色是針對 IIS 7 和 ASP.NET 支援之 Web 應用程式設計所自訂的角色。

背景工作角色

背景工作角色是適用於一般開發的角色,可以執行 Web 角色的背景處理。

此附錄著重於設定 Azure 診斷所需的程式碼。呼叫 RoleEntryPoint.OnStart 方法讓您有機會自訂角色執行個體的啟動。您可以提供自己的 OnStart 實作來執行為角色設定 WAD 所需的程式碼。

public override bool OnStart()
{
    string sSource = "WaAppAgent";
    string sEvent = null;

    try
    {
        DiagnosticMonitorConfiguration config = DiagnosticMonitor.GetDefaultInitialConfiguration();

        // Set an overall quota of 8GB.
        config.OverallQuotaInMB = 8192;

        // Set the sub-quotas and make sure it is less than the OverallQuotaInMB set above
        config.Logs.BufferQuotaInMB = 1024;
        config.Directories.BufferQuotaInMB = 0; // Use the rest of the storage here
        config.WindowsEventLog.BufferQuotaInMB = 1024;
        config.PerformanceCounters.BufferQuotaInMB = 1024;
        config.DiagnosticInfrastructureLogs.BufferQuotaInMB = 1024;

        // Get ScheduledTransferPeriod setting from ServiceConfiguration.cscfg and then set it 
        var myScheduledTransferPeriod = RoleEnvironment.GetConfigurationSettingValue("ScheduledTransferPeriod");
        TimeSpan myTimeSpan = TimeSpan.FromMinutes(Convert.ToDouble(myScheduledTransferPeriod));
        config.Logs.ScheduledTransferPeriod = myTimeSpan;
        config.Directories.ScheduledTransferPeriod = myTimeSpan;
        config.WindowsEventLog.ScheduledTransferPeriod = myTimeSpan;
        config.PerformanceCounters.ScheduledTransferPeriod = myTimeSpan;
        config.DiagnosticInfrastructureLogs.ScheduledTransferPeriod = myTimeSpan;

        // Get LogLevelFilter setting from ServiceConfiguration.cscfg and then set it
        var LogLevelFilter = RoleEnvironment.GetConfigurationSettingValue("LogLevelFilter");
        var myLogLevel = LogLevel.Undefined;
        switch (LogLevelFilter)
        {
            case ("Information"):
                myLogLevel = LogLevel.Information;
                break;
            case ("Verbose"):
                myLogLevel = LogLevel.Verbose;
                break;
            case ("Warning"):
                myLogLevel = LogLevel.Warning;
                break;
            case ("Critical"):
                myLogLevel = LogLevel.Critical;
                break;
            case ("Error"):
                myLogLevel = LogLevel.Error;
                break;
            default:
                break;
        } 

        // Filter what will be sent to persistent storage.
        config.Logs.ScheduledTransferLogLevelFilter = myLogLevel;
        config.DiagnosticInfrastructureLogs.ScheduledTransferLogLevelFilter = myLogLevel;
        config.WindowsEventLog.ScheduledTransferLogLevelFilter = myLogLevel;

        // Add in configuration settings for Windows Event logs
        config.WindowsEventLog.DataSources.Add("Application!*");
        config.WindowsEventLog.DataSources.Add("System!*");

        // Add a custom directory transfer
        DirectoryConfiguration directoryConfiguration = new DirectoryConfiguration();
        directoryConfiguration.Container = "wad-custom-logs";
        directoryConfiguration.DirectoryQuotaInMB = 0;
        directoryConfiguration.Path = @"c:\logs";
        config.Directories.DataSources.Add(directoryConfiguration);
 

        // Enable full crash dump collection.
        CrashDumps.EnableCollection(true);

        // Use 30 seconds for the perf counter sample rate.
        TimeSpan perfSampleRate = TimeSpan.FromSeconds(30D);

        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
            CounterSpecifier = @"\Memory\Available Bytes",
            SampleRate = perfSampleRate
        });

        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
            CounterSpecifier = @"\Processor(_Total)\% Processor Time",
            SampleRate = perfSampleRate
        });

        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
            CounterSpecifier = @"\Process(w3wp)\% Processor Time",
            SampleRate = perfSampleRate
        });

        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
            CounterSpecifier = @"\Process(w3wp)\Private Bytes",
            SampleRate = perfSampleRate
        });

        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
            CounterSpecifier = @"\Process(w3wp)\Thread Count",
            SampleRate = perfSampleRate
        });

        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
            CounterSpecifier = @"\.NET CLR Interop(_Global_)\# of marshalling",
            SampleRate = perfSampleRate
        });

        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
             CounterSpecifier = @"\.NET CLR Jit(_Global_)\% Time in Jit",
             SampleRate = perfSampleRate
         });

        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
            CounterSpecifier = @"\.NET CLR Loading(_Global_)\% Time Loading",
            SampleRate = perfSampleRate
        });

        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
            CounterSpecifier = @"\.NET CLR LocksAndThreads(_Global_)\Contention Rate / sec",
            SampleRate = perfSampleRate
        });

        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
            CounterSpecifier = @"\.NET CLR Memory(_Global_)\# Bytes in all Heaps",
            SampleRate = perfSampleRate
        });

        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
            CounterSpecifier = @"\.NET CLR Networking(_Global_)\Connections Established",
            SampleRate = perfSampleRate
        });

        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
            CounterSpecifier = @"\.NET CLR Remoting(_Global_)\Remote Calls/sec",
            SampleRate = perfSampleRate
        });

        // Apply the updated configuration to the diagnostic monitor.
        // The first parameter is for the connection string configuration setting.
        DiagnosticMonitor.Start("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString", config);

        sEvent = "Management OnStart called diagnostics";
        EventLog.WriteEntry(sSource, sEvent, EventLogEntryType. Information, 0);
    }
    catch (Exception e)
    {
        sEvent = "Management OnStart Event: " + e.Message;
        EventLog.WriteEntry(sSource, sEvent, EventLogEntryType.Error, 0);
    }

    return base.OnStart();
}

此附錄著重於在背景工作角色中設定 Azure 診斷所需的程式碼。

public override bool OnStart()
{
    // Set the maximum number of concurrent connections 
    ServicePointManager.DefaultConnectionLimit = 12;
    string sSource = "WaAppAgent";
    string sEvent = "WorkerRole OnStart Event: ";

    try
    {
        // For information on handling configuration changes
        // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.

        DiagnosticMonitorConfiguration config = DiagnosticMonitor.GetDefaultInitialConfiguration();

        // Set an overall quota of 8GB.
        config.OverallQuotaInMB = 8192;
        // Set the sub-quotas and make sure it is less than the OverallQuotaInMB set above
        config.Logs.BufferQuotaInMB = 1024;
        config.Directories.BufferQuotaInMB = 0; // Use the rest of the storage here
        config.WindowsEventLog.BufferQuotaInMB = 1024;
        config.PerformanceCounters.BufferQuotaInMB = 1024;
        config.DiagnosticInfrastructureLogs.BufferQuotaInMB = 1024;

        // Get ScheduledTransferPeriod setting from ServiceConfiguration.cscfg and then set it 
        var myScheduledTransferPeriod = RoleEnvironment.GetConfigurationSettingValue("ScheduledTransferPeriod");
        TimeSpan myTimeSpan = TimeSpan.FromMinutes(Convert.ToDouble(myScheduledTransferPeriod));
        config.Logs.ScheduledTransferPeriod = myTimeSpan;
        config.Directories.ScheduledTransferPeriod = myTimeSpan;
        config.WindowsEventLog.ScheduledTransferPeriod = myTimeSpan;
        config.PerformanceCounters.ScheduledTransferPeriod = myTimeSpan;
        config.DiagnosticInfrastructureLogs.ScheduledTransferPeriod = myTimeSpan;

        // Get LogLevelFilter setting from ServiceConfiguration.cscfg and then set it
        var LogLevelFilter = RoleEnvironment.GetConfigurationSettingValue("LogLevelFilter");
        var myLogLevel = LogLevel.Undefined;
        switch (LogLevelFilter)
        {
            case ("Information"):
                myLogLevel = LogLevel.Information;
                break;
            case ("Verbose"):
                myLogLevel = LogLevel.Verbose;
                break;
            case ("Warning"):
                myLogLevel = LogLevel.Warning;
                break;
            case ("Critical"):
                myLogLevel = LogLevel.Critical;
                break;
            case ("Error"):
                myLogLevel = LogLevel.Error;
                break;
            default:
                break;
        }

        // Filter what will be sent to persistent storage.
        config.Logs.ScheduledTransferLogLevelFilter = myLogLevel;
        config.DiagnosticInfrastructureLogs.ScheduledTransferLogLevelFilter = myLogLevel;
        config.WindowsEventLog.ScheduledTransferLogLevelFilter = myLogLevel;

        // Add in configuration settings for Windows Event logs
        config.WindowsEventLog.DataSources.Add("Application!*");
        config.WindowsEventLog.DataSources.Add("System!*");

        // Add a custom directory transfer
        DirectoryConfiguration directoryConfiguration = new DirectoryConfiguration();
        directoryConfiguration.Container = "wad-custom-logs";
        directoryConfiguration.DirectoryQuotaInMB = 0;
        directoryConfiguration.Path = @"c:\logs";
        config.Directories.DataSources.Add(directoryConfiguration);

        // Enable full crash dump collection.
        CrashDumps.EnableCollection(true);

        // Use 30 seconds for the perf counter sample rate.
        TimeSpan perfSampleRate = TimeSpan.FromSeconds(30D);

        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
            CounterSpecifier = @"\Memory\Available Bytes",
            SampleRate = perfSampleRate
        });

        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
            CounterSpecifier = @"\Processor(_Total)\% Processor Time",
            SampleRate = perfSampleRate
        });

        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
            CounterSpecifier = @"\Process(WaWorkerHost)\% Processor Time",
            SampleRate = perfSampleRate
        });

        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
            CounterSpecifier = @"\Process(WaWorkerHost)\Private Bytes",
            SampleRate = perfSampleRate
        }); 
                
        config.PerformanceCounters.DataSources.Add(new PerformanceCounterConfiguration()
        {
            CounterSpecifier = @"\Process(WaWorkerHost)\Thread Count",
            SampleRate = perfSampleRate
        });

        // Apply the updated configuration to the diagnostic monitor.
        // The first parameter is for the connection string configuration setting.
        DiagnosticMonitor.Start("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString", config);

    }
    catch (Exception e)  
        {
                sEvent += e.Message;
                EventLog.WriteEntry(sSource, sEvent, EventLogEntryType.Error, 0);
        } 
            
    return base.OnStart();   
}

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="Windows_Azure_Full_Diagnostics" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole1">
    <Sites>
      <Site name="Web">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="8080" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
      <Import moduleName="RemoteAccess" />
      <Import moduleName="RemoteForwarder" />
    </Imports>
    <ConfigurationSettings>
      <Setting name="ScheduledTransferPeriod" />
      <Setting name="LogLevelFilter" />
    </ConfigurationSettings>
    <LocalResources>
      <LocalStorage name="DiagnosticStore" cleanOnRoleRecycle="false" sizeInMB="8192" />
    </LocalResources>
  </WebRole>
  <WorkerRole name="WorkerRole1" vmsize="Small">
    <Imports>
      <Import moduleName="Diagnostics" />
      <Import moduleName="RemoteAccess" />
    </Imports>
    <LocalResources>
      <LocalStorage name="DiagnosticStore" sizeInMB="8192" cleanOnRoleRecycle="false" />
    </LocalResources>
    <ConfigurationSettings>
      <Setting name="ScheduledTransferPeriod" />
      <Setting name="LogLevelFilter" />
    </ConfigurationSettings>
  </WorkerRole>
</ServiceDefinition>

note附註
此組態檔是透過計算模擬器在本機使用。

<?xml version="1.0" encoding="utf-8"?>
<ServiceConfiguration serviceName="Windows_Azure_Full_Diagnostics" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="2" osVersion="*">
  <Role name="WebRole1">
    <Instances count="1" />
    <ConfigurationSettings>
      <Setting name="ScheduledTransferPeriod" value="1" />
      <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" />
      <Setting name="LogLevelFilter" value="Verbose" />
      <Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.Enabled" value="true" />
      <Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountUsername" value="me" />
      <Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountEncryptedPassword" value="MIIBnQYJKoZIhvcNAQcDoIIBjjCCAYoCAQAxggFOMIIBSgIBADAyMB4xHDAaBgNVBAMME1dpbmRvd3MgQXp1cmUgVG9vbHMCEDra5x6UQkuIRHdUChkiglEwDQYJKoZIhvcNAQEBBQAEggEAp8ADE0ov0pKTFo6V1AI94NmsUr8YcQ/dl4M63zbBQkrjSvqqzgofMcMwxYVO8gTwmr3eXawTNp2fbPdN68ZynNgRwEHBm67QP3y6lcAFvx8Amxvp8GZ6qxpAYGE8LhpqBNzoel55mot6IZg0I3qfXtl6SHyfLcyGuPv3nDEzhuYGuPSFR+UF82G2ZK0omLzSuI3KQcbFyTxaUYDIu/fSNOkHVOWwgpNND3SIvg+nSHfS38w+nskAA7bo7oN06LnC+3lLNRrpoKsPBaqogqfyhTkivc3+AJoQ6UAHIyyAJU6kfp4iP7gMl0ZU1mLVeqX5oDwmywf9FGRf7vSn2uEfiTAzBgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECAw305eQdOSogBA6i8i7rTruZOxAadm1g545" />
      <Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountExpiration" value="2011-12-31T23:59:59.0000000-05:00" />
      <Setting name="Microsoft.WindowsAzure.Plugins.RemoteForwarder.Enabled" value="true" />
    </ConfigurationSettings>
    <Certificates>
      <Certificate name="Microsoft.WindowsAzure.Plugins.RemoteAccess.PasswordEncryption" thumbprint="D91092F38C839BE56787A0528591E49510FCC711" thumbprintAlgorithm="sha1" />
    </Certificates>
  </Role>
  <Role name="WorkerRole1">
    <Instances count="1" />
    <ConfigurationSettings>
      <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" />
      <Setting name="ScheduledTransferPeriod" value="1" />
      <Setting name="LogLevelFilter" value="Verbose" />
      <Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.Enabled" value="true" />
      <Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountUsername" value="me" />
      <Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountEncryptedPassword" value="MIIBnQYJKoZIhvcNAQcDoIIBjjCCAYoCAQAxggFOMIIBSgIBADAyMB4xHDAaBgNVBAMME1dpbmRvd3MgQXp1cmUgVG9vbHMCEDra5x6UQkuIRHdUChkiglEwDQYJKoZIhvcNAQEBBQAEggEAp8ADE0ov0pKTFo6V1AI94NmsUr8YcQ/dl4M63zbBQkrjSvqqzgofMcMwxYVO8gTwmr3eXawTNp2fbPdN68ZynNgRwEHBm67QP3y6lcAFvx8Amxvp8GZ6qxpAYGE8LhpqBNzoel55mot6IZg0I3qfXtl6SHyfLcyGuPv3nDEzhuYGuPSFR+UF82G2ZK0omLzSuI3KQcbFyTxaUYDIu/fSNOkHVOWwgpNND3SIvg+nSHfS38w+nskAA7bo7oN06LnC+3lLNRrpoKsPBaqogqfyhTkivc3+AJoQ6UAHIyyAJU6kfp4iP7gMl0ZU1mLVeqX5oDwmywf9FGRf7vSn2uEfiTAzBgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECAw305eQdOSogBA6i8i7rTruZOxAadm1g545" />
      <Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountExpiration" value="2011-12-31T23:59:59.0000000-05:00" />
    </ConfigurationSettings>
    <Certificates>
      <Certificate name="Microsoft.WindowsAzure.Plugins.RemoteAccess.PasswordEncryption" thumbprint="D91092F38C839BE56787A0528591E49510FCC711" thumbprintAlgorithm="sha1" />
    </Certificates>
  </Role>
</ServiceConfiguration>

這是 Web 角色的 diagnostics.wadcfg 檔案範例。

<?xml version="1.0" encoding="utf-8" ?>
<DiagnosticMonitorConfiguration xmlns="http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration"
      configurationChangePollInterval="PT1M"
      overallQuotaInMB="4096">
  <DiagnosticInfrastructureLogs bufferQuotaInMB="0"
     scheduledTransferLogLevelFilter="Verbose"
     scheduledTransferPeriod="PT1M" />
  <Logs bufferQuotaInMB="0"
     scheduledTransferLogLevelFilter="Verbose"
     scheduledTransferPeriod="PT1M" />
  <Directories bufferQuotaInMB="0"
     scheduledTransferPeriod="PT1M">

    <!-- These three elements specify the special directories 
           that are set up for the log types -->
    <CrashDumps container="wad-crash-dumps" directoryQuotaInMB="0" />
    <FailedRequestLogs container="wad-frq" directoryQuotaInMB="0" />
    <IISLogs container="wad-iis" directoryQuotaInMB="0" />
  </Directories>

  <PerformanceCounters bufferQuotaInMB="0" scheduledTransferPeriod="PT1M">
    <!-- The counter specifier is in the same format as the imperative 
           diagnostics configuration API -->
    <PerformanceCounterConfiguration counterSpecifier="\Memory\Available Bytes" sampleRate="PT30S" />
    <PerformanceCounterConfiguration counterSpecifier="\Processor(_Total)\% Processor Time" sampleRate="PT30S" />
    <PerformanceCounterConfiguration counterSpecifier="\Process(w3wp)\% Processor Time" sampleRate="PT30S" />
    <PerformanceCounterConfiguration counterSpecifier="\Process(w3wp)\Private Bytes" sampleRate="PT30S" />
    <PerformanceCounterConfiguration counterSpecifier="\Process(w3wp)\Thread Count" sampleRate="PT30S" />
    <PerformanceCounterConfiguration counterSpecifier="\.NET CLR Interop(_Global_)\# of marshalling" sampleRate="PT30S" />
    <PerformanceCounterConfiguration counterSpecifier="\.NET CLR Loading(_Global_)\% Time Loading" sampleRate="PT30S" />
    <PerformanceCounterConfiguration counterSpecifier="\.NET CLR LocksAndThreads(_Global_)\Contention Rate / sec" sampleRate="PT30S" />
    <PerformanceCounterConfiguration counterSpecifier="\.NET CLR Memory(_Global_)\# Bytes in all Heaps" sampleRate="PT30S" />
    <PerformanceCounterConfiguration counterSpecifier="\.NET CLR Networking(_Global_)\Connections Established" sampleRate="PT30S" />
    <PerformanceCounterConfiguration counterSpecifier="\.NET CLR Remoting(_Global_)\Remote Calls/sec" sampleRate="PT30S" />
    <PerformanceCounterConfiguration counterSpecifier="\.NET CLR Jit(_Global_)\% Time in Jit" sampleRate="PT30S" />
  </PerformanceCounters>
  <WindowsEventLog bufferQuotaInMB="0"
     scheduledTransferLogLevelFilter="Verbose"
     scheduledTransferPeriod="PT1M">
    <!-- The event log name is in the same format as the imperative 
           diagnostics configuration API -->
    <DataSource name="Application!*" />
    <DataSource name="System!*" />
  </WindowsEventLog>
</DiagnosticMonitorConfiguration>

這是寫入 wad-control-container Blob 的預設組態。

<?xml version="1.0"?>
<ConfigRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <DataSources>
    <OverallQuotaInMB>4080</OverallQuotaInMB>
    <Logs>
      <BufferQuotaInMB>0</BufferQuotaInMB>
      <ScheduledTransferPeriodInMinutes>0</ScheduledTransferPeriodInMinutes>
      <ScheduledTransferLogLevelFilter>Undefined</ScheduledTransferLogLevelFilter>
    </Logs>
    <DiagnosticInfrastructureLogs>
      <BufferQuotaInMB>0</BufferQuotaInMB>
      <ScheduledTransferPeriodInMinutes>0</ScheduledTransferPeriodInMinutes>
      <ScheduledTransferLogLevelFilter>Undefined</ScheduledTransferLogLevelFilter>
    </DiagnosticInfrastructureLogs>
    <PerformanceCounters>
      <BufferQuotaInMB>0</BufferQuotaInMB>
      <ScheduledTransferPeriodInMinutes>0</ScheduledTransferPeriodInMinutes>
      <Subscriptions />
    </PerformanceCounters>
    <WindowsEventLog>
      <BufferQuotaInMB>0</BufferQuotaInMB>
      <ScheduledTransferPeriodInMinutes>0</ScheduledTransferPeriodInMinutes>
      <Subscriptions />
      <ScheduledTransferLogLevelFilter>Undefined</ScheduledTransferLogLevelFilter>
    </WindowsEventLog>
    <Directories>
      <BufferQuotaInMB>0</BufferQuotaInMB>
      <ScheduledTransferPeriodInMinutes>0</ScheduledTransferPeriodInMinutes>
      <Subscriptions>
        <DirectoryConfiguration>
          <Path>C:\Users\me\AppData\Local\dftmp\Resources\c95f5289-7d10-4bff-b105-198904c9ad93\directory\DiagnosticStore\FailedReqLogFiles</Path>
          <Container>wad-iis-failedreqlogfiles</Container>
          <DirectoryQuotaInMB>1024</DirectoryQuotaInMB>
        </DirectoryConfiguration>
        <DirectoryConfiguration>
          <Path>C:\Users\me\AppData\Local\dftmp\Resources\c95f5289-7d10-4bff-b105-198904c9ad93\directory\DiagnosticStore\LogFiles</Path>
          <Container>wad-iis-logfiles</Container>
          <DirectoryQuotaInMB>1024</DirectoryQuotaInMB>
        </DirectoryConfiguration>
        <DirectoryConfiguration>
          <Path>C:\Users\me\AppData\Local\dftmp\Resources\c95f5289-7d10-4bff-b105-198904c9ad93\directory\DiagnosticStore\CrashDumps</Path>
          <Container>wad-crash-dumps</Container>
          <DirectoryQuotaInMB>1024</DirectoryQuotaInMB>
        </DirectoryConfiguration>
      </Subscriptions>
    </Directories>
  </DataSources>
  <IsDefault>true</IsDefault>
</ConfigRequest>

本文對您有任何幫助嗎?
(剩餘 1500 個字元)
感謝您提供意見
顯示:
© 2015 Microsoft