Diagnostics are an important part of any software system. In addition to the obvious necessity of debugging the code, diagnostics can keep track of application performance and liveness, thus indicating a problem proactively, rather than waiting for the phone call from the system administrators.
Diagnostics means more than just compiling with debug symbols turned on. Certain code paths might want to execute only when diagnostics are turned on to full power, indicated by a compile-time switch. At other times, particularly in long-running systems (such as WebService-based systems), developers want to keep a log of the system's actions; frequently, debug reports from users are sketchy ("Um, when I clicked the button, it all just crashed"), and having a complete log of the system's actions can be invaluable in tracking the problem down. Not only can the log consist of custom-written messages (usually to a file), but the Windows Event Log is also available for use from within this namespace.
Diagnostics also includes the ability to track the health and performance of the application; under Windows 2000 and XP, this means interaction with the Performance utility. This is a powerful tool that can be launched from the Administrative Tools program group (under Windows NT, it is called Performance Monitor). By creating appropriate performance counters within the application, .NET programmers can give the system support staff (system administrators and production monitoring personnel, among others) the ability to monitor and track the application, even remotely. In addition to its diagnostic facilities, this namespace exposes operating system processes using the Process type. Use this type to launch new processes or take control of processes currently running on the system. The ProcessThread type lets you drill down into each thread that's running within a process for fine-grained control over running applications.
Most of the functionality in this namespace is disabled at runtime unless you've enabled debugging. If you are using command-line compilers, you can pass the /d:DEBUG switch to enable debugging (to enable tracing, use /d:TRACE). Alternatively, you can use the preprocessor directives #define TRACE or #define DEBUG. The advantage here is that you can leave all your debugging code in, and it does not affect your release builds. The related /debug switch adds debug symbols to your program. You need the debug symbols to obtain source file and line number information in stack traces or to run your program under the control of a debugger. In Visual Studio .NET, you can enable debugging and debug symbols by creating a debug build of your application.
Some diagnostic settings can be controlled using the application configuration file (appname.exe.config). This lets you control trace and debugging behavior without having to recompile. The root element in an application configuration file is the <configuration> element. Create a <system.diagnostics> element within that root element. All the settings mentioned in this chapter must be contained in that <system.diagnostics> element. Figure 29-1, Figure 29-2, Figure 29-3, and Figure 29-4 show the types in this namespace.