Friday, June 19, 2015

[ C# ] - Creating and using Custom Performance Monitor Counter

1. Introduction


Performance Monitor is a windows tool and it is useful monitor “System” and “Application performance” by measuring various parameters and plotting it as a graph. The measuring parameter is called “Performance Counter”. In this article, we are going to add our own performance counter that measures a UI activity in our sample application. Before that, we should first understand what is “PerfMon” tool and how it uses the performance counters to measure and plot System or application performance. Have a look at the below screen shot: 

Fig.1 Performance Monitor

The toolbar icons marked above are useful to add or remove a performance counter. Once we add a performance counter, it will be displayed in the bottom of the tool. In our example, “% Processor Time” is added as a performance counter, which is marked in the above screen shot. Once the Performance counter is available, a graph is plotted taking the “Measurement Time” as X-Axis and “% CPU Usage” as the Y-axis. The below video shows how do we plot “Private byte” as performance counter to measure the memory occupied by a specific process:


Video 1: Using Windows PerfMon utility




Now let us try creating our own performance counter, which measures various button clicks of an application.


2. Elements of Performance Monitor


Some very important objects involved in application performance monitoring are explained below. They together helps in creating a application specific “Custom Performance Counters”.

Have a look at the below picture:

Fig 2. Objects involved in custom performance counter

Performance Counter Category


The category groups the performance counters logically. For example, in the previous video we saw the performance counters groups named Process and System. These groups help in the picking the performance counter in a quick way.


Counter Creation Data


The counter creation data specifies the "performance counter type" (Simple counts, Time Measure, Average etc.,) "counter name" and "descriptive text" so that the monitor tool will communicate that information to the user stating what the performance counter will do for them. The name that will give here will be used while creating actual performance counter objects.

Performance Counters


The actual performance counter which has the performance measure routines like Increment, decrement, time Elapsed etc. These counters take the information required for creating the counter from “Counter Creation Data”.

To create a custom performance counters “CounterCreationData” are constructed. These creation data are used by the “Performance Counters” while it will be constructed later. These counter creation data are added to a collection and given to the “Category Group. We get more insight into it while we start out coding. For now let us look at the sample application that we are going to create.

3. About the example


Screen shot of the sample application is shown below:

Fig 3. Custom Performance Counter Example

The Register and Leave button shares same performance counter called “Register Click” and Update button uses a different performance counter called “Update Click”. The sample application increments the performance counters “Register Click” and “Update Click” when the corresponding buttons are clicked. When leave button is clicked, “Register Click” performance count is decremented.

In real case, these kinds of click counts are useful to measure Performance of the Operator; say for example, a click count on the print button measures how many billing is done in a given hour by a operator on the billing counter of a retail shop.

4. Creating Performance counters in C#


1) First the required name space is added to the implementation file. Code is below:  

//Sample 01: Using Directive
using System.Diagnostics;

2) A string variable is created to specify the Category Group Name for our performance counter. While using the PerfMon tool we can easily find our counters under the category group called “Button Usage”.

//Sample 02: Category Name and Counters belogs to it
private string CategoryName = "Button Usage";

3) The PerformanceCounter are the reference declared to hold the performance counter objects. We are going to use these objects to count the button clicks. Below the code for Declarations:

//Sample 03: Click counter for buttons
private PerformanceCounter RegisterClicks;
private PerformanceCounter UpdateClicks;

4) The class “PerformanceCounterCategory” is useful for creating the “Category Groups” of “Performance Counters”. Using the same class we are making call to the static function in the form load to check the Category Name “Button Usage” is already exists.

//Sample 03: Create Counters for Button Clicks
private void frmCounterEx_Load(object sender, EventArgs e)
{
    //3.1: Check counter available
    bool Counter_Available = PerformanceCounterCategory.Exists(CategoryName);

5) Once we make sure the Category not exists, we start creating out custom counters. First, the “CounterCreationData” objects are created by specifying the CounteName, CounterType and CounterHelp properties. In our case, we are creating the counter that counts the button clicks by the Operator of the application. So we use “NumberOfItems32” as the counter type from the enumeration “PerformanceCounterType”.

