跨appdomains的log4net

Yar*_*veh 17 log4net appdomain

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

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

Mic*_*rry 12

log4net的用户邮件列表中有与RollingFileAppender进行问题的解答.将以下行添加到log4net.config中的appender:

<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
Run Code Online (Sandbox Code Playgroud)


Lin*_*nky 9

虽然这个问题已经有几年了 - 但它可能对某人有所帮助:

可以使用父AppDomain中配置的记录器.需要做的是将LoggingEvents从子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);
    }
}
Run Code Online (Sandbox Code Playgroud)

,一个自定义类,它接收转发的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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

最后一个绑定两个并配置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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在 - 当你设置你的AppDomain时,你可以添加以下代码......

CrossDomainParentAppender crossDomainParentAppender = new CrossDomainParentAppender();
Type crossDomainType = typeof(CrossDomainChildLoggingSetup);
CrossDomainChildLoggingSetup crossDomainChildLoggingSetup = (CrossDomainChildLoggingSetup)domain.CreateInstanceFrom(crossDomainType.Assembly.Location, crossDomainType.FullName).Unwrap();
crossDomainChildLoggingSetup.ConfigureAppender(crossDomainParentAppender);
Run Code Online (Sandbox Code Playgroud)

...并且子域中记录的所有内容都会显示在父域日志中.(请注意:我使用过CreateInstaceFrom(assemblyFilePath,...)- 根据您的设置,您可能不需要通过filePath加载)

虽然我没有发现任何错误或问题:如果您发现任何可能出现的缺陷或问题,请告诉我.

  • 如果我可以建议改进 - 而不是BasicConfigurator.Configure(outputAppender),则更改为以下内容以获取父域配置:var hierarchy =(Hierarchy)LogManager.GetRepository(); hierarchy.Root.AddAppender(outboundAppender); hierarchy.Configured = true; (2认同)

Dar*_*rov 5

应该为每个app-domain初始化一次记录器.