Click here to Skip to main content
15,881,715 members
Articles / Programming Languages / C#
Article

Using Custom Attributes to Create Performance Counters

Rate me:
Please Sign up or sign in to vote.
3.58/5 (9 votes)
12 Jun 2007CPOL3 min read 61.8K   762   35   10
This article describes how to use custom attributes to automate performance counter and category creation.
Performance Monitor

Introduction

Performance counters provide an excellent method to monitor key performance indicators for an application. Before being able to write to a performance counter, two tasks need to be completed.

  • First, the performance counter category and the contained performance counters must be created on the machine where the application is going to use them. This can only be done by a user with administrative rights.
  • Second, the application needs to create writable instances of the performance counters.

By using custom attributes (this was inspired by Duncan Edwards Jones' article about performance counters) and a helper class, we can easily perform both tasks from a single definition for each performance counter.

Background

We recently introduced new search technology to our Web site and wanted to make sure that we get a good feeling for the performance of that search technology in the production environment. We also wanted to define thresholds for some performance indicators for the system and network monitoring tool so we can automatically raise alerts if performance drops below the threshold. Performance counters were the ideal solutions for us since they are lightweight, fast, and could easily be plugged into our monitoring tool.

For ease of use and maintenance reasons, we only wanted to define performance counters once in the code and then have the ability to use that definition to create the performance counters and categories on the machine as well as the instances in the application. Due to the application being a Web site, there was no way for the application to create the performance counters if they did not exist because it does not have administrative rights. At the same time we wanted to avoid having to create additional tools for performance counter and category creation.

Using the Custom Attributes

To associate a class with a performance counter category, simply decorate the class with the PerformanceCounterCategoryAttribute.

C#
[PerformanceCounterCategory("Random Test", PerformanceCounterCategoryType.MultiInstance)]
class Test
{
    ...

To associate a PerformanceCounter class member with a performance counter, simply decorate it with the PerformanceCounterAttribute.

C#
[PerformanceCounter("Random Rate", "", PerformanceCounterType.RateOfCountsPerSecond32)]
private static PerformanceCounter pcRandomRate;

[PerformanceCounter("Random Average", "", PerformanceCounterType.AverageCount64)]
private PerformanceCounter pcRandomAverage;
private PerformanceCounter pcRandomAverageBase;

[PerformanceCounter("Random Value", "", 
    PerformanceCounterType.NumberOfItems64, "Standard")]
private PerformanceCounter pcRandomValue;        

[PerformanceCounter("Random Value", "", 
    PerformanceCounterType.NumberOfItems64, "Inverted")]
private PerformanceCounter pcRandomInvertedValue;        

private bool usePerformanceCounters;

Note that counter types that need a base counter only have an attribute on the actual performance counter. The helper class will automatically create the base counter when needed. The helper class also assumes that the variable name for the base counter is the performance counter variable name with "Base" appended to it. The same assumption is made for the counter and base counter names.

If the performance counter category is created to support multi-instance counters and a counter does not have an instance name, the helper class uses _default as the instance name.

Declare a boolean variable that can be used to safeguard updating of performance counters in the application code.

Creating Writable Performance Counter Instances

To instantiate the performance counter for a given class, use the helper class PerformanceCounterFactory inside the constructor:

C#
public Test()
{
    pcRandomRate = pcRandomAverage = pcRandomAverageBase = pcRandomValue
        = pcRandomInvertedValue 
        = null;

    try
    {
        // create writable performance counter instances
        usePerformanceCounters = 
            PerformanceCounterFactory.CreateCounters(typeof(Test), this);
    }
    catch (Exception)
    {
        usePerformanceCounters = false;
    }
}

Updating Performance Counters

The performance counters can then be updated as usual from within the application code. Make sure the performance counter access is safeguarded with a boolean variable that indicates that the performance counter creation was successful.

C#
if (usePerformanceCounters)
{
    // set number counter
    pcRandomValue.RawValue = r;
    pcRandomInvertedValue.RawValue = randMax - r;
    // update rate counter
    pcRandomRate.Increment();
    // update average counter
    pcRandomAverage.IncrementBy(r);
    pcRandomAverageBase.Increment();
}

Installing Performance Counter Categories

The code above assumes that the performance counters and the category they belong to already exist. From the class definition and attributes, we can also create the category and performance counters by using the helper class in conjunction with an Installer and a PerformanceCounterInstaller. The following code needs to be added to the installer's constructor:

C#
// Create a new helper class instance
PerformanceCounterFactory category = new PerformanceCounterFactory(typeof(Test));

// now add the counters to the performance counter installer
counterInstaller.CategoryName = category.Name;
counterInstaller.CategoryType = category.CategoryType;
if (category.Help != null)
    counterInstaller.CategoryHelp = category.Help;
counterInstaller.Counters.AddRange(category.Counters);

If the performance counters for a performance counter category spread across multiple classes, use PerformanceCounterFactory.AddCounters(typeof(AdditionalTestClass)); to add them to the helper class before passing them to the PerformanceCounterInstaller.

Installing and uninstalling of performance counter categories can simply be done by running installutil with the given assembly.

To install a performance counter category and counters without using an installer, simply use the PerformanceCounterFactory constructors and the Create() method.

Points of Interest

Installers can be useful even if you do not intend to wrap them in an MSI.

History

  • 1.0 Initial version
  • 2.0 Migrated the code to .NET 2.0 and added support for performance counter instances

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
GeneralPerformanceCounterCategory.Exists Pin
Member 422196925-Jul-08 5:33
Member 422196925-Jul-08 5:33 
GeneralI need your changes. Pin
ga_c26-Apr-07 12:08
ga_c26-Apr-07 12:08 
GeneralCounters with instances Pin
Andreas Saurwein22-Oct-06 9:49
Andreas Saurwein22-Oct-06 9:49 
I had to make quite some changes to make it support counters with instances. For example remove the requirement for static members, since that wont allow instances. Also counter creation has to take into account an instance name.
Anybody interested in my changes, drop me a line.


Leon[^] - Enterprise Anti-Spam Server

GeneralRe: Counters with instances Pin
Andreas Piefke23-Oct-06 1:53
Andreas Piefke23-Oct-06 1:53 
GeneralRe: Counters with instances Pin
IgDev22-May-08 6:56
IgDev22-May-08 6:56 
GeneralRe: Counters with instances Pin
Andreas Piefke23-May-08 2:36
Andreas Piefke23-May-08 2:36 
GeneralRe: Counters with instances Pin
Uwe Keim13-Feb-07 2:54
sitebuilderUwe Keim13-Feb-07 2:54 
GeneralRe: Counters with instances Pin
Madmaximus15-Aug-07 4:20
Madmaximus15-Aug-07 4:20 
GeneralSmall fix for derived classes Pin
Red_F29-Aug-06 2:40
Red_F29-Aug-06 2:40 
GeneralWell done Pin
mhrushka6-Jun-06 8:47
mhrushka6-Jun-06 8:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.