log4net:运行时不同文件appender上的不同日志

 try 发布于 2023-02-04 19:42

早上好家伙.

我写了一个单一的C#2.0应用程序(称之为myapp).
Myapp被多次调用,并且在每次调用时都会生成一种将在分离的线程中执行的"任务".
如果您在短时间内多次调用myapp,则任务将并行执行.

通常我使用log4net进行日志记录; 我配置它XmlConfigurator.Configure(.xml)在启动时加载一个xml文件,然后我LogManager.GetLogger(name)在每个需要记录器的类中使用static ,非常简单.

相反,这种情况具有挑战性.我需要做的是:根据每次调用收到的args之一(称之为arg),我需要获得一个不同的RollingFileAppender,它记录在不同的文件中,例如.log.

举个例子:

第一次调用:myapp.exe -arg:01
- myapp创建thread1
- 将一个新的RollingFileAppender设置为01.log文件,如果不存在
- 该线程中使用的对象必须登录01.log文件

第二次调用:myapp.exe -arg:02
- 创建thread2
- 将一个新的RollingFileAppender设置为02.log文件,如果不存在
- 该线程中使用的对象必须登录02.log文件,但不能登录到log.01

第3次调用:myapp.exe -arg:01
- 创建thread03
- 将RollingFileAppender获取到01.log文件(它已经存在!)
- 此线程中使用的对象必须登录01.log文件,但不能登录到log.02

等等.我不需要将RollingAppender的配置保留在xml文件中,我可以通过编程方式创建它; 我的想法是使用一个静态包装器类,称之为LogHelper,如果基于arg不存在则创建appender ,并且当对象需要时(在类中我会使用类似的东西ILog log = LogHelper.GetLogger(name, arg)调度正确的ILog,以获取记录器使用而不是默认的log4net方法LogManager.GetLogger(name)).因此,如果我在2个不同的线程中有2个相同类的istances,当我记录每个文件的消息时,取决于或者arg(如果需要,我将在每个对象中注入arg).

我在StackOverflow中浏览了很多线程,但我找不到解决方案.

有人能指出我正确的方向吗?

提前致谢.

1 个回答
  • 我最终得到了一个略有不同的解决方案.
    我创建了一个LogMaster类似于默认log4net LogManager类的静态类(对于可怜的名字而言).
    不同之处在于您可以ILog根据以下内容获得不同的结果arg:LogMaster将为您将使用的ILoggerRepository每个不同创建一个新的arg.

    这里的代码:

    #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
        }
    }
    

    用法:

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

    使用此解决方案,您可以从检索ILog记录器的默认LogManager行为中受益:如果存储库中已存在具有相同名称的记录器,您将获得该等记录(回收行为).

    谢谢@ making3的建议!

    2023-02-04 19:44 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有