SimpleLog: added message handler, made a bunch of enhancements

This commit is contained in:
tmont 2009-04-11 20:53:14 +00:00
parent 9cec382640
commit ddeafdb9dd
9 changed files with 247 additions and 47 deletions

View File

@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SimpleLog {
public class DefaultMessageHandler : IMessageHandler, IMessageFormatter {
protected string dateFormat;
protected string lineTerminator;
protected string context;
protected string delimiter;
public DefaultMessageHandler() {
this.dateFormat = null;
this.lineTerminator = null;
this.context = "";
this.delimiter = "\t";
}
#region IMessageHandler Members
public string ConstructLogMessage(ILogHandler handler, string message, LogLevel level) {
List<string> messageData = new List<string>();
messageData.Add(string.Format("{0:" + this.DateFormat + "}", DateTime.Now));
messageData.Add(level.ToString().ToUpper());
if (!string.IsNullOrEmpty(this.Context)) {
messageData.Add(this.Context);
}
messageData.Add(message);
return string.Join(this.Delimiter, messageData.ToArray());
}
/// <summary>
/// Converts the message object to a string. If the message object
/// is an exception, the new message is a concatenation of the Message
/// and StackTrace. Otherwise, the object's ToString() method is used for
/// conversion.
/// </summary>
/// <param name="message">The message object to convert</param>
/// <returns>The message as a string</returns>
public string ConvertMessageToString(object message) {
string msg = null;
if (message is Exception) {
Exception e = (Exception)message;
msg = e.Message + "\n" + e.StackTrace;
}
else {
msg = message.ToString();
}
return msg;
}
/// <summary>
/// Gets or sets the context of this message handler
/// </summary>
public string Context {
get {
return this.context;
}
set {
this.context = value;
}
}
#endregion
public string Delimiter {
get {
return this.delimiter;
}
set {
this.delimiter = value;
}
}
#region IMessageFormatter members
public string DateFormat {
get {
return this.dateFormat;
}
set {
this.dateFormat = value;
}
}
public string LineTerminator {
get {
return this.lineTerminator;
}
set {
if (!Util.LineTerminatorIsValid(value)) {
throw new ArgumentException("Invalid line terminator; see SimpleLog.LineTerminator for valid line terminators");
}
this.lineTerminator = value;
}
}
#endregion
}
}

View File

@ -7,9 +7,9 @@ namespace SimpleLog {
public interface ILogHandler {
bool Log(object message, LogLevel level);
string Context { get; set; }
LogLevel? LogLevel { get; set; }
string DateFormat { get; set; }
IMessageHandler MessageHandler { get; set; }
void GracefulShutDown();
}
}

15
SimpleLog/ILogger.cs Normal file
View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SimpleLog {
public interface ILogger : IMessageFormatter {
bool Log(object message, LogLevel level);
void RegisterLogHandler(ILogHandler handler);
bool UnregisterLogHandler(ILogHandler handler);
int UnregisterLogHandlerType(string assemblyName);
}
}

View File

@ -0,0 +1,10 @@
using System;
namespace SimpleLog {
public interface IMessageFormatter {
string DateFormat { get; set; }
string LineTerminator { get; set; }
}
}

View File

@ -0,0 +1,11 @@
using System;
namespace SimpleLog {
public interface IMessageHandler : IMessageFormatter {
string ConstructLogMessage(ILogHandler handler, string message, LogLevel level);
string ConvertMessageToString(object message);
string Context { get; set; }
}
}

View File

