Partager via


ULS 記錄的秘訣

ULS 記錄的秘訣

UPDATE 2-4-2011: 我建議查看這個的更新範例,網址為: https://blogs.msdn.com/b/sharepoint_cht/archive/2011/03/21/uls-2.aspx 。 新範例較佳且更實用

當我將某些 ULS 記錄新增至最近的專案,我注意到一個煩人的副作用。 在 ULS 記錄中,此「區域」會顯示為 "Unknown"。 我知道這個問題的某些層面一直出現在其他地方,但是我就是想要盡快張貼一篇文章,以說明我找到可處理此問題的最權宜方法 (絕對比其他某些我已說明的解決方案輕鬆許多)。 有一件事值得提出的是,如果您根本不想這樣做,我相信最佳作法團隊在 CodePlex 上發佈的 Logging Framework 會自行處理這個問題。 但是我通常會撰寫自己的程式碼,因此我將在這裡簡短地說明解決方案。

第一件要注意的事是大部分的 SDK 文件是根據建立新 SPDiagnosticsCategory 的概念來操作。 此類別之新執行個體的建構函式可讓您提供「類別」名稱,而且當您這樣做時,您一定會看到要使用的任何自訂「類別」名稱出現在 ULS 記錄的「類別」欄中。 在大多數情況下,如果您要設計自己的自訂記錄,您可能也會想要有一個自訂「區域」,以搭配自訂「類別」。 不幸的是,SDK 讓您必須經歷相當複雜的練習,才能完成此作業,因為您無法使用簡單的建構函式,來建立新的「區域」並使用它,您必須撰寫自己從 SPDiagnosticsServiceBase 衍生的類別。

我選擇實作這一切的方法是建立一個 CS 檔案,以包含我的記錄類別與診斷服務基礎類別。 我將先從診斷基礎類別開始,我在下方貼上整個類別,然後我會逐步解說值得提出的要點﹕

    public class SteveDiagnosticService : SPDiagnosticsServiceBase

    {

        private const string LOG_AREA = "Steve Area";

        public enum LogCategories

        {

            SteveCategory

        }

        public SteveDiagnosticService()

            : base("Steve Diagnostics Service", SPFarm.Local)

        {

        }

        public SteveDiagnosticService(string name, SPFarm parent)

            : base(name, parent)

        {

        }

        protected override bool HasAdditionalUpdateAccess()

        {

            return true;

        }

        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()

        {

            List<SPDiagnosticsCategory> categories = new List<SPDiagnosticsCategory>();

            categories.Add(new SPDiagnosticsCategory(

  LogCategories.SteveCategory.ToString(),

             TraceSeverity.Medium, EventSeverity.Information));

            SPDiagnosticsArea area = new SPDiagnosticsArea(

             LOG_AREA, 0, 0, false, categories);

            List<SPDiagnosticsArea> areas = new List<SPDiagnosticsArea>();

            areas.Add(area);

            return areas;

        }

    }

 

現在讓我們看看有趣的部分:

private const string LOG_AREA = "Steve Area";

以下是我定義要寫入 ULS 記錄的「區域」名稱之位置。

public enum LogCategories

{

SteveCategory

}  

這是我要加入自訂「區域」的「類別」清單。 在此例中,我只有一個要與此「區域」搭配使用的類別,但是如果您需要數個類別,只要展開此列舉的內容即可。

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);

}

}

 

這是我們實作的兩個重要方法之一,它是我們實際寫入 ULS 記錄的位置。 第一行是我取得 SPDiagnosticCategory 的位置,而當我這麼做時,我參照它所屬的「區域」。 在第二行,我只是呼叫區域 SPDiagnosticsServiceBase 類別上的基礎類別方法,以寫入 ULS 記錄,其中包括傳遞與「區域」關聯的「類別」。

protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()

{

List<SPDiagnosticsCategory> theCategories = new List<SPDiagnosticsCategory>();

theCategories.Add(new SPDiagnosticsCategory(

  LogCategories.SteveCategory.ToString(),

             TraceSeverity.Medium, EventSeverity.Information));

SPDiagnosticsArea theArea = new SPDiagnosticsArea(

             LOG_AREA, 0, 0, false, theCategories);

List<SPDiagnosticsArea> theArea = new List<SPDiagnosticsArea>();

theArea.Add(area);

return theArea;

}

 

在這個 override 中,我返回所有自訂「區域」的 SharePoint。 在此例子中,我將使用一個「區域」,因此也只會傳回一個「區域」。 另外,如上所述,我只會使用一個自訂「類別」與「區域」搭配。 如果我要使用多個自訂「類別」,我會 1) 將它們加入前面所述的列舉,並且 2) 將每個「類別」加入在我此方法中定義的 theCategories List 執行個體。

那是加入自訂「區域」並使其出現在 ULS 記錄中適當欄位背後的真正主要魔法。 記錄類別實作也非常簡單,我將在這裡貼上記錄類別實作的主要類別,並稍做解說:

    public class Log

    {

        private const int LOG_ID = 11100;

    public static void WriteLog(string Message, TraceSeverity TraceLogSeverity)

        {

            try

            {

            //in this simple example, I’m always using the same category

              //you could of course pass that in as a method parameter too

              //and use it when you call SteveDiagnosticService

                SteveDiagnosticService.Local.LogMessage(LOG_ID,

                    SteveDiagnosticService.LogCategories.SteveCategory,

                    TraceLogSeverity, Message, null);

            }

            catch (Exception writeEx)

            {

                //ignore

                Debug.WriteLine(writeEx.Message);

            }

        }

    }

 

這樣便可以從參照此程式碼的方法來實作程式碼。 因為 WriteLog 是靜態方法,所以我的程式碼只是 Log.WriteLog(“This is my error message”, TraceSeverity.Medium); 。 在此範例的 ULS 記錄中,它會在 "Steve Area" 區域以及 "SteveCategory" 類別中,以 "This is my error message" 訊息建立一個項目。

這是翻譯後的部落格文章。英文原文請參閱 Tips for ULS Logging