SharePoint Logging and Microsoft’s Trace Log Provider
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 }
November 4th, 2009 at 11:48 am
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