2009-07-07 12 views
15

Tengo una aplicación que inicializa log4net de un dominio de aplicación y necesita usarlo en otro dominio de aplicación. ¿Es compatible?log4net across appdomains

En caso negativo, ¿debo inicializar log4net de cada dominio de aplicación? ¿Hay un riesgo en inicializaciones múltiples en la misma aplicación? ¿Debería usar el mismo log4net.config?

Respuesta

10

La lista de correo log4net-user tiene una respuesta que funciona con RollingFileAppender. Agregue la línea siguiente a la appender en log4net.config:

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

El registrador debe inicializarse una vez por dominio de aplicación.

+0

¿No causaría problemas de bloqueo cuando dos registradores intentan agregar al mismo archivo? – Bartosz

3

De acuerdo con darin, una vez por dominio de aplicación. Si está buscando que estas aplicaciones utilicen el registro consolidado, querrá elegir un objetivo de registro que no esté sujeto a contención (es decir, no FileAppender o RollingFileAppender).

7

Aunque la cuestión es de varios años - tal vez ayude a alguien:

Es posible utilizar los registradores configurados en el dominio de aplicación de los padres. Lo que se debe hacer es encaminar el LoggingEvent s desde el AppDomain hijo al Dominio de aplicación padre. Para ello, tiene que crear un Appender de encargo que envía los registros de dominio secundario ...

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

, una clase personalizada que recibe el LoggingEvent remitido y los añade a IAppender disponibles 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); 
     } 
    } 
} 

y finalmente una clase de instalación que une a los dos y configura 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); 
    } 
} 

ahora - al configurar su dominio de aplicación puede agregar el siguiente co de ...

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

... y todo lo que haya iniciado sesión en el dominio secundario aparece en el registro de dominios principal. (Nota: He utilizado CreateInstaceFrom(assemblyFilePath,...) - dependiendo de su configuración es posible que no requiere de carga por rutaArchivo)

Aunque no he encontrado ninguna errores o problemas: Si hay defectos o problemas que pudieran surgir por favor hágamelo saber .

+0

Exactamente el tipo de enfoque que estaba buscando. Gracias. –

+2

Si puedo sugerir una mejora, en lugar de BasicConfigurator.Configure (outputAppender), cambie a lo siguiente para elegir la configuración del dominio principal: var hierarchy = (Hierarchy) LogManager.GetRepository(); hierarchy.Root.AddAppender (outboundAppender); hierarchy.Configured = true; –

+0

¿Has recibido una Excepción Remoto al usar esto? Obtendré una excepción diciendo "Objeto '/a0720457_c9e6_4edf_bde5_86d96058cb4e/+mauuadzzsfpiaad3bjv4uss_264.rem' ha sido desconectado o no existe en el servidor." que creo es debido a la recolección de basura. ¿Alguna idea sobre cómo solucionar este problema? – Charlie

0

Mi respuesta se suma a la respuesta de Linky.

Para responder, la pregunta de Jack Allan. Puede resolver este resolviendo el cambio de la clase 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); 
    } 
} 

Aviso del FixFlags.All

La versión actual de la .... tiene un defecto que causa todos los appenders a registrar el mensaje, eso es como derrotando el propósito de log4net, ya que diferentes registradores pueden iniciar sesión en un nivel diferente, por ejemplo. Mi versión mejorada de la clase:

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

Esto distribuye el registro a la logmanager, esto va a saber dónde colocar el registro, que es responsable registrador etc.