6
votes

VS 2005, C# 2.0, .NET 2.0/3.0, Win2003

I'm trying to install a set of performance counters for a MultiInstance. I noticed that some system performance counter categories manage to keep a "total" alive even when there are no other instances. ASP.NET Apps 2.0.50727 is an example.

So I've been trying to duplicate this. I created the following routine in an Installer class which I then add to a Custom Action in a setup project.

public override void Install(System.Collections.IDictionary stateSaver)
{
    //Debugger.Break();
    CounterCreationData data = new CounterCreationData("ZCounter", "ZCtrHelp", PerformanceCounterType.NumberOfItems32);
    PerformanceCounterCategory.Create("ZCategory", "ZCatHelp", PerformanceCounterCategoryType.MultiInstance, new CounterCreationDataCollection(new CounterCreationData[] { data }));
    PerformanceCounter counter = new PerformanceCounter();
    counter.CategoryName = "ZCategory";
    counter.CounterName = "ZCounter";
    counter.InstanceName = "ZTotal";
    counter.InstanceLifetime = PerformanceCounterInstanceLifetime.Global;
    counter.ReadOnly = false;
    counter.RawValue = 0;
    base.Install(stateSaver);
}

If I uncomment the Debugger.Break() line, and step through, I can see the counter is actually created with the right instance name, and Visual Studio Server Explorer shows the instance along with the InstanceLifetime set to Global. I do not call the RemoveInstance() method in the setup program.

Nevertheless, a few seconds after the setup program completes, that instance disappears from the Performance Monitor and from the VS Server Explorer. How do I make it stick? Or can I?

4

4 Answers

7
votes

Some code has to be actively maintaining the counter. In all the instances you can think of, such as ASP.Net, there is a service keeping the counter up.

As you aren't happy with having a _Total instance only active while some instance of your app is running, you have to write some code that will maintain the performance counter outside of your application. There's no magic.

You can write a small service that does your monitoring needs. This will maintain the _Total counter. You need to decide on an update regimen. The easiest is to have every instance of your app update both instances (their own and _Total).

A bit of background on performance counters - the main thing to understand is that there is typically a shared memory region shared between processes that is updated via interlocked operations. A tool like PerfMon (or any other app) ends up connecting to the shared memory region to get the current values. So some process has to have that shared memory region opened and owned. Thus why you need code running. PerfMon is not creating the _Total instance for you (it does have some pretty convoluted combinations of counters allowing for averages and rates, but not a sum to create a summary instance).

1
votes

AFAIK a Global Performance Counter category will remain alive as long as any process has an active handle referencing it. System counters achieve this by keeping a handle to the total counter instance in some service.

0
votes

Try to create the category with "PerformanceCounterCategoryType.SingleInstance".

0
votes

Just a suggestion but try making

Counter.ReadOnly = true;

the first pass through and only setting it to False when you need to increment the counter.

And also if you make the Counter Readonly you clearly need to comment out the line:

Counter.RawData = 0;

I believe its set to 0 by default the first pass anyhow.

Hope this helps...