2009-07-07 7 views
15

J'ai une application qui initialise log4net à partir d'un domaine et doit l'utiliser dans un autre domaine. Est-ce supporté?log4net across appdomains

Sinon, dois-je initialiser log4net à partir de chaque domaine d'application? Y a-t-il un risque dans plusieurs initialisations dans la même application? Dois-je utiliser le même fichier log4net.config?

Répondre

10

La liste de diffusion log4net-user a une réponse qui fonctionne avec RollingFileAppender. Ajoutez la ligne suivante à la appender dans log4net.config:

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

L'enregistreur doit être initialisé une fois par domaine d'application.

+0

Ne causerait-il pas des problèmes de verrouillage lorsque deux enregistreurs essaient d'ajouter au même fichier? – Bartosz

3

En accord avec darin, une fois par domaine d'application. Si vous souhaitez que ces applications utilisent la consignation consolidée, vous devez choisir une cible de consignation qui ne sera pas sujette à un conflit (c'est-à-dire, pas FileAppender ou RollingFileAppender).

7

Bien que la question est de plusieurs années - peut-être il aide quelqu'un:

Il est possible d'utiliser les enregistreurs configurés dans le AppDomain parent. Ce qui doit être fait est route le LoggingEvent de l'enfant AppDomain au parent AppDomain. Pour cela, vous devez créer un Appender personnalisé qui transmet les dossiers sur le domaine des enfants ...

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

, une classe personnalisée qui reçoit le LoggingEvent et les a transmis à votre disposition ajoute 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); 
     } 
    } 
} 

et enfin une classe d'installation qui lie les deux et configure 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); 
    } 
} 

maintenant - lorsque vous configurez votre AppDomain vous pouvez ajouter la co suivante de ...

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

... et tout ce qui est enregistré dans le domaine enfant apparaît dans le journal des domaines parents. (S'il vous plaît noter: je CreateInstaceFrom(assemblyFilePath,...) - en fonction de votre configuration, vous ne pouvez pas exiger le chargement par filePath)

Bien que je ne l'ai pas trouvé de bugs ou problèmes: Si vous constatez des défauts ou des problèmes qui pourraient se poser s'il vous plaît laissez-moi savoir .

+0

Exactement le type d'approche que je cherchais. Je vous remercie. –

+2

Si je peux suggérer une amélioration - au lieu de BasicConfigurator.Configure (outputAppender), en passant à la suivante pour récupérer la configuration du domaine parent: var hierarchy = (Hierarchy) LogManager.GetRepository(); hierarchy.Root.AddAppender (outboundAppender); hierarchy.Configured = true; –

+0

Avez-vous obtenu une RemotingException en utilisant ceci? J'obtiendrai une exception disant que "Object '/a0720457_c9e6_4edf_bde5_86d96058cb4e/+mauuadzzsfpiaad3bjv4uss_264.rem' a été déconnecté ou n'existe pas sur le serveur." ce que je crois est à cause de la collecte des ordures. Des idées pour résoudre le problème? – Charlie

0

Ma réponse ajoute à la réponse de Linky.

Répondre à la question de Jack Allan. Vous pouvez résoudre ce problème en résolvant le changement de la classe 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); 
    } 
} 

Notez que le FixFlags.All

La version actuelle du .... a un défaut entraînant tous appenders pour enregistrer le message, thats comme vaincre le but de log4net, puisque différents enregistreurs peuvent se connecter à un niveau différent par exemple. Ma version améliorée de la classe:

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

Cela distribue le journal au logmanager, cela savoir où placer le journal, qui est responsable de l'enregistreur, etc.

Questions connexes