記錄最佳實踐 [關閉]
我想了解人們如何處理真實應用程序中的跟踪和日誌記錄。以下是一些可能有助於解釋您的答案的問題。
構架
你使用什麼框架?
- log4net
- System.Diagnostics.Trace
- System.Diagnostics.TraceSource
- 記錄應用程序塊
- 其他?
如果使用跟踪,是否使用 Trace.Correlation.StartLogicalOperation?
您是手動編寫此程式碼,還是使用某種形式的面向方面程式來完成它?願意分享程式碼片段嗎?
您是否對跟踪源提供任何形式的粒度?例如,WPF TraceSources 允許您在不同級別配置它們:
- System.Windows -所有 WPF 的設置
- System.Windows.Animation -專門為動畫覆蓋。
聽眾
您使用什麼日誌輸出?
- 文本文件
- XML 文件
- 事件日誌
- 其他?
如果使用文件,您使用滾動日誌還是僅使用單個文件?您如何使日誌可供人們使用?
查看
您使用什麼工具來查看日誌?
- 記事本
- 尾巴
- 事件查看器
- 系統中心運營經理/微軟運營經理
- WCF 服務跟踪查看器
- 其他?
如果您正在建構 ASP.NET 解決方案,您是否還使用 ASP.NET 健康監控?您是否在執行狀況監視器事件中包含跟踪輸出?Trace.axd 呢?
自定義性能計數器呢?
**更新:**對於 System.Diagnostics 的擴展,提供一些您可能需要的缺少的偵聽器,請參閱 CodePlex 上的 Essential.Diagnostics ( <http://essentialdiagnostics.codeplex.com/> )
構架
問:你們使用什麼框架?
答:System.Diagnostics.TraceSource,內置於 .NET 2.0。
它為應用程序提供了強大、靈活、高性能的日誌記錄,但是許多開發人員並沒有意識到它的功能並且沒有充分利用它們。
在某些領域,附加功能很有用,或者有時該功能存在但沒有很好的文件記錄,但這並不意味著整個日誌框架(被設計為可擴展的)應該像一些流行的替代方案一樣被丟棄並完全替換(NLog、log4net、Common.Logging 甚至 EntLib 日誌記錄)。
與其改變向應用程序添加日誌語句的方式並重新發明輪子,不如在您需要的幾個地方擴展 System.Diagnostics 框架。
在我看來,其他框架,甚至是 EntLib,都只是患有 Not Invented Here Syndrome,我認為他們浪費了時間重新發明在 System.Diagnostics 中已經很好工作的基礎知識(例如你如何編寫日誌語句),而不是填補現有的少數空白。簡而言之,不要使用它們——它們不是必需的。
你可能不知道的功能:
- 使用採用格式字元串和參數的 TraceEvent 重載可以幫助提高性能,因為參數作為單獨的引用保存,直到 Filter.ShouldTrace() 成功。這意味著在系統確認消息之前不會對參數值進行昂貴的 ToString() 呼叫。
- Trace.CorrelationManager 允許您關聯有關相同邏輯操作的日誌語句(見下文)。
- VisualBasic.Logging.FileLogTraceListener 適合寫入日誌文件並支持文件輪換。儘管在 VisualBasic 命名空間中,它也可以很容易地在 C#(或其他語言)項目中使用,只需包含 DLL。
- 使用 EventLogTraceListener 時,如果您使用多個參數和空或 null 格式字元串呼叫 TraceEvent,則如果您使用本地化消息資源,則參數將直接傳遞給 EventLog.WriteEntry()。
- 服務跟踪查看器工具(來自 WCF)對於查看活動相關日誌文件的圖表非常有用(即使您沒有使用 WCF)。這確實可以幫助調試涉及多個執行緒/活動的複雜問題。
- 通過清除所有偵聽器(或刪除預設值)來避免成本;否則 Default 會將所有內容傳遞給跟踪系統(並產生所有 ToString() 成本)。
您可能希望擴展的區域(如果需要):
- 數據庫跟踪偵聽器
- 彩色控制台跟踪偵聽器
- MSMQ / 電子郵件 / WMI 跟踪偵聽器(如果需要)
- 實現 FileSystemWatcher 以呼叫 Trace.Refresh 以進行動態配置更改
其他建議:
使用結構化事件ID,並保留一個參考列表(例如,將它們記錄在一個枚舉中)。
為系統中的每個(重要)事件擁有唯一的事件 ID 對於關聯和查找特定問題非常有用。很容易追溯到記錄/使用事件 ID 的特定程式碼,並且可以很容易地為常見錯誤提供指導,例如錯誤 5178 表示您的數據庫連接字元串錯誤等。
事件 id 應該遵循某種結構(類似於電子郵件和 HTTP 中使用的回复程式碼理論),這允許您在不知道具體程式碼的情況下按類別對待它們。
例如,第一個數字可以詳細說明一般類:1xxx 可用於“開始”操作,2xxx 用於正常行為,3xxx 用於活動跟踪,4xxx 用於警告,5xxx 用於錯誤,8xxx 用於“停止”操作,9xxx 用於致命錯誤,等等。
第二個數字可以詳細說明區域,例如21xx表示數據庫資訊(41xx表示數據庫警告,51xx表示數據庫錯誤),22xx表示計算模式(42xx表示計算警告等),23xx表示另一個模組等。
分配的結構化事件 ID 還允許您在過濾器中使用它們。
問:如果使用跟踪,是否使用 Trace.Correlation.StartLogicalOperation?
答: Trace.CorrelationManager 對於在任何類型的多執行緒環境中關聯日誌語句非常有用(這在當今幾乎是任何事情)。
您至少需要為每個邏輯操作設置一次 ActivityId 才能關聯。
然後可以將 Start/Stop 和 LogicalOperationStack 用於簡單的基於堆棧的上下文。對於更複雜的上下文(例如非同步操作),使用 TraceTransfer 到新的 ActivityId(在更改它之前)允許關聯。
服務跟踪查看器工具可用於查看活動圖(即使您不使用 WCF)。
問:您是手動編寫此程式碼,還是使用某種形式的面向方面程式來編寫?願意分享程式碼片段嗎?
答:您可能想要創建一個範圍類,例如 LogicalOperationScope,它 (a) 在創建時設置上下文,並且 (b) 在釋放時重置上下文。
這允許您編寫如下程式碼來自動包裝操作:
using( LogicalOperationScope operation = new LogicalOperationScope("Operation") ) { // .. do work here }在創建範圍時,如果需要,可以首先設置 ActivityId,呼叫 StartLogicalOperation,然後記錄 TraceEventType.Start 消息。在 Dispose 上,它可以記錄停止消息,然後呼叫 StopLogicalOperation。
問:你們是否提供任何形式的跟踪源粒度?例如,WPF TraceSources 允許您在不同級別配置它們。
答:是的,隨著系統變得越來越大,多個跟踪源很有用/很重要。
雖然您可能希望始終記錄所有警告及以上消息,或所有資訊及以上消息,但對於任何規模合理的系統,活動跟踪(開始、停止等)和詳細日誌記錄的數量會變得過多。
與其只有一個開關可以將其全部打開或關閉,不如能夠一次為系統的一個部分打開此資訊很有用。
這樣,您可以從通常的日誌記錄(所有警告、錯誤等)中定位重大問題,然後“放大”您想要的部分並將它們設置為活動跟踪甚至調試級別。
您需要的跟踪源的數量取決於您的應用程序,例如,您可能希望每個程序集或應用程序的每個主要部分都有一個跟踪源。
如果您需要更精細的控制,請添加單獨的布爾開關來打開/關閉特定的高容量跟踪,例如原始消息轉儲。(或者可以使用單獨的跟踪源,類似於 WCF/WPF)。
您可能還需要考慮將活動跟踪與一般(其他)日誌記錄分開的跟踪源,因為它可以更容易地按照您的需要配置過濾器。
請注意,即使使用不同的源,消息仍然可以通過 ActivityId 關聯,因此請根據需要使用盡可能多的消息。
聽眾
問:您使用什麼日誌輸出?
這可能取決於您正在編寫的應用程序類型以及正在記錄的內容。通常不同的東西會出現在不同的地方(即多個輸出)。
我通常將輸出分為三組:
(1) 事件 - Windows 事件日誌(和跟踪文件)
例如,如果編寫伺服器/服務,那麼在 Windows 上的最佳實踐是使用 Windows 事件日誌(您沒有要報告的 UI)。
在這種情況下,所有致命、錯誤、警告和(服務級別)資訊事件都應轉到 Windows 事件日誌。資訊級別應該為這些類型的高級事件保留,您希望在事件日誌中出現的事件,例如“服務啟動”、“服務停止”、“連接到 Xyz”,甚至可能是“計劃啟動” 、“使用者登錄”等。
在某些情況下,您可能希望將事件日誌寫入應用程序的內置部分,而不是通過跟踪系統(即直接寫入事件日誌條目)。這意味著它不會被意外關閉。(請注意,您仍然希望在跟踪系統中記錄相同的事件,以便進行關聯)。
相反,Windows GUI 應用程序通常會將這些報告給使用者(儘管他們也可能會記錄到 Windows 事件日誌中)。
事件也可能有相關的性能計數器(例如錯誤數/秒),協調任何直接寫入事件日誌、性能計數器、寫入跟踪系統並報告給使用者以便它們發生在同時。
即如果使用者在特定時間看到錯誤消息,您應該能夠在 Windows 事件日誌中找到相同的錯誤消息,然後在跟踪日誌中找到具有相同時間戳的相同事件(以及其他跟踪詳細資訊)。
(2) 活動 - 應用程序日誌文件或數據庫表(和跟踪文件)
這是系統進行的正常活動,例如提供網頁、送出股票市場交易、接受訂單、執行計算等。
活動跟踪(開始、停止等)在這裡很有用(以正確的粒度)。
此外,使用特定的應用程序日誌(有時稱為審核日誌)也很常見。通常這是一個數據庫表或應用程序日誌文件,包含結構化數據(即一組欄位)。
根據您的應用程序,這裡的情況可能會有些模糊。一個很好的例子可能是一個將每個請求寫入網路日誌的網路伺服器;類似的範例可能是消息傳遞系統或計算系統,其中每個操作都與特定於應用程序的詳細資訊一起記錄。
一個不太好的例子是股票市場交易或銷售訂單系統。在這些系統中,您可能已經記錄了活動,因為它們具有重要的業務價值,但是將它們與其他操作相關聯的原則仍然很重要。
除了自定義應用程序日誌外,活動通常還具有相關的性能計數器,例如每秒的事務數。
一般來說,您應該協調跨不同系統的活動記錄,即在增加性能計數器和記錄到跟踪系統的同時寫入應用程序日誌。如果您同時執行所有操作(或在程式碼中一個接一個),那麼調試問題會更容易(比它們都發生在程式碼中的不同時間/位置)。
(3) 調試跟踪 - 文本文件,或者 XML 或數據庫。
這是詳細級別和更低級別的資訊(例如,用於打開/關閉原始數據轉儲的自定義布爾開關)。這提供了系統在子活動級別所做的事情的膽量或細節。
這是您希望能夠為應用程序的各個部分打開/關閉的級別(因此有多個源)。您不希望這些東西弄亂 Windows 事件日誌。有時會使用數據庫,但更有可能是在特定時間後清除的滾動日誌文件。
此資訊與應用程序日誌文件之間的一個很大區別在於它是非結構化的。雖然應用程序日誌可能包含 To、From、Amount 等欄位,但詳細調試跟踪可能是程序員輸入的任何內容,例如“檢查值 X={value}, Y=false”或隨機註釋/標記,如“完成了,再試一次”。
一種重要的做法是確保您放入應用程序日誌文件或 Windows 事件日誌的內容也以相同的詳細資訊(例如時間戳)記錄到跟踪系統。這允許您在調查時關聯不同的日誌。
如果您計劃使用特定的日誌查看器,因為您有復雜的相關性,例如服務跟踪查看器,那麼您需要使用適當的格式,即 XML。否則,一個簡單的文本文件通常就足夠了——在較低級別,資訊大部分是非結構化的,因此您可能會發現數組轉儲、堆棧轉儲等。如果您可以關聯回更高級別的結構化日誌,事情應該好好地。
問:如果使用文件,您是使用滾動日誌還是僅使用單個文件?您如何使日誌可供人們使用?
答:對於文件,通常您希望從可管理性的角度滾動日誌文件(使用 System.Diagnostics,只需使用 VisualBasic.Logging.FileLogTraceListener)。
可用性再次取決於系統。如果您只是在談論文件,那麼對於伺服器/服務,可以在必要時訪問滾動文件。(Windows 事件日誌或數據庫應用程序日誌將有自己的訪問機制)。
如果您無法輕鬆訪問文件系統,那麼對數據庫的調試跟踪可能會更容易。[即實現一個數據庫 TraceListener]。
我為 Windows GUI 應用程序看到的一個有趣的解決方案是,它在執行時將非常詳細的跟踪資訊記錄到“飛行記錄器”中,然後當您將其關閉時,如果它沒有問題,它就會簡單地刪除該文件。
但是,如果它崩潰或遇到問題,則不會刪除該文件。如果它發現錯誤,或者下次執行時它會注意到該文件,然後它可以採取措施,例如壓縮它(例如 7zip)並通過電子郵件發送或以其他方式提供。
如今,許多系統都將故障自動報告給中央伺服器(在與使用者核對之後,例如出於隱私原因)。
查看
問:您使用什麼工具來查看日誌?
答:如果您有多個日誌出於不同的原因,那麼您將使用多個查看器。
Notepad/vi/Notepad++ 或任何其他文本編輯器是純文字日誌的基礎。
如果您有復雜的操作,例如帶有傳輸的活動,那麼您顯然會使用像服務跟踪查看器這樣的專用工具。(但如果你不需要它,那麼文本編輯器會更容易)。
由於我通常將高級資訊記錄到 Windows 事件日誌中,因此它提供了一種以結構化方式快速獲取概覽的方法(查找漂亮的錯誤/警告圖示)。如果日誌中沒有足夠的內容,您只需要開始搜尋文本文件,儘管至少日誌為您提供了一個起點。(此時,確保您的日誌具有協調的整體變得有用)。
通常,Windows 事件日誌還使這些重要事件可用於監控工具,如 MOM 或 OpenView。
其他 -
如果您登錄到數據庫,則可以輕鬆過濾和排序資訊(例如,放大特定的活動 ID。(對於文本文件,您可以使用 Grep/PowerShell 或類似工具來過濾您想要的特定 GUID)
MS Excel(或其他電子表格程序)。如果您可以使用正確的分隔符導入結構化或半結構化資訊,這對於分析結構化或半結構化資訊很有用,以便不同的值進入不同的列。
在調試/測試中執行服務時,為了簡單起見,我通常將它託管在控制台應用程序中,我發現彩色控制台記錄器很有用(例如,紅色表示錯誤,黃色表示警告等)。您需要實現自定義跟踪偵聽器。
請注意,該框架不包含彩色控制台記錄器或數據庫記錄器,因此,現在,如果您需要它們,則需要編寫它們(這不是太難)。
讓我很惱火的是幾個框架(log4net、EntLib 等)浪費時間重新發明輪子並重新實現了基本的日誌記錄、過濾和日誌記錄到文本文件、Windows 事件日誌和 XML 文件,每個框架都有自己的不同的方式(每個日誌語句都不同);然後,每個人都實現了自己的版本,例如數據庫記錄器,而其中大部分已經存在,而只需要為 System.Diagnostics 提供更多的跟踪偵聽器。談論重複工作的巨大浪費。
問:如果您正在建構 ASP.NET 解決方案,您是否還使用 ASP.NET 健康監控?您是否在執行狀況監視器事件中包含跟踪輸出?Trace.axd 呢?
這些東西可以根據需要打開/關閉。我發現 Trace.axd 對於調試伺服器如何響應某些事情非常有用,但它通常在使用頻繁的環境或長期跟踪中沒有用處。
問:自定義性能計數器呢?
對於專業應用程序,尤其是伺服器/服務,我希望看到它完全配備了性能監視器計數器和記錄到 Windows 事件日誌。這些是 Windows 中的標準工具,應該使用。
您需要確保包含您使用的性能計數器和事件日誌的安裝程序;這些應該在安裝時創建(以管理員身份安裝時)。當您的應用程序正常執行時,它不需要具有管理權限(因此無法創建失去的日誌)。
這是練習以非管理員身份進行開發的一個很好的理由(當您需要安裝服務等時,有一個單獨的管理員帳戶)。如果寫入事件日誌,.NET 將在您第一次寫入時自動創建失去的日誌;如果您以非管理員身份開發,您將儘早發現這一點,並避免在客戶安裝您的系統但由於他們沒有以管理員身份執行而無法使用它時出現令人討厭的意外。