runtime: System.Diagnostics.TraceSource doesn't read configuration from App.config in .NET Core?

The following code outputs “Hello, world!” as a trace message to the console when in a .NET Framework console application. When the same code is used in a .NET Core console application, it outputs nothing.

Program.cs

using System.Diagnostics;

namespace ConsoleApp5
{
    class Program
    {
        private readonly static TraceSource traceSource = new TraceSource("ConsoleApp5", SourceLevels.All);

        static void Main(string[] args)
        {
            traceSource.TraceEvent(TraceEventType.Information, 0, "Hello, world!");
        }
    }
}

App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <trace autoflush="true">
      <listeners>
        <add name="consoleTraceListener" />
        <add name="textWriterTraceListener" />
      </listeners>
    </trace>
    <sharedListeners>
      <add name="consoleTraceListener" type="System.Diagnostics.ConsoleTraceListener" traceOutputOptions="DateTime,ThreadId" />
      <add name="textWriterTraceListener" type="System.Diagnostics.TextWriterTraceListener" traceOutputOptions="DateTime,ThreadId" initializeData="Trace.log" />
    </sharedListeners>
    <sources>
      <source name="ConsoleApp5" switchValue="Verbose">
        <listeners>
          <add name="consoleTraceListener" />
          <add name="textWriterTraceListener" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>
</configuration>

Also, I found that if I try to read a connection string using System.Configuration.ConfigurationManager and I have the system.diagnostics section in the App.config, I receive the following error. I’m assuming that .NET Core doesn’t have a machine.config where the system.diagnostics section would normally be defined?

Unhandled Exception: System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize ---> System.Configuration.ConfigurationErrorsException: Unrecognized configuration section system.diagnostics. (C:\Users\jemiller\Documents\Visual Studio 2017\Projects\Library2\LibraryConsoleApplication\bin\Debug\netcoreapp2.0\LibraryConsoleApplication.dll.config line 6)
   at System.Configuration.ConfigurationSchemaErrors.ThrowIfErrors(Boolean ignoreLocal)
   at System.Configuration.BaseConfigurationRecord.ThrowIfParseErrors(ConfigurationSchemaErrors schemaErrors)
   at System.Configuration.ClientConfigurationSystem.EnsureInit(String configKey)
   --- End of inner exception stack trace ---
   at System.Configuration.ClientConfigurationSystem.EnsureInit(String configKey)
   at System.Configuration.ClientConfigurationSystem.PrepareClientConfigSystem(String sectionName)
   at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(String sectionName)
   at System.Configuration.ConfigurationManager.GetSection(String sectionName)
   at System.Configuration.ConfigurationManager.get_ConnectionStrings()
   at LibraryLibrary.LibraryContext..ctor(String name) in C:\Users\jemiller\Documents\Visual Studio 2017\Projects\Library2\LibraryLibrary\LibraryContext.cs:line 43
   at LibraryLibrary.LibraryContext..ctor() in C:\Users\jemiller\Documents\Visual Studio 2017\Projects\Library2\LibraryLibrary\LibraryContext.cs:line 39
   at LibraryConsoleApplication.Program.Main(String[] args) in C:\Users\jemiller\Documents\Visual Studio 2017\Projects\Library2\LibraryConsoleApplication\Program.cs:line 13

Is there I way I could specify the section similar to the following to get it to work? That is how it is defined in machine.config for .NET Framework.

  <configSections>
    <section name="system.diagnostics" type="System.Diagnostics.SystemDiagnosticsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
  </configSections>

Is there some other way in .NET Core to specify that configuration settings for system.diagnostics?

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 15
  • Comments: 66 (31 by maintainers)

Most upvoted comments

Because the Close button is too close to the Comment button 😃

I just spent a couple hours trying to figure this out. Why is this not well advertised? Developers are going to beat their heads on this like I did and that’s really bad business for y’all.

I just wanted to chime in as well and say what a loss this is. We used System.Diagnostics.Trace a lot, and it is pretty much the remaining issue in our Framework to Core migration, and a big one.

With System.Diagnostics.Trace:

  • internal components can expose trace output
  • activity can be correlated. for example, we can start an “operation”, and that operation will flow through to other components that are tracing
  • components can expose multiple discrete trace sources
  • components can access discrete trace options. for example, we can have a trace switch for whether or not to trace raw HTTP request and response data to our vendors
    • this is separate from “verbose”, “info”, “warning”, etc.
    • as a concrete example, each vendor integration has its own trace source. but they share a low-level HTTP component. That HTTP component has a switch for whether or not to trace the raw request/response data (which it will emit as ‘verbose’). The raw data tracing comes out of each vendor’s own trace source (each with its own current output level), hence we can specifically control the raw HTTP request/response data tracing, even though each vendor’s output will be coming out of its own trace source (tagged with the correlation id of the overall operation!)
      • thus if only one of those vendors is wired up to trace at “Verbose” level, only that vendor will have such output
  • different trace outputs can be routed to different locations (e.g. event log, file, database)
  • all of this can be configured via the config file

ILogger can also be set up with the config file, but doesn’t provide anything close to this. For example having a component expose multiple sources, or having specific tracing options (like the HTTP request/response data option). And the scoping seems to be per-log source, rather than carrying through across multiple components. The biggest issue is it can only be used via dependency injection, which is not always practical - e.g. how do you trace out of an extension method? Logging always seemed to be one of those grey areas for dependency injection, but in any case Logging is not quite the same as Tracing.

DiagnosticSource is a bit closer (any component can emit a diagnostic source), but it’s pretty onerous to use and to attach listeners. Everything would have to be done in code, and basically we’ll have to take all the informal Tracing, and put object wrappers on everything, it seems, in order for anything to make sense: It’s more of an event logging framework as far as I can tell. Hence its similarity to EventSource.

I tried wiring things up in code, but that still leaves TraceSwitches - I can configure the trace listeners and whatnot in Startup but there’s no way I can see to set a trace switch, they used to read from the configuration to set their runtime value

So, why is this being closed? TraceSource is basically completely non-usable as it stands now.

Thanks @steveharter for fixing this as a DCR. Hopefully this allows the folks above to migrate from .NET Framework to .NET 7. Commenters above, please let us know if this doesn’t unblock you.

… this is what happens when every few years a group of new developers appear which don’t have adequate exposure to technology, declare it bad, then start removing/replacing things that worked perfectly fine.

after 30+ years of programming i’ve learned that nothing survives, not even good things. sad, but true. everything everyone has worked on in .NET Core these past few years will also, eventually, be undone by some future generation of programmers that don’t have adequate exposure to technology, will declare it bad, then start removing/replacing things that work perfectly fine.

nothing fundamentally changed, but it was still changed. between the lack of backward compatibility (FROM MICROSOFT NO LESS!) and perpetual bugs being introduced to their development tools i’ve decided to retire early. make hay in the sun, watch the cattle graze, etc. i’ll come back if we’re lucky enough to experience another Carrington event and actually need to rebuild the world… but as it is, there are better things to invest precious lifespan into than other people’s messes.

</bittervet-rant>

Loosely related, https://github.com/wilson0x4d/diagnostics#bootstrapping-systemdiagnostics-in-net-core

… but it is not maintained, and not the most elegant code I’ve ever written, but if someone is determined to use app.config files and the classic logging framework then you may find some joy there.

such a shame. from DI to logging and everything in between +poof+ gone. what began as a xplat initiative turned into a rewrite from the ground up.

It would be great if Microsoft would add this functionality back in. The new logging API that requires dependency injection and other third party libraries is a monstrosity. You should not have to rely on third party software for something as fundamental as logging. Also, you shouldn’t have to rely on overly complicated design patterns such as dependency injection. TraceSource was straight forward and easy to use. The new way isn’t. Maybe it’s fine for an ASP.NET application, where it originated. It is not fine for a simple console application.

The latter looks like the root cause of several other issues we thought were caused by the CPS

Whenever you see ConfigurationErrorsException: Unrecognized configuration section it means the app.config used a named section that wasn’t registered. In .NETFramework that would happen in machine.config. In .NETCore we don’t have a machine.config, instead we have an implicit one https://github.com/dotnet/runtime/blob/cd75ae127698b66821b5a2d364aa5ff7aa1a4a2a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ImplicitMachineConfigHost.cs#L75-L94 Since we don’t have all the same sections supported in .NETCore many of those sections are not registered at all and produce this exception. The right fix in most cases is to remove the unused portion of the app.config. Perhaps we should improve that exception message so that it lets the developer know what to do.

