Friday, August 03, 2007

Enterprise Library Performance counters

I decided to get back to blogging, not so much because I am thinking that people will actually read my junk, but more so because I caught myself quickly forgetting things that I have done and need to relearn how to do them again.
My first post will be about using performance counters with Microsoft Enterprise Library 3.1 and Windows Vista. In order for you(or me) to be able to follow the example I will post here, you will have to have Enterprise Library 3.0 installed. You can download it here

After installing, make sure that you run the install instrumentation bat file with administrator privileges. You can do so by going to start->all programs->Microsoft patterns and practices->Enterprise Library then right click on Install Instrumentation and select Run as Administrator.



Now you are ready to use performance counters with your application.

Next step is to actually write your performance counter. I used Chris Burrows' .Net blog post as a basis for accomplishing this, but ran into a few problems that I feel should be documented. The code I will post here is identical to the one on his post, but I will add a few additional comments.

So let's start by creating a new Visual Studio Console Application project and naming it SamplePerformanceCounter.

Add a class to your solution called SimplestPerformanceClass and paste the following code in it:

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Common.Instrumentation;
using System.Diagnostics;


namespace SamplePerformanceCounter
{
[HasInstallableResources]
[PerformanceCountersDefinition(PerformanceCategory, "SampleInstrumentationCounterHelp")]
public class SimplestPerformanceClass
{
private const string PerformanceCategory = "Simplest Performance Category";

[PerformanceCounter("Operations Started/sec", "OperationStartedHelpResource", PerformanceCounterType.RateOfCountsPerSecond32)]

private EnterpriseLibraryPerformanceCounter _operationStarted = new EnterpriseLibraryPerformanceCounter(PerformanceCategory, "Operations Started/sec");

public void OperationStarted()
{
_operationStarted.Increment();

}

}
}


Also add a partial class called ProjectInstaller.cs with the following code:

using System.ComponentModel;
using System.Configuration.Install;
using System.Management.Instrumentation;
using Microsoft.Practices.EnterpriseLibrary.Common.Instrumentation;
using System;
using System.Management;

namespace SamplePerformanceCounter
{
///

/// Let the system know that the InstallUtil.exe tool will be run against this assembly
///

[RunInstaller(true)]
public partial class ProjectInstaller :System.Management.Instrumentation.DefaultManagementProjectInstaller
{
///
/// Represents the installer for the instrumentation events. Not intended for direct use.
///


public ProjectInstaller()
{
Installers.Add(new ReflectionInstaller());
}
}



}



Here is one place that personally got me here, namely this line:
public partial class ProjectInstaller :System.Management.Instrumentation.DefaultManagementProjectInstaller

I had the System.Management.Instrumentation, System.Configuration.Install and Microsoft.Enterprise.Practices.EnterpriseLibrary.Common assemblies referenced in my project, and I thought everything should work fine. However Visual Studio was finding only System.Management.Instrumentation.DefaultManagementInstaller, so when I was trying to install my assembly using installutils, things didn't work right. It turns out that I had to reference System.Management as well, despite the fact that that class resides in System.Management.Instrumentation.
After getting that done, I added the following code to Program.cs:

using System;
using System.Collections.Generic;
using System.Text;

namespace SamplePerformanceCounter
{
class Program
{
static void Main(string[] args)
{
SimplestPerformanceClass performance = new SimplestPerformanceClass();

for (int i = 0; i < 1000000; i++)
{
performance.OperationStarted();
}
}
}
}


and compiled my solution.

Now is a good time to ensure that all the enterprise library default performance counters are added to perfmon. you can do so by calling the performance and reliability tool from Administrative tools, or just typing perfmon in Start->Run.

After doing that, you will see this:



You can click on the performance monitor under the monitoring tools folder and select the green cross at the top of the window and you should be presented the "Add Counters" screen. If you scroll the list, you should be able to see Enterprise Library counters, provided you installed instrumentation correctly. If you don't see anything ent. lib. related stuff that means you need to go back and figure out what went wrong with the install. Most likely you had permission problems and will have to run the script again with admin privileges.
So now that we have our solution complete and we have ensured that the ent. lib. instrumentation stuff is installed correctly, we will have to install our process counters with installutil.
Start the visual studio command prompt that you can find under Visual Studio 2005-> command tools. Make sure that you start it with admin privileges and navigate to your default project directory, then navigate to your bin/Debug folder and execute
installutil SamplePerformanceCounter.exe.
Now when you go back to the add counters screen in perfmon, you should see Simplest Performance Category as an option


Go ahead and open up the category by clicking the little triangular thingy to the right of it and select the text that will show up. It's something like Operations/sec. Then click on add to bring it to the right side of the split screen and select OK. If you are unable to see it under your graph, you will have to add a Thread.Sleep method in order to have instance of the application running, while you add the category. Once you have it added to your monitor, you can go back and remove the Thread.Sleep call. You should be able to see something similar after you have done all that:



I definitely think that Microsoft could have done a better job addressing performance counters in the enterprise library considering how little is the documentation on the web. I also think that Microsoft could do a much better job at documenting the enterprise library, considering that the enterprise library hands on labs are not detailed enough, the documentation on MSDN is virtually non-existent and a developer has to rely solely on the community out there for help.
After all this is not a few month old project, but some years now.

Happy programming.

P.S. Almost forgot, You will have to add an App.config file to your solution that has instrumentation specified in it. Here is how you can do that:

Open the Enterprise Library Configuration tool by going to All Programs->Microsoft Patterns and Practices-> Ent. Lib. -> Enterprise Library Configuration tool.




Right Click on the blue cubes that say Ent. Lib. Configuration-> Add new application.

Now Right click on the Application Configuration Icon and add new Instrumentation block. Now select true for Performance counters enabled and save the newly created config file as App.config inside your project directory. Now all you have to do is go back to your project and add existing file, pointing to the newly created App.config and you are set.

No comments: