Peter Wone
Peter Wone

Reputation: 18805

Why do Trace methods disrespect TraceSwitch?

You'd think Trace.TraceInformation/Warning/Error would respect the level set in a TraceSwitch

Investigation reveals that there can be any number of TraceSwitch instances and therefore it's not clear which one ought to govern behaviour. There is a way to make a TraceSwitch instance take its level from config - you just specify a matching name when you create the instance.

If I'd designed things, the Trace class would have a static property TraceSwitch which would be set by the first trace switch definition in the config, and the TraceInfo etc methods would behave like this

    public static void TraceInformation(string message, params object[] p)
    {
      if (TraceSwitch.TraceInfo)
        //base behaviour
    }

This wasn't hard to produce as a wrapper.

namespace System.Diagnostics
{
  public static class TraceEx
  {
    private static TraceSwitch __traceSwitch;
    public static TraceSwitch TraceSwitch
    {
      get { return __traceSwitch; }
      set { __traceSwitch = value; }
    }
    static TraceEx()
    {
      __traceSwitch = new TraceSwitch("Default", "Default trace level is Off");
    }
    public static void TraceError(string message, params object[] p)
    {
      if (TraceSwitch.TraceError)
        Trace.TraceError(message, p);
    }
    public static void TraceInformation(string message, params object[] p)
    {
      if (TraceSwitch.TraceInfo)
        Trace.TraceInformation(message, p);
    }
    public static void TraceWarning(string message, params object[] p)
    {
      if (TraceSwitch.TraceWarning)
        Trace.TraceWarning(message, p);
    }
    public static void Write(string message, params object[] p)
    {
      if (TraceSwitch.TraceVerbose)
        Trace.Write(string.Format(message, p));
    }
    public static void WriteLine(string message, params object[] p)
    {
      Write(message + "\r\n", p);
    }
  }
}

Putting it in the same namespace meant all I had to do was reference the project and rename Trace to TraceEx. The question I'm posing is this: why didn't Microsoft do it like this? Is there some looming gotcha I haven't seen?


Well, that was unexpected (see accepted answer). Which only goes to show I was right to suspect I hadn't understood the grand design. All of the above turns into this:

<userSettings>
    <TraceFilterExperiment.Properties.Settings>
        <setting name="TraceLevel" serializeAs="String">
            <value>Warning</value>
        </setting>
    </TraceFilterExperiment.Properties.Settings>
</userSettings>

var eventTypeFilter = new EventTypeFilter(Properties.Settings.Default.TraceLevel);
foreach (TraceListener L in Trace.Listeners) 
  L.Filter = eventTypeFilter;

But I remain hazy on what exactly one would really do with TraceSwitch.

Upvotes: 0

Views: 471

Answers (1)

Jim Mischel
Jim Mischel

Reputation: 134125

The behavior you're suggesting already exists, albeit in a somewhat different form: you modify the listeners to enable the different error levels.

With your suggested behavior, sending different levels to different places (for example, verbose information to a log file, but only critical errors to the console) would require that your default trace switch be set to "allow everything," just as it is with the existing behavior. In other words, if a programmer wants to use Trace switches as they're intended, he would have to create a dummy trace switch that allows everything, and somehow make sure that it's the first trace switch defined. It's quite possible, for example, that switches are defined in some other configuration file (i.e. not application.exe.config), and there's no way to guarantee the order in which configuration files are loaded.

The Trace class itself is not the place to enforce the policy that you're suggesting. Trace exists to provide a common interface and a centralized point where trace messages can be sent and then distributed. It is the application's job to determine (via trace switches) what information is sent, and it is the listeners' job to determine whether that information is output.

The behavior you propose makes things easier for one particular application of Trace. It makes it confusing, more difficult, and possibly inconsistent for all other applications.

Upvotes: 2

Related Questions