跨appdomains的log4net

时间:2009-07-07 09:14:51

标签: log4net appdomain

我有一个应用程序,它从一个appdomain初始化log4net,需要在另一个appdomain中使用它。是否支持?

如果没有,我应该从每个appdomain初始化log4net吗?在同一个应用程序中进行多次初始化是否存在风险?我应该使用相同的log4net.config吗?

5 个答案:

答案 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,这将找出放置日志的位置,哪个记录器负责等。