Reuse RawBase performance counters when multiple RawFraction counters share a denominator

0

I want to set up PerformanceCounters for events that can occur in a system. I want to display a few counters for different events as a percentage (PerformanceCounterType.RawFraction), but each percent shares the same denominator (PerformanceCounterType.RawBase).

I thought it would be easy to use one counter as the RawBase for all the RawFraction counters, but I don't see how.

Here is a contrived example.

I set up three counters for different flavors of the event I want to count: Red, Green, and Blue. (Imagine a form with three buttons and we just want to count the percent of presses for each button.)

I set up one counter for the total number of events: Any

when Red occurs, I increment Red and Any.when blue occurs, I increment Blue and Any. When Green occurs, I increment Green and Any.

When I try to reuse the Any counter as a common RawBase counter, I get the exception:

System.ArgumentException   
  HResult=0x80070057   
  Message=Cannot create Performance Category with counter name Any button because the name is a duplicate.   
  Source=System   
  StackTrace:    
   at System.Diagnostics.PerformanceCounterCategory.CheckValidCounterLayout(CounterCreationDataCollection counterData)

It seems excessive to set up separate RawBase counters to calculate many RawFraction values that share the same denominator. Any suggestions?

Here is some test code.

public class PerfCounters
{

    private static string CategoryName = "Demo counters";
    private static string CategoryHelp = "Demo counters help";

    private static string buttonAnyCountName = "Any button";
    private static string buttonAnyCountHelp = "Any button help";
    private static PerformanceCounter buttonAnyCount;

    private static string buttonRedCountName = "% of Red button clicked";
    private static string buttonRedCountHelp = "Red button help";
    private static PerformanceCounter buttonRedCount;

    private static string buttonGreenCountName = "% of Green button clicked";
    private static string buttonGreenCountHelp = "Green button help";
    private static PerformanceCounter buttonGreenCount;

    private static string buttonBlueCountName = "% of Blue button clicked";
    private static string buttonBlueCountHelp = "Blue button help";
    private static PerformanceCounter buttonBlueCount;

    public PerfCounters()
    {
        if (PerformanceCounterCategory.Exists(CategoryName))
        {
            // this is a quick and dirty test, so it is easiest to delete and recreate the category on each run
            // just remmember to restart Performance Monitor after the counters are created.
            PerformanceCounterCategory.Delete(CategoryName);
        }

        CounterCreationDataCollection counterDataCollection = new CounterCreationDataCollection();
        counterDataCollection.Add(new CounterCreationData(buttonRedCountName, buttonRedCountHelp, PerformanceCounterType.RawFraction));
        counterDataCollection.Add(new CounterCreationData(buttonAnyCountName, buttonAnyCountHelp, PerformanceCounterType.RawBase));

        counterDataCollection.Add(new CounterCreationData(buttonBlueCountName, buttonBlueCountHelp, PerformanceCounterType.RawFraction));
        counterDataCollection.Add(new CounterCreationData(buttonAnyCountName, buttonAnyCountHelp, PerformanceCounterType.RawBase));

        counterDataCollection.Add(new CounterCreationData(buttonGreenCountName, buttonGreenCountHelp, PerformanceCounterType.RawFraction));
        counterDataCollection.Add(new CounterCreationData(buttonAnyCountName, buttonAnyCountHelp, PerformanceCounterType.RawBase));

        // next line throws 
        // System.ArgumentException - Cannot create Performance Category with counter name Any button because the name is a duplicate.
        PerformanceCounterCategory.Create(CategoryName, CategoryHelp, PerformanceCounterCategoryType.SingleInstance, counterDataCollection);

        buttonRedCount = new PerformanceCounter(CategoryName, buttonRedCountName, string.Empty, false);
        buttonBlueCount = new PerformanceCounter(CategoryName, buttonBlueCountName, string.Empty, false);
        buttonGreenCount = new PerformanceCounter(CategoryName, buttonGreenCountName, string.Empty, false);

        buttonAnyCount = new PerformanceCounter(CategoryName, buttonAnyCountName, string.Empty, false);
    }

    public void CountRed()
    {
        buttonRedCount.Increment();
        buttonAnyCount.Increment();
    }

    public void CountGreen()
    {
        buttonGreenCount.Increment();
        buttonAnyCount.Increment();
    }

    public void CountBlue()
    {
        buttonBlueCount.Increment();
        buttonAnyCount.Increment();
    }
}
c#
.net
performancecounter
asked on Stack Overflow Jun 19, 2019 by Michael Levy

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0