Monday, February 20, 2012

Log Manager With Extra Information Using SharePoint 2010 Unified Logging Service

Here is a wrapper class which covers the SharePoint ULS interface and logs information to the ULS. I attempted to add as much information as I could and allow for a property dictionary to be appended to the log entry.

namespace Demo.Web.Logging
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.SharePoint.Administration;
    using System.Diagnostics.Eventing;
    using System.Runtime.InteropServices;
    using System.Security.AccessControl;
    using System.Security.Principal;
    using System.Threading;
    using System.Diagnostics;

    public class LogManager
    {
        public static void Write(Exception ex, SPDiagnosticsCategory category, TraceSeverity severity)
        {
            if (ex.Data != null && !ex.Data.Contains("CallingFunction"))
            {
                ex.Data.Add("CallingFunction", System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.Name);
            }
            Dictionary<string, object> props = null;
            if (ex.Data != null && ex.Data.Count > 0)
            {
                props = new Dictionary<string, object>();
                foreach (string key in ex.Data)
                {
                    props.Add(key, ex.Data[key]);
                }
            }
            LoggingService.Log(ex.ToString(), props);
        }

        public static void Write(string message, Dictionary<string, object> props)
        {

            LoggingService.Log(message, props);
        }

        public static void Write(string message, Dictionary<string, object> props, TraceSeverity severity)
        {
            LoggingService.Log(message, props, severity);
        }

        public static void Write(string message, Dictionary<string, object> props, TraceSeverity severity, string categoryName)
        {
            LoggingService.Log(message, props, severity, categoryName);
        }

        public static void Write(string message, Dictionary<string, object> props, TraceSeverity severity, SPDiagnosticsCategory category)
        {
            //SPDiagnosticsService.Local.WriteTrace(0, new SPDiagnosticsCategory("My Category", TraceSeverity.Unexpected, EventSeverity.Error), TraceSeverity.Unexpected, ex.Message, ex.StackTrace);
            LoggingService.Log(message, props, severity, category);
        }
    }

    #region [ Internal ULS Access Implementation ]
    
    internal class LoggingService : SPDiagnosticsServiceBase
    {
        public static string DemoDiagnosticAreaName = "Demo";
        private static LoggingService _Current;
        public static LoggingService Current
        {
            get
            {
                if (_Current == null)
                {
                    _Current = new LoggingService();
                }

                return _Current;
            }
        }

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

        }

        protected override IEnumerable<spdiagnosticsarea> ProvideAreas()
        {
            List<spdiagnosticsarea> areas = new List<spdiagnosticsarea>
            {
                new SPDiagnosticsArea(DemoDiagnosticAreaName, new List<spdiagnosticscategory>
                {
                    new SPDiagnosticsCategory("Application", TraceSeverity.Unexpected, EventSeverity.Error),
                    new SPDiagnosticsCategory("WebService", TraceSeverity.Unexpected, EventSeverity.Error),
                    new SPDiagnosticsCategory("WebConfigMod", TraceSeverity.Unexpected, EventSeverity.Error)
                })
            };

            return areas;
        }

        public static void Log(string message)
        {
            Log(message, null);
        }

        public static void Log(string message, Dictionary<string, object> props)
        {
            Log(message, props, TraceSeverity.Unexpected);
        }
        public static void Log(string message, Dictionary<string, object> props, TraceSeverity severity)
        {
            Log(message, props, TraceSeverity.Unexpected, "Application");
        }
        public static void Log(string message, Dictionary<string, object> props, TraceSeverity severity, string categoryName)
        {
            SPDiagnosticsCategory category = LoggingService.Current.Areas[DemoDiagnosticAreaName].Categories[categoryName];
            Log(message, props, severity, category);
        }
        public static void Log(string message, Dictionary<string, object> props, TraceSeverity severity, SPDiagnosticsCategory category)
        {
            if (props == null)
            {
                props = new Dictionary<string, object>();
            }
            if (!props.ContainsKey("CallingFunction"))
            {
                props.Add("CallingFunction", (new StackTrace()).GetFrame(1).GetMethod().Name);
            }
            string propSerial = "{" + string.Join(",", props.Select(
                d => string.Format("\"{0}\":\"{1}\"", d.Key, d.Value.ToString())
                ).ToArray()) + "}";

            //SPDiagnosticsCategory category = LoggingService.Current.Areas[DemoDiagnosticAreaName].Categories[categoryName];
            LoggingService.Current.WriteTrace(0, category, TraceSeverity.Unexpected, message + " ~ Properties: " + propSerial);
        }
    }

    #endregion
    }
}

Wednesday, February 15, 2012

Log Manager With Extra Information Using Enterprise Library

Here is a pattern for logging which encourages extra information to be stored with the error.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Diagnostics;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.ExtraInformation;
using Microsoft.Practices.EnterpriseLibrary.Logging.Filters;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using System.Reflection;
using System.Collections;

namespace DemoServices.Logging
{
    public class LogManager
    {
        public static void Write(Exception ex, string title = "", string category = "", TraceEventType severity = TraceEventType.Error)
        {
            if (ex != null)
            {
                if (String.IsNullOrEmpty(title))
                {
                    title = System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.Name;
                }
                if (String.IsNullOrEmpty(category))
                {
                    category = System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.Name;
                }
                Dictionary<string, object> props = null;
                if (ex.Data != null && ex.Data.Count < 0)
                {
                    props = new Dictionary<string, object>();
                    foreach(string key in ex.Data) {
                        props.Add(key, ex.Data[key]);
                    }
                }
                Write(ex.ToString(), title, category, severity, props);
            }
        }

        public static void Write(string message, string title = "", string category = "", TraceEventType severity = TraceEventType.Error, IDictionary<string, object> props = null)
        {
            if (String.IsNullOrEmpty(title))
            {
                title = System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.Name;
            }
            if (String.IsNullOrEmpty(category))
            {
                category = System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.Name;
            }
            if (props == null)
            {
                props = new Dictionary<string, object>();
            }
            ManagedSecurityContextInformationProvider informationHelper = new ManagedSecurityContextInformationProvider();
            informationHelper.PopulateDictionary(props);
            DebugInformationProvider debugHelper = new DebugInformationProvider();
            debugHelper.PopulateDictionary(props);

            LogWriter logger = EnterpriseLibraryContainer.Current.GetInstance<logwriter>();
            logger.Write(message, new string[] { "Demo", category }, 20, 0, severity, title, props as Dictionary<string, object>);
        }

        //public static void Write(Exception ex, string title, string category, TraceEventType severity = TraceEventType.Error, Dictionary<string, object> props = null)
        //{
        //    if (ex != null)
        //    {
        //        Write(ex.ToString(), title, category, severity, props);
        //    }
        //}

        //public static void Write(string message, string title, string category, TraceEventType severity = TraceEventType.Error)
        //{
        //    Dictionary<string, object> props = new Dictionary<string, object>();
        //    //props.Add("CallingFunction", (new StackTrace()).GetFrame(1).GetMethod().Name);

        //    if (props == null)
        //    {
        //        props = new Dictionary<string, object>();
        //    }
        //    ManagedSecurityContextInformationProvider informationHelper = new ManagedSecurityContextInformationProvider();
        //    informationHelper.PopulateDictionary(props);
        //    DebugInformationProvider debugHelper = new DebugInformationProvider();
        //    debugHelper.PopulateDictionary(props);

        //    LogWriter logger = EnterpriseLibraryContainer.Current.GetInstance<logwriter>();
        //    logger.Write(message, new string[] { "Demo", category }, 20, 0, severity, title, props);
        //}

    }
}