Objective C # principle 36: use. Net runtime diagnostics)

Source: Internet
Author: User

Objective C # principle 36: diagnosis during. Net Runtime
Item 36: leverage. Net runtime diagnostics

When a problem occurs, they often do not occur during the experiment, and the machine has a tool for easy debugging. In many cases, problems that you cannot correct always occur on your machine, where there is no debugging environment and there is no good way to calculate problems. In practice, experienced developers will create a method for the system to capture as much information as possible during runtime .. The. NET Framework already contains some class sets. With these sets, you can perform some common debugging. In addition, these classes can be configured at runtime or during compilation. If you use them, you can easily find problems during actual operation. Use the existingCodeYou can send a Diagnostic message to a file or to a debugging terminal. In addition, you can specify a special debugging output level for your product. You should use these features in your development environment as soon as possible to ensure that you can use the output information to correct unexpected issues during actual operation. Do not write the diagnostic database on your own unless you understand what the framework already provides.

The system. Diagnostics. debug, system. Diagnostics. Trace and system. Diagnostics. EventLog classes provideProgramAll tools to create diagnostic information. The functions of the first two classes are basically the same. Apart from the differences, the trace class is controlled by the preprocessing operator trace, while the debug class is controlled by the debug preprocessing operator. When you develop a project using vs.net, the trace symbol is defined in both the debug and publish versions. You can use the trace class to create diagnostic information for all releases. The EventLog class provides an entry through which your program can write some system logs. The EventLog class does not support runtime configuration, but you can encapsulate it into a unified simple interface.

You can control the diagnostic output at runtime, And the. NET Framework uses an application configuration file to control various runtime settings. This is an XML file in the directory when the main application is running. This file has the same name as the application, but adds a. config suffix. For example, myapplication.exe can have an XML file of myapplication.exe. config to control it. All configuration information is contained in a configuration node:

<? XML version = "1.0" encoding = "UTF-8"?>
<Configuration>

</Configuration>

The. NET Framework uses predefined keywords to control the behavior of some classes in the framework. In addition, you can define your own configuration keywords and values.

You can combine the output switch and the trace. writelineif () method to control the output of the application. You can disable this output by default outside the application so that the application can achieve the best performance. When a problem is detected, you can enable this output to diagnose and correct the problem encountered in practice. Writelineif () is output only when the expression is true:

Bool _ printdiagnostics = true;
Trace. writelineif (_ printdiagnostics,
"Printing diagnostics today", "mysubsystem ");

The output switch you created is used to control the output level. An output switch can be a variable defined by the application configuration file and can be in one of the five states: off ), error, warning, info, and verbose ). These statuses are a part of the environment, and their values can be from 0 to 4. In this way, you may create a control for all Subsystem information. Define an output switch class and initialize it to create a switch:

Static private traceswitch libraryswitch = new
Traceswitch ("myassembly ",
"The switch for this Assembly ");

The first parameter is the name displayed by the switch, and the second parameter is the description. In this way, you can configure their values in the application configuration file at runtime. Set libraryswitch to Info:

<System. Diagnostics>
<Switches>
<Add name = "myassembly" value = "3"/>
</Switches>
</System. Diagnostics>

If you have edited the switch value in this configuration file, you have modified all the output statements controlled by that switch.

Another task: You need to configure where your output goes. By default, it is a listener linked to the trace class: A defaulttracelistener object. Defaulttracelistener sends information to the debugger, and some diagnostic information is printed and then terminated in its failure method (called when an assertion fails. In the product release environment, you cannot see such information. However, you can configure different listening objects to the product release environment: Add listeners to the application configuration file. The following adds a textwritertracelistener to the application:

<System. Diagnostics>
<Trace autoflush = "true" indentsize = "0">
<Listeners>
<Add name = "mylistener"
Type = "system. Diagnostics. textwritertracelistener"
Initializedata = "mylistener. log"/>
</Listeners>
</Trace>
</System. Diagnostics>

Textwritertracelistener prints all diagnostic information to a mylistener. log file. The name attribute specifies the name of the listener, and the type specifies the type of the listener object. It must be derived from system. Diagnostics. tracelistener. Only in rare cases do you create your own listener class, that is, you think the listener class of the. NET Framework is not enough. The value of initializedata is a string used to pass to the object constructor. Textwritertracelisteners uses it for file names.

You can make a small extension so that it can be easily used in every deployed assembly in the application. For each assembly, add a class to track the diagnosis created by the Assembly:

Internal class myassemblydiagnostics
{
Static private traceswitch myassemblyswitch =
New traceswitch ("myassembly ",
"The switch for this Assembly ");

Internal static void MSG (tracelevel L, object O)
{
Trace. writelineif (myassemblyswitch. level> = l,
O, "myassembly ");
}

Internal static void MSG (tracelevel L, string S)
{
Trace. writelineif (myassemblyswitch. level> = l,
S, "myassembly ");
}

// Add additional output methods to suit.
}

The myassemblydiagnostices class creates diagnostic information for this Assembly based on a switch. To create information, call any of the MSG that is reloaded by the general call:

Public void Method1 ()
{
Myassemblydiagnostics. MSG (tracelevel. info,
"Entering method1 .");

Bool rval = domorework ();

If (rval = false)
{
Myassemblydiagnostics. MSG (tracelevel. Warning,
"Domorework failed in Method1 ");
}

Myassemblydiagnostics. MSG (tracelevel. info,
"Exiting method1 .");
}

With a global switch, you can also component A Special Assembly switch to control the output of the entire application:

Internal static void MSG (tracelevel L, object O)
{
Trace. writelineif (libraryswitch. level> = L |
Globalswitch. level> = l,
O, "mylibrary ");
}

Internal static void MSG (tracelevel L, string S)
{
Trace. writelineif (libraryswitch. level> = L |
Globalswitch. level> = l,
S, "mylibrary ");
}

In this way, you can diagnose information on the application and control the output of individual library files more effectively. Anywhere in an application, you can set application-level diagnostics to error-level to discover errors. When you have an independent problem, you can improve the output level of the database to precisely identify the source of the problem.

In the actual environment, the diagnostic library is required for program Diagnosis and Maintenance for deployed applications. However, you do not have to write these diagnostic libraries:. Net FCL has completed the core functions. Use them as completely as possible, and then extend them when special requirements are met. In this way, all problems can be captured even in the product release environment.
============================

Item 36: leverage. Net runtime diagnostics
Problems happen. they don't always happen in the lab, on machines you can easily debug. the problems you can't fix always seem to occur on one user's machine in the field, with no debugging environment and no way to figure out the cause. experienced developers have learned to build in the capability to capture as much information as possible from systems running in the field. the. net Framework except des a set of classes that you can use to generate diagnostics. these are retriable at runtime or compile time. if you leverage them, you can more quickly find problems that occur only in the field. using Code already in the framework, you can send diagnostic messages to a file, to the system logger, or to a debugging terminal. in addition, you can specify the level of debugging output that your program produces. you shoshould use these features early in your development and make sure that you can produce the output you need to fix unanticipated problems in the field. don't write your own diagnostic library until you understand what's already provided.

the system. diagnostics. debug, system. diagnostics. trace, and system. diagnostics. eventLog classes provide all the tools you need to create diagnostic information from a running program. the first two classes have almost identical capabilities. the difference is that the trace class methods are controlled by the trace Preprocessor symbol, and the debug class methods are controlled by the debug Preprocessor symbol. when you create a project with. net, the trace symbol is defined for both release and debug builds, while the debug symbol is defined only for debug builds. you create all your release build diagnostics using the trace class. the EventLog class provides entry points so that your application can write to the System Event Log. the EventLog class does not support runtime configuration, but you can wrap it to conform to the same interface using strated shortly.

You can also control the diagnostic output at runtime. the. net Framework uses an application-configuration file to control a variety of runtime settings. this file is an XML document, located in the same directory as the main executable. the file shares the same name as the executable,. config appended. for example, myapplication.exe wocould be controlled by the myapplication.exe. config XML document. all the configuration information is contained in a configuration node:

<? XML version = "1.0" encoding = "UTF-8"?>
<Configuration>

</Configuration>

 

The. NET Framework uses predefined keys to control the behavior of framework classes. In addition, you can define your own configuration keys and values.

You combine the trace. writelineif () method and traceswitches to control the granularity of the output that your application generates. you turn off output by default so that you get the most performance possible out of your application. when you find problems, you can ratchet up the output to diagnose and correct any problems you find in the field. writelineif () generates output only when an expression evaluates to true:

Bool _ printdiagnostics = true;
Trace. writelineif (_ printdiagnostics,
"Printing diagnostics today", "mysubsystem ");

 

You create traceswitches to control the level of output. A traceswitch is a variable set using the application-configuration file to one of five states: off, error, warning, info, and verbose. these States are part of an enumeration and have values from 0 to 4. you can create a switch for each subsystem to control its messages. to create the switch, declare a variable of the traceswitch class and construct it:

Static private traceswitch libraryswitch = new
Traceswitch ("myassembly ",
"The switch for this Assembly ");

 

The first parameter is the display name for the switch; the second parameter is the description. you set the value of the switch at runtime in the application configuration file. the following snippet sets the libraryswitch to Info:

<System. Diagnostics>
<Switches>
<Add name = "myassembly" value = "3"/>
</Switches>
</System. Diagnostics>

 

If you edit the config file's value of the switch, you modify the output generated by all statements controlled by that switch.

One more task: You need to configure where your trace output goes. by default, One listener is connected to the trace class: A defaulttracelistener object. the defaulttracelistener sends messages to the debugger, and its fail method (called when asserts fail) prints a diagnostic messages and terminates the program. in a production environment, you won't see any of the messages. you can configure a different listener in a production environment; you add listeners in the application configuration file. the following snippet adds a textwritertracelistener to your application:

<System. Diagnostics>
<Trace autoflush = "true" indentsize = "0">
<Listeners>
<Add name = "mylistener"
Type = "system. Diagnostics. textwritertracelistener"
Initializedata = "mylistener. log"/>
</Listeners>
</Trace>
</System. Diagnostics>

 

This textwritertracelistener prints all diagnostic information to the mylistener. log File. the name attribute specifies the name for the listener. the Type specifies the type of object to create as a listener; it must be derived from system. diagnostics. tracelistener. on those rare occasions when the standard listener classes in. NET framework are not enough for you, create your own listener class. the initializedata value is a string that gets passed to the object's constructor. textwritertracelisteners use this value for the filename.

You can extend these basics a bit to make it easier to create diagnostics for each assembly you distribute in your application. for each assembly you create, add a class to track the diagnostics generated by that Assembly:

Internal class myassemblydiagnostics
{
Static private traceswitch myassemblyswitch =
New traceswitch ("myassembly ",
"The switch for this Assembly ");

Internal static void MSG (tracelevel L, object O)
{
Trace. writelineif (myassemblyswitch. level> = l,
O, "myassembly ");
}

Internal static void MSG (tracelevel L, string S)
{
Trace. writelineif (myassemblyswitch. level> = l,
S, "myassembly ");
}

// Add additional output methods to suit.
}

 

The myassemblydiagnostices class creates diagnostic messages for the Assembly, depending on a switch for that Assembly. To generate a message, call either of the overloaded MSG routines:

Public void Method1 ()
{
Myassemblydiagnostics. MSG (tracelevel. info,
"Entering method1 .");

Bool rval = domorework ();

If (rval = false)
{
Myassemblydiagnostics. MSG (tracelevel. Warning,
"Domorework failed in Method1 ");
}

Myassemblydiagnostics. MSG (tracelevel. info,
"Exiting method1 .");
}

 

You can also combine the Assembly-specific switch with a global switch to control the entire application's output:

Internal static void MSG (tracelevel L, object O)
{
Trace. writelineif (libraryswitch. level> = L |
Globalswitch. level> = l,
O, "mylibrary ");
}

Internal static void MSG (tracelevel L, string S)
{
Trace. writelineif (libraryswitch. level> = L |
Globalswitch. level> = l,
S, "mylibrary ");
}

This enables you to control application-wide diagnostics and more finely control an individual library's output. you can set the application-level diagnostics to the error level to find errors anywhere in the application. when you have isolated the problem, you can raise the level of that one library's output to a higher level and find the exact source of the problem.

Diagnostic libraries are necessary to diagnose and maintain programs that have been distributed to the field. don't write your own diagnostic library:. net FCL already has the core features you need. use it to the fullest and then extend it for your own purposes, and you will capture all problems, even in production environments

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.