How to: Register or Deregister a Performance Counter

Applies to: SharePoint Foundation 2010

This topic explains how to register a Windows Server 2008 performance counter for monitoring by the Microsoft SharePoint Foundation performance monitoring and HTTP request throttling system, and how to remove a counter from the system.

Important

The running example in this topic uses a console application. Regardless of the type of project, it is critical that you set the correct target .NET Framework and CPU. The project must target Microsoft .NET Framework 3.5 (not .NET Framework 4). The target CPU must be either Any CPU or x64. For information about the choice, see How to: Set the Correct Target Framework and CPU. By default, the target CPU is usually x86. To change it, right-click the project name in Solution Explorer, and select Properties. You can change the CPU on the Build tab by using the Platform target drop-down list.

Persistence of the Monitors and Health Score Calculators

Performance monitors in the HTTP request throttling system are created at run time, as SPSystemPerformanceCounterMonitor objects, by the system infrastructure. One such object is created for each SPPerformanceMonitorCreationData object in the persisted PerformanceMonitors property of the SPHttpThrottleSettings object that is itself persisted in the web application’s HttpThrottleSettings property. However, your code does not call a constructor for the SPPerformanceMonitorCreationData class. Instead, your code calls the SPHttpThrottleSettings.AddPerformanceMonitor() method. This method constructs the SPPerformanceMonitorCreationData object and adds it to the PerformanceMonitors collection. An important property of the SPPerformanceMonitorCreationData class is AssociatedHealthScoreCalculator. The health score calculator object is also created for you by the SPHttpThrottleSettings.AddPerformanceMonitor() method. The only time your code would call the constructor for the SPBucketHealthScoreCalculator is when you are creating a new calculator for purposes of swapping it with the existing calculator of an already registered performance monitor.

To create the Visual Studio solution

  1. Create a console application project in Microsoft Visual Studio, and set the target .NET Framework and CPU platform.

  2. Add a reference to the Microsoft.SharePoint.dll to the project. It is in %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\ISAPI.

  3. Open the program.cs, set an appropriate namespace and class name, and add using statements for the Microsoft.SharePoint, Microsoft.SharePoint.Administration, and Microsoft.SharePoint.Utilities namespaces. Your code should now look something like the following:

    using System;
    using Microsoft.SharePoint; 
    using Microsoft.SharePoint.Administration;
    using Microsoft.SharePoint.Utilities;
    
    namespace Contoso.SharePoint.Utilities
    {
        class PerformanceCounterRegistrar
        {
            static void Main(string[] args)
            {
    
            }
    // end Main
        }
    }
    

