turkinator
turkinator

Reputation: 925

c# - Serialize log4net Configuration to XML?

I'm having some trouble wrapping log4net in a static logging class.

I am using the following (unfinished) class to generate a log4Net configuration on the fly:

public class eLogConfig
{
    public bool AppendToFile = true;
    /// <summary>
    /// This is the Path to the folder that will contain the 
    /// Configuation and Logs folder
    /// Recommended path is ProgramData\\CompanyName
    /// </summary>
    public string ParentPath { get; set; }
    public string LogPattern = "%date [%thread] %-5level %logger - %message%newline";
    public int MaxLogFiles = 10;
    public int MaxLogSizeInMB = 10;
    public Level Level = Level.Debug;
    public string LogFilePath
    {
        get
        {
            return Path.Combine(LogFolder,
                Assembly.GetEntryAssembly().GetName().Name
                .e().ToFileName() + ".Log.txt");
        }
    }
    public string ConfigFilePath
    {
        get
        {
            return Path.GetFileNameWithoutExtension(
                    Assembly.GetEntryAssembly().Location
                ).e().ToFileName() + ".Log4Net.config";
        }
    }

    private string ConfigurationFolder
    {
        get
        {
            return Path.Combine(this.ParentPath, "Configuration");
        }
    }
    private string LogFolder
    {
        get
        {
            return Path.Combine(this.ParentPath, "Logs");
        }
    }

    /// <summary>
    /// Initializes a new eLogConfiguration object, for use with initializing a new eLog Logger
    /// </summary>
    /// <param name="ParentPath">The path which will contain the Configuration and Logs folders</param>
    public eLogConfig(DirectoryInfo ParentPath)
    {
        this.ParentPath = ParentPath.FullName;
        if (!Directory.Exists(this.ParentPath))
            Directory.CreateDirectory(this.ParentPath);
        if (!Directory.Exists(ConfigurationFolder))
            Directory.CreateDirectory(ConfigurationFolder);
        if (!Directory.Exists(LogFolder))
            Directory.CreateDirectory(LogFolder);
    }
    private bool initialized = false;
    public void Setup()
    {
        if (!initialized || !File.Exists(LogFilePath))
        {
            Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();

            PatternLayout patternLayout = new PatternLayout();
            patternLayout.ConversionPattern = this.LogPattern;
            patternLayout.ActivateOptions();

            RollingFileAppender roller = new RollingFileAppender();
            roller.AppendToFile = this.AppendToFile;
            roller.File = this.LogFilePath;
            roller.Layout = patternLayout;
            roller.MaxSizeRollBackups = MaxLogFiles;
            roller.MaximumFileSize = "{0}MB".e(this.MaxLogSizeInMB);
            roller.RollingStyle = RollingFileAppender.RollingMode.Size;
            roller.StaticLogFileName = true;
            roller.ActivateOptions();
            hierarchy.Root.AddAppender(roller);

            MemoryAppender memory = new MemoryAppender();
            memory.ActivateOptions();
            hierarchy.Root.AddAppender(memory);

            hierarchy.Root.Level = this.Level;
            hierarchy.Configured = true;

            //eFile.SaveAsString(hierarchy.Serialize(), ConfigurationFolder);
            initialized = true;
        }
    }
}

The code works to create a new ILogger in the Repository, and I can begin logging, but it seems the configuration gets saved into the running Application config, and I can't figure out how to get it to save the configuration to a file. As you can see, I've commented out the line which serializes and saves the hiearchy object, because I know thats wrong - this isn't serializing the configuration, and it throws an exception with errors reflecting Hierarchy's inner types.

I feel like I'm overthinking this, and my code could work much differently. I really just want a log4Net Config-File-Generator, which I can hand back to my static Logger class for use in XmlConfigurator.ConfigureAndWatch(string newConfigPath) or DOMConfigurator.ConfigureAndWatch(string newConfigPath)


For Reference:

