.Net Diagnostics

Code Contracts

Code contracts provide a way to specify preconditions, postconditions, and object invariants in your code. Preconditions are requirements that must be met when entering a method or property. Postconditions describe expectations at the time the method or property code exits. Object invariants describe the expected state for a class that is in a good state.

The benefits of code contracts include the following:

  • Improved testing: Code contracts provide static contract verification, runtime checking, and documentation generation.

  • Automatic testing tools: You can use code contracts to generate more meaningful unit tests by filtering out meaningless test arguments that do not satisfy preconditions.

  • Static verification: The static checker can decide whether there are any contract violations without running the program. It checks for implicit contracts, such as null dereferences and array bounds, and explicit contracts.

  • Reference documentation: The documentation generator augments existing XML documentation files with contract information. There are also style sheets that can be used with Sandcastle so that the generated documentation pages have contract sections.

Preconditions

For example, the following precondition expresses that parameter x must be non-null.

Contract.Requires(x != null);

If your code must throw a particular exception on failure of a precondition, you can use the generic overload of Requires as follows.

Contract.Requires<ArgumentNullException>(x != null, "x");

Postconditions

You can express standard postconditions by using the Ensures method. Postconditions express a condition that must be true upon normal termination of the method.

Contract.Ensures(this.F > 0);

Exceptional Postconditions

Exceptional postconditions are postconditions that should be true when a particular exception is thrown by a method. You can specify these postconditions by using the Contract.EnsuresOnThrow method, as the following example shows.

Contract.EnsuresOnThrow<T>(this.F > 0);

Invariants

Object invariants are conditions that should be true for each instance of a class whenever that object is visible to a client. They express the conditions under which the object is considered to be correct. The invariant methods are identified by being marked with the ContractInvariantMethodAttribute attribute. The invariant methods must contain no code except for a sequence of calls to the Invariant method, each of which specifies an individual invariant, as shown in the following example.

[ContractInvariantMethod]
protected void ObjectInvariant ()
{
    Contract.Invariant(this.y >= 0);
    Contract.Invariant(this.x > this.y);
    ...
}

Invariants are conditionally defined by the CONTRACTS_FULL preprocessor symbol. During run-time checking, invariants are checked at the end of each public method. If an invariant mentions a public method in the same class, the invariant check that would normally happen at the end of that public method is disabled. Instead, the check occurs only at the end of the outermost method call to that class.

Tracing, Event Tracing for Windows (ETW)

Event Tracing for Windows (ETW) is an efficient kernel-level tracing facility that lets you log kernel or application-defined events to a log file. You can consume the events in real time or from a log file and use them to debug an application or to determine where performance issues are occurring in the application. ETW lets you enable or disable event tracing dynamically, allowing you to perform detailed tracing in a production environment without requiring computer or application restarts. The Event Tracing API is broken into three distinct components:

  • Controllers, which start and stop an event tracing session and enable providers

  • Providers, which provide the events

  • Consumers, which consume the events

Controllers

Controllers are applications that define the size and location of the log file, start and stop event tracing sessions, enable providers so they can log events to the session, manage the size of the buffer pool, and obtain execution statistics for sessions. Session statistics include the number of buffers used, the number of buffers delivered, and the number of events and buffers lost.

Providers

Providers are applications that contain event tracing instrumentation. After a provider registers itself, a controller can then enable or disable event tracing in the provider. The provider defines its interpretation of being enabled or disabled. Generally, an enabled provider generates events, while a disabled provider does not. This lets you add event tracing to your application without requiring that it generate events all the time. Although the ETW model separates the controller and provider into separate applications, an application can include both components.

Consumers

Consumers are applications that select one or more event tracing sessions as a source of events. A consumer can request events from multiple event tracing sessions simultaneously; the system delivers the events in chronological order. Consumers can receive events stored in log files, or from sessions that deliver events in real time. When processing events, a consumer can specify start and end times, and only events that occur in the specified time frame will be delivered.

Event Logging

System administrators use the Event Viewer to get critical messages about the health of the system and applications, and informational messages. You should write error messages from your application to the event log so that the information can be read with the Event Viewer. Trace messages can be written to the event log if you configure the EventLogTraceListener class. The EventLogTraceListener has an EventLog object associated with it to write the event log entries. You can also use the EventLog class directly to write and read event logs.

Event-logging Classes

For writing event logs, two different Windows APIs exist. One API, available since Windows Vista, is wrapped by the classes in the namespace System.Diagnostics.Eventing. The other wrapper classes are in the System.Diagnostics namespace.

To write events to log you have to:

Create event source

string logName = "ProCSharpLog";
string sourceName = "EventLogDemoApp";

 if (!EventLog.SourceExists(sourceName))
 {
     var eventSourceData = new EventSourceCreationData(sourceName, logName);
     EventLog.CreateEventSource(eventSourceData);
 }
 
 using (var log = new EventLog(logName, ".", sourceName))
 {
     log.WriteEntry("Message 1");
     log.WriteEntry("Message 2", EventLogEntryType.Warning);
     log.WriteEntry("Message 3", EventLogEntryType.Information, 33);
 }

After this you can read the event log entries with the Event Viewer.

Performance Monitoring

Performance monitoring can be used to get information about the normal behavior of applications, to compare ongoing system behavior with previously established norms, and to observe changes and trends, particularly in applications running on the server. When you have a scenario of more and more users accessing the application, before the first user complains about a performance issue, the system administrator can already act and increase resources where needed. The Performance Monitor (PerfMon) is a great tool to see all the performance counts for acting early. Microsoft Windows has many performance objects, such as System, Memory, Objects, Process, Processor, Thread, Cache, and so on. Each of these objects has many counts to monitor. For example, with the Process object, the user time, handle count, page faults, thread count, and so on can be monitored for all processes or for specific process instances.

The System.Diagnostics namespace provides the following classes for performance monitoring:

  1. PerformanceCounter — Can be used both to monitor counts and to write counts. New performance categories can also be created with this class.

  2. PerformanceCounterCategory — Enables you to step through all existing categories, as well as create new ones. You can programmatically obtain all the counters in a category.

  3. PerformanceCounterInstaller — Used for the installation of performance counters. Its use is similar to that of the EventLogInstaller discussed previously.

PerfomanceCounter can be created like this to use predefined counter:

private PerformanceCounter theCPUCounter = 
   new PerformanceCounter("Process", "% Processor Time",              
      Process.GetCurrentProcess().ProcessName);

Or also you can create your own counter and view it via perfmon.exe

string categoryName = "Football";
             
if (!PerformanceCounterCategory.Exists(categoryName))
{
    string firstCounterName = "Goals scored";
    string firstCounterHelp = "Goals scored live update";
    string categoryHelp = "Football related real time statistics";
                 
    PerformanceCounterCategory customCategory = new PerformanceCounterCategory(categoryName);
    PerformanceCounterCategory.Create(categoryName, categoryHelp, PerformanceCounterCategoryType.SingleInstance, firstCounterName, firstCounterHelp);
}

//update of values
string counterName = "Goals scored";
PerformanceCounter footballScoreCounter = new PerformanceCounter(categoryName, counterName);
footballScoreCounter.ReadOnly = false;
while (true)
{
    footballScoreCounter.Increment();
    Thread.Sleep(1000);
    Random random = new Random();
    int goals = random.Next(-5, 6);
    footballScoreCounter.IncrementBy(goals);
    Thread.Sleep(1000);
}

Last updated