c# logging .net-3.5 trace tracelistener

c# - agregar/eliminar TraceListener a todos los TraceSources



logging .net-3.5 (3)

Estoy buscando una manera de agregar y eliminar un TraceListener para todos los TraceSources existentes.

(No estoy seguro de que mi enfoque sea correcto aquí, ¿qué otras formas podría usar? Básicamente, quiero registrar todos los resultados de rastreo en un archivo que usa el nombre del proyecto actual como nombre de archivo. Cada vez que un usuario crea o reabre un proyecto, quiero agregue los registros al archivo correcto. Solo puede haber un proyecto abierto a la vez.)

Ejemplo de código:

Creo varios TraceSources en mi aplicación, uno para cada clase

public class Class1 { private static readonly System.Diagnostics.TraceSource trace = new System.Diagnostics.TraceSource("Class1"); } public class Class2 { private static readonly System.Diagnostics.TraceSource trace = new System.Diagnostics.TraceSource("Class2"); }

Ahora quiero agregar o eliminar un traceListener a todos mis traceSources en Runtime, como esto:

private System.Diagnostics.TextWriterTraceListener myListener; private onProjectOpen() { // user created a new project or opened an existing one myListener = new System.Diagnostics.TextWriterTraceListener("log-"+projectname+".log"); ALL_TRACESOURCES.Add ( myListener) ; // <-- how to do this? } private onProjectClose() { // user closed a project ALL_TRACESOURCES.Remove( myListener) ; // <-- how to do this? myListener.Flush(); myListener.Close(); myListener.Dispose(); // <-- not sure if all this is neccessary }

Hasta ahora no he encontrado ninguna manera de hacer esto sin hacer públicas todas mis traceSources (parece una mala idea) y luego listar todas mis clases de esta manera:

Class1.Trace.Add( myListener ); Class2.Trace.Add( myListener ); ...

lo que parece ser una mala elección de diseño en varios niveles.

O

Agregue todos mis TraceSources a una colección global personalizada en el constructor de cada clase (Fácil de olvidar / desordenar; y las variables globales son malas)

¿Hay alguna manera mejor? Básicamente estoy buscando una manera de establecer otro oyente predeterminado


Acabo de encontrarme con este problema. En mi caso también tengo fuentes de rastreo creadas en cada clase. Los oyentes que están en app.config se agregan a todas las fuentes sin ningún problema, pero hay un oyente en particular que necesito agregar en tiempo de ejecución. Por supuesto, esto solo funciona con la fuente de rastreo a la que se agrega el oyente. Veo dos opciones: crear un único origen de seguimiento y pasarlo al resto de la aplicación (yuck), o tener un único origen de seguimiento estático en una clase auxiliar a la que todo lo demás hace referencia. Así que tengo:

public class LogHelper { /// /// The trace source logger for the application. /// public static readonly TraceSource Logger = new TraceSource("FruityBlergs", SourceLevels.All); }

La clase LogHelper también configura la escucha y varios otros filtros que se configuran en tiempo de ejecución. Esto me ha funcionado bien hasta ahora. Si por alguna razón una clase en particular necesita un comportamiento diferente, aún puede crear una fuente de rastreo en esa clase.


Basado en esta respuesta de y esta respuesta

Aquí hay una forma de hacerlo:

private static void AttachToAllTraceSources(TraceListener yourListener) { TraceSource ts = new TraceSource("foo"); List<WeakReference> list = (List<WeakReference>)GetInstanceField(typeof(TraceSource), ts, "tracesources"); foreach(var weakReference in list) { if(weakReference.IsAlive) { TraceSource source = (weakReference.Target as TraceSource); if(source != null && source.Name != "foo") { source.Listeners.Add(yourListener); } } } }


En .NET 4 y superior, puede usar Lazy<> para cargar de forma lenta sus TraceSources después de que se hayan configurado los escuchas. Vea el siguiente programa de ejemplo de trabajo:

public static class TraceSources { public static TraceSource Create(string sourceName) { var source = new TraceSource(sourceName); source.Listeners.AddRange(Trace.Listeners); source.Switch.Level = SourceLevels.All; return source; } } public class Class1 { private static readonly Lazy<TraceSource> trace = new Lazy<TraceSource>(() => TraceSources.Create("Class1")); public void DoSomething() { trace.Value.TraceEvent(TraceEventType.Information, 1, "Class1 speaking up"); } } public class Class2 { private static readonly Lazy<TraceSource> trace = new Lazy<TraceSource>(() => TraceSources.Create("Class2")); public void DoSomethingElse() { trace.Value.TraceEvent(TraceEventType.Information, 2, "Class2 speaking out"); } } public class Program { static void Main(string[] args) { try { var listener = new TextWriterTraceListener(@"C:/trace.txt"); Trace.Listeners.Add(listener); var classOne = new Class1(); var classTwo = new Class2(); classOne.DoSomething(); classTwo.DoSomethingElse(); } finally { Trace.Close(); } } }