ULS 日志记录提示第 2 部分
ULS 日志记录提示第 2 部分
在 ULS 日志记录提示的第 1 部分 (https://blogs.msdn.com/b/sharepoint_chs/archive/2011/03/21/uls.aspx),我提供了一些用于添加自定义 ULS 日志记录区域的代码,并介绍了如何在您的项目中使用它。 在使用一段时间后,我发现了以下几个问题:
1. 其中一些代码与最新的 SDK 不一致 – 基本上是我已实现而 SDK 暗示不需要的一些代码片段,以及我使用的与 SDK 示例稍有不同的一些代码(顺便说一句,该示例需要更新,我会单独进行处理)。
2. 仅当我将 TraceSeverity 设置为 Medium 时,日志记录才会发生;无法有效地对跟踪级别进行区分。
3. 最烦人的部分 – 当我尝试调用自定义区域所需的自定义类时,如果在 POST 活动期间我尝试执行任何日志记录,调用将失败。 在 POST 期间,它将触发关于无法更新 SPWeb 的所有常见错误,除非将 AllowUnsafeUpdates 属性设置为 true。 现在,在日志事件期间对 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 重写。 事实再次证明,我同样不会实际使用它,因此继续遵循“简即美”原则,将其删除。
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 问题的错误。
· 我的自定义日志记录区域和类别显示在管理中心,因此我可以进入配置诊断日志记录并更改跟踪和事件级别。 例如,当处于默认的 Medium 跟踪级别时,属于 TracingSeverity.Medium 的所有 ULS 写入均将写入日志,而属于 TracingSeverity.Verbose 的写入则不会写入日志。 如果我希望在日志中开始显示 TracingSeverity.Verbose 条目,只需转到配置诊断日志记录并将其中的跟踪级别更改为 Verbose。
总之,该解决方案更简单,功能更强大。 我认为这就是人们经常嚷嚷的一个所谓双赢解决方案。
附注: 在这里我想宣泄对 Portland Trailblazer 的 LaMarcus Aldridge 的不满。 这家伙未能入选西部 NBA 全明星团队,真是个笨蛋! 好了,闲话少说,我知道你们到这儿来都是想找点有用的 Share-n-Dipity-icous 信息。 希望我的文章对你们有帮助。
这是一篇本地化的博客文章。请访问 Tips for ULS Logging Part 2 以查看原文