My static logging class looks like this (also, it currently doesn't work because I've been playing with it to implement my new Config Generator\Wrapper):

/// <summary>
/// Log4Net wrapper, based on (http://code.google.com/p/codecampserver/source/list)
/// </summary>
public static partial class eLog
{
    private static readonly Dictionary<Assembly, Dictionary<Type, ILog>> _loggers = new Dictionary<Assembly, Dictionary<Type, ILog>>();
    private static bool _logInitialized;
    private static readonly object _lock = new object();

    public static string SerializeException(Exception exception)
    {
        return SerializeException(exception, string.Empty);
    }

    private static string SerializeException(Exception e, string exceptionMessage)
    {
        if (e == null) return string.Empty;

        exceptionMessage = string.Format(CultureInfo.InvariantCulture,
                                         "{0}{1}{2}\n{3}",
                                         exceptionMessage,

                                         string.IsNullOrEmpty(exceptionMessage) ? string.Empty : "\n\n",
                                         e.Message,
                                         e.StackTrace);

        if (e.InnerException != null)
            exceptionMessage = SerializeException(e.InnerException, exceptionMessage);

        return exceptionMessage;
    }

    private static ILog getLogger(Type source, Assembly assem)
    {
        EnsureInitialized();
        //.Location.Split('.')[0]
        lock (_lock)
        {
            if (!_loggers.ContainsKey(assem))
            {
                _loggers.Add(assem, new Dictionary<Type, ILog>());
            }

            if (_loggers[assem] == null)
            {
                _loggers[assem] = new Dictionary<Type, ILog>();
            }

            if (!_loggers[assem].ContainsKey(source))
            {
                var logger = LogManager.GetLogger(assem, source);
                _loggers[assem].Add(source, logger);
            }
            return _loggers[assem][source];
        }
    }

    /* Log a message object */
    public static void Debug(object source, string message)
    {
        Debug(source.GetType(), message);
    }

    public static void Debug(object source, string message, params object[] ps)
    {
        Debug(source.GetType(), string.Format(message, ps));
    }

    public static void Debug(Type source, string message)
    {
        ILog logger = getLogger(source, Assembly.GetEntryAssembly());
        if (logger.IsDebugEnabled)
            logger.Debug(message);
    }

    public static void Info(object source, object message)
    {
        Info(source.GetType(), message);
    }

    public static void Info(Type source, object message)
    {
        ILog logger = getLogger(source, Assembly.GetEntryAssembly());
        if (logger.IsInfoEnabled)
            logger.Info(message);
    }

    public static void Warn(object source, object message)
    {
        Warn(source.GetType(), message);
    }

    public static void Warn(Type source, object message)
    {
        ILog logger = getLogger(source, Assembly.GetEntryAssembly());
        if (logger.IsWarnEnabled)
            logger.Warn(message);
    }

    public static void Error(object source, object message)
    {
        Error(source.GetType(), message);
    }

    public static void Error(Type source, object message)
    {
        ILog logger = getLogger(source, Assembly.GetEntryAssembly());
        if (logger.IsErrorEnabled)
            logger.Error(message);
    }

    public static void Fatal(object source, object message)
    {
        Fatal(source.GetType(), message);
    }

    public static void Fatal(Type source, object message)
    {
        ILog logger = getLogger(source, Assembly.GetEntryAssembly());
        if (logger.IsFatalEnabled)
            logger.Fatal(message);
    }

    /* Log a message object and exception */

    public static void Debug(object source, object message, Exception exception)
    {
        Debug(source.GetType(), message, exception);
    }

    public static void Debug(Type source, object message, Exception exception)
    {
        getLogger(source, Assembly.GetEntryAssembly()).Debug(message, exception);
    }

    public static void Info(object source, object message, Exception exception)
    {
        Info(source.GetType(), message, exception);
    }

    public static void Info(Type source, object message, Exception exception)
    {
        getLogger(source, Assembly.GetEntryAssembly()).Info(message, exception);
    }

    public static void Warn(object source, object message, Exception exception)
    {
        Warn(source.GetType(), message, exception);
    }

    public static void Warn(Type source, object message, Exception exception)
    {
        getLogger(source, Assembly.GetEntryAssembly()).Warn(message, exception);
    }

    public static void Error(object source, object message, Exception exception)
    {
        Error(source.GetType(), message, exception);
    }

    public static void Error(Type source, object message, Exception exception)
    {
        getLogger(source, Assembly.GetEntryAssembly()).Error(message, exception);
    }

    public static void Fatal(object source, object message, Exception exception)
    {
        Fatal(source.GetType(), message, exception);
    }

    public static void Fatal(Type source, object message, Exception exception)
    {
        getLogger(source, Assembly.GetEntryAssembly()).Fatal(message, exception);
    }

    private static void initialize()
    {
        string path = Path.Combine(
                    eWindows.Paths.ProgramData, // ProgramData
                    Assembly.GetEntryAssembly().FullName.Split('.')[0]);
        eLogConfig config = new eLogConfig(new DirectoryInfo(path));
        config.Setup();

        //XmlConfigurator.ConfigureAndWatch(new FileInfo(path));
        //DOMConfigurator.Configure()

        _logInitialized = true;

    }

    public static void EnsureInitialized()
    {
        if (!_logInitialized)
        {
            initialize();
        }
    }
}

Upvotes: 1

Views: 1568

Answers (1)

turkinator
turkinator

Reputation: 925

I have finished creating the following simple Log4Net Config & Static Logging class (based on work from codecampserver), which serializes using the IXmlSerializable interface. The static Log class automatically handles all configuration of the Logger and allows one-line logging from any assembly which references the Log class, it will create new Configuration files and folders in C:\ProgramData\{MyRootNameSpace}\Configuration\ and log files in the C:\ProgramData\{MyRootNameSpace}\Logs\ directories.

*NOTE: This implementation only supports logging to 1 Appender per Entry-Assembly. Additional Loggers can be added, but modification of the Serialization and Logging classes may need to be done. See "To-Do" at the bottom for more information.

using log4net;
using log4net.Appender;
using log4net.Config;
using log4net.Core;
using log4net.Layout;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Xml.Linq;
using System.Runtime.CompilerServices;
using System.Diagnostics;
using System.Security.AccessControl; // Used in IsWritable(directory)
using System.Security.Principal; // Used in IsWritable(directory)

namespace LogWrapper
{
    public class LogConfig
    {
        /// <summary>
        /// Initializes a new LogConfig object, for use with initializing a new Logger
        /// </summary>
        public LogConfig(Type type, Assembly assem)
        {
            Type = type;
            EntryAssembly = assem;
        }
        private Type Type { get; set; }
        private Assembly assembly = Assembly.GetEntryAssembly();
        private Assembly EntryAssembly
        {
            get
            {
                return assembly;
            }
            set
            {
                if (assembly != null)
                    assembly = value;
                this.Update();
            }
        }
        public bool AppendToFile { get; set; } = true;
        private string parentPath = String.Empty;
        /// <summary>
        /// This is the Path to the folder that will contain the 
        /// Configuation and Logs folder
        /// Recommended path is ProgramData\\CompanyName
        /// </summary>
        private string ParentPath
        {
            get
            {
                if (String.IsNullOrEmpty(parentPath))
                {
                    return Path.Combine(
                        ProgramData, // ProgramData
                        EntryAssembly.FullName.Split('.')[0]);
                }
                else
                {
                    return parentPath;
                }
            }
            set
            {
                if (IsWritable(new DirectoryInfo(value)))
                {
                    parentPath = value;
                }
                this.Update();
            }
        }
        private string _pattern = "%-5level\t%date{yyyy-MM-dd HH:mm:ss.fff}\t[%thread]\t%logger\t%message%newline";
        public string LogPattern
        {
            get
            {
                return this._pattern;
            }
            set
            {
                if (!String.IsNullOrEmpty(value))
                {
                    this._pattern = value;
                    this.Update();
                }
            }
        }
        public int MaxLogFiles = 5;
        public int MaxLogSizeInMB = 5;
        private Level _level = Level.Debug;
        public Level Level
        {
            get
            {
                return this._level;
            }
            set
            {
                _level = value;
                this.Update();
            }
        }
        private string LogFilePath
        {
            get
            {
                return Path.Combine(LogFolder,
                    EntryAssembly.GetName().Name
                    .ToFileName() + ".log");
            }
        }
        private string ConfigFilePath
        {
            get
            {
                return Path.Combine(ConfigurationFolder,
                    Path.GetFileNameWithoutExtension(
                        EntryAssembly.Location
                    ).ToFileName() + ".Log4Net.config.xml");
            }
        }

        private string ConfigurationFolder
        {
            get
            {
                return Path.Combine(this.ParentPath, "Configuration");
            }
        }
        private string LogFolder
        {
            get
            {
                return Path.Combine(this.ParentPath, "Logs");
            }
        }
        private bool initialized = false;
        internal ILog Setup()
        {
            return this.Update(false);
        }
        internal ILog Update(bool overwrite = true)
        {
            if (!Directory.Exists(this.ParentPath))
                Directory.CreateDirectory(this.ParentPath);
            if (!Directory.Exists(ConfigurationFolder))
                Directory.CreateDirectory(ConfigurationFolder);
            if (!Directory.Exists(LogFolder))
                Directory.CreateDirectory(LogFolder);
            if (!File.Exists(ConfigFilePath) || overwrite)
            {
                var config = this.Serialize();
                File.Create(ConfigFilePath).Close();
                File.WriteAllText(ConfigFilePath, config.ToString());
            }
            var logger = LogManager.GetLogger(EntryAssembly, Type);
            XmlConfigurator.ConfigureAndWatch(new FileInfo(ConfigFilePath));
            if (!initialized)
            {
                initialized = true;
            }
            return logger;
        }
        private XDocument Serialize()
        {
            XDocument xDoc = new XDocument();

            //apender
            var param = new XElement("param");
            param.SetAttributeValue("name", "ConversionPattern");
            param.SetAttributeValue("value", LogPattern);

            var layout = new XElement("layout", param);
            layout.SetAttributeValue("type", typeof(PatternLayout));

            var file = new XElement("file");
            file.SetAttributeValue("value", LogFilePath);

            var append = new XElement("appendToFile");
            append.SetAttributeValue("value", AppendToFile);

            var rollingstyle = new XElement("rollingStyle");
            rollingstyle.SetAttributeValue("value",
                Enum.GetName(typeof(RollingFileAppender.RollingMode)
                    , RollingFileAppender.RollingMode.Size));

            var maxFiles = new XElement("maxSizeRollBackups");
            maxFiles.SetAttributeValue("value", MaxLogFiles);

            var maxFileSize = new XElement("maximumFileSize");
            maxFileSize.SetAttributeValue("value", "{0}MB".FormatWith(MaxLogSizeInMB));

            var staticLogFile = new XElement("StaticLogFileName");
            staticLogFile.SetAttributeValue("value", true);

            var appender = new XElement("appender"
                , file
                , append
                , rollingstyle
                , maxFiles
                , maxFileSize
                , staticLogFile
                , layout);
            appender.SetAttributeValue("name", EntryAssembly.GetName().Name);
            appender.SetAttributeValue("type", typeof(RollingFileAppender));

            //Root
            var level = new XElement("level");
            level.SetAttributeValue("value", Level.Name);
            var appRef = new XElement("appender-ref");
            appRef.SetAttributeValue("ref", EntryAssembly.GetName().Name);

            var root = new XElement("root", level, appRef);

            //Config
            var section = new XElement("section");
            section.SetAttributeValue("name", "log4net");
            section.SetAttributeValue("type", "{0}, {1}".FormatWith(typeof(Log4NetConfigurationSectionHandler), "log4net"));

            var configSection = new XElement("configSections", section);

            var configuration = new XElement("configuration",
                configSection,
                new XElement("log4net",
                    appender, root));

            return XDocument.Parse(configuration.ToString());
        }
        //Helper Methods
        private static string ProgramData
        {
            get
            {
                return Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
            }
        }
        private static bool IsWritable(DirectoryInfo destDir)
        {
            if (string.IsNullOrEmpty(destDir.FullName) || !Directory.Exists(destDir.FullName)) return false;
            try
            {
                DirectorySecurity security = Directory.GetAccessControl(destDir.FullName);
                SecurityIdentifier users = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
                foreach (AuthorizationRule rule in security.GetAccessRules(true, true, typeof(SecurityIdentifier)))
                {
                    if (rule.IdentityReference == users)
                    {
                        FileSystemAccessRule rights = ((FileSystemAccessRule)rule);
                        if (rights.AccessControlType == AccessControlType.Allow)
                        {
                            if (rights.FileSystemRights == (rights.FileSystemRights | FileSystemRights.Modify)) return true;
                        }
                    }
                }
                return false;
            }
            catch
            {
                return false;
            }
        }
    }
    /// <summary>
    /// Log4Net wrapper, modified from codecampserver (http://code.google.com/p/codecampserver/source/list)
    /// </summary>
    public static partial class Log
    {
        private static readonly Dictionary<Assembly, Dictionary<Type, ILog>> _loggers = new Dictionary<Assembly, Dictionary<Type, ILog>>();
        private static bool _logInitialized;
        private static readonly object _lock = new object();