if (!Counter_Available)
{
//3.2: Form Countercreation Data
CounterCreationData RegButtonClick = new CounterCreationData();
RegButtonClick.CounterName = "ResgisterClick";
RegButtonClick.CounterType = PerformanceCounterType.NumberOfItems32;
RegButtonClick.CounterHelp = "How many time register button is clicked. Useful to know how many customers registered for a given
time";

CounterCreationData LeaveButtonClick = new CounterCreationData();
LeaveButtonClick.CounterName = "UpdateClick";
LeaveButtonClick.CounterType = PerformanceCounterType.NumberOfItems32;
LeaveButtonClick.CounterHelp = "How many time Leave button is clicked. Useful to know how many customers left for a given time";

6) Once counter creation data is ready, they are added to the collection ”CounterCreationDataCollection” by using the add method. Note that we are going to use RegisterClick counter for both “Register” and “Leave” button clicks. Below is the code change:

//3.3: Create Collection of CreationData
CounterCreationDataCollection ClickCounters = new CounterCreationDataCollection();
ClickCounters.Add(RegButtonClick);
ClickCounters.Add(LeaveButtonClick);

7) Next we are making call to Create static method of the PerformanceCounterCategory type to create the category group called “Button Usage”. We are passing the “ClickCounters” to the collection created in the previous step to create a new counter category. Also, note that before making a call to this function we are checking the counter exits. As we create this new Performance counter category in the form load event, the counter will be visible in the performance counter only when the form is loaded into memory. This Create call may fail stating "Requested registry access is not allowed" as you are making change to the OS level (i.e.) adding a new performance category type and two new counters inside it. So make sure to run this sample application or Visual studio (If are going to launch it from Visual studio itself) in administrator mode.

//3.4: Create new Performance counter Category
PerformanceCounterCategory.Create(CategoryName, "Various click counter on the Form. Used to weigh each button in this form",
    PerformanceCounterCategoryType.SingleInstance, ClickCounters);

8) OK. Everything is ready. Now we will create our own Performance counters. The custom counters can be created using “PerformanceCounter” object of the Dotnet framework. So for, the category has null reference to the performance counters and the below code creates actual performance counters. Make sure to use same name, which we specified as part of “CounterCreationData”.

//3.5: Now create actual measuring counters
RegisterClicks = new PerformanceCounter(CategoryName, "ResgisterClick", false);
UpdateClicks = new PerformanceCounter(CategoryName, "UpdateClick", false);

9) At this stage, windows know the existence of new performance counters “registerclick” and “updateclick” counters under the category name “Button Usage”. Now we will write code to perform actual counting of the buttons. In the button click events we are making the counts. Register and leave buttons share same counter object called RegisterClicks. In the registration counter is incremented and in the leave (Un-Register) the same counter is decremented by making call to the respective functions Increment() and Decrement(). Update click uses separate UpdateClick counter. Below is code which uses the custom counters.

//Sample 04: Increment and Decrement Counters
private void btnRegister_Click(object sender, EventArgs e)
{
    RegisterClicks.Increment();
}

private void btnLeave_Click(object sender, EventArgs e)
{
    RegisterClicks.Decrement();
}

private void btnUpdate_Click(object sender, EventArgs e)
{
    UpdateClicks.Increment();
}

10) Finally, we delete our custom counters in the form-closing event and code for that is given below:


//Sample 05: If counter category Exists, delete it
private void frmCounterEx_FormClosed(object sender, FormClosedEventArgs e)
{
    bool Counter_Available = PerformanceCounterCategory.Exists(CategoryName);
    if (Counter_Available)
        PerformanceCounterCategory.Delete(CategoryName);
}

5. Running the Sample Application


To see how our own Performance counters work, launch the sample application or visual studio (If we plan to run the application from visual studio IDE Itself) in administrator mode and then form is opened, launch performance monitor by using the PerfMon. The Performance monitor tool will now display our performance counters under the group “Button Usage”. Add all the counters for monitoring and then click the button in the form to see the change in the graph over time. The below video shows the Performance counters in action:

Video 2: Custom Performance Counters




Source Code: Download

*** When a New Article posted, get Notification to the email that you give below: ***

Follow us on G+

DISCLAIMER

The opinions expressed herein are my own personal opinions and do not represent my current or previous employer's view in anyway