Windows OS and .NET runtime provide a host of performance counters that developers and administrators can use to probe into the performance of an application. But developers will always find the need to have counters specific to their applications. For example, an accounting application can have counters like Accounts created, Transactions processed, total running balance, Number of users logged on to the application and so on.
.NET Framework classes provide rich set of APIs which can help developer to create custom counters with relative ease. In the following sections I will explain how this can be done with VB.NET.
Creating custom counter categories
All performance counters fall under specific categories. For example you have %Processor time, %User time, etc. under the Processor category. So, we would need to create our custom categories and then specify one or more counters under it. There are two ways by which we can create them: through VS.NET Server Explorer or programmatically. Let's see each of these in detail.
1. Using Server Explorer
Visual Studio.NET makes life easier here by giving us an interface to create counters at design time. Enlisted below are the steps you can follow to create the same.
- Open the Server Explorer
- Select Servers -> your computer name -> Performance Counters
- Right click Performance Counters and select "Create New Category..."
- In the dialog box, enter the name of the Category and any description you would like in the Category Description text box.
- In the counter list builder frame click "New" to add a new Performance Counter.
- Enter the name of the performance counter and select the Type, and any description you would like as the Counter description.
- Click OK.
Below is a snapshot of the Performance counter builder.
2. Doing it programmatically
System.Diagnostics namespace provides classes which we can use to create and manipulate custom performance counters. Given below are the steps which we typically use for this purpose.
- Create a collection of type
- Create the counters you want to create as objects of type
CounterCreationData and set their necessary properties.
- Add the
CounterCreationData objects to the collection by calling the collection's
- Call the
Create method on the
PerformanceCounterCategory class and pass the collection to it.
'Assumes import statement for System.Diagnostics.dll
Dim CounterDatas As New System.Diagnostics.CounterCreationDataCollection()
'Create the counters and set their properties.
Dim cdCounter1 As New System.Diagnostics.CounterCreationData()
Dim cdCounter2 As New System.Diagnostics.CounterCreationData()
cdCounter1.CounterName = "Transactions Active"
cdCounter1.CounterHelp = "Indicates number of active transactions"
cdCounter1.CounterType = Diagnostics.PerformanceCounterType.NumberOfItems64
cdCounter2.CounterName = "Users Logged on"
cdCounter2.CounterHelp = "Gives the number of users logged on to the " _
cdCounter2.CounterType = Diagnostics.PerformanceCounterType.NumberOfItems64
'Add both counters to the collection.
'Create the category and pass the collection to it.
"A set of counters for the accounting application", CounterDatas)
If you need to create a category with just one performance counter, you can use the overload of the
Create method as follows:
"A set of counters for the accounting application", _
"Transactions Active","Gives number of transactions being processed")
There are a few things to consider regarding custom performance counters.
- You cannot create custom categories and counters on remote machines.
- Our interaction with custom counters and categories is restricted to read-only mode unless you explicitly specify otherwise. By default the counters created under server explorer are read only and under read-only mode you cannot update the value of the counter.
- To create custom counters on the local computer you need administrative access.
- You cannot create new counters within existing custom categories. If you need to add counters to categories that already exist, the only way you can do so is to delete the category and recreate it with all of its contents, including the new counters you want to add.
- If you try to create a counter that already exists, an error would be thrown. You can check the existence of a counter before you create one. For example:
If Not (PerformanceCounterCategory.Exists("MyCat")) Then
PerformanceCounterCategory.Create("MyCat", "Desc", "MyCtr", "Desc")
Performance Counter Types
Another important aspect of a performance counter is its type. In the example shown earlier, we had assumed a type
NumberofItems64 without actually knowing what it is. Well, in this section I will explain the various counter types and this should give an idea as to where each type can be used. Given below is a table explaining the important counter types and where they can be used appropriately.
|If You Need To||Use||Example
|Maintain a simple count of items, operations, and so on.|
|You might use this counter type to track the number of orders received as a 32-bit number.|
|Maintain a simple count with a higher capacity|
|You might use this counter type to track orders for a site that experiences very high volume; stored as a 64-bit number.|
|Track the amount per second of an item or operation|
|You might use this counter type to track the orders received per second on a retail site; stored as a 32-bit number.|
|Track the amount per second with a higher capacity|
|You might use this counter type to track the orders per second for a site that experiences very high volume; stored as a 64-bit number.|
|Calculate average time to perform a process or to process an item|
|You might use this counter type to calculate the average time an order takes to be processed; stored as a 32-bit number.|
Updating and reading Performance counters
Okay, now that we have an idea about performance counter categories and their types and that we have created them, let's see how this can we manipulate them in our application.
System.Diagnostics namespace provides
PerformanceCounter class using which we can read and manipulate values of counters. Let's look and some of the properties and methods of this class which we can use.
|Gets or sets the name of the performance counter category for this performance counter.|
|Gets the description for this performance counter.|
|Gets or sets the name of the performance counter that is associated with this PerformanceCounter instance.|
|Gets the counter type of the associated performance counter.|
|Gets or sets an instance name for this performance counter.|
|Gets or sets the computer name for this performance counter|
|Gets or sets the raw, or uncalculated, value of this counter.|
|Gets or sets a value indicating whether this PerformanceCounter instance is in read-only mode.|
|Decrements the associated performance counter by one through an efficient atomic operation.|
|Increments the associated performance counter by one through an efficient atomic operation.|
|Increments or decrements the value of the associated performance counter by a specified amount through an efficient atomic operation.|
|Obtains a counter sample, and returns the raw, or uncalculated, value for it.|
|Obtains a counter sample and returns the calculated value for it.|
|Deletes the category instance specified by the PerformanceCounter object InstanceName property.|
Now, let's see a few of them in action with a simple code snippet. Here we are incrementing a counter before beginning some processing and then decrement it back once it's over.
Dim myCounter As New PerformanceCounter("Accounting", _
"Transactions Active", false)
' Start a transaction
' <<<Do some processing>>>
' Complete transaction
Note: In the code piece shown above we programmatically created an instance of the
PerformanceCounter object. In VS.NET, we can do this by just dragging an icon of from the toolbox into the designer surface.
Adding and Removing Instances
It is likely to have more than one instance of a performance object. For instance, the Processor performance object has one instance for every processor on the system.
You add instances by setting a raw value for the counter. If no instance exists for the counter, it will be created the first time you set the
RawValue property, and all subsequent actions on the raw value are assumed to impact that instance if no other is specified. You can create additional instances by specifying a new instance name and then setting a value after it.
' Assumes the category and counter have already been created.
Dim myCounter As New System.Diagnostics.PerformanceCounter( _
'Set the raw value to automatically create instance1.
myCounter.RawValue = 100
'State that you will now be working with a different instance.
myCounter.InstanceName = "instance2"
'Setting the value actually creates instance2.
myCounter.RawValue = 200
You may need to remove instances dynamically in your application. For example if you have an instance for every logged on user you may need to delete an instance when the user logs off. You can delete instances by using the
RemoveInstance method of the
Dim PerformanceCounter1 As New PerformaceCounter( _
"Accounting"," Logged on Users", false)
PerformanceCounter1.InstanceName = "Admin"
Deleting a Performance counter category
Like in the case of creation, we can use the VS.NET Server Explorer to delete Performance counter categories or do it programmatically.
Using Sever Explorer
- Locate the performance category in Server Explorer
- Right click the category and select Delete
Doing it programmatically
- Call the
Delete method on the
PerformanceCounterCategory class, specifying category to remove as a parameter.
Note: Using the above approaches, you can only delete user defined categories, not Windows-standard performance objects. We cannot delete categories on remote computers.
VS.NET has a very nifty feature called Project Installers. You can add installers for several objects like custom performance counter objects. If we add installers to the project and run
InstallUtil.exe against the assembly (with the
/i switch), these counters get installed automatically. Likewise these counters would be automatically removed when we run Installutil.exe with a
Adding an installer is pretty easy. Right click the object on the designer surface and select "Add Installer". You can also change the properties of the installer using the Properties pane of the Installer. These are the settings that would be applied when the assembly is installed using InstallUtil.
Custom performance counters are a great value addition that a development team can make to a production environment. It is definitely one of the easiest ways to monitor the health and performance of the application. The .NET Framework and VS.NET definitely makes implementation of counters a relatively simple task.