65.9K
CodeProject 正在变化。 阅读更多。
Home

在 SharePoint 中实现更好日志记录的五点建议

starIconstarIconstarIconstarIconstarIcon

5.00/5 (6投票s)

2013年7月15日

CPOL

5分钟阅读

viewsIcon

30360

如何为您的应用程序实现更好的日志记录。

引言

为 SharePoint 编写的大部分代码都在高度不可预测的环境中运行。即使您的代码在开发环境中没有产生任何异常,相同的代码在生产环境中也可能莫名其妙地失败。因此,日志记录是您的解决方案和代码中至关重要的一个部分。

通常,日志记录是开发人员中一个相当流行的话题。有些人喜欢“我们自定义的日志系统”,另一些人则使用现有的框架,最后,其余的人可能会依赖本地操作系统提供的服务,例如 Windows API(这可不是开玩笑的!)。

如果您为 SharePoint 编写自定义代码,以下是一些改进您的解决方案的日志记录部分的建议

建议 #0 - 不要使用第三方日志框架

即使您坚持使用 log4netNLogEventLogSystem.Diagnostic.Trace,或者试图发明您自己的轮子,那么**永远不要再使用这些东西**。

SharePoint 有自己的日志系统,称为“统一日志记录系统 (ULS)”。如果您仍然想知道为什么您要使用 ULS 而不是您喜欢的日志框架,那么请考虑以下事实:

  • ULS 由 SharePoint 使用,因此如果您使用第三方日志记录,您将需要整合来自几个不同源的日志。
  • ULS 可以通过中央管理和 PowerShell 轻松配置。
  • ULS 可以在没有提升权限的情况下写入 Windows 事件日志(!)。
  • ULS 会缩小硬盘上的文本日志文件(!)。
  • ULS 不需要修改 `web.config` 文件(!)。这对于多服务器场来说是一个相当重要的考虑因素。
  • SharePoint 可以将来自多个服务器的 ULS 日志(不仅仅是日志……)聚合到日志数据库(使用情况和运行状况数据收集服务应用程序)。

建议 #1 - 最简单的情况不做任何处理

默认情况下,SharePoint 会捕获未处理的异常并将它们报告给 ULS 日志。如果您有未处理的异常,您可以轻松地在 ULS 日志中找到错误及其堆栈跟踪。如果您启用了“VerboseEx”日志记录级别,您甚至可以看到对数据库的 SQL 查询。

您还可以使用 ULSViewer 来获得更方便的日志查看体验。

与此同时,有一个例外情况——那就是关于 WebParts。如果您的自定义 WebPart 因异常而失败,那么最终用户只会看到默认的错误页面。如果您遇到配置错误的个人 WebPart 属性的错误,您可能会花费更多时间,您将无法跟踪和调试此错误,除非您以该特定用户的身份登录。如果您开发自定义 WebPart,那么更好的方法可能不仅仅是显示错误,还要提供一些关于如何修复该错误的建议。

建议 #2 - 使用 SPMonitoredScope 类

SPMonitoredScope 可以简单地这样使用:

using (new SPMonitoredScope("My Monitored Scope"))
{
 // Do Stuff...
}

您将简单地获得进入/退出日志记录,以及用于范围调用的耗时。默认情况下,SPMonitoredScope 的日志记录级别为“Verbose”。

SPMonitoredScope 还可以帮助记录性能和资源使用/分配情况。

using (new SPMonitoredScope("My Scope Name",1000,
 new SPRequestUsageCounter(3),
 new SPSqlQueryCounter(10)))
{
 //Do Stuff...
}

如果您达到了执行时间(1000 毫秒),或者 SPSite/SPWeb 分配的总数超过 3,或者 SQL 查询的总数超过 10,那么日志记录级别将提升到“High”。此外,您还将获得这些参数的实际值以及创建 SPSite/SPWeb 对象和执行 SQL 查询的实际位置(通过堆栈跟踪)。

也许,关于 SPMonitoredScope 最有趣的事实是,跟踪信息会被推送到 Developer Dashboard

如果您有以下代码:

using (new SPMonitoredScope("My Monitored Scope"))
{
    using (new SPMonitoredScope("My Sub-Monitored Scope"))
    {
        using (new SPMonitoredScope("My Sub-Sub-Monitored Scope"))
        {
        }

        using (new SPMonitoredScope("Another deep scope"))
        {
        }
    }
}

那么您将在 Developer Dashboard 中看到这张图:

 

建议 #3 - 使用 SPDiagnosticsService 写入日志

您可以通过 SPDiagnosticsService 类写入 ULS。

这是写入跟踪日志的示例:

SPDiagnosticsService diagSvc = SPDiagnosticsService.Local;
diagSvc.WriteTrace(0,
                   new SPDiagnosticsCategory("My Category",
                                             TraceSeverity.Monitorable,
                                             EventSeverity.Error),
                   TraceSeverity.Monitorable,
                   "An exception occurred: {0}",
                   new object[] {ex});

对于每个日志记录,ULS 都有“Area”(区域)和“Category”(类别)。默认情况下,“Area”的值为“Unknown”。

此外,您还可以直接写入事件日志:

SPDiagnosticsService diagSvc = SPDiagnosticsService.Local;
diagSvc.WriteEvent(0,
                   new SPDiagnosticsCategory("My Category",
                                             TraceSeverity.Monitorable,
                                             EventSeverity.Warning),
                   EventSeverity.Error,
                   "Exception occured {0}", new object[] {ex});

建议 #4 - 继承 SPDiagnosticsServiceBase 以获得对日志记录过程的更多控制

如果您正在开发一个大型组件或产品,那么创建您自己的“Diagnostics Service”是合理的——它本质上是一个继承自 SPDiagnosticsServiceBase 的新类。您可以定义自己的“Area”和“Category”,以及执行日志记录的更好方法。中央管理和 PowerShell 还可以为每个“Category”或“Area”设置不同的日志记录级别。

这是开始的示例:

public class LoggingService : SPDiagnosticsServiceBase
{
    public static string DiagnosticAreaName = "My";
    private static LoggingService _Current;
    public static LoggingService Current
    {
        get
        {
            if (_Current == null)
            {
               _Current = new LoggingService();
            }

            return _Current;
         }
    }

    private LoggingService(): base("My Logging Service", SPFarm.Local)
    {
    }

    protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()
    {
        List<SPDiagnosticsArea> areas = new List<SPDiagnosticsArea>
        {
            new SPDiagnosticsArea(DiagnosticAreaName, new List<SPDiagnosticsCategory>
            {
                new SPDiagnosticsCategory("WebParts", 
                            TraceSeverity.Unexpected, EventSeverity.Error)
            })
        };
        return areas;
    }

    public static void LogError(string categoryName, string errorMessage)
    {
        SPDiagnosticsCategory category =   
             LoggingService.Current
                           .Areas[DiagnosticAreaName]
                           .Categories[categoryName];
        LoggingService.Current.WriteTrace(0, category, 
              TraceSeverity.Unexpected, errorMessage);
     }
}

最后,实际调用可以是这样的:

LoggingService.LogError("WebParts", ex.ToString());

建议 #5 - 利用 diagnostics.asmx Web 服务进行客户端应用程序开发

原来 SharePoint 有一个 `/_vti_bin/diagnostics.asmx` Web 服务。它只有一个方法,该方法将日志写入 ULS,类别为“SharePoint Foundation -> Unified Logging Service”,级别为“Verbose”。

如果您正在开发 Silverlight 或 JavaScript 应用程序,那么该 Web 服务可能是唯一可以让开发人员或管理员访问的日志记录方式。其他选项则很难实现。

SharePoint 有很多 JavaScript 库,它还提供了 ULSOnError(msg, url, line)ULSSendException(ex) 等函数。您无法简单地直接调用这些函数,因此您只需要包含一个值为“true”的额外调用 ULS.enable。否则,您将什么也得不到。

ULS.enable = true;
ULSOnError("Hello trace", document.location.href, 0);

附注:不要忘记 ULS 是为开发人员和管理员创建的。您可以考虑为最终用户创建一些东西,SharePoint 列表可能是一个不错的选择。

再附注:嗯,实际上有六个建议,但第 6 个建议在帖子标题中会显得很蹩脚。

© . All rights reserved.