UDPTraceListener et EntLib3.1 Logging application block

 

J'ai recemment mis en place un service NT et je voulais voir en temps réel ce qui se passait dans mes process, utilisant le logging application block , j'ai ecrit un TraceListener custom, qui ecrit la trace sur un port UDP. A l'aide d'un utilitaire en console, il est possible de voir passer en temps reel toute la trace, voici comment faire :

UdpTraceListener.cs

.
   1:  using System.Net;
   2:  using System.Net.Sockets;
   3:  using System.Text;
   4:   
   5:  using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
   6:  using Microsoft.Practices.EnterpriseLibrary.Logging;
   7:  using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;
   8:  using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;
   9:   
  10:  namespace Serialcoder.Logging
  11:  {
  12:     [ConfigurationElementType(typeof(Configuration.UDPTraceListenerData))]
  13:     public class UDPTraceListener : FormattedTraceListenerBase
  14:     {
  15:        private Microsoft.Practices.EnterpriseLibrary.Logging.LogEntry m_entry;
  16:        UdpClient m_Sock;
  17:        IPEndPoint m_Iep;
  18:   
  19:        public UDPTraceListener() 
  20:           : base()
  21:        {
  22:        }
  23:   
  24:        public UDPTraceListener(ILogFormatter formatter) 
  25:           : base(formatter)
  26:        {
  27:        }
  28:   
  29:        public UDPTraceListener(int port, ILogFormatter formatter)
  30:           : base(formatter)
  31:        {
  32:           m_Sock = new UdpClient();
  33:           m_Iep = new IPEndPoint(IPAddress.Broadcast, port);
  34:        }
  35:   
  36:        public override void Write(string message)
  37:        {
  38:           byte[] data = Encoding.UTF8.GetBytes(message);
  39:           m_Sock.Send(data, data.Length, m_Iep);
  40:           InstrumentationProvider.FireTraceListenerEntryWrittenEvent();
  41:        }
  42:   
  43:        public override void WriteLine(string message)
  44:        {
  45:           Write(message);
  46:        }
  47:   
  48:        public override void TraceData(System.Diagnostics.TraceEventCache eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, object data)
  49:        {
  50:           m_entry = (LogEntry)data;
  51:           string message = this.Formatter.Format(m_entry);
  52:           this.Write(message);
  53:        }
  54:   
  55:        public override bool IsThreadSafe
  56:        {
  57:           get
  58:           {
  59:              return true;
  60:           }
  61:        }
  62:   
  63:        protected override string[] GetSupportedAttributes()
  64:        {
  65:           return new string[2] { "formatter", "port" };
  66:        }
  67:   
  68:        protected override void Dispose(bool disposing)
  69:        {
  70:           base.Dispose(disposing);
  71:           m_Sock.Close();
  72:           m_Iep = null;
  73:           m_Sock = null;
  74:        }
  75:   
  76:     }
  77:  }

Le fichier de configuration :


.


   1:  using System.Configuration;
   2:  using System.Diagnostics;
   3:   
   4:  using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
   5:  using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
   6:  using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;
   7:  using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
   8:  using Microsoft.Practices.ObjectBuilder;
   9:   
  10:  namespace Serialcoder.Logging.Configuration
  11:  {
  12:     [Assembler(typeof(UDPTraceListenerAssembler))]
  13:     public class UDPTraceListenerData : TraceListenerData
  14:     {
  15:        private const string PORT = "port";
  16:        private const string FORMATTERNAMEPROPERTY = "formatter";
  17:   
  18:        public UDPTraceListenerData() 
  19:        {
  20:        }
  21:   
  22:        public UDPTraceListenerData(int port, string formatterName)
  23:           : this("unnamed", port, formatterName)
  24:        {
  25:        }
  26:   
  27:        public UDPTraceListenerData(string name, int port, string formatterName)
  28:           : this(name, port, formatterName, TraceOptions.None)
  29:        {
  30:        }
  31:   
  32:        public UDPTraceListenerData(string name, int port, string formatterName, TraceOptions traceOptions)
  33:           : base(name, typeof(UDPTraceListener), traceOptions)
  34:        {
  35:           this.Port = port;
  36:           this.Formatter = formatterName;
  37:        }
  38:   
  39:        [ConfigurationProperty(PORT,IsRequired=true)]
  40:        public int Port
  41:        {
  42:           get { return (int)base[PORT]; }
  43:           set { base[PORT] = value; }
  44:        }
  45:   
  46:        [ConfigurationProperty(FORMATTERNAMEPROPERTY, IsRequired = false)]
  47:        public string Formatter
  48:        {
  49:           get { return (string)base[FORMATTERNAMEPROPERTY]; }
  50:           set { base[FORMATTERNAMEPROPERTY] = value; }
  51:        }
  52:   
  53:     }
  54:   
  55:     public class UDPTraceListenerAssembler : TraceListenerAsssembler
  56:     {
  57:        public override TraceListener Assemble(IBuilderContext context, Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.TraceListenerData objectConfiguration, IConfigurationSource configurationSource, ConfigurationReflectionCache reflectionCache)
  58:        {
  59:           UDPTraceListenerData castedObjectConfiguration
  60:              = (UDPTraceListenerData)objectConfiguration;
  61:   
  62:           ILogFormatter formatter = GetFormatter(context, castedObjectConfiguration.Formatter, configurationSource, reflectionCache);
  63:   
  64:           TraceListener createObject = new UDPTraceListener(castedObjectConfiguration.Port, formatter);
  65:           return createObject;
  66:        }
  67:     }
  68:   
  69:  }

la partie interessante de ce code est l'ecriture sur un port udp réaliser par :



ensuite il faut ajouter ce listener dans la sections des listeners du ficher de configuration

 




         <add port="20202" listenerDataType="Serialcoder.Logging.Configuration.UDPTraceListenerData, Serialcoder.Logging, Version=3.1.0.0, Culture=neutral, PublicKeyToken=null"
traceOutputOptions="None" type="Serialcoder.Logging.UDPTraceListner, Serialcoder.Logging, Version=3.1.0.0, Culture=neutral, PublicKeyToken=null"
name="UDP Trace Listener" formatter="Condensed Informations" />

on indique alors via l'attribut "port", le port sur lequel on veut envoyer la trace.

 

pour ecouter il suffit de faire une petite application console :

 

.


   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Text;
   4:   
   5:  namespace ServiceTraceListnerConsole
   6:  {
   7:     class Program
   8:     {
   9:        static void Main(string[] args)
  10:        {
  11:           if (args == null || args.Length != 2)
  12:           {
  13:              Console.WriteLine("Using :");
  14:              Console.WriteLine();
  15:              Console.WriteLine("ServiceTraceListnerConsole <IPEndpoint> <Port>");
  16:              Console.WriteLine();
  17:              Console.WriteLine("Example :");
  18:              Console.WriteLine("ServiceTraceListnerConsole 192.168.1.1 20202");
  19:              return;
  20:           }
  21:   
  22:           new ServiceListner(args[0], Convert.ToInt32(args[1]));
  23:        }
  24:     }
  25:  }

et son fichier d'ecoute du port UDP :


.


   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Text;
   4:  using System.Threading;
   5:  using System.Net;
   6:   
   7:  namespace ServiceTraceListnerConsole
   8:  {
   9:     public class ServiceListner
  10:     {
  11:        private string m_IPEndPoint;
  12:        private int m_Port;
  13:        private System.Threading.Thread m_Thread;
  14:        private System.Threading.ManualResetEvent m_EventStop;
  15:        private System.Net.Sockets.UdpClient m_Sock;
  16:   
  17:        public ServiceListner(string ipEndPoint , int port)
  18:        {
  19:           m_IPEndPoint = ipEndPoint;
  20:           m_Port = port;
  21:           m_EventStop = new System.Threading.ManualResetEvent(false);
  22:           m_Thread = new System.Threading.Thread(Listen);
  23:           m_Thread.Start();
  24:        }
  25:   
  26:        private void Listen()
  27:        {
  28:           // IPEndPoint iep = new IPEndPoint(IPAddress.Parse(m_IPEndPoint), m_Port);
  29:           m_Sock = new System.Net.Sockets.UdpClient(m_Port);
  30:           while (true)
  31:           {
  32:              IAsyncResult result = m_Sock.BeginReceive(new AsyncCallback(ReceiveMessage), null);
  33:              WaitHandle[] handles = new WaitHandle[] { m_EventStop, result.AsyncWaitHandle };
  34:              int index = WaitHandle.WaitAny(handles);
  35:              if (index == 0)
  36:              {
  37:                 m_Sock.Close();
  38:                 break;
  39:              }
  40:           }
  41:        }
  42:   
  43:        private void ReceiveMessage(IAsyncResult ar)
  44:        {
  45:           IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0);
  46:           byte[] data = m_Sock.EndReceive(ar, ref iep);
  47:           string message = Encoding.UTF8.GetString(data);
  48:           Console.WriteLine(message);
  49:        }
  50:     }
  51:  }

Sur les applications existantes utilisant le LAB il s'uffit d'utiliser ce listener pour voir apparaitre la trace dans une console, ceci peut etre interessant pendant la phase d'installation d'un nouveau service ou dans une application web.

Aucun commentaire: