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 :
<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" />
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:
Enregistrer un commentaire