To add a performance monitor

  1. In the Main method, declare an array of Double values that define the boundaries of the buckets that the health score calculator uses to assign health scores to the values. Buckets are subranges of possible counter values. The array must meet the following conditions:

    • The values of the elements must be well-ordered, either from smallest to largest or from largest to smallest.

    • The values must also be well-ordered from healthiest to least healthy. So, where buckets is the name of the array object, buckets[0] is a healthier value than buckets[1], buckets[1] is a healthier value than buckets[2], and so on. Therefore, buckets[buckets.Length-1] must always be the least healthy value in buckets.

    An array with 10 elements, the standard size for arrays that define performance buckets, creates 11 buckets: Values that are healthier than buckets[0] are in the first bucket, whereas values that are less healthy than buckets[10] are in the eleventh bucket. The health score calculator assigns a health score to a value (or to the result of a function on multiple values), depending on the bucket to which the value belongs. The score is an Int32 from 0 to 10. Values in the healthiest bucket are assigned 0, and those in the least healthy bucket are assigned 10. The array can have fewer than 10 elements. For example, suppose the possible values of a hypothetical performance counter range from 0 to 50.0 (with the low values indicating health), and suppose the numbers 10.0, 20.0, 30.0, and 40.0 are used as the boundaries of the buckets. In this scenario, an object of the standard health score calculator class, SPBucketHealthScoreCalculator, would generate health scores according to the following rules:

    • 0 for performance values less than 10

    • 3 for values between 10.0 and 20.0

    • 5 for values between 20.0 and 30.0

    • 8 for values between 30.0 and 40.0

    • 10 for values above 40.0

    In constructing your bucket array, it is important be aware that the request throttling system goes into throttling mode only if at least one counter being monitored has a score of 10 (based on a weighted average of multiple samples of the counter). Hence, for an array of 10 or fewer elements, choosing the value for the last element in the array is critical. This should be a value that indicates a degree of poor health extreme enough to justify blocking some HTTP requests. Similarly, for an array of 20 elements, values that are less healthy than the next-to-last element will be scored as 10.

    Note

    The array could have only one element, in which case values less healthy than the value of the single element would get health score 10 and all others would get health score 0. Because no value less than 10 triggers throttling, why would one ever bother to have more than one element in the array? In other words, why not have a binary system of health scores: "healthy" and "unhealthy"? The answer is that the health score of the least healthy counter is added to the header of the HTTP response object, even if it is less than 10 and, thus, there is no throttling. If this value can vary over a wider range of values than just two, clients can use that reported value to note trends in the health of the farm. Client applications can also use the health score to improve synchronization with the server. For example, a client application could set a longer synchronization interval for higher (less healthy) health scores. (Some Microsoft Office applications do this.) On the other hand, there is little point to having more than 10 elements in the array because there are only 11 possible health scores, so more than 11 buckets would simply cause values in two or more consecutive buckets to receive the same health score. However, as noted earlier, you may have fewer than 10 elements, and that may be appropriate for some kinds of performance counters.

    The following code shows a declaration of an array that is intended to create buckets for the Windows Server 2008 counter named "Processor\% Processor Time\_Total". This counter reports the percentage of time the processors of the server are spending on processes other than the System Idle process. For more information about this counter, see Processor Object.

    double[] busyProcessorBuckets = new double[10] {20.0, 28.8, 37.6, 46.4, 55.2, 64.0, 72.8, 81.6, 90.4, 99.2}; 
    

    In this example, the difference between any two values is the same. That need not be the case. For some kinds of counters, it may be appropriate to have values that progress exponentially. Note, also, that in this example, the values are ascending. However, for some kinds of performance counters, larger values are healthier than smaller values. Because the buckets array must be ordered from healthiest to least healthy, the values must be descending in a buckets array for such a counter.

  2. Still in the Main method, get a reference to the web application, and then get a reference to the throttle settings by calling the GetHttpThrottleSettings(SPPersistedObject) method. The following example shows how.

    Uri webApplicationUri = new Uri("Http://localhost/");
    SPWebApplication webApplication = SPWebApplication.Lookup(webApplicationUri);
    SPHttpThrottleSettings throttleSettings = SPHttpThrottleSettings.GetHttpThrottleSettings(webApplication);
    
  3. Still in the Main method, call the SPHttpThrottleSettings.AddPerformanceMonitor() method, passing it the name of the counter, its category, its instance, and your bucket array as parameters. Pass true or false for the last parameter depending on whether the array is ascending or descending, respectively. The following code continues the running example.

    throttleSettings.AddPerformanceMonitor("Processor",
                                           "% Processor Time",
                                           "_Total",
                                           busyProcessorBuckets,
                                           true);
    

    Tip

    The SPHttpThrottleSettings.AddPerformanceMonitor() method does not check whether a performance monitor is already monitoring the same instance of the same counter. Successive calls of the method, with the same parameters, register redundant performance counter objects.

To verify that the performance counter is registered

  • Use the SharePoint Management Shell cmdlet Get-SPWebApplicationHttpThrottlingMonitor to get a list of the registered performance monitors for the web application. The following shows the syntax of the call to the cmdlet.

    Get-SPWebApplicationHttpThrottlingMonitor –identity http://<Web application URL>
    

    The output for the newly registered performance monitor looks like the following:

    Category                        : Processor
    Counter                         : % Processor Time
    Instance                        : _Total
    AssociatedHealthScoreCalculator : [20.0,28.8,37.6,46.4,55.2,64.0,72.8,81.6,90.4,99.2]
    

To deregister a performance counter

  • Deregistering a performance monitor is similar to registering one, except that your code calls RemovePerformanceMonitor(). One overload of this method deregisters all performance counters that have a specific category, counter, and instance name. A second overload deregisters all counters with a specified category and counter name, so if different monitors are monitoring different instances of a specific counter, they can all be removed in a single call. The following example shows the RemovePerformanceMonitor() method being used to remove the monitor in the running example.

    Uri webApplicationUri = new Uri("Http://localhost/");
    SPWebApplication webApplication = SPWebApplication.Lookup(webApplicationUri);
    SPHttpThrottleSettings throttleSettings = SPHttpThrottleSettings.GetHttpThrottleSettings(webApplication);
    
    // Remove the monitor. 
    throttleSettings.RemovePerformanceMonitor("Processor",
                                              "% Processor Time",
                                              "_Total");
    

See Also

Concepts

Request Throttling