log4net:运行时在不同文件追加器上的不同日志 [英] log4net: different logs on different file appenders at runtime

查看:73
本文介绍了log4net:运行时在不同文件追加器上的不同日志的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

早上好.

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

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 be executed in a separated thread.
If you call myapp several times in a short time, task are executed in parallel.

通常,我将log4net用于日志记录目的.我将其配置为在启动时通过XmlConfigurator.Configure(<config>.xml)加载xml文件,然后在需要记录器的每个类中都使用静态LogManager.GetLogger(name),非常简单.

Generally I use log4net for logging purposes; I configure it loading an xml file by XmlConfigurator.Configure(<config>.xml) at startup, then I use static LogManager.GetLogger(name) in every class I need a logger, quite simple.

相反,这种情况具有挑战性. 我需要做的是:根据每次调用收到的args之一(将其称为 arg ),我需要获取另一个登录不同文件的 RollingFileAppender , G. .log.

This scenario is challenging, instead. I need to do is this: based on one of the args received on every call (call it arg), I need to get a different RollingFileAppender that logs in a different file, e. g. .log.

仅举一个例子:

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

1st call: myapp.exe -arg:01
- myapp creates thread1
- set a new RollingFileAppender to 01.log file, if not exists
- objects used in this thread must log in 01.log file

第2次通话:myapp.exe -arg:02
-创建thread2
-将新的RollingFileAppender设置为02.log文件(如果不存在的话)
-此线程中使用的对象必须登录02.log文件,但不能登录log.01

2nd call: myapp.exe -arg:02
- create thread2
- set a new RollingFileAppender to 02.log file, if not exists
- objects used in this thread must log in 02.log file, but not in log.01

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

3rd call: myapp.exe -arg:01
- create thread03
- get the RollingFileAppender to 01.log file (it already exists!)
- objects used in this thread must log in 01.log file, but not in log.02

以此类推. 我不需要将RollingAppender的配置保留在xml文件中,可以通过编程方式创建它;我的想法是使用一个静态包装器类,称为LogHelper,它会基于 arg 创建不存在的附加程序,并在对象需要时分派正确的ILog距离(在类中,我会使用某些东西例如ILog log = LogHelper.GetLogger(name, arg),以使记录器代替默认的log4net方法LogManager.GetLogger(name))使用. 因此,如果我在2个不同的线程中有2个相同类的距离,则当我记录消息时,每个文件都记录一个,具体取决于 arg (我将在每个对象中注入 arg ,如果需要).

And so on. I don't need to leave the configuration of RollingAppender in xml file, I can create it programmatically; my idea is to use a static wrapper class, call it LogHelper, that creates appenders if they do not exist based on arg, and that dispatch right ILog istances when needed by objects (in classes I would use something like ILog log = LogHelper.GetLogger(name, arg) to get a logger to use instead o default log4net method LogManager.GetLogger(name)). So if I have 2 istances of the same class in 2 different threads, when I log messages goes one per file, depending or arg (I will inject arg in every object, if needed).

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

I browse many threads here in StackOverflow, but I can't find a solution.

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

Can someone point me to the right direction?

谢谢.

推荐答案

我最终得到了一个略有不同的解决方案.
我创建了一个LogMaster静态类(对不起的名字不好意思),它的工作方式类似于默认的log4net LogManager类.
区别在于您可以基于arg获得不同的ILog距离:LogMaster将为将要使用的每个不同的arg创建一个新的ILoggerRepository.

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.

代码在这里:

#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);

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

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).

谢谢@ making3的建议!

Thank you @making3 for your suggestions!

这篇关于log4net:运行时在不同文件追加器上的不同日志的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