使用共享程序集时如何配置log4net?

使用共享程序集时如何配置log4net?,log4net,log4net-configuration,Log4net,Log4net Configuration,使用共享程序集时如何配置log4net 我有多个依赖于公共组件的组件。每个组件都位于其自己的部件中。所有组件都使用log4net进行日志记录。所有组件都加载到单个进程空间中,但组件的使用顺序不同。所有外部组件在第一次使用时加载各自的log4net配置,以尝试将日志数据发送到它们的服务器。公共组件不加载任何配置。此外,还有一个遗留组件不使用公共组件。第一次使用时,它也会超出并加载其配置。我无法直接接触此旧组件的代码或配置 我面临的问题是,由于组件在第一次使用时加载其配置,最后加载配置的人获胜。这会

使用共享程序集时如何配置log4net

我有多个依赖于公共组件的组件。每个组件都位于其自己的部件中。所有组件都使用log4net进行日志记录。所有组件都加载到单个进程空间中,但组件的使用顺序不同。所有外部组件在第一次使用时加载各自的log4net配置,以尝试将日志数据发送到它们的服务器。公共组件不加载任何配置。此外,还有一个遗留组件不使用公共组件。第一次使用时,它也会超出并加载其配置。我无法直接接触此旧组件的代码或配置

我面临的问题是,由于组件在第一次使用时加载其配置,最后加载配置的人获胜。这会导致日志记录发生,但所有日志输出最终都会进入加载的最后一个配置。显然,查看日志文件并将其他组件的日志条目写入其中是很难看的

我通过使用RepositoryAttribute和AliasRepositoryAttribute找到了一个部分解决方案。允许外部组件将其配置加载到其“记录器存储库”中,并有效地将它们彼此隔离。遗留组件现在可以愉快地写入自己的日志,而不会受到我的组件的干扰,我的组件也可以愉快地写入自己的日志,而不会在其他日志中产生干扰

我说的是部分解决方案,因为仍然存在通用组件的日志记录情况。使用AliasRepositoryAttribute时,加载的第一个组件将为公共组件添加别名,即使它是调用公共组件的另一个组件,也会获得所有日志输出。这很糟糕,因为在后面的组件中我将丢失重要的日志信息,而在第一个日志中我将有不相关的日志信息

以下代码演示了该问题:

公共:(替代公共组件)

使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用log4net;
使用log4net.Config;
[程序集:存储库(“CommonLib”)]
命名空间公共库
{
公共类公共类
{
静态只读ILog Log=LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
公共void docomon(来自的字符串)
{
Log.Debug(“docomon:+from”);
}
}
}
库A:(替代其中一个出口组件)

使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Xml;
使用CommonLib;
使用log4net;
使用log4net.Config;
[大会:储存库(“ALib”)]
[程序集:别名存储库(“CommonLib”)]
名称空间ALib
{
公共静态类LogPrep
{
静态bool_loaded=false;
公共静态void())
{
如果(_已加载)
返回;
var doc=新的XmlDocument();
doc.LoadXml(
@"
");
XmlConfigurator.Configure(doc.DocumentElement);
_加载=真;
}
}
公共类AClass
{
静态只读ILog Log=LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
公共无效DoA()
{
LogPrep.sure();
Log.Debug(“DoA”);
var common=新的CommonClass();
common.DoCommon(“A”);
}
}
}
库B:(替代另一个出口组件)

使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Xml;
使用CommonLib;
使用log4net;
使用log4net.Config;
[汇编:存储库(“BLib”)]
[程序集:别名存储库(“CommonLib”)]
名称空间BLib
{
公共类B类
{
静态只读ILog Log=LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
公共静态类LogPrep
{
静态bool_loaded=false;
公共静态void())
{
如果(_已加载)
返回;
var doc=新的XmlDocument();
doc.LoadXml(
@"
");
XmlConfigurator.Configure(doc.DocumentElement);
_加载=真;
}
}
公屋空置日期(
{
LogPrep.sure();
Log.Debug(“DoB”);
var common=新的CommonClass();
普通文件(“B”);
}
}
}
可执行容器:(旧组件的代理)

使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Xml;
使用System.Xml.Linq;
使用ALib;
使用BLib;
使用log4net;
使用log4net.Config;
命名空间TestLog4NetRepositories
{
班级计划
{
private static readonly ILog Log=LogManager.GetLogger(typeof(Program));
静态void Main(字符串[]参数)
{
//设置一个在控制台上登录的简单配置。
var doc=新的XmlDocument();
doc.LoadXml(
@"
");
XmlConfigurator.Configure(doc.DocumentElement);
Log.Info(“输入应用程序”);
var a=新的AClass();
a、 DoA();
var b=新的b类();
b、 DoB();
Log.Info(“退出应用程序”);
}
}
}
如果运行此代码,请注意Common的输出将以绿色打印,而不会以红色打印

log4net: Creating repository [BLib] using type [log4net.Repository.Hierarchy.Hierarchy]
log4net:ERROR Failed to alias repository [CommonLib] System.InvalidOperationException: Repository [CommonLib] is already aliased to repository [ALib]. Aliases cannot be redefined.
    at log4net.Core.DefaultRepositorySelector.AliasRepository(String repositoryAlias, ILoggerRepository repositoryTarget)
    at log4net.Core.DefaultRepositorySelector.LoadAliases(Assembly assembly, ILoggerRepository repository)
尽管上面的可执行容器显示