DekGenius.com
[ Team LiB ] Previous Section Next Section

Recipe 6.12 Implementing a Simple Performance Counter

Problem

You need to use a performance counter to track application-specific information. The simpler performance counters find, for example, the change in a counter value between successive samplings or just count the number of times an action occurs. Other, more complex counters exist but are not dealt with in this recipe. For example, a custom counter could be built to keep track of the number of database transactions, the number of failed network connections to a server, or even the number of users connecting to your web service per minute.

Solution

Create a simple performance counter that finds, for example, the change in a counter value between successive samplings or to simply count the number of times an action occurs. Use the following method to create a simple custom counter:

public PerformanceCounter CreateSimpleCounter(string counterName, string counterHelp, 
    PerformanceCounterType counterType, string categoryName, string categoryHelp)
{
    CounterCreationDataCollection counterCollection = 
            new CounterCreationDataCollection( );

    // Create the custom counter object and add it to the collection of counters
    CounterCreationData counter = new CounterCreationData(counterName, counterHelp,
            counterType);
    counterCollection.Add(counter);

    // Create category
    if (PerformanceCounterCategory.Exists(categoryName))
    {
        PerformanceCounterCategory.Delete(categoryName);
    }

    PerformanceCounterCategory appCategory = 
        PerformanceCounterCategory.Create(categoryName, 
                                          categoryHelp, counterCollection);

    // Create the counter and initialize it
    PerformanceCounter appCounter = 
        new PerformanceCounter(categoryName, counterName, false);

    appCounter.RawValue = 0;

    return (appCounter);
}

Discussion

The first action this method takes is to create a counterCollection object and CounterCreationData object. The CounterCreationData object is created using the counterName, counterHelp, and countertype parameters passed to the CreateSimpleCounter method. The CounterCreationData object is then added to the counterCollection.

The ASPNET user account, by default, prevents performance counters from being read. You can either increase the permissions allowed by this account or use impersonation to enable this functionality. However, this then becomes a deployment requirement of your web application. Decreasing security for the ASPNET account may very well be frowned upon by IT folks deploying your application.


If categoryName—a string containing the name of the category that is passed as a parameter to the method—is not registered on the system, a new category is created from a PerformanceCounterCategory object. If one is registered, it is deleted and created anew from a PerformanceCounterCategory object. Finally, the actual performance counter is created from a PerformanceCounter object. This object is initialized to zero and returned by the method.

The CreateSimpleCounter method returns a PerformanceCounter object that will be used by an application. The application can perform several actions on a PerformanceCounter object. An application can increment or decrement it using one of these three methods:

long value = appCounter.Increment( );
long value = appCounter.Decrement( );
long value = appCounter.IncrementBy(i);

// Additionally, a negative number may be passed to the 
// IncrementBy method to mimic a DecrementBy method 
// (which is not included in this class). For example:
long value = appCounter.IncrementBy(-i);

The first two methods accept no parameters, while the third accepts a long containing the number by which to increment the counter. All three methods return a long type indicating the new value of the counter.

In addition to incrementing or decrementing this counter, you can also take samples of the counter at various points in the application. A sample is a snapshot of the counter and all of its values at a particular instance in time. A sample may be taken using the following line of code:

CounterSample counterSampleValue = appCounter.NextSample( );

The NextSample method accepts no parameters and returns a CounterSample structure.

At another point in the application, a counter can be sampled again, and both samples can be passed in to the static Calculate method on the CounterSample class. These actions may be performed on a single line of code as follows:

float calculatedSample = CounterSample.Calculate(counterSampleValue, 
                                                 appCounter.NextSample( ));

The calculated sample calculatedSample may be stored for future analysis.

The simpler performance counters already available in the .NET Framework are:


CounterDelta32 /CounterDelta64

Determines the difference (or change) in value between two samplings of this counter. The CounterDelta64 counter can hold larger values than CounterDelta32.


CounterTimer

Calculates the percentage of the CounterTimer value change over the CounterTimer time change.


CounterTimerInverse

Calculates the inverse of the CounterTimer counter.


CountPerTimeInterval32/CountPerTimeInterval64

Calculates the number of items waiting (possibly within a queue) over the time elapsed.


ElapsedTime

Calculates the difference in time between when this counter recorded the start of an event and the current time, measured in seconds.


NumberOfItems32 /NumberOfItems64

This counter returns its raw value. The NumberOfItems64 counter can hold larger values than NumberOfItems32. This counter does not need to be passed to the static Calculate method of the CounterSample class; there are no values that must be calculated. Instead, use the RawValue property of the PerformanceCounter object (i.e., in this recipe, the appCounter.RawValue property would be used).


NumberOfItemsHEX32 /NumberOfItemsHEX64

This counter returns its raw value in hexadecimal format. The NumberOfItemsHEX64 counter can hold larger values than NumberOfItemsHEX32. This counter does not need to be passed to the static Calculate method of the CounterSample class; there are no values that must be calculated. Instead, use the RawValue property of the PerformanceCounter object (i.e., in this recipe, the appCounter.RawValue property would be used).


RateOfCountsPerSecond32 /RateOfCountsPerSecond64

Calculates the RateOfCountsPerSecond* value change over the RateOfCountsPerSecond* time change, measured in seconds. The RateOfCountsPerSecond64 counter can hold larger values than the RateOfCountsPerSecond32 counter.


Timer100Ns

Calculates the percentage of the Timer100Ns value change over the Timer100Ns time change, measured in 100ns time units.


Timer100nsInverse

Calculates the inverse of the Timer100Ns counter.

See Also

See Recipe 6.13; see the "PerformanceCounter Class," "PerformanceCounterType Enumeration," "PerformanceCounterCategory Class," "ASP.NET Impersonation," and "Monitoring Performance Thresholds" topics in the MSDN documentation.

    [ Team LiB ] Previous Section Next Section