[ Team LiB ] |
Recipe 6.13 Implementing Performance Counters that Require a Base CounterProblemYou 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). SolutionCreate 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; } DiscussionThe 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.
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:
See AlsoSee 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 ] |