The official Fatica Labs Blog! RSS 2.0
# Saturday, 04 December 2010

Ho appreso da un mio collega l’esistenza del comando unix/linux tail, che com il flag –f monitora costantemente un file e scrive a console le nuove linee aggiunte. Questo è ottimo se si sta seguendo realtime un log su file. L’unico problema di questa soluzione è che – almeno nell ‘ implementazione che abbiamo usato-  usando il RollingFileAppender di log4net il file rimaneva locked, e durante la rinomina automatica falliva e si rischiava di perdere comopletamente un segmento di log.

A tale scopo ho scritto una piccola utility C# che fa esattamente la stessa cosa di tail –f, che troavate su codeplex a questo indirizzo.

Una breve descrizione della command line:

 

  • tailf mylog.txt continuously dump on the console the content of mylog.txt as soon new lines are written into it.
  • tailf -n:15 mylog.txt continuously dump on the console the content of mylog.txt as soon new lines are written into it. At startup the last 15 lines are dumped.
  • tailf mylog.txt -f:ERROR continuously dump on the console the content of mylog.txt as soon new lines are written into it. Just lines containing "ERROR" are shown.
  • tailf mylog.txt -f:"ERROR|WARN" continuously dump on the console the content of mylog.txt as soon new lines are written into it. Just lines containing "ERROR" or "WARN" are shown; double quotes are necessary since | is a special char in the command shell.
Per avere invece al volo un idea di come usare il codice per altri scopi date un’ occhiata qui.
Saturday, 04 December 2010 06:04:53 (GMT Standard Time, UTC+00:00)  #    Comments [0] - Trackback
log4net

# Monday, 05 July 2010

A volte si vuole ottenere l amedesima configurazione di logging per log con diverso nome, accomunati da una radice: xEs se usiamo NHibernate avremo NHibernate.Cfg.XmlHbmBinding,NHibernate.Cfg.Configuration, NHibernate.Cfg.SettingsFactory, NHibernate.Dialect.Dialect … e via discorrendo. E’ bello sapere che log4net supporta una gerarchia tra logger, e che questa è implicata dal nome: se voglio, per esempio, per tutti i logger di NH loggare solo i messaggi di fatal error posso scrivere:

<logger name="NHibernate" >
    <level value="FATAL" />
  </logger>

 

Ed tutti i logger NHibernate.* cadranno in questo caso. Ovviamente lo stesso lo posso fare con una sotto gerarchia, per esempio con name=”NHibernate.Cfg” riferirò tutti i log di configurazione.

Buono a sapersi, anche per quando si decidono i nomi dei logger nelle proprie applicazioni.

Monday, 05 July 2010 10:56:00 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
log4net

# Tuesday, 27 April 2010

Per abilitare il logging delle query con NHibernate occorre:

  1. Avere nella bin dell applicativo ( ie: nella /bin per le applicazioni web, a fianco dell’ esequibile per le applicazioni stand-alone ) la dll di log4net.
  2. Aggiungere nel file di configurazione la sessione di config per log4net:
  3. <configuration>
      <configSections>
        <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>

      </configSections>
      <log4net>
        <appender name="console" type="log4net.Appender.ConsoleAppender">
          <layout type="log4net.Layout.PatternLayout">
            <param name="ConversionPattern" value="%-5p - %m%n" />
          </layout>
        </appender>
        <logger name="NHibernate.SQL" additivity="false">
          <level value="ALL"/>
          <appender-ref ref="console" />
        </logger>
        <root>
          <priority value="WARN" />
          <appender-ref ref="console" />
        </root>
      </log4net>
    </configuration>

    Con questa configurazione si usa il console appender, per un’applicativo web potrebbe essere meglio usare un TraceAppender o un altro appender di proprio gusto ;-)

     

  4. Assicurarsi di chiamare, almeno una voltanell’applicazione log4net.XmlConfigurator.Configure()
  5. Aggiungere questa proprietà nella configurazione di NH:                                         <property name="show_sql">true</property>

Se NON vogliamo mettere nulla di log4net nella configurazione:

Possiamo configurare log4net dall’ applicativo, con un paio di linee di codice:

   1:              TraceAppender app = new TraceAppender();
   2:              app.Layout = new SimpleLayout();
   3:              LoggerMatchFilter filter = new LoggerMatchFilter();
   4:              filter.LoggerToMatch="NHibernate.SQL";
   5:              filter.AcceptOnMatch = true;
   6:              filter.ActivateOptions();
   7:              app.AddFilter(filter); // L'ordine di questo filtro
   8:              app.AddFilter(new DenyAllFilter()); // e di quest'altro E' importante
   9:              app.ActivateOptions();
  10:              BasicConfigurator.Configure( app);
 
 
 

