martedì 9 dicembre 2008

Aggiungere un TraceListener ad una classe da codice

Vogliamo aggiungere un listener del Trace di una applicazione. Sebbene questa operazione si possa eseguire direttamente dal file di configurazione dell'applicazione (App.config), preferisco gestirla da codice, in modo da avere un maggiore controllo ed una maggiore comprensione su quello che accade.

Il Trace è il modo migliore per gestire i log in .NET . Per info cercare informazioni su msdn alla voce TraceSource.

Nel file App.config (se non esiste, va creato nella directory base del progetto) bisogna definire un "source" avente come nome, il nome che daremo al nostro Trace. In questo caso "ApplicationTraceName".
Poi bisogna associare al source uno "switch", che serve ad indicare il livello minimo di ascolto rispetto a questa source. In questo caso "Verbose", cioè ascoltiamo tutto ciò che la source notifica.
E' ovviamente possibile gestire più di una source.

xml version="1.0" encoding="utf-8" ?>

<configuration>

  <system.diagnostics>

    <sources>   

      <source name="ApplicationTraceName" switchName="VerboseSwitch">      

      source>     

    sources>

    <sharedListeners>     

    sharedListeners>

    <switches>

      <add name="VerboseSwitch" value="Verbose" />

    switches>

  system.diagnostics>

configuration>




Definiamo ora la sorgente del flusso di Trace. Deve essere una classe che fa da wrapper alla classe TraceSource. Deve avere un metodo per registrare un listener ed un metodo per lanciare un nuovo evento di Trace. Il nome affibiato al TraceSource deve essere quello dichiarato nell' App.config. 

        public static class ApplicationTrace

        {

            static private System.Diagnostics.TraceSource Source = new System.Diagnostics.TraceSource("ApplicationTraceName");

             ///

            ///     Writes a trace event message to the trace listeners in the

            ///     System.Diagnostics.TraceSource.Listeners

            ///     collection using the specified event type, event identifier, and message.

            ///

            ///

One of the System.Diagnostics.TraceEventType values

            ///  that specifies the event type of the trace data.

            ///

A numeric identifier for the event.

            ///

The trace message to write.

            [System.Diagnostics.Conditional("TRACE")]

            static public void TraceEvent(System.Diagnostics.TraceEventType eventType, int id, string message)

            {

                Source.TraceEvent(eventType, id, message); Source.Flush();

             }

            ///

            /// Add a listener to the trace

            ///

            ///

            static public void AddListener(System.Diagnostics.TraceListener listener)

            {

                Source.Listeners.Add(listener);

            }

      }


Definita la sorgente del flusso di Trace, da codice creiamo il listener che ascolta il flusso di dati e lo scrive da qualche parte. Per fare questo usiamo gli oggetti del namespace System.Diagnostic di .NET

System.Diagnostics.ConsoleTraceListener traceListener = new System.Diagnostics.ConsoleTraceListener();

//impostiamo il verbose level

traceListener.Filter = new System.Diagnostics.EventTypeFilter(System.Diagnostics.SourceLevels.Verbose);

Nota: qui avremmo potuto definire un filtro più restrittivo, ad esempio a livello Information. 


Infine, colleghiamo il listener creato alla sorgente di Trace usando il metodo della sorgente per l'aggiunta di listener:

ApplicationTrace.AddListener(traceListener);

Abbiamo terminato. Ora, ogni volta che verrà invocato il metodo TraceEvent, l'evento sarà tracciato a Console.

ApplicationTrace.TraceEvent(System.Diagnostics.TraceEventType.Verbose, 0, "my message");



Il codice completo è questo:

public class MyClass{

        public MyClass()

        {

            System.Diagnostics.ConsoleTraceListener traceListener = new System.Diagnostics.ConsoleTraceListener();

            //information  level

            traceListener.Filter = new System.Diagnostics.EventTypeFilter(System.Diagnostics.SourceLevels.Verbose);        

            ApplicationTrace.AddListener(traceListener);

        }

         public void myMethod() {

            ApplicationTrace.TraceEvent(System.Diagnostics.TraceEventType.Verbose, 0, "my message");

        }

    }

  static void Main(string[] args)

        {

            MyClass myClass = new MyClass();

            myClass.myMethod();

            Console.ReadLine();

}


Infine, si può pensare di voler redirigere il flusso del Trace verso un altro output che non sia la console, ad esempio scrivendo su un file di log. Per fare questo basta ridefinire in questo modo il listener:

          System.Diagnostics.TextWriterTraceListener traceListener = new System.Diagnostics.TextWriterTraceListener("myfilename.txt");


Ovviamente si può creare un insieme di listener a piacere, in modo da scrivere il log su più destinazioni diverse (files, console, maschere a video, pagine web...) anche a livelli di log differenti.

Nessun commento:

Lettori fissi