Logging to ULS in SharePoint 2010


One of the pieces of developing custom components is logging information. No matter if it’s for diagnostic purposes or when an error occurs, logging allows you to track the health of your custom component. When developing custom components for SharePoint 2007 we hadn’t much choice. Although SharePoint 2007 shipped with the Unified Logging Service, we couldn’t use it. The SharePoint SDK was pretty clear about it: although some methods were publicly available, ULS was for internal use only and was not supposed to be used in custom code. Because of this, we couldn’t provide a similar logging experience to SharePoint and had to develop custom logging solutions. SharePoint 2010 changes this situation: using the new ULS is now supported and may be used for logging in custom code.

Logging using SharePoint 2010 101

Using the SharePoint 2010 ULS is pretty easy. Using just a few lines of code you can log information from your custom components:

try
{
    var i = 0;
    var a = 2 / i;
}
catch (Exception ex)
{
    SPDiagnosticsService.Local.WriteTrace(0, new SPDiagnosticsCategory("My Category", TraceSeverity.Unexpected, EventSeverity.Error), TraceSeverity.Unexpected, ex.Message, ex.StackTrace);
}

Calling the snippet above will log the following message in the ULS log: Custom message logged in the SharePoint ULS log. It works…. almost. Did you notice the Unknown label where the product name should be mentioned? While it’s not necessary for simple solutions, it would definitely make it easier to track which messages originate from which solutions if we actually could provide the product name.

Logging v2

The SharePoint API doesn’t provide any method which would allow you to provide the name of the product that logged the message. In order to write the product name to the ULS you have to create a custom Logging Service. You can do this by inheriting from the SPDiagnosticsServiceBase class:

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

            return _Current;
        }
    }

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

    }

    protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()
    {
        List<SPDiagnosticsArea> areas = new List<SPDiagnosticsArea>
        {
            new SPDiagnosticsArea(MaventionDiagnosticAreaName, 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[MaventionDiagnosticAreaName].Categories[categoryName];
        LoggingService.Current.WriteTrace(0, category, TraceSeverity.Unexpected, errorMessage);
    }
}

Instead of using the SPDiagnosticService.Local you would use now our custom LoggingService:

try
{
    var i = 0;
    var a = 2 / i;
}
catch (Exception ex)
{
    LoggingService.LogError("WebParts", ex.Message);
}

Let’s take a look at the result: Custom message logged in the SharePoint ULS log. The message is logged together with the product name. As you can see using a custom Logging Service, you can log the name of your solution what makes it easier to track your custom messages. When implementing custom Logging Service you have to provide a list of categories and logging levels supported by the service. You can do this by overriding the ProvideAreas method. In my example I implemented only one category but depending on your solution you could add multiple categories and severity levels.

Technorati Tags: SharePoint 2010

Others found also helpful: