How to use TraceSource across classes

Captain Comic picture Captain Comic · Dec 7, 2010 · Viewed 16k times · Source

I was recently studying documentation on TraceSource. Microsift says that TraceSource is a new way and should be used instead of old Trace class.

// create single TraceSource instance to be used for logging
static TraceSource ts = new TraceSource("TraceTest");

// somewhere in the code
ts.TraceEvent(TraceEventType.Warning, 2, "File Test not found");

Now my question. You have large project with several assemblies where you have lots of classes. Say you wanna trace specific bit of functionality that is spread across classes. Obvious idea is that you need to create one specific TraceSource .

1) To work with Tracesource I need to create instance first. What is MS thinking about sharing this instance across various classes or assemblies? Should I create one dummy class with static singleton property? What are you doing in that case.

2) Why do I need TraceSource instance? Every propery is described in the configuration file. The old logic based on Trace class did not require some instance and provided the way to work with static methods only.

Answer

wageoghe picture wageoghe · Dec 8, 2010

*1. Just define the TraceSource in each class where you want to use it. You can make the TraceSource static so that it shared among all instances of the class you define it in. No need to share the instance among all classes (types) that need the "same" TraceSource. Each time you decleare a new TraceSource (TraceSource ts = new TraceSource("somename"); instance, you get a new TraceSource object, but it references the same config information. So, if you create a new TraceSource in each of several classes and you use the same name for each one, you will get different instances of TraceSource, but they will all be configured the same. In short, there is no need to try to share the TraceSource instances among classes. There is also no need to create a dummy class with a static singleton. See my examples below. I have also included several more links from here on SO that describe how to work with TraceSources.

//
// In this example, tracing in classes A and B is controlled by the "TraceTest" TraceSource
// in the app.config file.  Tracing in class C is controlled by the "TraceTestTwo"
// TraceSource in the app.config.
//
// In addition to using different TraceSource names, you can also use SourceSwitches 
// (in the app.config).  See some examples of app.config in the
// "turning-tracing-off-via-app-config" link below.
//

public class A
{
  private static readonly TraceSource ts = new TraceSource("TraceTest");

  public void DoSomething()
  {
    ts.TraceEvent(TraceEventType.Warning, 2, "File Test not found");   
  }
}

public class B
{
  //
  //Use the same config info for TraceTest in this class
  //It's ok to use a different instance of TraceSource, but with the same name,
  //in this class, the new instance will be configured based on the params in the
  //app.config file.
  //
  private static readonly TraceSource ts = new TraceSource("TraceTest");

  public void DoSomething()
  {
    ts.TraceEvent(TraceEventType.Warning, 2, "File Test not found");   
  }
}

public class C
{
  //
  //Use a different TraceSource in this class.
  //
  private static readonly TraceSource ts = new TraceSource("TraceTestTwo");

  public void DoSomething()
  {
    ts.TraceEvent(TraceEventType.Warning, 2, "File Test not found");   
  }
}

*2. One benefit to using multiple TraceSources is that you have more granular control over your tracing. You can trace via "TraceTest" at one level (or not at all) and via "TraceTestTwo" at a different level (or, again, not at all). You can send each TraceSource to its own TraceListener or send all to the same TraceListener, or mix and match. Compare the ability to tailor the configuration of individual TraceSources to the limitation of only using the static methods on the Trace class. You can configure where the "trace" information goes (which TraceListener(s)) or the level of the "trace" information, but you cannot control the level per class or per functional area like you can when using TraceSources. Finally, one more benefit to multiple TraceSources is the "free" context information that you can get in your output. By default (or optionally, I can't remember), the TraceListener will log the name of the TraceSource that logged a message. So, you can look at that line in your output and get some idea of the class or functional area where it came from without having to put a log of contextual information in the call site. In the code examples above, the trace output from classes A and B will be tagged with "TraceTest" and the trace output from class B will be tagged with "TraceTestTwo".

Please forgive the link bombardment below, but I have posted some pretty good information (if I do say so myself!) about TraceSource and System.Diagnostics in the past.

If you are going to use TraceSource, consider using the library mentioned in this SO post for formatting your output like log4net/NLog:

Does the .Net TraceSource/TraceListener framework have something similar to log4net's Formatters?

See my answer in this post for more info on using TraceSource and some ideas on how you can improve your "TraceSource experience".

More info on TraceSource: Add Trace methods to System.Diagnostics.TraceListener

More info on TraceSource: System.Diagnostics.Debug namespace vs Other logging solutions (log4net, MS Enterprise Library, etc.)

More info on TraceSource: Turning tracing off via app.config