In questo caso si possono saltare gli step da 1 a 3. Questo codice deve essere chiamato una volta nell’applicazione in fase di startup, per un’applicazione web, potrebbe andare bene l’evento di startup dell'applicazione in global.asax. Con l’appender e i filtri configurati si ottiene nell'area trace di Visual Studio ( Output-tab Debug)  l’output delle sole query generate da NH ( senza gli altri logger, se servono  si possono togliere i filtri )

Tuesday, 27 April 2010 16:43:20 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
NHibernate | log4net

# Saturday, 17 April 2010

Uno scenario di possibile utilizzo di RemotingAppender è quando si voglia concentrare in un unico punto i log di più app domain hostati nello stesso processo. Infatti un app domain separato vede difatto un’altra configurazione di log4net e, se si volesse per esempio usare un appender su file, ci sarebbe una violazione di condivisione. Per cui RemotingAppender torna utile, consentendo di ribaltare il log di tutti gli app domain sul programma principale. Per prima cosa bisogna mettere il programma principale in grado di ricevere le chiamate di log via remoting. Supponiamo che MyLauncher sia la classe che avvia un processo in un AppDomain separato, potremmo scrivere:

class MyLauncher:MarshalByRefObject,log4net.Appender.RemotingAppender.IRemoteLoggingSink
{

E’ necessario che la classe derivi da MarshalByRef object, in quanto ne esporremo l’istanza via remoting. Deve altresì implementare IRemoteLoggingSink , per fungere da target per i messaggi di log4net.

A questo punto bisogna registrare il canale e l’istanza dell’oggetto atto a fare il sink dei messaggi:

   1:  private void PrepareRemotingLoggerListener()
   2:  {
   3:              var channel = new IpcChannel("log4net"+Guid.NewGuid().ToString());
   4:   
   5:              ChannelServices.RegisterChannel(channel, false);
   6:              var oref = RemotingServices.Marshal(this, null);
   7:              AppenderURI = channel.GetUrlsForUri(oref.URI)[0];
   8:  }

 

Supponiamo di chiamare il codice di sopra per ogni hosting di app domain. Il canale viene battezzato con una componente casuale, in modo da non entrare in conflitto con altre istanze dello stesso programma, o all’interno del medesimo processo se vi fossero più app domain esterni in esecuzione. Per registrare con remoting un istanza già creata si è usato RemotingServices.Marshal(---). Il codice memorizza in una proprietà AppenderURI: questo sarà l’indirizzo da usarsi con remoting appender per definire la proprietà Sink.In pratica è l’indirizzo remoting dell’oggetto “sink” dei messaggi.

Implementare IRemoteLoggingSink è facilissimo:

   1:          #region IRemoteLoggingSink Members
   2:   
   3:          public void LogEvents(log4net.Core.LoggingEvent[] events)
   4:          {
   5:              foreach (var le in events)
   6:                  logger.Logger.Log(le); // logger è un'istanza di 
//ILog nel programma principale, ottenuta con logManager.GetLogger...
   7:          }
   8:   
   9:          #endregion

In questo modo si ottiene un redirect di tutti i messaggi sul logger dell’applicazione principale, con filtri e appender come stabilito dalla configurazione dell’applicativo principale. I messaggi saranno accodati, quindi non ci saranno violazioni di condivisione anche con appender su file fisico.

Nell’app domain basterà configurare log4net in modo da utilizzare RemotingAppender. Il modo più facile è utilizzare BasicConfigurator:

   1:    BasicConfigurator.Configure(CreateAppender());
   2:    logger = LogManager.GetLogger("logger name");
 

CreateAppender si occuperà di creare il RemotingAppender in questo modo:

   1:          private IAppender CreateAppender()
   2:          {
   3:              RemotingAppender ra = new RemotingAppender();
   4:              ra.Layout = new log4net.Layout.SimpleLayout();
   5:              ra.Sink = LoggerURI; // Indirizzo del "sink"
   6:              ra.BufferSize = 512;
   7:              ra.Lossy = false;
   8:              ra.ActivateOptions(); // Ricordarsi di chiamare !!!
   9:              return ra;
  10:          }

Ed il gioco è fatto. LoggerUri è l’indirizzo dell’oggetto di sink ( vedi AppenderURI di prima ). BufferSize è il numero di messaggi da accodare prima di fare effettivamente la chiamata al canale: per ragioni di performance è meglio non abbassare troppo la soglia dei messaggi da raggruppare.

Saturday, 17 April 2010 09:02:23 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
log4net | Programmin

My Stack Overflow
Contacts

Send mail to the author(s) E-mail

Tags
profile for Felice Pollano at Stack Overflow, Q&A for professional and enthusiast programmers
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2017
Felice Pollano
Sign In
Statistics
Total Posts: 157
This Year: 0
This Month: 0
This Week: 0
Comments: 124
This blog visits
All Content © 2017, Felice Pollano
DasBlog theme 'Business' created by Christoph De Baene (delarou) and modified by Felice Pollano