ULS 記錄秘訣的第 2 部分
ULS 記錄秘訣的第 2 部分
在 ULS 記錄秘訣的第 1 部分 (https://blogs.msdn.com/b/sharepoint_cht/archive/2011/03/21/uls.aspx) 我包括一些程式碼以新增自訂 ULS 記錄區域,並示範如何在專案中使用它。 在撰寫一些後,我發現一些事情:
1. 有一些程式碼對最新的 SDK 沒有作用:基本上,SDK 暗示我應該不需要某些已實作的程式碼片段,而且我正在進行的一些東西與 SDK 範例稍微不同 (因此需要更新,而我將會分開處理它)。
2. 只有將 TraceSeverity 設定為 Medium 時,才會執行記錄;沒有一個有效的方法可設置於不同追蹤層級中。
3. 最令人困擾的部分:當我嘗試呼叫我的自訂區域所需的自訂類別時,它會在我嘗試於 POST 活動期間執行任何記錄時失敗。 除非將 AllowUnsafeUpdates 屬性設定為 true,否則它會觸發所有關於在 POST 期間無法更新 SPWeb 的常見錯誤。 現在於記錄事件期間在 SPWeb 上設定該屬性,好讓我的記錄事件可運作,似乎讓人幾近瘋狂 (順便對所有感到瘋狂的人說抱歉)。 因此我下定決心要找出更好的方法。
在本文中,我將根據上一個範例進行改善,並逐漸新增它。 以下是我們即將示範的內容
1. 自訂區域的改善類別;在這個版本中它實際上已精簡化。
2. 在管理中心的 [監視] 區段中與「設定診斷記錄」的整合。 此整合將進一步允許在自訂「區域」與「類別」上設定追蹤層級。
3. 登錄資訊:登錄和取消登錄自訂 ULS 記錄類別,因此它會與管理中心整合,而且可以從管理中心移除。
首先,讓我們查看此類別的新精簡版本。 在此版本與第一篇文章所顯示的版本之間有許多相似處,但是這個版本較為精簡和簡單。 如下所示:
[Guid("833B687D-0DD1-4F17-BF6A-B64FBC1AC6A8")]
public class SteveDiagnosticService : SPDiagnosticsServiceBase
{
private const string LOG_AREA = "Steve Area";
public enum LogCategories
{
SteveCategory
}
public SteveDiagnosticService()
{
}
public SteveDiagnosticService(string name, SPFarm parent)
: base(name, parent)
{
}
public static SteveDiagnosticService Local
{
get
{
return SPDiagnosticsServiceBase.GetLocal<SteveDiagnosticService>();
}
}
public void LogMessage(ushort id, LogCategories LogCategory,
TraceSeverity traceSeverity, string message,
params object[] data)
{
if (traceSeverity != TraceSeverity.None)
{
SPDiagnosticsCategory category
= Local.Areas[LOG_AREA].Categories[LogCategory.ToString()];
Local.WriteTrace(id, category, traceSeverity, message, data);
}
}
protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()
{
yield return new SPDiagnosticsArea(LOG_AREA, 0, 0, false,
new List<SPDiagnosticsCategory>()
{
new
SPDiagnosticsCategory(LogCategories.AzureConfig.ToString(),
TraceSeverity.Medium, EventSeverity.Information, 1,
Log.LOG_ID)
});
}
}
以下是從第一個版本所做的重要變更:
1. 將 Guid 屬性新增至類別:
[Guid("833B687D-0DD1-4F17-BF6A-B64FBC1AC6A8")]
我將 Guid 屬性新增至類別,因為 SharePoint 需要它才能在設定資料庫中識別其唯一性。
2. 已變更預設的建構函式:
public SteveDiagnosticService()
{
}
現在它只是標準的空建構函式。 在我呼叫建構函式的其他超載之前,它需要服務與 SPFarm 的名稱。 總共就這麼少的程式碼,愈簡單愈好。
3. 已刪除 HasAdditionalUpdateAccess override。 我又再一次沒有真正使用它,因此繼續「多不一定是好」的原則,我移除了它。
4. 將 ProvideAreas 方法大幅縮短;現在它符合在 SDK 中使用的相同模式:
yield return new SPDiagnosticsArea(LOG_AREA, 0, 0, false,
new List<SPDiagnosticsCategory>()
{
new
SPDiagnosticsCategory(LogCategories.AzureConfig.ToString(),
TraceSeverity.Medium, EventSeverity.Information, 1,
Log.LOG_ID)
});
因此上述已處理的問題 #1:我的程式碼現在看起來較為簡潔和精巧。 其他問題:缺少追蹤層級、在 POST 期間記錄時擲出例外狀況,以及與管理中心整合:透過稍微修改程式碼並登錄,這一切基本上都已修正。 在 SDK 中的範例目前在這個部分比較弱,但是我會使它執行我們所需要的功能。 為了簡化這些作業,我針對含有上述自訂 ULS 類別的組件建立一個新功能。 我已經新增一個功能接收器,我在 FeatureInstalled 事件期間登錄自訂 ULS 組件,我在 FeatureUninstalling 事件期間取消登錄它。 這對於我的案例是一個很好的解決方案,因為我將我的功能建立成伺服器陣列範圍功能,因此在新增和部署解決方案時,會自動啟用。 因此,執行此登錄與取消登錄變得非常簡單;如下所示:
public override void FeatureInstalled(SPFeatureReceiverProperties properties)
{
try
{
SteveDiagnosticsService.Local.Update();
}
catch (Exception ex)
{
throw new Exception("Error installing feature: " + ex.Message);
}
}
public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
{
try
{
SteveDiagnosticsService.Local.Delete();
}
catch (Exception ex)
{
throw new Exception("Error uninstalling feature: " + ex.Message);
}
}
另一件要在這裡指出的事情是,我可以參照 "SteveDiagnosticService",因為我 a) 已在封裝功能的專案中使用自訂記錄類別新增組件的參照,而且 b) 我已為組件使用自訂記錄類別新增一個 using 陳述式至我的功能接收器類別。
透過登錄我的自訂 ULS 記錄類別,我獲得許多好處:
· 當我在 POST 期間寫入 ULS 記錄時,我不會再收到更新 SPWeb 問題的任何錯誤
· 我的自訂記錄「區域」與「類別」會出現在管理中心內,這樣我就可以進入「設定」診斷記錄並變更追蹤和事件層級。 例如,當在「中等」追蹤的預設層級時,所有 ULS 寫入記錄的內容為 TracingSeverity.Medium 時,會寫入記錄,但是寫入內容為 TracingSeverity.Verbose 時,則不會寫入記錄。 如果我希望讓 TracingSeverity.Verbose 項目開始出現在記錄中,我會直接進入「設定」診斷記錄,並將那裡的「追蹤」層級變更為「詳細資訊」。
大體上,解決方案變得更簡單且更實用。 我想這是我一直聽到的其中一項雙贏方案。
附註: 我想要在這裡為波特蘭的先驅 LaMarcus Aldridge 記錄我的反對票。 他無法進入 NBA 西區聯盟明星球隊真是太可惜了。 好了,說夠了個人的評論,我知道您們來這裡都希望找到真正有用的資訊。 希望本文對您有幫助。
這是翻譯後的部落格文章。英文原文請參閱 Tips for ULS Logging Part 2