Вопрос по log4net, appdomain – log4net через домены приложений

16

У меня есть приложение, которое инициализирует log4net из одного домена приложений и должен использовать его в другом домене приложений. Это поддерживается?

Если нет, я должен инициализировать log4net из каждого домена приложения? Есть ли риск в нескольких инициализациях в одном приложении? Должен ли я использовать тот же log4net.config?

Ваш Ответ

5   ответов
3

Согласитесь с Дарином, один раз за домен приложения. Если вы хотите, чтобы эти приложения использовали консолидированное ведение журнала, вам нужно выбрать цель ведения журнала, которая не будет предметом конкуренции (то есть не FileAppender или RollingFileAppender).

11

log4net-пользователь В списке рассылки есть ответ, который работает с RollingFileAppender. Добавьте следующую строку для appender в log4net.config:

<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
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

В текущей версии .... есть недостаток, который заставляет всех участников регистрировать сообщения, например, побеждать цель 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);
    }
}

Это распределяет журнал в диспетчер журналов, выясняет, где разместить журнал, какой регистратор отвечает и т.д.

9

Хотя вопрос уже несколько лет - может, кому-то это поможет

Можно использовать регистраторы, настроенные в родительском домене приложений. Что нужно сделать, это направитьLoggingEvents от дочернего домена приложений до родительского домена приложений. Для этого вам нужно создать пользовательский 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с ...

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

Теперь - когда вы настраиваете свой домен приложений, вы можете добавить следующий код ...

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)

Хотя я не нашел никаких ошибок или проблем: Если вы видите какие-либо недостатки или проблемы, которые могут возникнуть, пожалуйста, дайте мне знать.

Это замечательно, но, кажется, теряет имя метода в журналах, просто показывает? вместо
Именно тот подход, который я искал. Спасибо.
Если я могу предложить улучшение - вместо BasicConfigurator.Configure (outputAppender), изменив на следующее, чтобы выбрать конфигурацию родительского домена: varierarchy = (Hierarchy) LogManager.GetRepository (); hierarchy.Root.AddAppender (outboundAppender); ierarchy.Configured = true;
Вы получили RemotingException при использовании этого? Я получу исключение, в котором будет сказано: «Объект» /a0720457_c9e6_4edf_bde5_86d96058cb4e/+mauuadzzsfpiaad3bjv4uss_264.rem' был отключен или не существует на сервере. & quot; который я считаю из-за сбора мусора. Любые идеи о том, как это исправить?
Я понял. Я переопределил CrossDomainChildLoggingSetup.InitializeLifetimeService, чтобы вернуть значение null, поскольку в каждом домене приложения только один, и он очищается при выгрузке AppDomain. Затем я реализовал ISponsor для обработки времени жизни CrossDomainParentAppender и использовал этот код для его инициализации: var sponsor = new MySponsor (this, k); var lease = (ILease) RemotingServices.GetLifetimeService (crossDomainParentAppender); lease.Register (спонсор);
5

.

Не приведет ли это к проблемам с блокировкой, когда два регистратора пытаются добавить один и тот же файл?

Похожие вопросы