log4net: different logs on different file appenders at runtime

后端 未结 2 1015
时光说笑
时光说笑 2021-02-15 02:52

Good morning guys.

I wrote a single istance C# 2.0 app (call it myapp).
Myapp is called many times, and at every call generates a sort of \"task\" that will

相关标签:
2条回答
  • 2021-02-15 03:29

    I've done something similar, where I needed a different log for every instance of a class. You can create logs dynamically with a few steps.

    It looks like a default Logger (Line 97) is already defined, but it's internal to their assembly, so it will need to be inherited (as far as I know).

    public sealed class DynamicLogger : Logger 
    { 
        internal DynamicLogger(string name) : base(name) 
        { 
            base.Hierarchy = (log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository();
        } 
    }
    

    Sample method to retrieve an ILog:

    public static ILog GetSample(string arg)
    {
        var logger = new DynamicLogger(arg);
        logger.Level = Level.All;
    
        var consoleAppender = new ConsoleAppender();
        consoleAppender.Name = arg;
        consoleAppender.Layout = new PatternLayout(arg + ": %m%newline");
        logger.AddAppender(consoleAppender);
    
        var newLog = new LogImpl(logger);
        if (_logs.Any(log => log.Logger.Name == newLog.Logger.Name) == false)
            _logs.Add(newLog);
    
        return newLog;
    }
    

    Basic usage:

    var foo = DynamicLog.GetSample("foo");
    var bar = DynamicLog.GetSample("bar");
    foo.Error("Test");
    bar.Error("Test");
    

    For your scenario, look at creating a RollingFileAppender, and look at the available properties on the object, since this was just an example.

    EDIT: Added the below for storing ILog's, and modified the original GetSample method above.

    Add an array of ILog's and a GetLogger method:

    private static List<ILog> _logs = new List<ILog>();
    
    public static ILog GetLogger(string name)
    {
        return _logs.SingleOrDefault(a => a.Logger.Name == name);
    }
    

    Sample usage:

    DynamicLog.GetSample("foo");
    var foo = DynamicLog.GetLogger("foo");
    
    0 讨论(0)
  • 2021-02-15 03:30

    I ended up with a slightly different solution.
    I created a LogMaster static class (sorry for poor name) that work similar to the default log4net LogManager class.
    The difference is that you can get different ILog istances based on arg: LogMaster will create a new ILoggerRepository for each different arg you will use.

    Here the code:

    #region Usings
    using System;
    using System.IO;
    
    using log4net;
    using log4net.Appender;
    using log4net.Config;
    using log4net.Core;
    using log4net.Filter;
    using log4net.Layout;
    using log4net.Repository;
    using log4net.Repository.Hierarchy;
    
    
    #endregion
    
    
    namespace Common.Voyager
    {
        /// <summary>
        /// A static class that emulates defualt log4net LogManager static class.
        /// The difference is that you can get various loggers istances based from an args.
        /// LogMaster will create a different logger repository for each new arg it will receive.
        /// </summary>
        public static class LogMaster
        {
            #region Const
            private const string RollingFileAppenderNameDefault = "Rolling";
            private const string MemoryAppenderNameDefault = "Memory";
            #endregion
    
    
            #region Constructors
            static LogMaster()
            {
            }
            #endregion
    
    
            #region Public Methods
            public static ILog GetLogger(string arg, string name)
            {
                //It will create a repository for each different arg it will receive
                var repositoryName = arg;
    
                ILoggerRepository repository = null;
    
                var repositories = LogManager.GetAllRepositories();
                foreach (var loggerRepository in repositories)
                {
                    if (loggerRepository.Name.Equals(repositoryName))
                    {
                        repository = loggerRepository;
                        break;
                    }
                }
    
                Hierarchy hierarchy = null;
                if (repository == null)
                {
                    //Create a new repository
                    repository = LogManager.CreateRepository(repositoryName);
    
                    hierarchy = (Hierarchy)repository;
                    hierarchy.Root.Additivity = false;
    
                    //Add appenders you need: here I need a rolling file and a memoryappender
                    var rollingAppender = GetRollingAppender(repositoryName);
                    hierarchy.Root.AddAppender(rollingAppender);
    
                    var memoryAppender = GetMemoryAppender(repositoryName);
                    hierarchy.Root.AddAppender(memoryAppender);
    
                    BasicConfigurator.Configure(repository);
                }
    
                //Returns a logger from a particular repository;
                //Logger with same name but different repository will log using different appenders
                return LogManager.GetLogger(repositoryName, name);
            }
            #endregion
    
    
            #region Private Methods
            private static IAppender GetRollingAppender(string arg)
            {
                var level = Level.All;
    
                var rollingFileAppenderLayout = new PatternLayout("%date{HH:mm:ss,fff}|T%2thread|%25.25logger|%5.5level| %message%newline");
                rollingFileAppenderLayout.ActivateOptions();
    
                var rollingFileAppenderName = string.Format("{0}{1}", RollingFileAppenderNameDefault, arg);
    
                var rollingFileAppender = new RollingFileAppender();
                rollingFileAppender.Name = rollingFileAppenderName;
                rollingFileAppender.Threshold = level;
                rollingFileAppender.CountDirection = 0;
                rollingFileAppender.AppendToFile = true;
                rollingFileAppender.LockingModel = new FileAppender.MinimalLock();
                rollingFileAppender.StaticLogFileName = true;
                rollingFileAppender.RollingStyle = RollingFileAppender.RollingMode.Date;
                rollingFileAppender.DatePattern = ".yyyy-MM-dd'.log'";
                rollingFileAppender.Layout = rollingFileAppenderLayout;
                rollingFileAppender.File = string.Format("{0}.{1}", "log", arg);
                rollingFileAppender.ActivateOptions();
    
                return rollingFileAppender;
            }
    
            private static IAppender GetMemoryAppender(string station)
            {
                //MemoryAppender
                var memoryAppenderLayout = new PatternLayout("%date{HH:MM:ss} | %message%newline");
                memoryAppenderLayout.ActivateOptions();
    
                var memoryAppenderWithEventsName = string.Format("{0}{1}", MemoryAppenderNameDefault, station);
                var levelRangeFilter = new LevelRangeFilter();
                levelRangeFilter.LevelMax = Level.Fatal;
                levelRangeFilter.LevelMin = Level.Info;
    
                var memoryAppenderWithEvents = new MemoryAppenderWithEvents();
                memoryAppenderWithEvents.Name = memoryAppenderWithEventsName;
                memoryAppenderWithEvents.AddFilter(levelRangeFilter);
                memoryAppenderWithEvents.Layout = memoryAppenderLayout;
                memoryAppenderWithEvents.ActivateOptions();
    
                return memoryAppenderWithEvents;
            }
            #endregion
        }
    }
    

    Usage:

    var arg = "myArg";
    var loggerName = "MyLogger";
    var log = LogMaster.GetLogger(arg, loggerName);
    

    Using this solution you can benefit from default LogManager behavior retrieving ILog loggers: if a logger with the same name already exists in a repository, you will get back that istance (recycling behavior).

    Thank you @making3 for your suggestions!

    0 讨论(0)
提交回复
热议问题