SharePoint Logging and Microsoft’s Trace Log Provider

By | December 18, 2008

Microsoft has a posted example of how to log to the Trace Log here.

So how does one use this in their application?  The below code is how I plugged it into our SharePoint development framework.  I’d love to hear how you are using it.

Step 1:

I modified the Microsoft’s TraceProvider’s RegisterTraceProvider and UnregisterTraceProvider methods as follows:

        private static readonly object RegisterLock = new object();
        private static bool isRegistered = false;
        public static unsafe void RegisterTraceProvider()
        {
            lock (RegisterLock)
            {
                if (!isRegistered)
                {
                    SPFarm farm = SPFarm.Local;
                    Guid traceGuid = farm.TraceSessionGuid;
                    uint result = NativeMethods.RegisterTraceGuids(ControlCallback, null,
                        ref traceGuid, 0, IntPtr.Zero, null, null, out hTraceReg);
                    System.Diagnostics.Debug.Assert(result == NativeMethods.ERROR_SUCCESS);
                    isRegistered = true;
                }
            }
        }
 
        public static void UnregisterTraceProvider()
        {
            lock (RegisterLock)
            {
                if (isRegistered)
                {
                    uint result = NativeMethods.UnregisterTraceGuids(hTraceReg);
                    System.Diagnostics.Debug.Assert(result == NativeMethods.ERROR_SUCCESS);
                    isRegistered = false;
                }
            }
        }

Step 2:

I created our own TraceLogProvider object extending our BaseLogProvider which implements our custom ILogProvider interface.  This provider object makes the appropriate calls into Microsoft’s TraceProvider, but now exposes a friendly logging interface to use within our application.

    public class TraceLogProvider : BaseLogProvider, IDisposable
    {
        public string ApplicationName { get; set; }
 
        public void Log(string msg, LogSeverity severity)
        {
            var traceSeverity = GetTraceSeverity(severity);
 
            TraceProvider.RegisterTraceProvider();
 
            string[] lines = msg.Split(new string[] { Environment.NewLine },
                StringSplitOptions.RemoveEmptyEntries);
            foreach (string line in lines)
            {
                TraceProvider.WriteTrace(0, traceSeverity, Guid.Empty, "Your Company Name",
                    ApplicationName, "General", line);
            }
        }
 
        private TraceProvider.TraceSeverity GetTraceSeverity(LogSeverity severity)
        {
            switch (severity)
            {
                case LogSeverity.Info:
                    return TraceProvider.TraceSeverity.InformationEvent;
                case LogSeverity.Warn:
                    return TraceProvider.TraceSeverity.WarningEvent;
                default:
                    return TraceProvider.TraceSeverity.CriticalEvent;
            }
        }
 
        #region IDisposable Members
 
        public virtual void Dispose()
        {
            TraceProvider.UnregisterTraceProvider();
        }
 
        #endregion
    }

And for reference, our BaseLogProvider is shown below:

    public abstract class BaseLogProvider : ILogProvider
    {
        #region ILogProvider Members
 
        public virtual void Info(string msg)
        {
            Log(msg, LogSeverity.Info);
        }
 
        public virtual void Info(Exception e)
        {
            Log(e, LogSeverity.Info);
        }
 
        public virtual void Info(string msg, Exception e)
        {
            Log(msg, e, LogSeverity.Info);
        }
 
        public virtual void Warn(string msg)
        {
            Log(msg, LogSeverity.Warn);
        }
 
        public virtual void Warn(Exception e)
        {
            Log(e, LogSeverity.Warn);
        }
 
        public virtual void Warn(string msg, Exception e)
        {
            Log(msg, e, LogSeverity.Warn);
        }
 
        public virtual void Error(string msg)
        {
            Log(msg, LogSeverity.Error);
        }
 
        public virtual void Error(Exception e)
        {
            Log(e, LogSeverity.Error);
        }
 
        public virtual void Error(string msg, Exception e)
        {
            Log(msg, e, LogSeverity.Error);
        }
 
        public virtual void Log(Exception e, LogSeverity severity)
        {
            Log(FormatException(e), severity);
        }
 
        public virtual void Log(string msg, Exception e, LogSeverity severity)
        {
            Log(msg + "\n" + FormatException(e), severity);
        }
 
        public abstract void Log(string msg, LogSeverity severity);
 
        #endregion
 
        protected virtual string FormatException(Exception ex)
        {
            StringBuilder stringBuilder = new StringBuilder();
 
            stringBuilder.AppendLine(ex.ToString());
            if (ex.InnerException != null)
            {
                stringBuilder.AppendLine(ex.InnerException.ToString());
                if (ex.InnerException.InnerException != null)
                {
                    stringBuilder.AppendLine(ex.InnerException.InnerException.ToString());
                }
            }
 
            return stringBuilder.ToString();
        }
    }
 
    public enum LogSeverity
    {
        Info,
        Warn,
        Error
    }

One thought on “SharePoint Logging and Microsoft’s Trace Log Provider

  1. bhakthil

    Hi,
    I tried to use the code for logging in my SP application. but, when I set the Verbosity level in Central Admin, the loging messages still appear. for example I set the event throttling to None, but still Info, Warn and Error messages are logged. is that a bug or am I missing something?

    Thank You,
    bhakthil

Leave a Reply

Your email address will not be published. Required fields are marked *