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.
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); }
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 Recipe 6.13; see the “PerformanceCounter Class,” “PerformanceCounterType Enumeration,” “PerformanceCounterCategory Class,” “ASP.NET Impersonation,” and “Monitoring Performance Thresholds” topics in the MSDN documentation.