Partager via


ULS 日志记录提示

ULS 日志记录提示

2011 年 2 月 4 日更新: 我建议看一看 https://blogs.msdn.com/b/sharepoint_chs/archive/2011/03/21/uls-2.aspx 上针对此内容的更新示例。新的示例更好,而且功能更多。

我将部分 ULS 日志记录添加到最近的一个项目时,发现了一个有点令人烦恼的副作用。 在 ULS 日志中,区域 (Area) 显示为未知 (Unknown)。 我知道其他人介绍过这一问题的某些方面,但我只想赶快发一篇文章,介绍我发现的此问题的最佳处理方法(当然比我看到的其他一些解决方法更好)。 值得指出的是,如果您根本不想这样做,我相信最佳实践团队在 CodePlex 上提供的日志记录框架可能会自动执行此操作。 但我通常会尽可能多地编写自己的代码,所以我将在此简单介绍一下解决方法。

首先需要注意,大多数 SDK 文档基于创建一个新 SPDiagnosticsCategory 的思路。 该类的新实例的构造函数允许您提供类别名称,当您这样做时,一定会发现要使用的任何自定义类别名称显示在 ULS 日志的“类别”(Category) 列中。 大多数情况下,如果您执行自己的自定义日志记录,您还需要一个自定义区域与自定义类别配合使用。 遗憾的是,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;

}

 

在此重写中,我将我所有的自定义区域返回到 SharePoint。 在本例中,我只使用我的一个区域,所以这是我发回的所有内容。 此外,如上所述,我只将一个自定义类别与我的区域一起使用。 如果我想使用多个自定义类别,那么我会:1) 将它们添加到上述枚举中 2) 然后将每个添加到我在此方法中定义的 theCategories 列表实例中。

这实际才是添加自定义区域并将其显示在 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”区域中创建一个条目和包含“This is my error message”消息的“SteveCategory”类别。

这是一篇本地化的博客文章。请访问 Tips for ULS Logging 以查看原文