If you are like me, you have learned not always to rely on hardware to run your perfectly written applications. Sometimes, and without any reasons, applications just refused to start. It happened to me, a workstation that was supposed to be running 24/7 was shutdown by a new employee who did not read the yellow Post-it stuck on the screen. The impact was not dramatic but I have looked around to find a way to monitor my physically distributed applications.
I didn’t want to rely on a database to store trace. I wanted something else. I finally found, what I think is ideal for this situation: The Performance Counters. That let me monitored a computer using another computer (I hope the 2 won’t go down at the same time).
What they are
Windows performance counters allow your applications to publish, capture, and analyze the performance data that are provided by others applications. You can use this information to determine bottlenecks, performance, and/or reliability.
For example, you might use a performance counter to track the messages queued in a stack of your own and write code that performs a specific action whenever the queue reaches a preset limit.
Visual Studio .NET provides everything we need to easily connect to performance counters on both local and remote computers and retrieve values from these counters. We can also create our very own custom counters.
How to use them
We have to create our very own Category that will contain our Counters. All those need to be created at the same time. Also, if the Category already exists, it cannot be created again.
Once created, Counters can be used in operations that will let us increment its value, decrease its value, or read the current value.
Create the demo solution
A simple application would have done the 3 operations I wanted to show you. But I found this to simplistic.
To have a more realistic solution, we will create 3 projects. The first project will increment counters. The second one will decrease these same counters. And guess what, the last one will read the current values and display them.
The first application: Incrementing counters
This first application is the more complex and has more lines then the 2 others. It only counts about 30 lines of codes! Its interface is very simple. It has 2 buttons. Each button increments a different counter. What you don’t see is that these counters are also created here.
Figure 1: The first application
'Declare constants because we want theses 'same values through all applications Private Const kCategoryName As String = "EMoreau-DemoApp" Private Const kCounter1Name As String = "Counter1" Private Const kCounter2Name As String = "Counter2"
If Not PerformanceCounterCategory.Exists(kCategoryName) Then CreateCounters() End If
Dim objCounters As New CounterCreationDataCollection Dim objCounterData As CounterCreationData 'Create a first counter objCounterData = New CounterCreationData(kCounter1Name, _ "The first counter we have created.", _ PerformanceCounterType.NumberOfItems32) objCounters.Add(objCounterData) 'Create a second counter objCounterData = New CounterCreationData(kCounter2Name, _ "The second counter we have created.", _ PerformanceCounterType.NumberOfItems32) objCounters.Add(objCounterData) 'Create a new category to hold our counters PerformanceCounterCategory.Create(kCategoryName, _ "Demo for Level Extreme .Net magazine", _ objCounters)
Once the counters are created, we can start using them right away. This is the code you will find in one of the 2 buttons:
'Increments the counter named "Counter1" Dim objCounter As New PerformanceCounter(kCategoryName, kCounter1Name, False) objCounter.Increment()
The second application: Decreasing counters
The second application is even easier.
Figure 2: The second application
Then a single event procedure is used for both buttons. The first part of the procedure is to detect which button was pressed:
Dim strCounterName As String If sender Is btnDecrease1 Then strCounterName = kCounter1Name Else strCounterName = kCounter2Name End If
Try Dim objCounter As New PerformanceCounter( _ kCategoryName, strCounterName, False) If objCounter.RawValue > 0 Then objCounter.Decrement() End If Catch ex As System.InvalidOperationException Microsoft.VisualBasic.Beep() Catch ex As Exception MessageBox.Show(ex.ToString) End Try
Notice that if you need to decrease the counter by a value different then 1, you can use the IncrementBy method with a negative argument.
The third application: Reading values
This last application has 2 features.
Figure 3: The third application
Try Dim objCounter1 As New PerformanceCounter(kCategoryName, kCounter1Name) lblCounter1.Text = objCounter1.RawValue.ToString Catch ex As System.InvalidOperationException lblCounter1.Text = "Counter1 does not exist" Catch ex As Exception MessageBox.Show(ex.ToString) End Try
The second feature allows us to completely delete the category and all its counters from the system:
If PerformanceCounterCategory.Exists(kCategoryName) Then PerformanceCounterCategory.Delete(kCategoryName) End If
Remote uses
If you don’t need to update the counters, you could use a different constructor to read a performance counter available on a different computer:
Dim objCounter1 As New PerformanceCounter( _ kCategoryName, kCounter1Name, "", "ComputerName")
VS.Net IDE and the performance counters
Have you ever saw the Performance Counters section in the Server Explorer of Visual Studio .Net?
Figure 4: VS.Net IDE
The Performance application
Another tool you can use to monitor any counters including your own, is the Performance application available from the “Administrative tools”.
Figure 5: The Performance application
Conclusion
Creating your custom performance counters is really easy. Monitoring them is also easy (you don’t even need to write code if you want to use the Performance application provided by Windows).
I hope you appreciated the topic and see you next month.