19

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

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

4

5 回答 5

14

log4net-user邮件列表有一个适用于 RollingFileAppender 的答案。将以下行添加到 log4net.config 中的 appender:

<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
于 2009-08-25T18:35:26.170 回答
9

虽然这个问题已经有好几年了 - 也许它可以帮助某人:

可以使用在父 AppDomain 中配置的记录器。需要做的是将LoggingEvents从子AppDomain路由到父AppDomain。为此,您需要创建一个自定义 Appender,将记录转发出子域...

/// <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的 s ...

/// <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 加载)

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

于 2014-04-24T13:41:53.610 回答
5

记录器应在每个应用程序域中初始化一次。

于 2009-07-07T09:17:06.223 回答
3

同意darin,每个应用程序域一次。如果您希望这些应用程序使用合并日志记录,您将需要选择不会受到争用的日志记录目标(即不是 FileAppender 或 RollingFileAppender)。

于 2009-07-07T12:29:31.523 回答
1

我的回答增加了 Linky 的回答。

要回答,杰克艾伦的问题。您可以通过解决更改 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

当前版本的 .... 有一个缺陷导致所有附加程序记录消息,这就像破坏了 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);
    }
}

这会将日志分发给日志管理器,这将找出日志的放置位置、负责的记录器等。

于 2018-02-19T12:02:46.597 回答