跨应用程序域的 log4net

发布于 2024-07-26 02:17:16 字数 152 浏览 5 评论 0原文

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

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

I have an application which initializes log4net from one appdomain and needs to use it in another appdomain. Is it supported?

If not, should I initialize log4net from each appdomain? Is there a risk in multiple initializations in the same application? Should I use the same log4net.config?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

我是男神闪亮亮 2024-08-02 02:17:16

log4net-user 邮件列表有一个答案与 RollingFileAppender 一起使用。 将以下行添加到 log4net.config 中的附加程序:

<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />

The log4net-user mailing list has an answer that works with RollingFileAppender. Add the following line to the appender in log4net.config:

<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
九公里浅绿 2024-08-02 02:17:16

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

可以使用父 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 加载)

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

Although the question is several years old - maybe it helps someone:

It is possible to use the loggers configured in the parent AppDomain.
What needs to be done is route the LoggingEvents from the child AppDomain to the parent AppDomain. For this you need to create a custom Appender that forwards the records out of the Child domain...

/// <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);
    }
}

, a custom class that receives the forwarded LoggingEvent and appends them to available IAppenders ...

/// <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);
        }
    }
}

and finally a setup class that ties the two and configures 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);
    }
}

Now - when you setup up your AppDomain you can add the following code...

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

...and everything logged in the child domain turns up in the parent domains log.
(Please note: I used CreateInstaceFrom(assemblyFilePath,...) - depending on your setup you may not require loading by filePath)

Although I haven't found any bugs or problems: If you see any flaws or problems that could arise please let me know.

叹梦 2024-08-02 02:17:16

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

The logger should be initialized once per app-domain.

好听的两个字的网名 2024-08-02 02:17:16

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

Agree with darin, once per app domain. If you're looking to have these applications use consolidated logging, you'll want to choose a logging target that won't be subject to contention (i.e. not FileAppender or RollingFileAppender).

恬淡成诗 2024-08-02 02:17:16

我的回答补充了 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);
    }
}

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

My answer adds to Linky 's answer.

To answer, Jack Allan 's question. You can solve this by solving the changing the CrossDomainOutboundAppender class:

/// <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);
    }
}

Notice the FixFlags.All

The current version of the .... has a flaw causing all appenders to log the message, thats like defeating the purpose of log4net, since different loggers can log at a different level for example. My improved version of the class:

/// <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);
    }
}

This distributes the log to the logmanager, this will find out where to place the log, which logger is responsible etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文