Created
January 4, 2014 19:23
-
-
Save gregjsmith/8259547 to your computer and use it in GitHub Desktop.
A class to log arbitrary information / objects graphs / Exceptions to the event logs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public sealed class EventLogger | |
{ | |
private static readonly EventLogger Singleton = new EventLogger(); | |
private static readonly EventLogTraceListener EventListener; | |
private static readonly string LogLevel; | |
public static EventLogger Instance | |
{ | |
get { return Singleton; } | |
} | |
EventLogger() {} | |
static EventLogger() | |
{ | |
LogLevel = ConfigurationManager.AppSettings["Logging.Level"]; | |
if (string.IsNullOrWhiteSpace(LogLevel)) | |
{ | |
LogLevel = "Normal"; | |
} | |
var source = ConfigurationManager.AppSettings["Logging.Event.Source"]; | |
if (string.IsNullOrWhiteSpace(source)) | |
{ | |
throw new InvalidOperationException(@" | |
Attempting to write to the EventLogger but could not. | |
It was not possible to create an EventLog Listener because no Event Source has been specified. | |
An event Source should be specified by an Application Setting with the key ""Logging.Event.Source"" within the configuration file, ie: | |
<appSettings> | |
<add key=""Logging.Event.Source"" value=""MyApplication""/> | |
</appSettings> | |
"); | |
} | |
if (EventListener == null) | |
{ | |
EventListener = new EventLogTraceListener(source); | |
} | |
if (!Trace.AutoFlush) | |
{ | |
Trace.AutoFlush = true; | |
} | |
if (!Trace.Listeners.Contains(EventListener)) | |
{ | |
Trace.Listeners.Add(EventListener); | |
} | |
} | |
public void Log<T>(T item) | |
{ | |
var msg = ObjectToString(item); | |
Trace.TraceInformation(msg); | |
} | |
public void Verbose<T>(T item) | |
{ | |
if (LogLevel != "Verbose") | |
{ | |
return; | |
} | |
var message = ObjectToString(item); | |
Trace.TraceInformation(message); | |
} | |
public void Error(Exception exception) | |
{ | |
var errorMessage = ErrorToString(exception); | |
Trace.TraceError(errorMessage); | |
} | |
private string ObjectToString(object item, int indent = 0, int recursion = 0) | |
{ | |
if (recursion > MaxRecursiveCalls) | |
{ | |
return "Too many recursive calls made to this section - stopping output here to prevent Overflow."; | |
} | |
if (item == null) | |
{ | |
return ""; | |
} | |
if (item is string) | |
{ | |
return item as string; | |
} | |
if (item is Type) | |
{ | |
return item.ToString(); | |
} | |
var sb = new StringBuilder(); | |
if (item is ICollection) | |
{ | |
var name = item.GetType().Name; | |
sb.AppendLine(Indent(indent) + name + ": "); | |
int count = 1; | |
foreach (var thing in item as ICollection) | |
{ | |
if (thing.GetType().IsClass && thing.GetType() != typeof(string)) | |
{ | |
sb.AppendLine(Indent(indent + 2) + thing.GetType().Name + " " + count++ + ": "); | |
var message = ObjectToString(thing, indent + 4, recursion +1); | |
sb.AppendLine(message); | |
} | |
else | |
{ | |
sb.AppendLine(Indent(indent) + name + ": " + thing); | |
} | |
} | |
return sb.ToString(); | |
} | |
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(item)) | |
{ | |
string name = descriptor.Name; | |
object value = descriptor.GetValue(item); | |
if (value != null) | |
{ | |
if (value is ICollection) | |
{ | |
sb.AppendLine(Indent(indent) + name + ": "); | |
int count = 1; | |
foreach (var thing in value as ICollection) | |
{ | |
if (thing.GetType().IsClass && thing.GetType() != typeof(string)) | |
{ | |
sb.AppendLine(Indent(indent + 2) + thing.GetType().Name + " " + count++ + ": "); | |
var message = ObjectToString(thing, indent + 4, recursion + 1); | |
sb.AppendLine(message); | |
} | |
else | |
{ | |
sb.AppendLine(Indent(indent) + name + ": " + thing); | |
} | |
} | |
} | |
else if (value.GetType().IsClass && value.GetType() != typeof(string)) | |
{ | |
sb.AppendLine(Indent(indent) + name + ": "); | |
var message = ObjectToString(value, indent + 4, recursion + 1); | |
sb.AppendLine(message); | |
} | |
else | |
{ | |
sb.AppendLine(Indent(indent) + name + ": " + value); | |
} | |
} | |
} | |
return sb.ToString(); | |
} | |
private string ErrorToString(Exception exception, int indent = 0, int recursion = 0) | |
{ | |
if (recursion > MaxRecursiveCalls) | |
{ | |
return "Too many recursive calls made to this section - stopping output here to prevent Overflow."; | |
} | |
var sb = new StringBuilder(); | |
sb.AppendLine(Indent(indent) + "Message: " + exception.Message); | |
sb.AppendLine(Indent(indent) + "Source: " + exception.Source); | |
sb.AppendLine(Indent(indent) + "Class: " + exception.TargetSite.DeclaringType); | |
sb.AppendLine(Indent(indent) + "Method: " + exception.TargetSite); | |
sb.AppendLine(Indent(indent) + "Stack: "); | |
foreach (var s in Formatted(exception.StackTrace)) | |
{ | |
sb.AppendLine(Indent(indent) + s); | |
} | |
if (exception.InnerException != null) | |
{ | |
var inner = ErrorToString(exception.InnerException, indent + 4, recursion+1); | |
sb.AppendLine(); | |
sb.AppendLine(Indent(indent) + "Inner Exception:"); | |
sb.AppendLine(inner); | |
} | |
return sb.ToString(); | |
} | |
private const int MaxRecursiveCalls = 10; | |
private static string Indent(int count) | |
{ | |
return "".PadLeft(count); | |
} | |
private static string[] Formatted(string stackTrace) | |
{ | |
var lines = stackTrace.Split(new[] {" "}, Int16.MaxValue, StringSplitOptions.RemoveEmptyEntries); | |
return lines; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment