SimpleLog 1.3.0 branch reintegration

This commit is contained in:
tmont 2009-04-19 22:10:13 +00:00
parent 4854704b2c
commit e0853422a4
25 changed files with 914 additions and 336 deletions

View File

@ -0,0 +1,68 @@
using System.Collections.Generic;
using NUnit.Framework;
using NUnit.Mocks;
using NUnit.Framework.SyntaxHelpers;
using SimpleLog.Framework;
namespace SimpleLog.Tests {
[TestFixture]
public class ConfigTest {
[SetUp]
public void SetUp() {
}
[Test]
public void TestLoadConfig() {
string configFile = "Test.config";
Config config = new Config(configFile);
//verify that logger configs were set up correctly
Assert.That(config.HasLoggerConfig("SimpleLog.DefaultLogger"));
LoggerConfig loggerConfig = config.GetLoggerConfig("SimpleLog.DefaultLogger");
Assert.That(loggerConfig, Is.Not.Null);
IDictionary<string, LogHandlerConfig> handlerData = loggerConfig.HandlerData;
Assert.That(handlerData, Is.Not.Null);
Assert.That(handlerData.ContainsKey("SimpleLog.ConsoleWindowLogHandler"));
Assert.That(handlerData.ContainsKey("SimpleLog.FileLogHandler"));
LogHandlerConfig handlerConfig = handlerData["SimpleLog.ConsoleWindowLogHandler"];
Assert.That(handlerConfig, Is.Not.Null);
Assert.That(handlerConfig.Settings, Is.TypeOf(typeof(Dictionary<string, string>)));
Assert.That(handlerConfig.Settings.Count, Is.EqualTo(3));
Assert.That(handlerConfig.HasSetting("DebugForeColor"));
Assert.That(handlerConfig.GetSetting("DebugForeColor"), Is.EqualTo("Cyan"));
Assert.That(handlerConfig.HasSetting("FatalForeColor"));
Assert.That(handlerConfig.GetSetting("FatalForeColor"), Is.EqualTo("White"));
Assert.That(handlerConfig.HasSetting("FatalBackColor"));
Assert.That(handlerConfig.GetSetting("FatalBackColor"), Is.EqualTo("Red"));
handlerConfig = handlerData["SimpleLog.FileLogHandler"];
Assert.That(handlerConfig, Is.Not.Null);
Assert.That(handlerConfig.Settings, Is.TypeOf(typeof(Dictionary<string, string>)));
Assert.That(handlerConfig.Settings.Count, Is.EqualTo(3));
Assert.That(handlerConfig.HasSetting("LogDirectory"));
Assert.That(handlerConfig.GetSetting("LogDirectory"), Is.EqualTo("c:\\WINDOWS\\Temp"));
Assert.That(handlerConfig.HasSetting("FilePrefix"));
Assert.That(handlerConfig.GetSetting("FilePrefix"), Is.EqualTo("simplelog_"));
Assert.That(handlerConfig.HasSetting("FileSuffix"));
Assert.That(handlerConfig.GetSetting("FileSuffix"), Is.EqualTo(".log"));
}
[Test]
[ExpectedException("System.Collections.Generic.KeyNotFoundException")]
public void TestLogHandlerConfigGetSetting() {
LogHandlerConfig config = new LogHandlerConfig();
config.GetSetting("foo");
}
[Test]
[ExpectedException("System.Collections.Generic.KeyNotFoundException")]
public void TestConfigGetLoggerConfig() {
Config config = new Config();
config.GetLoggerConfig("foo");
}
}
}

View File

@ -0,0 +1,34 @@
using System;
using SimpleLog;
namespace SimpleLog.Tests {
/// <summary>
/// To run this test, modify the project properties' "Application"
/// section and set the output type to "Console Application", and
/// set the startup object to this class. Then compile, and
/// start a debugging instance of this class.
/// </summary>
internal static class ConsoleColorTest {
static void Main(string[] args) {
DefaultLogger logger = LoggerManager.GetLogger(typeof(DefaultLogger)) as DefaultLogger;
logger.LogLevel = SimpleLog.Framework.LogLevel.All;
logger.Debug("Debug message");
logger.Info("Info message");
logger.Warning("Warning message");
logger.Error("Error message");
logger.Fatal("Fatal message");
try {
throw new Exception("Oh noes!! an exception");
}
catch (Exception e) {
logger.Fatal(e);
}
Console.ReadLine();
}
}
}

View File

@ -1,7 +1,6 @@
using System; using System;
using NUnit.Framework; using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers; using NUnit.Framework.SyntaxHelpers;
using SimpleLog.LogHandlers;
namespace SimpleLog.Tests { namespace SimpleLog.Tests {
[TestFixture] [TestFixture]
@ -16,7 +15,7 @@ namespace SimpleLog.Tests {
[Test] [Test]
public void TestLog() { public void TestLog() {
Assert.That(this.handler.Log("yay", Framework.LogLevel.Critical)); Assert.That(this.handler.Log("yay", Framework.LogLevel.Fatal));
Assert.That(this.handler.Log("yay", Framework.LogLevel.Debug)); Assert.That(this.handler.Log("yay", Framework.LogLevel.Debug));
} }
@ -29,7 +28,7 @@ namespace SimpleLog.Tests {
[Test] [Test]
public void TestAccessors() { public void TestAccessors() {
Assert.That(handler.MessageHandler, Is.TypeOf(typeof(DefaultMessageHandler))); Assert.That(handler.MessageHandler, Is.TypeOf(typeof(DefaultMessageHandler)));
Assert.That(handler.LogLevel, Is.EqualTo(null)); Assert.That(handler.LogLevel, Is.EqualTo(SimpleLog.Framework.LogLevel.None));
} }
} }

View File

@ -10,20 +10,24 @@ namespace SimpleLog.Tests {
private DefaultLogger Logger; private DefaultLogger Logger;
private DynamicMock Handler; private DynamicMock Handler;
private string TempFile;
[SetUp] [SetUp]
public void Init() { public void SetUp() {
this.Logger = new DefaultLogger(); this.Logger = new DefaultLogger();
this.Logger.MessageHandler = new DefaultMessageHandler(); this.Logger.MessageHandler = new DefaultMessageHandler();
this.Handler = new DynamicMock(typeof(ILogHandler)); this.Handler = new DynamicMock(typeof(ILogHandler));
this.TempFile = null;
} }
[TearDown] [TearDown]
public void DeInit() { public void TearDown() {
this.Logger.UnregisterAllLogHandlers(); this.Logger.UnregisterAllLogHandlers();
this.Logger.Enabled = true; this.Logger.Enabled = true;
this.Logger.MessageHandler = new DefaultMessageHandler(); this.Logger.MessageHandler = new DefaultMessageHandler();
if (this.TempFile != null && System.IO.File.Exists(this.TempFile)) {
System.IO.File.Delete(this.TempFile);
}
} }
[Test] [Test]
@ -35,8 +39,6 @@ namespace SimpleLog.Tests {
this.Logger.RegisterLogHandler(handler); this.Logger.RegisterLogHandler(handler);
Assert.That(this.Logger.LogHandlerCount, Is.EqualTo(1)); Assert.That(this.Logger.LogHandlerCount, Is.EqualTo(1));
//this.Logger.UnregisterLogHandlerType("SimpleLog.Framework.ILogHandler");
Assert.That(this.Logger.UnregisterLogHandlerType("SimpleLog.Framework.ILogHandler"), Is.EqualTo(1)); Assert.That(this.Logger.UnregisterLogHandlerType("SimpleLog.Framework.ILogHandler"), Is.EqualTo(1));
Assert.That(this.Logger.LogHandlerCount, Is.EqualTo(0)); Assert.That(this.Logger.LogHandlerCount, Is.EqualTo(0));
@ -64,6 +66,8 @@ namespace SimpleLog.Tests {
this.Logger.MessageHandler = (IMessageHandler)msgHandler.MockInstance; this.Logger.MessageHandler = (IMessageHandler)msgHandler.MockInstance;
this.Handler.ExpectAndReturn("Log", true, "foobar", LogLevel.Warning); this.Handler.ExpectAndReturn("Log", true, "foobar", LogLevel.Warning);
//h4x0rz!
this.Handler.ExpectAndReturn("get_LogLevel", LogLevel.None);
this.Logger.RegisterLogHandler((ILogHandler)this.Handler.MockInstance); this.Logger.RegisterLogHandler((ILogHandler)this.Handler.MockInstance);
@ -83,6 +87,8 @@ namespace SimpleLog.Tests {
this.Logger.MessageHandler = (IMessageHandler)msgHandler.MockInstance; this.Logger.MessageHandler = (IMessageHandler)msgHandler.MockInstance;
this.Handler.ExpectAndReturn("Log", false, "foobar", LogLevel.Warning); this.Handler.ExpectAndReturn("Log", false, "foobar", LogLevel.Warning);
//h4x0rz!
this.Handler.ExpectAndReturn("get_LogLevel", LogLevel.None);
this.Logger.RegisterLogHandler((ILogHandler)this.Handler.MockInstance); this.Logger.RegisterLogHandler((ILogHandler)this.Handler.MockInstance);
@ -101,11 +107,21 @@ namespace SimpleLog.Tests {
this.Handler.ExpectNoCall("Log"); this.Handler.ExpectNoCall("Log");
this.Logger.RegisterLogHandler((ILogHandler)this.Handler.MockInstance); this.Logger.RegisterLogHandler((ILogHandler)this.Handler.MockInstance);
//h4x0rz!
this.Handler.ExpectAndReturn("get_LogLevel", LogLevel.None);
Assert.That(this.Logger.Log("yay", LogLevel.Debug)); Assert.That(this.Logger.Log("yay", LogLevel.Debug));
this.Handler.Verify(); this.Handler.Verify();
msgHandler.Verify(); msgHandler.Verify();
} }
[Test]
public void TestLoadConfig() {
this.TempFile = System.IO.Path.GetTempFileName();
}
} }
} }

View File

@ -1,23 +1,27 @@
using NUnit.Framework; using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers; using NUnit.Framework.SyntaxHelpers;
using SimpleLog.Framework;
namespace SimpleLog.Tests { namespace SimpleLog.Tests {
[TestFixture] [TestFixture]
public class LoggerManagerTest { public class LoggerManagerTest {
[SetUp]
public void SetUp() {
LoggerManager.LoadConfig(null);
}
[Test] [Test]
public void TestGetLogger() { public void TestGetLogger() {
DefaultLogger logger = LoggerManager.GetLogger<DefaultLogger>(); DefaultLogger logger = LoggerManager.GetLogger(typeof(DefaultLogger)) as DefaultLogger;
Assert.That(logger, Is.TypeOf(typeof(DefaultLogger))); Assert.That(logger, Is.TypeOf(typeof(DefaultLogger)));
DefaultLogger logger2 = LoggerManager.GetLogger<DefaultLogger>(); DefaultLogger logger2 = LoggerManager.GetLogger(typeof(DefaultLogger)) as DefaultLogger;
Assert.That(logger2, Is.TypeOf(typeof(DefaultLogger))); Assert.That(logger2, Is.TypeOf(typeof(DefaultLogger)));
} }
[Test] [Test]
[ExpectedException("System.ArgumentException")] [ExpectedException("System.ArgumentException")]
public void TestGetLoggerThrowsArgumentException() { public void TestGetLoggerThrowsArgumentException() {
LoggerManager.GetLogger<object>(); LoggerManager.GetLogger(typeof(object));
} }
} }

View File

@ -6,12 +6,13 @@
<ProductVersion>9.0.30729</ProductVersion> <ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{4ECCF9B6-8A33-4D17-97EA-BA2D9D9178DD}</ProjectGuid> <ProjectGuid>{4ECCF9B6-8A33-4D17-97EA-BA2D9D9178DD}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SimpleLog.Tests</RootNamespace> <RootNamespace>SimpleLog.Tests</RootNamespace>
<AssemblyName>SimpleLog.Tests</AssemblyName> <AssemblyName>SimpleLog.Tests</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<StartupObject>SimpleLog.Tests.ConsoleColorTest</StartupObject>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@ -26,7 +27,8 @@
<DebugType>none</DebugType> <DebugType>none</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath> <OutputPath>bin\Release\</OutputPath>
<DefineConstants></DefineConstants> <DefineConstants>
</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
@ -34,8 +36,13 @@
<Reference Include="nunit.core, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" /> <Reference Include="nunit.core, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
<Reference Include="nunit.framework, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" /> <Reference Include="nunit.framework, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
<Reference Include="nunit.mocks, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" /> <Reference Include="nunit.mocks, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ConfigTest.cs" />
<Compile Include="ConsoleColorTest.cs" />
<Compile Include="ConsoleLogHandlerTest.cs" /> <Compile Include="ConsoleLogHandlerTest.cs" />
<Compile Include="DefaultLoggerTest.cs" /> <Compile Include="DefaultLoggerTest.cs" />
<Compile Include="DefaultMessageHandlerTest.cs" /> <Compile Include="DefaultMessageHandlerTest.cs" />
@ -47,6 +54,11 @@
<Name>SimpleLog</Name> <Name>SimpleLog</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="Test.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Properties\" /> <Folder Include="Properties\" />
</ItemGroup> </ItemGroup>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8" ?>
<LoggerConfig>
<Logger Class="SimpleLog.DefaultLogger">
<LogHandlers>
<LogHandler Class="SimpleLog.ConsoleWindowLogHandler">
<Setting Name="DebugForeColor" Value="Cyan"/>
<Setting Name="FatalForeColor" Value="White"/>
<Setting Name="FatalBackColor" Value="Red"/>
</LogHandler>
<LogHandler Class="SimpleLog.FileLogHandler">
<Setting Name="LogDirectory" Value="c:\WINDOWS\Temp"/>
<Setting Name="FilePrefix" Value="simplelog_"/>
<Setting Name="FileSuffix" Value=".log"/>
</LogHandler>
</LogHandlers>
</Logger>
</LoggerConfig>

View File

@ -6,7 +6,7 @@
<Producer>Tommy Montgomery</Producer> <Producer>Tommy Montgomery</Producer>
<Copyright>Copyright (C) 2009 Tommy Montgomery</Copyright> <Copyright>Copyright (C) 2009 Tommy Montgomery</Copyright>
<MajorVersion>1</MajorVersion> <MajorVersion>1</MajorVersion>
<MinorVersion>2</MinorVersion> <MinorVersion>3</MinorVersion>
<BuildNumber>0</BuildNumber> <BuildNumber>0</BuildNumber>
<RevisionNumber>0</RevisionNumber> <RevisionNumber>0</RevisionNumber>
<PropertiesDir>Properties</PropertiesDir> <PropertiesDir>Properties</PropertiesDir>
@ -56,4 +56,10 @@
<RemoveDir Directories="$(PropertiesDir)"/> <RemoveDir Directories="$(PropertiesDir)"/>
</Target> </Target>
<Target Name="Clean">
<RemoveDir Directories="$(PropertiesDir)"/>
<RemoveDir Directories="bin"/>
<RemoveDir Directories="obj"/>
</Target>
</Project> </Project>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" ?>
<LoggerConfig>
<Logger Class="SimpleLog.DefaultLogger">
<LogHandlers>
<LogHandler Class="SimpleLog.ConsoleWindowLogHandler">
<Setting Name="DebugForeColor" Value="DarkGreen"/>
<Setting Name="InfoForeColor" Value="Gray"/>
<Setting Name="WarningForeColor" Value="Yellow"/>
<Setting Name="ErrorForeColor" Value="Red"/>
<Setting Name="FatalForeColor" Value="White"/>
<Setting Name="FatalBackColor" Value="Red"/>
</LogHandler>
<LogHandler Class="SimpleLog.FileLogHandler">
<Setting Name="LogDirectory" Value="c:\log"/>
<Setting Name="FilePrefix" Value="simplelog_"/>
<Setting Name="FileSuffix" Value=".log"/>
</LogHandler>
</LogHandlers>
</Logger>
</LoggerConfig>

View File

@ -34,20 +34,39 @@
</DefineConstants> </DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\SimpleLog.XML</DocumentationFile> <DocumentationFile>bin\Release\SimpleLog.xml</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Src\ConsoleLogHandler.cs" />
<Compile Include="Src\ConsoleWindowLogHandler.cs" />
<Compile Include="Src\DefaultLogger.cs" /> <Compile Include="Src\DefaultLogger.cs" />
<Compile Include="Src\DefaultMessageHandler.cs" /> <Compile Include="Src\DefaultMessageHandler.cs" />
<Compile Include="Src\FileLogHandler.cs" />
<Compile Include="Src\Framework\ILogger.cs" /> <Compile Include="Src\Framework\ILogger.cs" />
<Compile Include="Src\Framework\ILogHandler.cs" /> <Compile Include="Src\Framework\ILogHandler.cs" />
<Compile Include="Src\Framework\IMessageFormatter.cs" /> <Compile Include="Src\Framework\IMessageFormatter.cs" />
<Compile Include="Src\Framework\IMessageHandler.cs" /> <Compile Include="Src\Framework\IMessageHandler.cs" />
<Compile Include="Src\Framework\LoggerManager.cs" /> <Compile Include="Src\Framework\Config.cs" />
<Compile Include="Src\Framework\LoggerConfig.cs" />
<Compile Include="Src\Framework\LogHandlerConfig.cs" />
<Compile Include="Src\Framework\Util.cs" /> <Compile Include="Src\Framework\Util.cs" />
<Compile Include="Src\LogHandlers\ConsoleLogHandler.cs" /> <Compile Include="Src\LoggerManager.cs" />
<Compile Include="Src\LogHandlers\ConsoleWindowLogHandler.cs" /> </ItemGroup>
<Compile Include="Src\LogHandlers\FileLogHandler.cs" /> <ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Content Include="SimpleLog.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Properties\" /> <Folder Include="Properties\" />

View File

@ -1,7 +1,7 @@
using System; using System;
using SimpleLog.Framework; using SimpleLog.Framework;
namespace SimpleLog.LogHandlers { namespace SimpleLog {
/// <summary> /// <summary>
/// Log handler for console output (e.g. use this instead of Console.WriteLine()). /// Log handler for console output (e.g. use this instead of Console.WriteLine()).
@ -102,13 +102,21 @@ namespace SimpleLog.LogHandlers {
/// <param name="level">The log level</param> /// <param name="level">The log level</param>
/// <returns>One of the STD_* constants</returns> /// <returns>One of the STD_* constants</returns>
protected virtual uint GetStreamType(LogLevel level) { protected virtual uint GetStreamType(LogLevel level) {
if (level >= SimpleLog.Framework.LogLevel.Warning) { if ((level & SimpleLog.Framework.LogLevel.Default) > 0) {
return STD_ERROR_HANDLE; return STD_ERROR_HANDLE;
} }
return STD_OUTPUT_HANDLE; return STD_OUTPUT_HANDLE;
} }
/// <summary>
/// Applies a configuration object. There is no configuration defined
/// for this log handler.
/// </summary>
public virtual void ApplyConfig(LogHandlerConfig config) {
}
} }
} }

View File

@ -0,0 +1,166 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using SimpleLog.Framework;
namespace SimpleLog {
/// <summary>
/// Log handler for writing log messages to a console window (e.g. cmd.exe).
///
/// The colors of the various log levels are defined in GetConsoleColor().
/// </summary>
public class ConsoleWindowLogHandler : ConsoleLogHandler {
private IDictionary<string, ConsoleColor> colors;
#region Constructors
/// <summary>
/// Constructs a new ConsoleWindowLogHandler with the default title
/// and width
/// </summary>
public ConsoleWindowLogHandler() : this("SimpleLog Console Window") {
}
/// <summary>
/// Constructs a new ConsoleWindowLogHandler with the specified title
/// and default width
/// </summary>
/// <param name="title">Title of the console window</param>
public ConsoleWindowLogHandler(string title) : this(title, 100) {
}
/// <summary>
/// Constructs a new ConsoleWindowLogHandler with a user defined
/// title and width
/// </summary>
/// <param name="title">Title of the console window</param>
/// <param name="width">Width of the console window</param>
public ConsoleWindowLogHandler(string title, int width) : base() {
Win32.AllocConsole();
Console.Title = title;
Console.WindowWidth = width;
this.Colors = new Dictionary<string, ConsoleColor>() {
{"Debug", ConsoleColor.DarkGreen},
{"Info", ConsoleColor.Gray},
{"Warning", ConsoleColor.Yellow},
{"Error", ConsoleColor.Red},
{"Fatal", ConsoleColor.White + ((int)ConsoleColor.Red << 4)}
};
}
#endregion
/// <summary>
/// Gets the console handler
/// </summary>
/// <param name="streamType">Either stderr or stdout</param>
protected IntPtr GetConsoleHandle(uint streamType) {
return Win32.GetStdHandle(streamType);
}
/// <summary>
/// Gets the colors for the console based on the given log level.
///
/// Override this method in your own class if you want to modify the
/// colors. Ideally these would be set by some config file, but
/// that can come later.
/// </summary>
protected virtual ConsoleColor GetConsoleColors(LogLevel level) {
switch (level) {
case SimpleLog.Framework.LogLevel.Debug:
return this.Colors["Debug"];
case SimpleLog.Framework.LogLevel.Info:
return this.Colors["Info"];
case SimpleLog.Framework.LogLevel.Warning:
return this.Colors["Warning"];
case SimpleLog.Framework.LogLevel.Error:
return this.Colors["Error"];
case SimpleLog.Framework.LogLevel.Fatal:
return this.Colors["Fatal"];
default:
throw new IndexOutOfRangeException("Unknown log level");
}
}
/// <summary>
/// Gets the colors associated with each log level
/// </summary>
public IDictionary<string, ConsoleColor> Colors {
get {
return this.colors;
}
private set {
this.colors = value;
}
}
#region Overrides
/// <summary>
/// Logs a message to the console window
/// </summary>
/// <param name="message">The message to log</param>
/// <param name="level">The log level of the message</param>
public override bool Log(string message, LogLevel level) {
uint streamType = this.GetStreamType(level);
System.IO.TextWriter writer = this.GetOutputStream(streamType);
IntPtr consoleHandle = GetConsoleHandle(streamType);
//get the original colors of the console
Win32.CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
Win32.GetConsoleScreenBufferInfo(consoleHandle, out bufferInfo);
ushort colorInfo = (ushort)this.GetConsoleColors(level);
//set the console colors
Win32.SetConsoleTextAttribute(consoleHandle, colorInfo);
//write the message to the console
writer.Write(message);
//reset the console colors
Win32.SetConsoleTextAttribute(consoleHandle, bufferInfo.wAttributes);
return true;
}
/// <summary>
/// Applies the given configuration to the log handler
///
/// <para>
/// Each setting in the config file maps a log level to one of
/// the System.ConsoleColor constants. The Name attribute should
/// be one of the LogLevel constants (e.g. "Debug") followed by
/// either "BackColor" or "ForeColor". The Value attribute is
/// any one of the System.ConsoleColor enum names (e.g. "DarkGreen").
/// </para>
/// </summary>
/// <example>
/// <LogHandler Class="SimpleLog.ConsoleWindowLogHandler">
/// <Setting DebugForeColor="DarkGreen"/>
/// <Setting FatalForeColor="White"/>
/// <Setting FatalBackColor="Red"/>
/// </LogHandler>
/// </example>
/// <param name="config">A log handler configuration</param>
public override void ApplyConfig(LogHandlerConfig config) {
foreach (KeyValuePair<string, string> setting in config.Settings) {
if (setting.Key.EndsWith("ForeColor")) {
string level = setting.Key.Replace("ForeColor", "");
if (this.Colors.ContainsKey(level)) {
this.Colors[level] = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), setting.Value);
}
}
else if (setting.Key.EndsWith("BackColor")) {
string level = setting.Key.Replace("BackColor", "");
if (this.Colors.ContainsKey(level)) {
this.Colors[level] = this.Colors[level] + ((int)(ConsoleColor)Enum.Parse(typeof(ConsoleColor), setting.Value) << 4);
}
}
}
}
#endregion
}
}

View File

@ -86,7 +86,7 @@ namespace SimpleLog {
LogLevel allowedLevel; LogLevel allowedLevel;
IMessageHandler messageHandler; IMessageHandler messageHandler;
foreach (ILogHandler handler in this.logHandlers) { foreach (ILogHandler handler in this.logHandlers) {
allowedLevel = (handler.LogLevel == SimpleLog.Framework.LogLevel.None) ? (LogLevel)this.LogLevel : handler.LogLevel; allowedLevel = (handler.LogLevel == SimpleLog.Framework.LogLevel.None) ? this.LogLevel : handler.LogLevel;
if ((level & allowedLevel) > 0) { if ((level & allowedLevel) > 0) {
messageHandler = handler.MessageHandler ?? this.MessageHandler; messageHandler = handler.MessageHandler ?? this.MessageHandler;
messageHandler.DateFormat = messageHandler.DateFormat ?? this.DateFormat; messageHandler.DateFormat = messageHandler.DateFormat ?? this.DateFormat;
@ -109,20 +109,6 @@ namespace SimpleLog {
this.logHandlers.Add(handler); this.logHandlers.Add(handler);
} }
/// <summary>
/// Unregisters all log handlers that are instances or
/// derived instances of the specified class
/// </summary>
/// <param name="qualifiedClassName">The fully qualified class name (e.g. SimpleLog.Framework.ILogHandler)</param>
/// <returns>The number of log handlers that were removed</returns>
public int UnregisterLogHandlerType(string qualifiedClassName) {
return this.logHandlers.RemoveAll(
delegate(ILogHandler handler) {
return (handler.GetType().FullName == qualifiedClassName);
}
);
}
/// <summary> /// <summary>
/// Unregisters all log handlers /// Unregisters all log handlers
/// </summary> /// </summary>
@ -184,6 +170,20 @@ namespace SimpleLog {
this.lineTerminator = value; this.lineTerminator = value;
} }
} }
/// <summary>
/// Applies the given configuration to this logger
/// </summary>
/// <param name="config">A configuration</param>
public void ApplyConfig(LoggerConfig config) {
foreach (KeyValuePair<string, LogHandlerConfig> pair in config.HandlerData) {
string className = pair.Key;
LogHandlerConfig handlerConfig = pair.Value;
ILogHandler handler = (ILogHandler)Activator.CreateInstance(Type.GetType(className));
handler.ApplyConfig(handlerConfig);
this.RegisterLogHandler(handler);
}
}
#endregion #endregion
#region Accessors #region Accessors
@ -210,6 +210,20 @@ namespace SimpleLog {
#endregion #endregion
#region Convenience methods #region Convenience methods
/// <summary>
/// Unregisters all log handlers that are instances or
/// derived instances of the specified class
/// </summary>
/// <param name="qualifiedClassName">The fully qualified class name (e.g. SimpleLog.ILogHandler)</param>
/// <returns>The number of log handlers that were removed</returns>
public int UnregisterLogHandlerType(string qualifiedClassName) {
return this.logHandlers.RemoveAll(
delegate(ILogHandler handler) {
return (handler.GetType().FullName == qualifiedClassName);
}
);
}
/// <summary> /// <summary>
/// Logs a debug message /// Logs a debug message
/// </summary> /// </summary>
@ -241,8 +255,8 @@ namespace SimpleLog {
/// <summary> /// <summary>
/// Logs a critical message /// Logs a critical message
/// </summary> /// </summary>
public bool Critical(object message) { public bool Fatal(object message) {
return this.Log(message, LogLevel.Critical); return this.Log(message, LogLevel.Fatal);
} }
#endregion #endregion

View File

@ -1,8 +1,9 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using SimpleLog.Framework; using SimpleLog.Framework;
namespace SimpleLog.LogHandlers { namespace SimpleLog {
/// <summary> /// <summary>
/// Log handler for filesystem-based logging /// Log handler for filesystem-based logging
/// </summary> /// </summary>
@ -23,7 +24,7 @@ namespace SimpleLog.LogHandlers {
protected string logDirectory; protected string logDirectory;
/// <summary> /// <summary>
/// The string that prepends each log file name (e.g. /// The string that prepends each log file name (e.g.
/// in logger_20090417.log, "logger" is the filePrefix) /// in logger_20090417.log, "logger_" is the filePrefix)
/// </summary> /// </summary>
protected string filePrefix; protected string filePrefix;
/// <summary> /// <summary>
@ -49,7 +50,7 @@ namespace SimpleLog.LogHandlers {
/// <param name="prefix">The file prefix</param> /// <param name="prefix">The file prefix</param>
/// <param name="suffix">The file suffix (e.g. ".log")</param> /// <param name="suffix">The file suffix (e.g. ".log")</param>
public FileLogHandler(string dir, string prefix, string suffix) { public FileLogHandler(string dir, string prefix, string suffix) {
this.messageHandler = new DefaultMessageHandler(); this.MessageHandler = new DefaultMessageHandler();
this.LogLevel = SimpleLog.Framework.LogLevel.None; this.LogLevel = SimpleLog.Framework.LogLevel.None;
this.LogDirectory = dir; this.LogDirectory = dir;
this.FilePrefix = prefix; this.FilePrefix = prefix;
@ -114,7 +115,7 @@ namespace SimpleLog.LogHandlers {
/// </summary> /// </summary>
protected virtual string BuildFileName() { protected virtual string BuildFileName() {
string fileName = this.logDirectory + Path.DirectorySeparatorChar + this.FilePrefix; string fileName = this.logDirectory + Path.DirectorySeparatorChar + this.FilePrefix;
fileName += "_" + string.Format("{0:yyyyMMdd}", DateTime.Now) + this.FileSuffix; fileName += string.Format("{0:yyyyMMdd}", DateTime.Now) + this.FileSuffix;
return fileName; return fileName;
} }
@ -154,5 +155,14 @@ namespace SimpleLog.LogHandlers {
} }
} }
/// <summary>
/// Applies the configuration to this log handler
/// </summary>
public void ApplyConfig(LogHandlerConfig config) {
foreach (KeyValuePair<string, string> setting in config.Settings) {
Util.SetPropertyDynamically(this, setting.Key, setting.Value);
}
}
} }
} }

View File

@ -0,0 +1,93 @@
using System;
using System.Xml;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SimpleLog.Framework {
/// <summary>
/// Global SimpleLog configuration object
/// </summary>
public sealed class Config {
private IDictionary<string, LoggerConfig> loggerData;
#region Constructors
/// <summary>
/// Constructs a new LoggerConfig object with no initial data
/// </summary>
public Config() {
this.LoggerData = new Dictionary<string, LoggerConfig>();
}
/// <summary>
/// Constructs a new LoggerConfig object initialized with
/// the data provided by the given configuration file
/// </summary>
/// <param name="configFile">Configuration file to load</param>
public Config(string configFile) : this() {
this.Load(configFile);
}
#endregion
/// <summary>
/// Loads a configuration file
/// </summary>
/// <param name="configFile">Path to the config file to load</param>
public void Load(string configFile) {
XmlDocument document = new XmlDocument();
document.Load(configFile);
XmlNodeList loggers = document.GetElementsByTagName("Logger");
foreach (XmlElement element in loggers) {
string className = element.GetAttribute("Class");
this.LoggerData[className] = new LoggerConfig();
XmlNodeList h = element.GetElementsByTagName("LogHandlers");
if (h.Count > 0) {
foreach (XmlElement handler in ((XmlElement)h[0]).GetElementsByTagName("LogHandler")) {
string handlerClass = handler.GetAttribute("Class");
XmlNodeList settings = handler.GetElementsByTagName("Setting");
LogHandlerConfig config = new LogHandlerConfig(settings);
this.LoggerData[className].AddHandler(handlerClass, config);
}
}
}
}
/// <summary>
/// Gets a LoggerConfig for the given name
/// </summary>
/// <param name="loggerName">Fully qualified name of ILogger implementation</param>
/// <exception cref="System.Collections.Generic.KeyNotFoundException"></exception>
public LoggerConfig GetLoggerConfig(string loggerName) {
if (!this.HasLoggerConfig(loggerName)) {
throw new KeyNotFoundException("The logger " + loggerName + " has no configuration");
}
return this.LoggerData[loggerName];
}
/// <summary>
/// Determines whether a config object has been registered for the specified logger
/// </summary>
/// <param name="loggerName">The qualified name of the ILogger implementation</param>
public bool HasLoggerConfig(string loggerName) {
return this.LoggerData.ContainsKey(loggerName);
}
/// <summary>
/// Gets or sets the logger data
/// </summary>
private IDictionary<string, LoggerConfig> LoggerData {
get {
return this.loggerData;
}
set {
this.loggerData = value;
}
}
}
}

View File

@ -30,5 +30,10 @@
/// </summary> /// </summary>
IMessageHandler MessageHandler { get; set; } IMessageHandler MessageHandler { get; set; }
/// <summary>
/// Applies a configuration to the log handler
/// </summary>
void ApplyConfig(LogHandlerConfig config);
} }
} }

View File

@ -15,12 +15,6 @@
/// <param name="handler">The log handler to register</param> /// <param name="handler">The log handler to register</param>
void RegisterLogHandler(ILogHandler handler); void RegisterLogHandler(ILogHandler handler);
/// <summary>
/// Removes all log handlers that match the given assembly name
/// </summary>
/// <returns>Number of log handlers that were unregistered</returns>
int UnregisterLogHandlerType(string assemblyName);
/// <summary> /// <summary>
/// Unregisters all registered log handlers /// Unregisters all registered log handlers
/// </summary> /// </summary>
@ -45,5 +39,11 @@
/// </summary> /// </summary>
IMessageHandler MessageHandler { get; set; } IMessageHandler MessageHandler { get; set; }
/// <summary>
/// Applies the given configuration to the logger
/// </summary>
/// <param name="config">A logger configuration</param>
void ApplyConfig(LoggerConfig config);
} }
} }

View File

@ -0,0 +1,76 @@
using System.Xml;
using System.Collections.Generic;
namespace SimpleLog.Framework {
/// <summary>
/// Configuration object for log handlers
/// </summary>
public sealed class LogHandlerConfig {
private IDictionary<string, string> settings;
/// <summary>
/// Constructs a new log handler configuration object
/// with default settings
/// </summary>
public LogHandlerConfig() {
this.Settings = new Dictionary<string, string>();
}
/// <summary>
/// Constructs a new log handler configuration object initialized
/// with the given settings
/// </summary>
/// <param name="settings">An XML node list containing settings information</param>
public LogHandlerConfig(XmlNodeList settings) : this() {
this.LoadSettings(settings);
}
/// <summary>
/// Loads settings from XML
/// </summary>
/// <param name="settings">An XML node list containing settings information</param>
/// <exception cref="System.Xml.XmlException">If the XML element does not have the "Name" and "Value" attributes</exception>
public void LoadSettings(XmlNodeList settings) {
foreach (XmlElement element in settings) {
if (!element.HasAttribute("Name") || !element.HasAttribute("Value")) {
throw new XmlException("LogHandler <Setting> tag must have Name and Value attributes");
}
this.Settings[element.GetAttribute("Name")] = element.GetAttribute("Value");
}
}
/// <summary>
/// Gets whether the specified setting is defined
/// </summary>
public bool HasSetting(string key) {
return this.Settings.ContainsKey(key);
}
/// <summary>
/// Gets the setting specified by <paramref name="key"/>
/// </summary>
/// <exception cref="System.Collections.Generic.KeyNotFoundException"></exception>
public string GetSetting(string key) {
if (!this.HasSetting(key)) {
throw new KeyNotFoundException("The key " + key + " does not exist");
}
return this.Settings[key];
}
/// <summary>
/// Gets the settings of this configuration
/// </summary>
public IDictionary<string, string> Settings {
get {
return this.settings;
}
private set {
this.settings = value;
}
}
}
}

View File

@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SimpleLog.Framework {
/// <summary>
/// Configuratino object for ILogger implementations
/// </summary>
public sealed class LoggerConfig {
private IDictionary<string, LogHandlerConfig> handlerData;
/// <summary>
/// Constructs a new LoggerConfig object
/// </summary>
public LoggerConfig() {
this.HandlerData = new Dictionary<string, LogHandlerConfig>();
}
/// <summary>
/// Adds a log handler key/value pair
/// </summary>
/// <param name="className">Qualified name of the ILogHandler implementation (e.g. "SimpleLog.FileLogHandler")</param>
/// <param name="config">A configuration object</param>
public void AddHandler(string className, LogHandlerConfig config) {
this.HandlerData.Add(className, config);
}
/// <summary>
/// Gets the log handler data associated with this config object
/// </summary>
public IDictionary<string, LogHandlerConfig> HandlerData {
get {
return this.handlerData;
}
private set {
this.handlerData = value;
}
}
}
}

View File

@ -1,51 +0,0 @@
using System;
using System.Reflection;
using System.Collections.Generic;
namespace SimpleLog.Framework {
/// <summary>
/// Manages ILogger instances in a singletonish way and provides
/// a single point of entry to creating loggers. If singleton
/// behavior is not desired, just instantiate each logger class
/// normally.
/// </summary>
public static class LoggerManager {
/// <summary>
/// Registry of ILogger instances
/// </summary>
private static Dictionary<string, ILogger> registry = new Dictionary<string, ILogger>();
/// <summary>
/// Gets a logger from the registry.
/// <para>This will reuse a logger that has already been instantiated,
/// or create a new instance and stick it in the registry for
/// later use.</para>
///
/// <para>The specified class must implement the SimpleLog.Framework.ILogger
/// interface</para>
///
/// </summary>
/// <code>DefaultLogger logger = LogManager.GetLogger{DefaultLogger}();</code>
/// <typeparam name="T">Must implement the SimpleLog.Framework.ILogger interface</typeparam>
/// <returns></returns>
public static T GetLogger<T>() {
Type type = typeof(T);
string index = type.FullName;
if (LoggerManager.registry.ContainsKey(index)) {
ILogger logger;
LoggerManager.registry.TryGetValue(index, out logger);
return (T)logger;
}
//Type interfaceType = type.GetInterface("ILogger");
if (type.GetInterface("ILogger") != null && type.IsClass) {
return (T)Activator.CreateInstance(type);
}
throw new ArgumentException("The type specified (" + index + ") does not implement the " + (typeof(ILogger).FullName) + " interface");
}
}
}

View File

@ -1,12 +1,15 @@
using System; using System;
using System.Reflection;
using System.Runtime.InteropServices;
namespace SimpleLog.Framework { namespace SimpleLog.Framework {
#region Structs and enumerations
/// <summary> /// <summary>
/// Log level enumeration /// Log level enumeration
/// </summary> /// </summary>
[Flags] [Flags]
public enum LogLevel { public enum LogLevel : int {
/// <summary> /// <summary>
/// No log level specified /// No log level specified
/// </summary> /// </summary>
@ -30,23 +33,19 @@ namespace SimpleLog.Framework {
/// <summary> /// <summary>
/// Critical death level only /// Critical death level only
/// </summary> /// </summary>
Critical = 16, Fatal = 16,
/// <summary>
/// Preferred alias of Critical
/// </summary>
OhNoes = 16,
/// <summary> /// <summary>
/// Debug and Info only /// Debug and Info only
/// </summary> /// </summary>
LowPriority = Debug | Info, LowPriority = Debug | Info,
/// <summary> /// <summary>
/// Default log level: Warning, Error and Critical /// Default log level: Warning, Error and Fatal
/// </summary> /// </summary>
Default = Warning | Error | Critical, Default = Warning | Error | Fatal,
/// <summary> /// <summary>
/// All messages are logged /// All messages are logged
/// </summary> /// </summary>
All = Debug | Info | Warning | Error | Critical All = Debug | Info | Warning | Error | Fatal
} }
/// <summary> /// <summary>
@ -56,17 +55,120 @@ namespace SimpleLog.Framework {
/// <summary> /// <summary>
/// Windows line terminator (CRLF) /// Windows line terminator (CRLF)
/// </summary> /// </summary>
public static readonly string Windows = "\r\n"; public const string Windows = "\r\n";
/// <summary> /// <summary>
/// Macintosh line terminator (CR) /// Macintosh line terminator (CR)
/// </summary> /// </summary>
public static readonly string Mac = "\r"; public const string Mac = "\r";
/// <summary> /// <summary>
/// Unix line terminator (LF) /// Unix line terminator (LF)
/// </summary> /// </summary>
public static readonly string Unix = "\n"; public const string Unix = "\n";
} }
#endregion
#region Win32 API stuff
/// <summary>
/// Win32 API stuff
/// </summary>
public static class Win32 {
/// <summary>
/// 16-bit coordinate struct
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct COORD {
/// <summary>
/// x-coordinate
/// </summary>
public UInt16 x;
/// <summary>
/// y-coordinate
/// </summary>
public UInt16 y;
}
/// <summary>
/// 16-bit rectangle struct
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct SMALL_RECT {
/// <summary>
/// Left side of the rectangle
/// </summary>
public UInt16 Left;
/// <summary>
/// Top of the rectangle
/// </summary>
public UInt16 Top;
/// <summary>
/// Right side of the rectangle
/// </summary>
public UInt16 Right;
/// <summary>
/// Bottom of the rectangle
/// </summary>
public UInt16 Bottom;
}
/// <summary>
/// Console screen buffer info struct
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct CONSOLE_SCREEN_BUFFER_INFO {
/// <summary>
/// Location the console screen
/// </summary>
public COORD dwSize;
/// <summary>
/// Location of the cursor
/// </summary>
public COORD dwCursorPosition;
/// <summary>
/// Meta information of the console
/// </summary>
public ushort wAttributes;
/// <summary>
/// Bounds of the console window
/// </summary>
public SMALL_RECT srWindow;
/// <summary>
/// Maximum size of the window
/// </summary>
public COORD dwMaximumWindowSize;
}
/// <summary>
/// Allocates a console window
/// </summary>
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool AllocConsole();
/// <summary>
/// Gets the output pointer based on the stream type (stderr or stdout)
/// </summary>
/// <param name="type">One of the STD_* constants</param>
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr GetStdHandle(UInt32 type);
/// <summary>
/// Sets the color of the text to be written to the console
/// </summary>
/// <param name="consoleHandle">A console handle returned by GetStdHandle()</param>
/// <param name="attributes">Bitwise pairing of ConsoleColors</param>
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool SetConsoleTextAttribute(IntPtr consoleHandle, ushort attributes);
/// <summary>
/// Gets info about the console window screen
/// </summary>
/// <param name="consoleHandle">A console handle return by GetStdHandle()</param>
/// <param name="bufferInfo"></param>
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool GetConsoleScreenBufferInfo(IntPtr consoleHandle, out CONSOLE_SCREEN_BUFFER_INFO bufferInfo);
}
#endregion
#region Utility class
/// <summary> /// <summary>
/// Utility class /// Utility class
/// </summary> /// </summary>
@ -77,10 +179,35 @@ namespace SimpleLog.Framework {
/// </summary> /// </summary>
public static bool LineTerminatorIsValid(string lineTerminator) { public static bool LineTerminatorIsValid(string lineTerminator) {
return return
lineTerminator == LineTerminator.Unix || lineTerminator == LineTerminator.Unix ||
lineTerminator == LineTerminator.Windows || lineTerminator == LineTerminator.Windows ||
lineTerminator == LineTerminator.Mac; lineTerminator == LineTerminator.Mac;
} }
/// <summary>
/// Sets a property dynamically through reflection, if that property exists
/// </summary>
/// <param name="source">The object with the property to set</param>
/// <param name="propertyName">The property name to set</param>
/// <param name="value">The value to set the property to</param>
/// <returns>TRUE if successfully set, FALSE otherwise</returns>
public static bool SetPropertyDynamically(object source, string propertyName, object value) {
PropertyInfo prop = source.GetType().GetProperty(propertyName);
if (prop != null) {
MethodInfo method = prop.GetSetMethod(false);
if (method != null) {
try {
//value = Convert.ChangeType(value, prop.PropertyType);
method.Invoke(source, new object[] { value });
return true;
}
catch { }
}
}
return false;
}
} }
#endregion
} }

View File

@ -1,202 +0,0 @@
using System;
using System.Runtime.InteropServices;
using SimpleLog.Framework;
namespace SimpleLog.LogHandlers {
/// <summary>
/// Colors for console output. Stolen from log4net.ColoredConsoleAppender (verbatim).
/// </summary>
[Flags]
public enum ConsoleColor : int {
/// <summary>
/// The color blue
/// </summary>
Blue = 0x0001,
/// <summary>
/// The color green
/// </summary>
Green = 0x0002,
/// <summary>
/// The color red
/// </summary>
Red = 0x0004,
/// <summary>
/// The color white (Red, Green and Blue combined)
/// </summary>
White = Blue | Green | Red,
/// <summary>
/// The color yellow (Red and Green combined)
/// </summary>
Yellow = Red | Green,
/// <summary>
/// The color purple (Red and Blue combined)
/// </summary>
Purple = Red | Blue,
/// <summary>
/// The color cyan (Green and Blue combined)
/// </summary>
Cyan = Green | Blue,
/// <summary>
/// Brightens a color
/// </summary>
HighIntensity = 0x0008,
}
/// <summary>
/// Log handler for writing log messages to a console window (e.g. cmd.exe).
///
/// The colors of the various log levels are defined in GetConsoleColor().
/// </summary>
public class ConsoleWindowLogHandler : ConsoleLogHandler {
#region Constructors
/// <summary>
/// Constructs a new ConsoleWindowLogHandler with the default title
/// and width
/// </summary>
public ConsoleWindowLogHandler() : this("SimpleLog Console Window") {
}
/// <summary>
/// Constructs a new ConsoleWindowLogHandler with the specified title
/// and default width
/// </summary>
/// <param name="title">Title of the console window</param>
public ConsoleWindowLogHandler(string title) : this(title, 100) {
}
/// <summary>
/// Constructs a new ConsoleWindowLogHandler with a user defined
/// title and width
/// </summary>
/// <param name="title">Title of the console window</param>
/// <param name="width">Width of the console window</param>
public ConsoleWindowLogHandler(string title, int width) : base() {
ConsoleWindowLogHandler.AllocConsole();
Console.Title = title;
Console.WindowWidth = width;
}
#endregion
/// <summary>
/// Gets the console handler
/// </summary>
/// <param name="streamType">Either stderr or stdout</param>
protected IntPtr GetConsoleHandle(uint streamType) {
return ConsoleWindowLogHandler.GetStdHandle(streamType);
}
/// <summary>
/// Gets the colors for the console based on the given log level.
///
/// Override this method in your own class if you want to modify the
/// colors. Ideally these would be set by some config file, but
/// that can come later.
/// </summary>
protected virtual ConsoleColor GetConsoleColors(LogLevel level) {
switch (level) {
case SimpleLog.Framework.LogLevel.Debug:
return ConsoleColor.Green;
case SimpleLog.Framework.LogLevel.Info:
return ConsoleColor.White;
case SimpleLog.Framework.LogLevel.Warning:
return ConsoleColor.Yellow | ConsoleColor.HighIntensity;
case SimpleLog.Framework.LogLevel.Error:
return ConsoleColor.Red | ConsoleColor.HighIntensity;
case SimpleLog.Framework.LogLevel.Critical:
return (ConsoleColor.White | ConsoleColor.HighIntensity) + ((int)(ConsoleColor.Red | ConsoleColor.HighIntensity) << 4);
default:
return ConsoleColor.White;
}
}
#region Overrides
/// <summary>
/// Logs a message to the console window
/// </summary>
/// <param name="message">The message to log</param>
/// <param name="level">The log level of the message</param>
public override bool Log(string message, LogLevel level) {
uint streamType = this.GetStreamType(level);
System.IO.TextWriter writer = this.GetOutputStream(streamType);
IntPtr consoleHandle = GetConsoleHandle(streamType);
//get the original colors of the console
CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
GetConsoleScreenBufferInfo(consoleHandle, out bufferInfo);
ushort colorInfo = (ushort)this.GetConsoleColors(level);
//set the console colors
ConsoleWindowLogHandler.SetConsoleTextAttribute(consoleHandle, colorInfo);
//write the message to the console
writer.Write(message);
//reset the console colors
ConsoleWindowLogHandler.SetConsoleTextAttribute(consoleHandle, bufferInfo.wAttributes);
return true;
}
#endregion
#region Win32 API stuff
[StructLayout(LayoutKind.Sequential)]
private struct COORD {
public UInt16 x;
public UInt16 y;
}
[StructLayout(LayoutKind.Sequential)]
private struct SMALL_RECT {
public UInt16 Left;
public UInt16 Top;
public UInt16 Right;
public UInt16 Bottom;
}
[StructLayout(LayoutKind.Sequential)]
private struct CONSOLE_SCREEN_BUFFER_INFO {
public COORD dwSize;
public COORD dwCursorPosition;
public ushort wAttributes;
public SMALL_RECT srWindow;
public COORD dwMaximumWindowSize;
}
/// <summary>
/// Allocates a console window
/// </summary>
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool AllocConsole();
/// <summary>
/// Gets the output pointer based on the stream type (stderr or stdout)
/// </summary>
/// <param name="type">One of the STD_* constants</param>
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr GetStdHandle(UInt32 type);
/// <summary>
/// Sets the color of the text to be written to the console
/// </summary>
/// <param name="consoleHandle">A console handle returned by GetStdHandle()</param>
/// <param name="attributes">Bitwise pairing of ConsoleColors</param>
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool SetConsoleTextAttribute(IntPtr consoleHandle, ushort attributes);
/// <summary>
/// Gets info about the console window screen
/// </summary>
/// <param name="consoleHandle">A console handle return by GetStdHandle()</param>
/// <param name="bufferInfo"></param>
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool GetConsoleScreenBufferInfo(IntPtr consoleHandle, out CONSOLE_SCREEN_BUFFER_INFO bufferInfo);
#endregion
}
}

View File

@ -0,0 +1,113 @@
using System;
using System.Xml;
using System.Reflection;
using System.Collections.Generic;
using SimpleLog.Framework;
namespace SimpleLog {
/// <summary>
/// Manages ILogger instances in a singletonish way and provides
/// a single point of entry to creating loggers. If singleton
/// behavior is not desired, just instantiate each logger class
/// normally.
/// </summary>
public static class LoggerManager {
/// <summary>
/// Registry of ILogger instances
/// </summary>
private static IDictionary<string, ILogger> Registry = new Dictionary<string, ILogger>();
/// <summary>
/// Global configuration object for all loggers
/// </summary>
private static Config config = null;
/// <summary>
/// Default location of the configuration file
/// </summary>
public const string DEFAULT_CONFIG_LOCATION = "SimpleLog.config";
/// <summary>
/// Sets up the LoggerConfig if one hasn't already been set by an
/// external source
/// </summary>
static LoggerManager() {
if (LoggerManager.Config == null) {
if (System.IO.File.Exists(LoggerManager.DEFAULT_CONFIG_LOCATION)) {
LoggerManager.LoadConfig(LoggerManager.DEFAULT_CONFIG_LOCATION);
}
else {
LoggerManager.LoadConfig(null);
}
}
}
/// <summary>
/// Loads or reloads the global configuration from a file
/// </summary>
/// <param name="configFile">Path to the configuration file, or null</param>
public static void LoadConfig(string configFile) {
if (configFile != null) {
LoggerManager.Config = new Config(configFile);
}
else {
LoggerManager.Config = new Config();
}
}
/// <summary>
/// Gets a logger from the registry.
/// <para>This will reuse a logger that has already been instantiated,
/// or create a new instance and stick it in the registry for
/// later use.</para>
///
/// <para>The specified class must implement the SimpleLog.Framework.ILogger
/// interface</para>
///
/// </summary>
/// <code>DefaultLogger logger = (DefaultLogger)LoggerManager.GetLogger(typeof(DefaultLogger));</code>
/// <param name="type">The type of logger to create</param>
/// <returns></returns>
public static ILogger GetLogger(Type type) {
string loggerName = type.FullName;
//if the logger has already been instantiated, return it
if (LoggerManager.Registry.ContainsKey(loggerName)) {
return LoggerManager.Registry[loggerName];
}
if (type.GetInterface("ILogger") != null) {
if (type.IsClass && !type.IsAbstract) {
ILogger logger = (ILogger)Activator.CreateInstance(type);
if (LoggerManager.Config.HasLoggerConfig(loggerName)) {
LoggerConfig loggerConfig = LoggerManager.Config.GetLoggerConfig(loggerName);
logger.ApplyConfig(loggerConfig);
}
return logger;
}
else {
throw new ArgumentException("The type specified (" + loggerName + ") is not an instantiable class");
}
}
else {
throw new ArgumentException("The type specified (" + loggerName + ") does not implement the " + (typeof(ILogger).FullName) + " interface");
}
}
/// <summary>
/// Gets the global configuration object
/// </summary>
public static Config Config {
get {
return LoggerManager.config;
}
private set {
LoggerManager.config = value;
}
}
}
}

View File

@ -1,20 +0,0 @@
@echo off
if exist "SimpleLog/bin" (
echo deleting SimpleLog/bin...
rmdir /S /Q "SimpleLog/bin"
)
if exist "SimpleLog/obj" (
echo deleting SimpleLog/obj...
rmdir /S /Q "SimpleLog/obj"
)
if exist "SimpleLog.Tests/bin" (
echo deleting SimpleLog.Tests/bin...
rmdir /S /Q "SimpleLog.Tests/bin"
)
if exist "SimpleLog.Tests/obj" (
echo deleting SimpleLog.Tests/obj...
rmdir /S /Q "SimpleLog.Tests/obj"
)

1
clean.bat Normal file
View File

@ -0,0 +1 @@
%WINDIR%\Microsoft.NET\Framework\v3.5\MSBuild.exe /target:Clean SimpleLog.sln