using System; using System.Collections.Generic; using System.Text; using Microsoft.SharePoint.Administration; using System.Diagnostics; using System.Reflection; namespace MyProject.Logging { public enum MyLoggerCategory { TimerJob = 1, FeatureReceiver = 10, EventHandler = 20, Webpart = 30, General = 40 } //To use elsewhere: //Change DiagnosticsAreaName and DiagnosticsServiceName //Refactor to change name of class //Refactor to change category enum //Change values in enum //Make sure that static method Register() is run to register in central admin //And unregister when done //Probably in SPFarm level FeatureReceiver FeatureActivation event public class MyLogger : SPDiagnosticsServiceBase { private static string DiagnosticsAreaName = "MyLogger"; private static string DiagnosticsServiceName = "My Logging Service"; internal static MyLogger Local { get { return MyLogger.GetLocal(); } } public MyLogger() : base(DiagnosticsServiceName, SPFarm.Local) { } public MyLogger(string name, SPFarm parent) : base(name, parent) { } /// /// Provide the logging areas and categories for this logging service. /// protected override IEnumerable ProvideAreas() { List areas = new List(); List categories = new List(); foreach (string catName in Enum.GetNames(typeof(MyLoggerCategory))) { uint catId = (uint)(int)Enum.Parse(typeof(MyLoggerCategory), catName); categories.Add(new SPDiagnosticsCategory(catName, TraceSeverity.Medium, EventSeverity.Error, 0, catId)); } areas.Add(new SPDiagnosticsArea(DiagnosticsAreaName, 0, 0, false, categories)); return areas; } /// /// Writes an Error to the Windows Event Log, and to the SharePoint ULS logs /// public static void Error(MyLoggerCategory category, string message) { WriteLog(category, TraceSeverity.None, EventSeverity.Error, message); } /// /// Writes an Error to the Windows Event Log, and to the SharePoint ULS logs /// public static void Error(MyLoggerCategory category, Exception ex) { StringBuilder sb = new StringBuilder(ex.Message); Exception innerEx = ex.InnerException; while (innerEx != null) { sb.Append("; "); sb.Append(innerEx.Message); innerEx = innerEx.InnerException; } WriteLog(category, TraceSeverity.None, EventSeverity.Error, string.Format("({0}) - {1}", ex.GetType().ToString(), sb.ToString()) ); } /// /// Writes a Warning to the Windows Event Log, and to the SharePoint ULS logs /// public static void Warning(MyLoggerCategory category, string message) { WriteLog(category, TraceSeverity.None, EventSeverity.Warning, message); } /// /// Writes an Information level entry to the Windows Event Log, and to the SharePoint ULS logs /// public static void Information(MyLoggerCategory category, string message) { WriteLog(category, TraceSeverity.None, EventSeverity.Information, message); } /// /// Writes a High level message to the SharePoint ULS only /// public static void High(MyLoggerCategory category, string message) { WriteLog(category, TraceSeverity.High, EventSeverity.None, message); } /// /// Writes a Medium level message to the SharePoint ULS only /// public static void Medium(MyLoggerCategory category, string message) { WriteLog(category, TraceSeverity.Medium, EventSeverity.None, message); } /// /// Writes a Low level message to the SharePoint ULS only (i.e. Most Verbose, or most detailed) /// public static void Low(MyLoggerCategory category, string message) { WriteLog(category, TraceSeverity.Verbose, EventSeverity.None, message); } /// /// Actually controls the writing. Calls to WriteEvent ALSO writes to the ULS log. That's why the public logging methods /// all use TraceSeverity.None. /// private static void WriteLog(MyLoggerCategory category, TraceSeverity trcSeverity, EventSeverity evtSeverity, string message) { uint catId = (uint) category; SPDiagnosticsCategory diagCat = MyLogger.Local.Areas[DiagnosticsAreaName].Categories[catId]; StackTrace stackTrace = new StackTrace(); StackFrame stackFrame = stackTrace.GetFrame(2); MethodBase methodBase = stackFrame.GetMethod(); message = string.Format("{0}.{1} : {2}", methodBase.DeclaringType.Name, methodBase.Name, message); if (evtSeverity != EventSeverity.None) { //Problem - event source might not be registered on Server, and the app pool might not be able to create it. //Therefore, catch the exception, and write it into the logs. Nothing gets written to the Windows log, //but at least it's somewhat handled. try { MyLogger.Local.WriteEvent(0, diagCat, evtSeverity, message); } catch (Exception ex) { MyLogger.Local.WriteTrace(0, diagCat, TraceSeverity.Unexpected, string.Format("Unable to write to event log {0} : {1}", ex.GetType().ToString(), ex.Message)); // If there was an error writing to the event log, make sure the tracelog is written to instead. switch (evtSeverity) { case EventSeverity.Error: trcSeverity = TraceSeverity.Unexpected; break; case EventSeverity.Warning: trcSeverity = TraceSeverity.Monitorable; break; case EventSeverity.Information: trcSeverity = TraceSeverity.High; break; } } } if (trcSeverity != TraceSeverity.None) { MyLogger.Local.WriteTrace(0, diagCat, trcSeverity, message); } } /// /// Registers the class for logging. Run in a Feature Receiver at the farm level /// public static void Register() { MyLogger diagnosticService = new MyLogger(String.Empty, SPFarm.Local); diagnosticService.Update(true); } /// /// Unregisters the class. Run in a Feature Receiver at the farm level /// public static void Unregister() { MyLogger log = MyLogger.Local; if (log != null) { log.Delete(); log.Unprovision(); log.Uncache(); } } } }