2009-07-07 3 views
15

У меня есть приложение, которое инициализирует log4net из одного appdomain и должно использовать его в другом appdomain. Поддерживается ли это?log4net через appdomains

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

ответ

10

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

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

Регистратор должен быть инициализирован один раз для домена приложения.

+0

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

3

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

7

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

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

/// <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 вы можете добавить следующее совместное de ...

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)

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

+0

Точно такой тип подхода, который я искал. Спасибо. –

+2

Если я могу предложить улучшение - вместо BasicConfigurator.Configure (outputAppender), для перехода к конфигурации родительского домена необходимо следующее: var hierarchy = (Иерархия) LogManager.GetRepository(); hierarchy.Root.AddAppender (outboundAppender); hierarchy.Configured = true; –

+0

У вас возникло исключение RemotingException при использовании этого? Я получу исключение, если «Object» /a0720457_c9e6_4edf_bde5_86d96058cb4e/+mauuadzzsfpiaad3bjv4uss_264.rem 'был отключен или не существует на сервере. " который, я считаю, связан с сборкой мусора. Есть какие нибудь идеи как это починить? – Charlie

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

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

Смежные вопросы