@deeprobin please hold off for now. We need API to fix this.

@RussKie that’s because ConfigurationManager doesn’t have the type registration for the section. I’ve added that in a prototype here; https://github.com/ericstj/runtime/tree/addDiagConfig. We’ll need some more work to refine API on this and test it if we want to make the change. Removing up-for-grabs for now.

The logic to read the TraceSource initialization xml should live in https://github.com/dotnet/runtime/tree/main/src/libraries/System.Configuration.ConfigurationManager/src . Would it make sense to do it implicitly when the ConfigurationManager is initialized (no new method required)?

TraceSource would have to expose a few new public methods to make it possible for System.Configuration.ConfigurationManager to initialize it. For example, a new method to return all TraceSwitches instance. These new public methods would have to go through an API review.

Wait, so you’re telling me that we have win32 forms in .net core 6, but no tracing? Let me repeat that again, are you telling me there isn’t any way to do tracing in .net core??? Someone needs to lay off the crack.

oversight?

TraceSource is a very slow tracing mechanism. It was an intentional decision to remove it as the tracing mechanism for the core .NET runtime libraries, not an oversight.

.NET runtime libraries such as networking or sockets have been unified on System.Diagnostics.EventSource as the one and only built-in high-performance tracing mechanism.

rewrite all tracing simply because there’s no way to configure TraceSource, TraceSwitch

TraceSource can be configured programmatically as shown above.

Marco, is this a fair summary of your suggestions?

  1. stick on .NET Framework 4.8 forever
  2. rewrite all tracing simply because there’s no way to configure TraceSource, TraceSwitch

and that as long as Microsoft makes money, there is no reason for them to work out this oversight?

Being honest with yourself, do these seem like particularly constructive suggestions?

“It does not benefit you to fight the people who fight for more.”

I think this got directed to the wrong devs, we want https://github.com/orgs/dotnet/teams/area-system-diagnostics-tracesource for this. Thanks @tarekgh for helping clarify ownership here and I noticed @jkotas fixed the label, appreciate it!

@wilson0x4d What you said is exactly how I feel about it. Looking forward to retirement. I have often theorized that all the original developers at Microsoft who created .NET quit for higher paying jobs elsewhere. Then Microsoft was left with people who didn’t know the existing code base who decided to re-write everything. That might be fine if the result was something that worked better, but, that’s not the case. Web development in particular has taken a turn for the worse. It was better 20 years ago.

The .NET Core geniuses decided config files are bad and got rid of them

For what it’s worth, we migrated to NLog and its support to load from Config files without restarting has helped tremendously. It’s performance is among the best as well. Very happy with our choice.

On Mon, Oct 28, 2019 at 15:01 Jon Miller notifications@github.com wrote:

I should say, maybe I would be fine with configuring it programmatically. That is, if you could configure it globally. The way it stands now, you can’t. You have to configure each TraceSource instance, which typically are going to be all over the place. For practical purposes, it makes it unusable. Unfortunately, Microsoft doesn’t care. They would rather just push you into using the new piece of garbage.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/dotnet/corefx/issues/24829?email_source=notifications&email_token=ADVNZV4QIZYVW6CVGUQGVLTQQ4ZGXA5CNFSM4EAOHWDKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOECOAV7A#issuecomment-547097340, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADVNZV7AVVNQ5OJFHQL54GLQQ4ZGXANCNFSM4EAOHWDA .

ConfigurationManager is there now. However, it has been lobotomized and only supports things like ConnectionStrings. And App.config doesn’t work in certain contexts, like if you have a unit test assembly, it is not read. System.Diagnostics.TraceSource doesn’t use App.config in .NET Core. So, you have to programmatically configure every single instance you have, making it for practical purposes unusable.

I looked at the source code for TraceSource in .NET Core. It appears that the code does not read configuration settings from App.config. In addition, it looks like .NET Core doesn’t even have a ConsoleTraceListener. So, it looks like you can’t even log to the console using TraceSource even if you programmatically configured it.