        public static string SerializException(Exception exception)
        {
            return SerializException(exception, string.Empty);
        }

        private static string SerializException(Exception e, string exceptionMessage)
        {
            if (e == null) return string.Empty;

            exceptionMessage = string.Format(CultureInfo.InvariantCulture,
                                            "{0}{1}{2}\n{3}",
                                            exceptionMessage,
                                            string.IsNullOrEmpty(exceptionMessage) ? string.Empty : "\n\n",
                                            e.Message,
                                            e.StackTrace);

            if (e.InnerException != null)
                exceptionMessage = SerializException(e.InnerException, exceptionMessage);

            return exceptionMessage;
        }

        private static ILog getLogger(Type source, Assembly assem)
        {
            //EnsureInitialized(assem, source);
            lock (_lock)
            {
                if (!_loggers.ContainsKey(assem))
                {
                    _loggers.Add(assem, new Dictionary<Type, ILog>());
                }

                if (_loggers[assem] == null)
                {
                    _loggers[assem] = new Dictionary<Type, ILog>();
                }

                if (!_loggers[assem].ContainsKey(source))
                {
                    _loggers[assem].Add(source, new LogConfig(source, assem).Setup());
                }
                var logger = _loggers[assem][source];
                return logger;
            }
        }
        public static void Debug(string message = "", Exception ex = null, [CallerMemberName] string methodName = "")
        {
            MethodBase method = new StackTrace().GetFrame(1).GetMethod();
            Debug(method.DeclaringType, "{0}()\t{1}".FormatWith(methodName, message.ToCSVFormat()), ex);
        }
        public static void Info(string message = "", Exception ex = null, [CallerMemberName] string methodName = "")
        {
            MethodBase method = new StackTrace().GetFrame(1).GetMethod();
            Info(method.DeclaringType, "{0}()\t{1}".FormatWith(methodName, message.ToCSVFormat()), ex);
        }
        public static void Warn(string message = "", Exception ex = null, [CallerMemberName] string methodName = "")
        {
            MethodBase method = new StackTrace().GetFrame(1).GetMethod();
            Warn(method.DeclaringType, "{0}()\t{1}".FormatWith(methodName, message.ToCSVFormat()), ex);
        }
        public static void Error(string message = "", Exception ex = null, [CallerMemberName] string methodName = "", [CallerFilePath] string file = "")
        {
            MethodBase method = new StackTrace().GetFrame(1).GetMethod();
            Error(method.DeclaringType, "{0}()\t{1} in {2}".FormatWith(methodName, message.ToCSVFormat(), file), ex);
        }
        public static void Error(Exception ex, [CallerMemberName] string methodName = "", [CallerFilePath] string file = "")
        {
            MethodBase method = new StackTrace().GetFrame(1).GetMethod();
            Error(method.DeclaringType, "{0}()\t{1} in {2}".FormatWith(methodName, ex.Message.ToCSVFormat(), file), ex);
        }
        public static void Fatal(string message = "", Exception ex = null, [CallerMemberName] string methodName = "", [CallerLineNumber] int line = -1, [CallerFilePath] string file = "")
        {
            MethodBase method = new StackTrace().GetFrame(1).GetMethod();
            Fatal(method.DeclaringType, "{0}()\t{1} at Line# {2} in [{3}]".FormatWith(methodName, message.ToCSVFormat()), ex);
        }
        public static void Fatal(Exception ex = null, [CallerMemberName] string methodName = "", [CallerLineNumber] int line = -1, [CallerFilePath] string file = "")
        {
            MethodBase method = new StackTrace().GetFrame(1).GetMethod();
            Fatal(method.DeclaringType, "{0}()\t{1} at Line# {2} in [{3}]".FormatWith(methodName, ex.Message.ToCSVFormat()), ex);
        }
        public static LogConfig Config
        {
            get
            {
                return new LogConfig(MethodBase.GetCurrentMethod().DeclaringType, Assembly.GetEntryAssembly());
            }
            set
            {
                _loggers[Assembly.GetEntryAssembly()][MethodBase.GetCurrentMethod().DeclaringType] = value.Update();
            }
        }
        /* Log a message object */
        private static void Debug(Type source, string message)
        {
            ILog logger = getLogger(source, Assembly.GetEntryAssembly());
            if (logger.IsDebugEnabled)
                logger.Debug(message);
        }
        private static void Info(Type source, object message)
        {
            ILog logger = getLogger(source, Assembly.GetEntryAssembly());
            if (logger.IsInfoEnabled)
                logger.Info(message);
        }
        private static void Warn(Type source, object message)
        {
            ILog logger = getLogger(source, Assembly.GetEntryAssembly());
            if (logger.IsWarnEnabled)
                logger.Warn(message);
        }
        private static void Error(Type source, object message)
        {
            ILog logger = getLogger(source, Assembly.GetEntryAssembly());
            if (logger.IsErrorEnabled)
                logger.Error(message);
        }
        private static void Fatal(Type source, object message)
        {
            ILog logger = getLogger(source, Assembly.GetEntryAssembly());
            if (logger.IsFatalEnabled)
                logger.Fatal(message);
        }

        /* Log a message object and exception */
        private static void Debug(object source, object message, Exception exception)
        {
            Debug(source.GetType(), message, exception);
        }
        private static void Debug(Type source, object message, Exception exception)
        {
            getLogger(source, Assembly.GetEntryAssembly()).Debug(message, exception);
        }
        private static void Debug(Type source, string message, Exception exception)
        {
            getLogger(source, Assembly.GetEntryAssembly()).Debug(message, exception);
        }
        private static void Info(object source, object message, Exception exception)
        {
            Info(source.GetType(), message, exception);
        }
        private static void Info(Type source, object message, Exception exception)
        {
            getLogger(source, Assembly.GetEntryAssembly()).Info(message, exception);
        }
        private static void Info(Type source, string message, Exception exception)
        {
            getLogger(source, Assembly.GetEntryAssembly()).Info(message, exception);
        }
        private static void Warn(object source, object message, Exception exception)
        {
            Warn(source.GetType(), message, exception);
        }
        private static void Warn(Type source, object message, Exception exception)
        {
            getLogger(source, Assembly.GetEntryAssembly()).Warn(message, exception);
        }
        private static void Warn(Type source, string message, Exception exception)
        {
            getLogger(source, Assembly.GetEntryAssembly()).Warn(message, exception);
        }
        private static void Error(object source, object message, Exception exception)
        {
            Error(source.GetType(), message, exception);
        }
        private static void Error(Type source, object message, Exception exception)
        {
            getLogger(source, Assembly.GetEntryAssembly()).Error(message, exception);
        }
        private static void Error(Type source, string message, Exception exception)
        {
            getLogger(source, Assembly.GetEntryAssembly()).Error(message, exception);
        }
        private static void Fatal(object source, object message, Exception exception)
        {
            Fatal(source.GetType(), message, exception);
        }
        private static void Fatal(Type source, object message, Exception exception)
        {
            getLogger(source, Assembly.GetEntryAssembly()).Fatal(message, exception);
        }
        private static void Fatal(Type source, string message, Exception exception)
        {
            getLogger(source, Assembly.GetEntryAssembly()).Fatal(message, exception);
        }
        private static void initialize(Assembly assem, Type t)
        {
            _logInitialized = true;
        }
        private static void EnsureInitialized(Assembly assem, Type t)
        {
            if (!_logInitialized)
            {
                initialize(assem, t);
            }
        }
    }
}