@ -15,28 +15,48 @@ namespace SimpleLog {
}
public struct LineTerminator {
/// <summary>
/// Windows line terminator (CRLF)
/// </summary>
public static readonly string Windows = "\r\n";
/// <summary>
/// Macintosh line terminator (CR)
/// </summary>
public static readonly string Mac = "\r";
/// <summary>
/// Unix line terminator (LF)
/// </summary>
public static readonly string Unix = "\n";
}
public class Logger {
public class Logger : ILogger {
/// <summary>
/// The singleton instance of this logger. All interactions
/// with the logger should be done via this static property.
/// </summary>
public static readonly Logger Instance = new Logger();
/// <summary>
/// Gets or sets whether this logger is enabled or not
/// </summary>
public bool Enabled;
protected List<ILogHandler> LogHandlers;
protected IMessageHandler messageHandler;
protected LogLevel logLevel;
protected string dateFormat;
protected string lineTerminator;
public bool Enabled;
private Logger() {
this.LogHandlers = new List<ILogHandler>();
this.logLevel = LogLevel.Warning;
this.dateFormat = "YYYY-MM-dd HH:ii:ss";
this.lineTerminator = LineTerminator.Unix;
this.lineTerminator = SimpleLog.LineTerminator.Unix;
this.Enabled = true;
this.messageHandler = new DefaultMessageHandler();
this.dateFormat = "YYYY-MM-dd HH:ii:ss";
}
#region ILogger members
/// <summary>
/// Logs a message at the specified log level
/// </summary>
@ -47,12 +67,15 @@ namespace SimpleLog {
bool success = true;
if (this.Enabled) {
string convertedMessage = this.ConvertMessageToString(message);
string convertedMessage;
LogLevel allowedLevel;
IMessageHandler messageHandler;
foreach (ILogHandler handler in this.LogHandlers) {
LogLevel allowedLevel = handler.LogLevel ?? this.GlobalLogLevel;
allowedLevel = handler.LogLevel ?? this.LogLevel;
if (level <= allowedLevel) {
convertedMessage = this.ConstructLogMessage(handler, convertedMessage);
messageHandler = handler.MessageHandler ?? this.MessageHandler;
convertedMessage = messageHandler.ConvertMessageToString(message);
convertedMessage = messageHandler.ConstructLogMessage(handler, convertedMessage, level);
success = (success && handler.Log(convertedMessage, allowedLevel));
}
}
@ -60,34 +83,61 @@ namespace SimpleLog {
return success;
}
protected string ConvertMessageToString(object message) {
string msg = null;
if (message is Exception) {
Exception e = (Exception)message;
msg = e.Message + "\n" + e.StackTrace;
}
else {
msg = message.ToString();
}
return msg;
}
protected virtual string ConstructLogMessage(ILogHandler handler, string message) {
string dateFormat = handler.DateFormat ?? this.GlobalDateFormat;
string timestamp = string.Format("{0:" + dateFormat + "}", DateTime.Now);
return timestamp;
}
/// <summary>
/// Registers a log handler with this logger
/// </summary>
/// <param name="handler">The log handler to register</param>
public void RegisterLogHandler(ILogHandler handler) {
this.LogHandlers.Add(handler);
}
/// <summary>
/// Unregisters the given log handler
/// </summary>
/// <returns>TRUE if successfully unregistered, FALSE if not</returns>
public bool UnregisterLogHandler(ILogHandler handler) {
if (this.LogHandlers.Contains(handler)) {
this.LogHandlers.Remove(handler);
handler.GracefulShutDown();
return true;
}
return false;
}
/// <summary>
/// Removes all log handlers that match the given assembly name
/// </summary>
/// <returns>Number of log handlers that were unregistered</returns>
public int UnregisterLogHandlerType(string assemblyName) {
int count = 0;
foreach (ILogHandler handler in this.LogHandlers) {
if (handler.GetType().AssemblyQualifiedName == assemblyName) {
count += this.UnregisterLogHandler(handler) ? 1 : 0;
}
}
return count;
}
#endregion
#region Accessors
/// <summary>
/// Gets or sets the global message handler
/// </summary>
public IMessageHandler MessageHandler {
get {
return this.messageHandler;
}
set {
this.messageHandler = value;
}
}
/// <summary>
/// Gets or sets the global log level
/// </summary>
public LogLevel GlobalLogLevel {
public LogLevel LogLevel {
get {
return this.logLevel;
}
@ -95,10 +145,13 @@ namespace SimpleLog {
this.logLevel = value;
}
}
#endregion
#region IMessageFormatter members
/// <summary>
/// Gets or sets the global date format
/// </summary>
public string GlobalDateFormat {
public string DateFormat {
get {
return this.dateFormat;
}
@ -109,17 +162,16 @@ namespace SimpleLog {
/// <summary>
/// Gets or sets the global line terminator
/// </summary>
public string GlobalLineTerminator {
public string LineTerminator {
get {
return this.lineTerminator;
}
set {
if (value == LineTerminator.Unix || value == LineTerminator.Windows || value == LineTerminator.Mac) {
this.lineTerminator = value;
}
else {
if (!Util.LineTerminatorIsValid(value)) {
throw new ArgumentException("Invalid line terminator; see SimpleLog.LineTerminator struct for valid line terminators");
}
this.lineTerminator = value;
}
}
#endregion

View File

@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SimpleLog {
public class MessageHandler {
}
}

View File

@ -45,10 +45,14 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ILogger.cs" />
<Compile Include="IMessageFormatter.cs" />
<Compile Include="ILogHandler.cs" />
<Compile Include="IMessageHandler.cs" />
<Compile Include="Logger.cs" />
<Compile Include="MessageHandler.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Util.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

20
SimpleLog/Util.cs Normal file
View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SimpleLog {
public static class Util {
/// <summary>
/// Determines whether the given line terminator is a valid line terminator
/// </summary>
public static bool LineTerminatorIsValid(string lineTerminator) {
return
lineTerminator == LineTerminator.Unix ||
lineTerminator == LineTerminator.Windows ||
lineTerminator == LineTerminator.Mac;
}
}
}