Skip to content

[API Proposal]: support System.Diagnostics.TraceSource to be initialized from the app.config file. #72967

@steveharter

Description

@steveharter

Background and motivation

Original issue: #23937

This helps adoption from those moving from .NET Framework who use TraceSource for logging. There is currently no support for automatically reading the app.config and applying those settings to TraceSource and associated TraceFilter and TraceSwitch instances. Support for Trace.Refresh() based on .NET Framework is also added which allows the application to update existing TraceSource and Switch instances when the config file changes.

The TraceSource code lives in System.Diagnostics.TraceSource.dll which is shipped inbox but the processing of the app.config is done in System.Configuration.ConfigurationManager.dll which is OOB.

The proposed APIs essentially allow interaction between these two separate assemblies and these APIs are used internally and not intended for general use. The one exception is the TraceConfiguration.Register() method to light-up the config side.

Although not a stated goal in the issue above, these new APIs make it possible to support reading from another format, such as a JSON file, by using a similar approach as done in System.Configuration.ConfigurationManager.dll which reads from the app.config XML file.

API Proposal

These live in System.Diagnostics.TraceSource.dll:

namespace System.Diagnostics
{
    public abstract class Switch
    {
         // Needed to reset Value if this Switch is removed from config and Trace.Refresh is called.
+        public string DefaultValue { get { throw null; } }

-        protected string Value { get; set; }
+        public string Value { get; set; }

         // Called by the config system when Trace.Refresh() is called.
+        public void Refresh();

         // Invoke the config system to initialize the switch from the config file.
+        public static event EventHandler<InitializingSwitchEventArgs>? Initializing { add; remove; }
    }

    public sealed class Trace
    {
         // Invoke the config system to refresh TraceSources from the config file
+        public static event EventHandler? Refreshing{ add; remove; }
    }

    public class TraceSource
    {
         // Needed to reset Level if removed from config and Trace.Refresh is called.
+        public SourceLevels DefaultLevel { get; }

         // Invoke the config system to initialize a TraceSource.
+        public static event EventHandler<InitializingTraceSourceEventArgs>? Initializing { add; remove; }
    }

+    public sealed class InitializingSwitchEventArgs : EventArgs
+    {
+        public InitializingSwitchEventArgs(Switch @switch);
+        public System.Diagnostics.Switch Switch { get; }
+    }

+    public sealed class InitializingTraceSourceEventArgs : EventArgs
+    {
+        public InitializingTraceSourceEventArgs(TraceSource traceSource) { }
+        public System.Diagnostics.TraceSource TraceSource { get; }
+        public bool WasInitialized { get; set; }
+    }
}

These live in System.Configuration.ConfigurationManager.dll:

// Use the Diagnostics namespace even though in config
namespace System.Diagnostics
{
+    public static class TraceConfiguration
+    {
+        // Subscribe to the new events and create TraceSources etc. from the config file.
+        // This is really the only new API that is called by the user; the rest are for internal use.
+        // Is there a better name here? Such as "EnableConfigurationFiles()"
+        public static void Register();
+    }
}

API Usage

Given the app.config file:

<configuration>
  <system.diagnostics>
    <sources>
      <source name="TestTraceSource">
        <listeners>
          <add name = "listener" type="System.Diagnostics.TextWriterTraceListener" initializeData="listener.log" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>
</configuration>

Then code using TraceSource will be initialized to the values in the app.config:

TraceConfiguration.Register(); // Needed to light up the config system (not necessary in .NET Framework)
TraceSource trace = new("TestTraceSource");
int i = trace.Listeners.Count; // Returns 2; one for the default, and one for the entry in the app.config

Alternative Designs

No response

Risks

No response

Metadata

Metadata

Assignees

Labels

api-approvedAPI was approved in API review, it can be implementedarea-System.DiagnosticsblockingMarks issues that we want to fast track in order to unblock other important work

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions