views:

1020

answers:

4

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?

A: 

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

Christian.K
I probably could, but that defeats the purpose of having a "Total" instance (used to aggregrate the results of all the other instances). I know it's possible; as I mentioned, ASP.NET is doing it somehow. Maybe it uses some other process to keep the "__Total__" instance in the counter set?
Alan McBee
I don't know about the "other process" thing - but would be interested if there is such a beast.I'd create the SingleInstance counter and everytime I update the MultiInstance/specific instance-one I'd update the SingleInstance/global-one by the same value. I.e. do the "aggregation" manually.
Christian.K
Sorry I didn't see this comment earlier. Two problems: 1) SingleInstance *category* means there are no named instances. 2) I know I can update multiple instances (one "total" and one "process" instance) -- that's not my problem. The problem is "how do I KEEP the "total" instance of the MultipleInstance category showing in the perf counter list when there are no instances running at all?
Alan McBee
Yes, you're right of course. Sorry, I was a bit slow-witted. Just two days ago I was dealing with performance counters again (incidentally a "_Total" instance as well) and now I got it. :-)
Christian.K
A: 

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...

Mike Fielden
I'll try this out, and let you know today.
Alan McBee
Mike: the test failed. If it had worked, there would have been a single instance named "ZTotal" in Performance Monitor for that category and counter, and there is not.
Alan McBee
+1  A: 

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.

CriGoT
+4  A: 

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).

EWizard
I consider this to be the right answer to my question. However, the check mark is gone; I can't select it as the correct answer.I knew that PerfMon wasn't creating the _Total counter; it just wasn't clear to me that there was always a service keeping the _Total counter alive. The "PerformanceCounterInstanceLifetime.Global" suggests it should do this; otherwise, what's the point of that name?BTW, I'm not at all averse to writing any amount of code, services or whatever. I just wasn't aware that was how it was being done. I resent being thought of as a lazy programmer.
Alan McBee