在解决方案中跨多个程序集使用相同的Log4net记录器的最佳模式是什么?

在解决方案中跨多个程序集使用相同的Log4net记录器的最佳模式是什么?,log4net,projects-and-solutions,Log4net,Projects And Solutions,我有一个解决方案,包括一个主要的winforms应用程序,以及相关的内部编写的类库dll,我希望从中登录。无论主UI客户端或关联的dll是否调用此日志,此日志都应由同一个记录器执行。当然,dll可能会被其他解决方案中具有不同记录器的其他应用程序使用,但在这些情况下,会有不同的log4net配置,可能会有不同的Appender套件 一种方法是在主应用程序中创建一个单例并从中记录,但是由于log4net是它自己的单例,只要我们将相同的字符串(或类型)传递给log4net.LogManager.Get

我有一个解决方案,包括一个主要的winforms应用程序,以及相关的内部编写的类库dll,我希望从中登录。无论主UI客户端或关联的dll是否调用此日志,此日志都应由同一个记录器执行。当然,dll可能会被其他解决方案中具有不同记录器的其他应用程序使用,但在这些情况下,会有不同的log4net配置,可能会有不同的Appender套件

一种方法是在主应用程序中创建一个单例并从中记录,但是由于log4net是它自己的单例,只要我们将相同的字符串(或类型)传递给
log4net.LogManager.GetLogger,就可以引用它,我们将记录到相同的目的地(在我的情况下,我希望使用RollingFileAppender)

这很有效。然而,由于DLL将有许多类,这意味着我们希望从中记录的每个类实例化或静态类将需要i)定义记录器名称的参数(以便记录到相同的目标),ii)在每个入口点需要调用
log4net.LogManager.GetLogger(loggerName)

这里使用的最佳模式是什么?正确的方法是在每个程序集中创建一个单例实例吗?我在这里担心的是,我们仍然需要将记录器名称传递给dll的每个入口点,这似乎有些过分。为了避免传入记录器名称,我可以假设它始终等于
System.Reflection.Assembly.GetCallingAssembly().GetName().name

如果这对log4net来说太难了,还有其他更简单的解决方案,比如企业日志块吗? 或者最好的解决方案是面向方面编程(AOP)方法


我想你可以在app.config中使用loggerName


我可以问一下为什么整个应用程序的loggerName必须相同吗?

我们采用了一种与此类似的方法来使用log4net

我们在主应用程序和类库程序集中都使用log4net。我们围绕它编写了一个包装器类,这样所有日志都会以相同的配置出现在我们调用它的任何地方,同时也确保它是一个单例。这个包装器类在我们的应用程序中随处可见


因此,类库和主应用程序都以相同的配置注销到相同的日志文件,这正是我们想要的。这就是您试图实现的目标吗?

首先,您应该创建一个包装类(将您的应用程序与日志提供商分离)

此包装器类可以采用记录器标识符。如果您使用的是IoC容器,那么只需插入记录器的名称或现有的预配置实例

如果您使用的是Unity(其他容器也类似),您可以执行以下操作

// During application initialization
IUnityContainer myContainer = new UnityContainer();
LoggingService concreteLoggingService = new LoggingService( "logID" );
myContainer.RegisterInstance<ILoggingService>( concreteLoggingService );

// This would be injected, so you wouldn't see this, but it's here for consistency
ILoggingService loggingService = myContainer.Resolve<ILoggingService>();
loggingService.LogMessage( "message" );
//在应用程序初始化期间
IUnityContainer myContainer=新的UnityContainer();
LoggingService concreteLoggingService=新的LoggingService(“logID”);
myContainer.RegisterInstance(具体记录服务);
//这将被注入,所以你不会看到这个,但它在这里的一致性
ILoggingService loggingService=myContainer.Resolve();
loggingService.LogMessage(“消息”);
现在,假设您有一个IoC容器。您也可以创建服务定位器:

// During application initialization
ServiceLocator.Register<ILoggingService>( new LoggingService( "logID" ) );

// Retrieved as needed
ILoggingService loggingServce = LoggingServiceLocator.Locate<ILoggingService>();
loggingService.LogMessage( "message" );
//在应用程序初始化期间
ServiceLocator.Register(新的LoggingService(“logID”));
//根据需要检索
ILoggingService loggingServce=LoggingServiceLocator.Locate();
loggingService.LogMessage(“消息”);

在第二种情况下,您需要编写所有管道代码。有了IoC容器,你就可以开箱即用了。

如何实现你自己的,这样你就可以在整个应用程序中使用Trace.Write了?

差不多一年后,但我想我还是会有所贡献的

根据您对Carl帖子的评论,我认为您可能误解了log4net的工作原理。是的,loggername确实标识了记录器。是的,记录器可以有许多附加器。但是,许多记录器也可以向同一个appender写入数据。因此,您可以将记录器“A”、“B”和“C”配置为所有日志文件“X”。你可以像这样找到伐木工人:

ILog logger_a = LogManager.GetLogger("A");
ILog logger_b = LogManager.GetLogger("B");
ILog logger_c = LogManager.GetLogger("C");
现在,如果您使用这些记录器中的任何一个进行登录,如果您以这种方式配置它们,它们都可以转到同一个位置(文件“X”)

在整个应用程序中不使用相同记录器名称的优点是,您可以通过配置文件控制应用程序中不同位置的日志记录级别。因此,如果使用记录器“A”和“B”的代码工作正常,但使用记录器“C”的代码出现问题,则可以关闭“A”和“B”,然后一直向上打开“C”。这样一来,你就没有那么多的信息需要挖掘才能找到你的问题

大多数人(或者至少大多数log4net示例)实际上为每个类创建一个静态记录器实例,以该类命名(我不记得确切的语法,但很容易找到示例)。这为控制日志提供了非常高的粒度级别

在app.config文件中,您可以通过配置一个名为“*”的记录器来控制同一级别的所有记录器,也可以配置特定记录器(使用完全限定的typename),甚至可以通过部分完全限定的typename进行配置。例如,您可以很容易地使命名空间ABC中的所有类都在“info”级别记录,命名空间DEF中的所有类都在“error”级别记录,命名空间GHI中的所有类都不记录。所有这些记录器都可以登录到相同的目标(例如文件X)


可能已经太晚了,无法提供帮助,但可能不是…

我从未见过比log4net更具意义的使用模式:

在任何需要日志记录的类上,执行以下操作:

private static ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
在host layers AssemblyInfo.cs中,执行以下操作:

[assembly: log4net.Config.XmlConfigurator]
<