2011-05-31 20 views
17

Actualmente estoy ejecutando un servicio de Windows que crea varias instancias de una clase.Archivo de registro único para cada instancia de la clase

En la parte superior de la clase de servicio y todas las demás clases en mi solución, tener algo como esto:

private static readonly ILog _log = LogManager.GetLogger(typeof(SomeClassTypeHere)); 

En mi App.config, tengo Log4net configurado para un solo archivo:

<log4net debug="true"> 
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"> 
     <file value="Logs\SomeLogFileName.xml" /> 
     <appendToFile value="true" /> 
     <rollingStyle value="Size" /> 
     <countDirection value="1" /> 
     <maxSizeRollBackups value="30" /> 
     <maximumFileSize value="10MB" /> 
     <staticLogFileName value="true" /> 
     <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> 
     <layout type="log4net.Layout.XmlLayoutSchemaLog4j"> 
     <locationInfo value="true" /> 
     </layout> 
    </appender> 

    <root> 
     <level value="INFO" /> 
     <appender-ref ref="RollingFileAppender" /> 
    </root> 
    </log4net> 

Esto funciona muy bien en la mayoría de los aspectos, y todo se registra en un único archivo. Sin embargo, me gustaría crear un archivo de registro separado para cada instancia de una clase en particular que crea mi servicio.
Esta es una clase que a menudo necesitamos para monitorear el apoyo y podemos tener un puñado de instancias que se ejecutan al mismo tiempo.
No sabemos qué instancias se ejecutarán en un momento dado, por lo que hace que crear archivos estáticos en la configuración sea un poco doloroso.

intenté despegar el modificador de sólo lectura y establecer lo siguiente en el constructor de la clase:

_log = LogManager.GetLogger("DataCollectionClass_" + deviceName + "_" + DateTime.Now.ToString("MMddyyyy"), typeof(SomeClassTypeHere)); 

Pero eso requiere que defino una appender manualmente en la configuración, lo que sería engorroso y difícil de seguir el ritmo de .

¿Alguna idea de hacer esto en L4N? He visto los enlaces here, pero realmente no sé si es necesario ese armado.

Respuesta

14

El siguiente código muestra cómo puede configurar programáticamente log4Net sin utilizar un archivo de configuración para lograr el efecto que está buscando. Básicamente, solo implica crear un registrador con nombre y agregarlo a la jerarquía.

He usado como punto de partida una de las respuestas de here.

using log4net; 
using log4net.Appender; 
using log4net.Layout; 
using log4net.Repository.Hierarchy; 

namespace LoggerTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      DeviceConnection dev1 = new DeviceConnection("Device1"); 
      DeviceConnection dev2 = new DeviceConnection("Device2"); 

      dev1.DoSomething(); 
      dev2.DoSomething(); 
     } 
    } 

    public class DeviceConnection 
    { 
     private string name; 
     private readonly ILog logger; 

     public DeviceConnection(string _name) 
     { 
      name = _name; 

      logger = TestLogger.AddNamedLogger(name); 

      logger.Info("---- Begin Logging for DeviceConnection: " + name); 
     } 

     public void DoSomething() 
     { 
      logger.Info("Doing something for device connection " + name); 
     } 
    } 

    public static class TestLogger 
    { 
     private static PatternLayout _layout = new PatternLayout(); 
     private const string LOG_PATTERN = "%d [%t] %-5p %m%n"; 

     public static string DefaultPattern 
     { 
      get { return LOG_PATTERN; } 
     } 

     static TestLogger() 
     { 
      _layout.ConversionPattern = DefaultPattern; 
      _layout.ActivateOptions(); 

      Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository(); 
      hierarchy.Configured = true; 
     } 

     public static PatternLayout DefaultLayout 
     { 
      get { return _layout; } 
     } 

     public static ILog AddNamedLogger(string name) 
     { 
      Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository(); 
      Logger newLogger = hierarchy.GetLogger(name) as Logger; 

      PatternLayout patternLayout = new PatternLayout(); 
      patternLayout.ConversionPattern = LOG_PATTERN; 
      patternLayout.ActivateOptions(); 

      RollingFileAppender roller = new RollingFileAppender(); 
      roller.Layout = patternLayout; 
      roller.AppendToFile = true; 
      roller.RollingStyle = RollingFileAppender.RollingMode.Size; 
      roller.MaxSizeRollBackups = 4; 
      roller.MaximumFileSize = "100KB"; 
      roller.StaticLogFileName = true; 
      roller.File = name + ".log"; 
      roller.ActivateOptions(); 

      newLogger.AddAppender(roller); 

      return LogManager.GetLogger(name); 
     } 
    } 
} 
+0

In Si el código no era evidente, la instancia llamada dev1 siempre se registra en Device1.log, y la instancia denominada dev2 se registra en Device2.log. El código se prueba y usted debería poder copiarlo en el programa.cs archivo de un nuevo proyecto de consola para probarlo. – dhochee

+0

Eso ayuda, ¡gracias! – Killnine

1

Use ADO.Net appender y regístrese en una base de datos SQL Server y simplemente solicite la información que necesita.

Otra alternativa es el panel de control de log4net: http://www.l4ndash.com/. Hace un trabajo bastante decente al integrar registros de diversas fuentes y luego dividirlos en diferentes formas. Precio razonable, también.

+0

Eso suena como un buen plan; sin embargo, en mi corp. ambiente, no tenemos una base de datos para dedicar solo al registro de este servicio. Quizás los equipos migrarán a eso con el tiempo, pero por ahora cada equipo debe usar un archivo plano (o una colección de estos). > = ( – Killnine

+0

@ AdminK9: vea mi respuesta enmendada –

1

log4net tiene un concepto llamado jerarquía de registradores.

Un registrador se dice que es un antepasado de otro registrador si su nombre seguido de un punto es un prefijo de el nombre logger descendiente. Se dice que un registrador es un padre de un registrador hijo si no hay antepasados ​​ entre él y el registrador descendiente . La jerarquía funciona mucho de la misma manera que el espacio de nombres y la jerarquía de clases en .NET. Esto es muy conveniente como pronto veremos.

Así que realmente debería crear sus registradores de instancia específicos con . caracteres en lugar de _ caracteres.

_log = LogManager.GetLogger("DataCollectionClass." + deviceName + "." + DateTime.Now.ToString("MMddyyyy"), typeof(SomeClassTypeHere)); 

Luego, en el archivo de configuración, consulte la jerarquía del registrador de la siguiente manera.

<log4net> 
    <!-- Other log4net configuration omitted for brevity --> 
    <logger name="DataCollectionClass"> 
    <!-- Put your appender-ref entries here --> 
    </logger> 
</log4net> 

Observe cómo la referencia del nombre del registrador no contiene el nombre completo utilizado en el código. Solo hace referencia a la raíz del nombre. Piénsalo de la misma manera que piensas en los espacios de nombres.

+0

+1 para este enfoque. Tengo el mismo requisito que OP y parece que 'jerarquía' es adecuada para este requisito. Prefiero usar el archivo de configuración para el enfoque programático (aunque Supongo que app.config podría funcionar allí de alguna manera). Investigaré más esta opción. – SleepyBoBos

+2

Hola. No estoy seguro de cómo crea un archivo diferente por instancia. ¿El appender controla el nombre del archivo? – uriDium

0

Tengo un artículo que podría ayudar:

http://horth.com/blog/?p=165

Se trata de cambiar un archivo de registro en tiempo de ejecución. Lo que podría hacer es pasar el nombre del archivo para cada instancia en su archivo log4net. De esta forma, podría crear un archivo de registro para cada instancia de su clase. De esta forma, su archivo de configuración es simple y, sin embargo, tiene la flexibilidad de crear un nuevo archivo de registro para cada instancia de clase.

Se mencionó anteriormente que también podría iniciar sesión en una base de datos con indicadores para cada instancia. Si no quiere comprar nada, use SQL Express que permite bases de datos de 10GB. Incluso puede escribir directamente en el archivo MDF en lugar de instalar SQL.

Cuestiones relacionadas