2011-08-05 18 views
9

Tengo una aplicación de servicio que al inicio lee un archivo XML e inicia un subproceso para cada entrada en el archivo XML. Cada subproceso crea una instancia de una clase de trabajador que requiere un registrador para registrar cualquier salida en un archivo de registro específico de subprocesos.Inicio de sesión en un archivo de registro individual para cada subproceso individual

En los servicios app.config tengo los ajustes de configuración log4net configurado para utilizar un appender XML y el archivo se especifica como un PatternString como se muestra abajo:

<appender name="XmlAppender" type="log4net.Appender.FileAppender"> 
    <file type="log4net.Util.PatternString" value="D:\Temp\Logs\%property{LogName}.log" /> 
    <immediateFlush value="true"/> 
    <appendToFile value="true" /> 
    <layout type="log4net.Layout.SimpleLayout" /> 
</appender> 

En un método hilo bloqueado para cada instancia de la clase trabajadora creada Obtengo el registrador usando el método log4net.LogManager.GetLogger("MyLogger") y luego configuro la propiedad actual de los hilos de la propiedad PatternStrings LogName usando ThreadContext.Properties["LogName"] = "Log name prefix".

Todos los archivos se crean pero cuando se llama al registrador, simplemente registra todos los mensajes en un archivo aparentemente aleatorio.

He buscado durante bastante tiempo tratando de encontrar una solución o algunas respuestas a lo que estoy haciendo mal, pero no he tenido suerte.

¿Alguien tiene alguna idea de por qué sucede esto?

Respuesta

12

Creo que he solucionado el problema. Los pasos siguen:

  • Cree un individuo llamado LoggerRepository en cada hilo.
  • Establezca la propiedad ThreadContexts para el nombre del archivo de registro.
  • Utilice XmlConfiguratior para configurar el repositorio.
  • Utilice LogManager para obtener el registrador con nombre (en el archivo de configuración XML) utilizando el LoggerRepository con nombre para esa cadena.

A cambio, obtengo un nuevo registrador configurado que apunta al archivo respectivo para ese hilo.

La configuración XML es el mismo que era originalmente y se muestra aquí para completar:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <configSections>  
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/> 
    </configSections> 
    <log4net> 
    <logger name="ProductionLogger"> 
     <appender-ref ref="XmlAppender"/>  
     <level value="ALL"/> 
    </logger> 
    <appender name="XmlAppender" type="log4net.Appender.FileAppender"> 
     <file type="log4net.Util.PatternString" value="D:\Temp\Logs\%property{LogName}.log" /> 
     <immediateFlush value="true"/> 
     <appendToFile value="true" /> 
     <layout type="log4net.Layout.SimpleLayout" /> 
    </appender> 
    </log4net> 
</configuration> 

El código para crear los madereros se encuentra por debajo. Cada vez que se ejecuta este código, se ejecuta en su propio hilo.

ILoggerRepository loggerRepository = LogManager.CreateRepository(logFileName + "Repository"); 
ThreadContext.Properties["LogName"] = logFileName; 
log4net.Config.XmlConfigurator.Configure(loggerRepository); 
ILog logger = LogManager.GetLogger(logFileName + "Repository", "ProductionLogger"); 

Esto parece funcionar sin problemas hasta el momento. Avanzaré con esta solución por el momento, pero actualizaré esta publicación si descubro algo más.

+1

¡Gracias! Tuve el mismo problema con el enhebrado y el inicio de sesión en diferentes archivos. Revisé muchas publicaciones y soluciones, pero solo esta me abrazó. –

+0

Muchas gracias ... Este enfoque resolvió mi problema ... – Emerson

4

La respuesta de Adam ha funcionado bastante bien para mí, pero hay una que me gustaría añadir. Si existe la posibilidad de que su logFileName se reutilice en su aplicación, deberá verificar que el repositorio aún no exista.

string repoName = String.Format("{0}Repository", logFileName); 

// Check for existing repository 
ILoggerRepository[] allRepos = LogManager.GetAllRepositories(); 
ILoggerRepository repo = allRepos.Where(x => x.Name == repoName).FirstOrDefault(); 

// If repository does not exist, create one, set the logfile name, and configure it 
if (repo == null) 
{ 
    repo = LogManager.CreateRepository(repoName); 
    ThreadContext.Properties[KEY_LOG_FILE] = logFileName; 
    log4net.Config.XmlConfigurator.Configure(repo); 
} 

// Set logger 
ILog logger = LogManager.GetLogger(repoName, logName); 
+1

Puede llamar directamente a FirstOrDefault, sin Where, como este: 'allRepos.FirstOrDefault (x => x.Name == repoName);' –

Cuestiones relacionadas