Usage & Output

Example Usage:

namespace Test.Sandbox
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        //Example 1: 
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            Log.Debug();
            Log.Debug("button1 Clicked");
            Log.Debug("Fake Error Occured", new Exception("Fake Error"));
        }
        //Example 2:
        private void button2_Click(object sender, RoutedEventArgs e)
        {
            Log.Config.Level = Level.Error; // Set error level (updates logconfig.xml)
            Log.Debug(); //Does not get written because Level has been set to 'Error', above
            Log.Error();
            Log.Error("This is an Error");
            Log.Error(new Exception("Fake Error 2"));
        }

    }
}

Output from button1_Click:

DEBUG   2015-12-07 13:11:05.618 [9] Test.Sandbox.MainWindow button1_Click() 
DEBUG   2015-12-07 13:11:05.623 [9] Test.Sandbox.MainWindow button1_Click() button1 Clicked
DEBUG   2015-12-07 13:11:05.623 [9] Test.Sandbox.MainWindow button1_Click() Fake Error Occured
System.Exception: Fake Error

Output from button2_Click:

ERROR   2015-12-07 13:11:07.033 [9] Test.Sandbox.MainWindow button2_Click()  in C:\Projects\Test.NET\Test.Sandbox\MainWindow.xaml.cs
ERROR   2015-12-07 13:11:07.034 [9] Test.Sandbox.MainWindow button2_Click() This is an Error in C:\Projects\Test.NET\Test.Sandbox\MainWindow.xaml.cs
ERROR   2015-12-07 13:11:07.034 [9] Test.Sandbox.MainWindow button2_Click() Fake Error 2 in C:\Projects\Test.NET\Test.Sandbox\MainWindow.xaml.cs
System.Exception: Fake Error 2

Output Folder Structure:

Folders


Logger Configurable Properties:

Setting these properties will automatically update the logger.config.xml file associated with the Entry-Assembly (& type)

Log.Config.AppendToFile = true;
Log.Config.Level = Level.Debug;
Log.Config.LogPattern = "%-5level %date %message";
Log.Config.MaxLogFiles = 5;
Log.Config.MaxLogSizeInMB = 5;

To-Do:

  1. (Performance Improvement) Find an alternate way of getting CallingMethod.DeclaringType without using StackTrace on Log.Debug(), Log.Info() and Log.Warn() messages.
  2. Collect additional StackTrace info for Log.Error() and Log.Fatal()
  3. Multiple Appender Support
  4. Configurable output folder paths
  5. Implement PatternBuilder class & interface

Upvotes: 1

Related Questions