Can tracing via TraceSource be configured through code from external assembly

287 Views Asked by At

Most TraceSource tracing examples show how it is done via configuration. I am trying to achieve this via code.

I have a simple assembly as follows:

using System;
using System.Diagnostics;
using System.Threading;

namespace TracingLib
{
    public class AppTracer
    {
        public event EventHandler AppStarted;
        public event EventHandler AppStopped;
        private bool CancelRequested = false;
        public void Start()
        {
            Thread thread = new Thread(new ThreadStart(() =>
            {
                if(AppStarted != null) AppStarted(this, new EventArgs());

                TraceSource ts = new TraceSource("ThreadSource");

                ts.TraceInformation("Thread Begins");
                //ts.Flush();
                int i = 0;
                while (!CancelRequested)
                {

                    ts.TraceInformation("i: {0}", i++);
                    //ts.Flush();
                    Debug.Print("i : {0}", i);
                    Thread.Sleep(5000);
                }

                if (AppStopped != null) AppStopped(this, new EventArgs());
            }));
            thread.Start();
        }

        public void Stop()
        {
            CancelRequested = true;
        }
    }
}

I am consuming this in a console application.

using System;
using System.Threading;
using TracingLib;

namespace caTracingLibImplementation
{
    class Program
    {
        static void Main(string[] args)
        {
            AppTracer tracer = new AppTracer();
            ManualResetEvent waiter = new ManualResetEvent(false);
            tracer.AppStopped += (sender, e) =>
            {
                waiter.Set();
            };

            TraceSource ts = new TraceSource("ThreadSource");            
            ts.Listeners.Add(new ConsoleTraceListener());
            var sw = new SourceSwitch("foo");
            sw.Level = SourceLevels.Warning;
            ts.Switch = sw;
            tracer.Start();
            Console.WriteLine("AppTracer started...");
            Thread.Sleep(10000);
            tracer.Stop();
            Console.WriteLine("AppTracer stopped...");
            Console.WriteLine("Waiting to stop...");
            waiter.WaitOne();
            Console.WriteLine("End of program");
        }
    }
}

If I try to enable tracing via the console application I cannot see the trace messages.

2

There are 2 best solutions below

3
user1112560 On

Firstly, You need to supply TraceListeners to the TraceSource defined in AppTracer.

This code would work using configuration files would work because the .NET framework keeps a single instance of each listener obtained from the configuration file and assigns them to each TraceSource based on the initial string parameter.

If the string parameter for the TraceSource is not defined in app.config then there will be no listeners saved in global state. Therefore each instance of a TraceSource must have all the listeners supplied to it.

TraceSource.Initialize() Source

Secondly, the switch: sw.Level = SourceLevels.Warning; will disable any statements logged with: ts.TraceInformation()

0
Jeremy On

If you are configuring your TraceSource at run time then I think the most appropriate solution for your code is to:

  1. Inject that dynamic TraceSource into the constructor of AppTracer.
  2. OR pass the TraceSource in through Start().

I would lean toward #1 over #2.

As user1112560 mentions, you will not see TraceInformation output if your switch level is set to Warning. The precedence is Off, Error, Warning, Information, Verbose. See MSDN Trace Switches.