How to: Programmatically Read Monitored Values

Applies to: SharePoint Foundation 2010

This topic explains how your code can read the values of Windows Server 2008 performance counters that are being monitored by the Microsoft SharePoint Foundation performance monitoring and request throttling 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 Microsoft .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 by default. 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.

Programmatically Reading a Performance Counter

The following procedure shows how to use the SharePoint Foundation performance monitoring APIs to read a performance counter. There are many subtleties to the underlying performance counter system of the operating system (OS). Some counters, for example, do not give an accurate value until they are read a second time by consuming code. We recommend that you be familiar with the following topics and with the particular counters your code is reading. Many of these are about managed or unmanaged APIs that are not directly relevant, but they will deepen your understanding of the underlying system.

We recommend also that you search for knowledge base, blog, and forum entries about each of the counters whose data your code is reading.

Note

.NET Framework has APIs for reading the value of Windows Server 2008 performance counters, but this topic assumes that you want to be sure you are working with counters that have been registered for monitoring with the Microsoft SharePoint Foundation performance monitoring and request throttling system.

To read a performance counter

  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 console application project. It is in %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\ISAPI.

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

    using System;
    using System.Threading;
    using Microsoft.SharePoint; 
    using Microsoft.SharePoint.Administration;
    using Microsoft.SharePoint.Utilities;
    
    namespace Contoso.SharePoint.Utilities
    {
        class PerformanceCounterReader
        {
            static void Main(string[] args)
            {
    
            }
    // end Main
        }
    }
    
  4. In the Main method, get a reference to the web application whose performance monitors are to be read. The following code shows how.

    static void Main(string[] args)
    {
        Uri webApplicationUri = new Uri("Http://localhost/");
        SPWebApplication webApplication = SPWebApplication.Lookup(webApplicationUri);
    
    }
    

    All of the remaining code in this topic is added to the Main method.

  5. Get a reference to the throttle settings of the web application and to the collection of registered monitors.

    SPHttpThrottleSettings throttleSettings = SPHttpThrottleSettings.GetHttpThrottleSettings(webApplication);
    SPSystemPerformanceMonitorCollection monitors = throttleSettings.GenerateMonitors();
    
  6. Get a reference to the monitor whose value is to be read. In some cases, you will know at design time the position of the monitor in the collection and can use an indexer to refer to it. If it is the last counter, for example, you could use this line: SPSystemPerformanceCounterMonitor counterMonitor = (SPSystemPerformanceCounterMonitor)monitors[monitors.Count - 1];. (Note that you must cast the monitor object to the specific non-abstract monitor type to which it belongs.) In other scenarios, your code may need to iterate through the collection looking for a monitor with a particular set of Category, Counter, and Instance property values. In the following example, the code loops through all the registered monitors, reads the Value property, and reports their names and values.

    foreach (SPSystemPerformanceMonitor monitor in monitors)
    {
        SPSystemPerformanceCounterMonitor counterMonitor = (SPSystemPerformanceCounterMonitor)monitor;
        Console.WriteLine(counterMonitor.Name);
    
        // Read and display the counter value. 
        double currentValue = Convert.ToDouble(counterMonitor.Value); 
        Console.WriteLine(currentValue.ToString());                  
    }
    
    Console.WriteLine("Press return to end application.");
    Console.Readline();
    
  7. Note that, for many kinds of performance counters, a default value is always reported on the first read of the counter because the value of the counter is a function of two raw data points. You must read the counter a second time, with a wait in between, to get a valid value. For example, if the counter that is being monitored is Processor\% Processor Time\_Total, the get accessor of Value needs at least a full second to generate a valid value after the first time it is read by calling code. To ensure that your code gets a valid value, use a call of Sleep(Int32) to wait at least one second, and then read Value again. The following code illustrates this.

    foreach (SPSystemPerformanceMonitor monitor in monitors)
    {
        SPSystemPerformanceCounterMonitor counterMonitor = (SPSystemPerformanceCounterMonitor)monitor;
        Console.WriteLine(counterMonitor.Name);
    
        // Read the counter value, wait 1.5 seconds, and read again for a valid value.
        double currentValue = Convert.ToDouble(counterMonitor.Value); 
        Thread.Sleep(1500);
        currentValue = Convert.ToDouble(counterMonitor.Value);
    
        // Write the valid value to the screen.
        Console.WriteLine(currentValue.ToString());                  
    }
    
    Console.WriteLine("Press return to end application.");
    Console.Readline();
    

    Tip

    When you have a valid value, if you need that same value again, use the LastValue property. Reading Value again causes another fetch of the underlying counter’s value, which is normally a different value.

See Also

Concepts

Request Throttling