我有一个应用程序,它从一个appdomain初始化log4net,需要在另一个appdomain中使用它。是否支持?
如果没有,我应该从每个appdomain初始化log4net吗?在同一个应用程序中进行多次初始化是否存在风险?我应该使用相同的log4net.config吗?
答案 0 :(得分:12)
log4net-user邮件列表的答案适用于RollingFileAppender。将以下行添加到log4net.config中的appender:
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
答案 1 :(得分:9)
虽然这个问题已经有好几年了 - 也许对某人有所帮助:
可以使用父AppDomain中配置的记录器。
需要做的是将LoggingEvent
从子AppDomain路由到父AppDomain。为此,您需要创建一个自定义Appender,将记录转发出Child域...
/// <summary>
/// Represents an <see cref="IAppender"/> implementation that forwards a <see cref="LoggingEvent"/> to a given Receiver.
/// Instances of this class should be created in the child domain.
/// </summary>
public class CrossDomainOutboundAppender : AppenderSkeleton
{
private readonly CrossDomainParentAppender crossDomainParentAppender;
public CrossDomainOutboundAppender(CrossDomainParentAppender crossDomainParentAppender)
{
if (crossDomainParentAppender == null)
{
throw new ArgumentNullException("crossDomainParentAppender");
}
this.crossDomainParentAppender = crossDomainParentAppender;
}
protected override void Append(LoggingEvent loggingEvent)
{
LoggingEvent copied = new LoggingEvent(loggingEvent.GetLoggingEventData());
crossDomainParentAppender.Append(copied);
}
}
,一个自定义类,它接收转发的LoggingEvent并将它们附加到可用的IAppender
...
/// <summary>
/// Represents a Receiver that sends Log4Nets <see cref="LoggingEvent"/> to all available <see cref="IAppender"/>s.
/// Instances of this class should be created in the ParentDomain.
/// </summary>
[Serializable]
public class CrossDomainParentAppender : MarshalByRefObject
{
public void Append(LoggingEvent loggingEvent)
{
foreach (IAppender usedAppender in LogManager.GetRepository().GetAppenders())
{
usedAppender.DoAppend(loggingEvent);
}
}
}
最后是一个设置类,它将两者联系起来并配置log4net:
public class CrossDomainChildLoggingSetup : MarshalByRefObject
{
private CrossDomainParentAppender parentAppender;
public void ConfigureAppender(CrossDomainParentAppender crossDomainParentAppender)
{
parentAppender = crossDomainParentAppender;
CrossDomainOutboundAppender outboundAppender = new CrossDomainOutboundAppender(parentAppender);
log4net.Config.BasicConfigurator.Configure(outboundAppender);
}
}
现在 - 当您设置AppDomain时,可以添加以下代码...
CrossDomainParentAppender crossDomainParentAppender = new CrossDomainParentAppender();
Type crossDomainType = typeof(CrossDomainChildLoggingSetup);
CrossDomainChildLoggingSetup crossDomainChildLoggingSetup = (CrossDomainChildLoggingSetup)domain.CreateInstanceFrom(crossDomainType.Assembly.Location, crossDomainType.FullName).Unwrap();
crossDomainChildLoggingSetup.ConfigureAppender(crossDomainParentAppender);
...并且子域中记录的所有内容都会显示在父域日志中。
(请注意:我使用了CreateInstaceFrom(assemblyFilePath,...)
- 根据您的设置,您可能不需要通过filePath加载)
虽然我没有发现任何错误或问题:如果您发现任何可能出现的缺陷或问题,请告诉我们。
答案 2 :(得分:5)
每个app-domain应该初始化一次记录器。
答案 3 :(得分:3)
同意darin,每个app域一次。如果您希望这些应用程序使用统一日志记录,您将需要选择一个不会受到争用的日志记录目标(即不是FileAppender或RollingFileAppender)。
答案 4 :(得分:0)
我的回答增加了林吉的答案。
回答杰克艾伦的问题。您可以通过解决更改CrossDomainOutboundAppender类来解决此问题:
/// <summary>
/// Represents an <see cref="IAppender"/> implementation that forwards a <see cref="LoggingEvent"/> to a given Receiver.
/// Instances of this class should be created in the child domain.
/// </summary>
public class CrossDomainOutboundAppender : AppenderSkeleton
{
private readonly CrossDomainParentAppender crossDomainParentAppender;
public CrossDomainOutboundAppender(CrossDomainParentAppender crossDomainParentAppender)
{
if (crossDomainParentAppender == null)
{
throw new ArgumentNullException("crossDomainParentAppender");
}
this.crossDomainParentAppender = crossDomainParentAppender;
}
protected override void Append(LoggingEvent loggingEvent)
{
LoggingEvent copied = new LoggingEvent(loggingEvent.GetLoggingEventData(FixFlags.All));
crossDomainParentAppender.Append(copied);
}
}
注意FixFlags.All
当前版本的....有一个缺陷导致所有appender记录消息,这就像破坏了log4net的目的,因为不同的记录器可以记录在不同的级别,例如。我改进的班级版本:
/// <summary>
/// Represents a Receiver that sends Log4Nets <see cref="LoggingEvent"/> to all available <see cref="IAppender"/>s.
/// Instances of this class should be created in the ParentDomain.
/// </summary>
[Serializable]
public class CrossDomainParentAppender : MarshalByRefObject
{
public void Append(LoggingEvent loggingEvent)
{
LogManager.GetRepository().Log(loggingEvent);
}
}
这会将日志分发到logmanager,这将找出放置日志的位置,哪个记录器负责等。