DekGenius.com
[ Team LiB ] Previous Section Next Section

Recipe 6.13 Implementing Performance Counters that Require a Base Counter

Problem

You need to use some of the more advanced performance counters to accurately track information about your application. This performance counter exists as two counters used together. The first counter is the main counter, which is divided by the second counter, called the base counter. Essentially, the first counter is the numerator and the second counter is the denominator; the custom counter reports the result of this division operation. The main counter is used in tandem with its base counter type to calculate, for example, the average amount of time it takes for an action (e.g., connecting to a server) to complete or the average number of actions that occur during a single process (e.g., database timeouts).

Solution

Create a complex performance counter, which is used in tandem with the base counter type to calculate, for example, the average amount of time it takes for an action to complete or the average number of actions that occur during a single process. Use the following method to create a complex custom counter:

public void CreateComplexCounter(string counterName, string counterHelp, 
    PerformanceCounterType counterType, string baseCounterName, 
    string baseCounterHelp,  PerformanceCounterType baseCounterType, 
    string categoryName, string categoryHelp, 
    out PerformanceCounter appCounter,
    out PerformanceCounter appBaseCounter)
{
    CounterCreationDataCollection counterCollection = 
      new CounterCreationDataCollection( );

    // Create the custom counter object and its base counter object
    //    and add them to the collection of counters (they must be 
    //    added successively)
    CounterCreationData counter = new CounterCreationData(counterName, 
      counterHelp, counterType);
    counterCollection.Add(counter);
    CounterCreationData BaseCounter = 
      new CounterCreationData(baseCounterName, 
            baseCounterHelp, baseCounterType);
    counterCollection.Add(BaseCounter);

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

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

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

    newAppCounter.RawValue = 0;
    newAppBaseCounter.RawValue = 0;

    appCounter = newAppCounter;
    appBaseCounter = newAppBaseCounter;
}

Discussion

The CreateComplexCounter method returns two PerformanceCounter objects as out parameters; one is the counter, and the other is the base counter. These two counters are used in tandem; the base counter controls some aspect of the denominator in the calculation relating these two counters. Since the value of the appCounter parameter, returned from this method, depends on the value in the appBaseCounter parameter, we are considering these types of counters as complex counters.

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.


This method operates similarly to the CreateSimpleCounter method described in Recipe 6.12. The one major difference is that two CounterCreationData objects are created and added to the CounterCreationDataCollection object. This first CounterCreationData object is the main counter used in the calculation for this counter. The second is the base counter, used in the denominator of the calculation for this counter. These counters must be added, in order, to the CounterCreationDataCollection object. In addition, the counter defined by the counterName parameter must be added before the counter defined by the baseCounterName parameter.

The application can perform several actions on these PerformanceCounter objects. An application can increment or decrement a PerformanceCounter object using one of these three methods:

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

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

// Additionally, a negative number may be passed in to the IncrementBy method
//    to mimic a DecrementBy method (which is not included in this class)
long value = newAppCounter.IncrementBy(-i);
long value = newAppBaseCounter.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 these counters, you can also take samples of these counters 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 lines of code:

CounterSample counterSampleValue = newAppCounter.NextSample( );
CounterSample counterSampleValue = newAppBaseCounter.NextSample( );

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

At another point in the application, a counter may be sampled again, and the 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, 
                                                 newAppCounter.NextSample( ));

Note that you need to pass only the newAppCounter samples; the newAppBaseCounter samples are handled for you. The calculated sample calculatedSample may be stored for future analysis. See Recipe 6.12 for a definition of the Calculate method.

The complex performance counters defined in the .NET Framework are defined here:


AverageCount64

Calculates the AverageTimer64 value change over the AverageBase value change. This counter uses AverageBase as its base counter type.


AverageTimer32

Calculates the AverageTimer32 value change over the number of ticks per second, all over the AverageBase value change. This counter uses AverageBase as its base counter type.


CounterMultiTimer

Calculates the percentage of CounterMultiTimer value change over the CounterMultiTimer time change divided by CounterMultiBase. This counter uses CounterMultiBase as its base counter type.


CounterMultiTimerInverse

Calculates the inverse of the CounterMultiTimer counter. This counter uses CounterMultiBase as its base counter type.


CounterMultiTimer100Ns

Calculates the percentage of CounterMultiTime100Ns value change over the CounterMultiTime100Ns time change divided by CounterMultiBase. The value of this counter is measured in 100ns time units. This counter uses CounterMultiBase as its base counter type.


CounterMultiTimer100NsInverse

Calculates the inverse of the CounterMultiTimer100Ns counter. This counter uses CounterMultiBase as its base counter type.


RawFraction

Calculates a percentage of the RawFraction counter value over the RawBase counter value. This counter uses RawBase as its base counter type.


SampleCounter

Calculates the SampleCounter value change over their corresponding SampleBase value change per second. This counter uses SampleBase as its base counter type.


SampleFraction

Calculates the percentage of SampleCounter value change over the SampleBase value change. This counter uses SampleBase as its base counter type.

See Also

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

    [ Team LiB ] Previous Section Next Section