Collecting performance data from local and remote systems using C#

Performance data

Perfmon is a well known tool to monitor performance data for your local and remote systems. This code snippet gives you a worker class that can be used to connect to local or remote perfmon / system performance data, and provide the resulting information stream to your c# application.

Local and remote

To connect remote data, you need to be part of the performance monitor users group. If your programm runs as administrator, you should have that permission by default. For othe rusers simply add the user that your programm will run as to the performance monitor group, and you will be done.

Running a monitor

The main routine below is the simplest way to create and connect to a performance counter. This loop will create a cpu monitor counter on a remote machine (in this case minion.corp.nhcoding.nl), and loop to get the next sample.Hammering counters for value’s can give some very weird results, which is why we check if a datapoint is ready for collection.

static void Main(string[] args)
        {
            var counter = new CounterManager("Processor", "% Processor Time", "_Total", "minion.corp.nhcoding.nl");
            while (!Console.KeyAvailable) {
                if (counter.CounterReady()) {
                    Console.WriteLine(counter.GetCounter());
                }
            }            
        }

The actual worker class

Below is the actual worker class wrapping the performance counter. The class maintains a timer to signal readyness through the CounterReady() call. Once this returns true, you can safely extract a new datapoint with the GetCounter() method.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class CounterManager
    {

        private PerformanceCounter _counter;
        private DateTime _readyTime;

        /// <summary>
        /// Initialize the requested performance counter. the counter needs about a second
        /// to register and collect meaningfull data.
        /// </summary>
        /// <param name="categoryname"></param>
        /// <param name="countername"></param>
        /// <param name="instancename"></param>
        /// <param name="machine">remote computer name, you need to member of the performance monitor users group</param>
        public CounterManager(string categoryname, string countername, string instancename, string machine)
        {
            _counter = new PerformanceCounter(categoryname, countername, instancename, machine);
            float initialValue = _counter.NextValue();
            _readyTime = DateTime.Now.AddSeconds(1);
        }

        /// <summary>
        /// Indicates if the counter is ready to provide the next sample point.
        /// </summary>
        /// <returns></returns>
        public bool CounterReady()
        {
            return DateTime.Now > _readyTime;
        }

        /// <summary>
        /// Get the next sample point
        /// </summary>
        /// <returns></returns>
        public float GetCounter()
        {
            float currentValue = _counter.NextValue();
            _readyTime = DateTime.Now.AddSeconds(1);
            return currentValue;
        }
    }
}

You could replace the polling approach in the above code with an actual event based on a timer, so your application will be alerted on each sample that becomes available. An example on how to implement such events can be found in the document Raising an event on a usercontrol, and subscribing to it from an ASPX page While that document is aimed at ASP.NET, you can use the exact same technique to create and subscribe to events in another type of application. Now that the way has been paved for retrieving the data, the next step will be providing a few of these counters in a nice dashboard like graphic form. This will be covered by a forthcoming post 🙂

For querying the categories and counters that are installed on a system, see Enumerating available performance counters on local and remote systems using C#