早上好家伙.
我写了一个单一的C#2.0应用程序(称之为myapp).
Myapp被多次调用,并且在每次调用时都会生成一种将在分离的线程中执行的"任务".
如果您在短时间内多次调用myapp,则任务将并行执行.
通常我使用log4net进行日志记录; 我配置它XmlConfigurator.Configure(
在启动时加载一个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中浏览了很多线程,但我找不到解决方案.
有人能指出我正确的方向吗?
提前致谢.
我最终得到了一个略有不同的解决方案.
我创建了一个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的建议!