This topic has not yet been rated - Rate this topic

System.Diagnostics.PerformanceData Namespace

Use the classes in this namespace to provide counter data. The counters are used to expose performance metrics to consumers such as the Performance Monitor. The namespace does not contain classes for consuming the counter data. For a complete description of the performance counters architecture, see Performance Counters.

The classes in this namespace support the new architecture (version 2.0) for performance counters that was introduced in Windows Vista. In the new architecture, the provider no longer responds to consumer requests directly, but instead simply maintains the counter data. The system injects a thread into the provider's process when the provider creates an instance of the counter set; the thread is responsible for handling consumer requests.

The following steps show the process for writing a counters provider.

  1. The counters that the provider provides is defined in an XML-based manifest. The counters are logically grouped into counter sets. The counters within a counter set are identified by a numeric identifier that is unique within the counter set. A provider can define one or more counter sets. A counter set is identified by a Guid that is unique to a provider. Note that if you use these classes to write your provider:

    • The callback attribute of the provider element is ignored.

    • The reference value for the name attribute of the counterAttribute element is ignored.

    For details on writing the manifest, see Performance Counters Schema.

  2. After writing your manifest, use the CTRPP tool to compile the manifest (ctrpp provider.man). The tool generates four files: .h, .c, .rc, and *_r.h. You can ignore the .h and .c files. The .rc file contains the localized strings defined in your manifest. You use the .rc and *_r.h files to create the compiled resource file (.res) that you include in your project. The following call shows how to compile the resource file:

    rc /r /i "c:\Program Files\Microsoft SDKs\Windows\v6.0\Include" provider.rc
    

    If you get an error that references sal.h, copy the sal.h file from your Microsoft Visual Studio, Visual C include directory to the directory you specify for the /i switch.

    Add a path to the compiled resource file (.res) to your project's Application property page.

  3. Write your provider. The following steps show the calls made by a provider:

    1. Call the CounterSet.CounterSet constructor to define the counter set. Call this method for each counter set defined in the manifest.

    2. For each counter set, call one of the CounterSet.AddCounter methods to add the counters to the set. Call this method for each counter defined in the counter set.

    3. Call the CounterSet.CreateCounterSetInstance method to create an instance of the counter set (an instance contains the counter data). For single instance counter sets, call this method one time. For multiple instance counter sets, call this method for each instance for which you need to provide counter data (use a unique name for each instance).

    4. Use the CounterSetInstance.Counters property to access and set the counter data for the counter.

  4. After you finish your provider, use the LodCtr tool to register the counters on the computer. For example,

    lodctr /m:provider.man
    

    The example assumes the manifest and executable file are in the current directory. For complete details on using the LodCtr, see Microsoft Technet.

You can use the classes in this namespace on computers that run the Windows Vista and later operating systems.

  Class Description
Public class CounterData Contains the raw data for a counter.
Public class CounterSet Defines a set of logical counters.
Public class CounterSetInstance Creates an instance of the logical counters defined in the CounterSet class.
Public class CounterSetInstanceCounterDataSet Contains the collection of counter values.
  Enumeration Description
Public enumeration CounterSetInstanceType Specifies whether the counter set allows multiple instances such as processes and physical disks, or a single instance such as memory.
Public enumeration CounterType Defines the possible types of counters. Each counter is assigned a counter type. The counter type determines how the counter data is calculated, averaged, and displayed.

The following shows a simple manifest:

<!-- <?xml version="1.0" encoding="UTF-16"?> -->
<instrumentationManifest xsi:schemaLocation="http://schemas.microsoft.com/win/2004/08/events eventman.xsd" 
     xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     xmlns:trace=http://schemas.microsoft.com/win/2004/08/events/trace>

    <instrumentation>

        <counters xmlns=http://schemas.microsoft.com/win/2005/12/counters>

            <provider
              applicationIdentity = "provider1.exe"
              providerType = "userMode"
              providerGuid = "{51D1685C-35ED-45be-99FE-17261A4F27F3}">

               <counterSet guid = "{582803C9-AACD-45e5-8C30-571141A22092}"
                  uri = "Microsoft.Windows.System.PerfCounters.Typing"
                  name = "$(string.CounterSet1.Name)" 
                  description = "$(string.CounterSet1.Description)" 
                  instances = "single">

                    <counter id = "1"
                      uri = "Microsoft.Windows.System.PerfCounters.Typing.TotalWords"
                      name = "$(string.CS1.Counter1.Name)"
                      description = "$(string.CS1.Counter1.Description)"
                      type = "perf_counter_rawcount"
                      detailLevel = "standard"/>

                    <counter id = "2"
                      uri = "Microsoft.Windows.System.PerfCounters.Typing.WordsInInterval"
                      name = "$(string.CS1.Counter2.Name)"
                      description = "$(string.CS1.Counter2.Description)"
                      type = "perf_counter_delta"
                      detailLevel = "standard"/>

                    <counter id = "3"
                      uri = "Microsoft.Windows.System.PerfCounters.Typing.LetterAPressed"
                      name = "$(string.CS1.Counter3.Name)"
                      description = "$(string.CS1.Counter3.Description)"
                      type = "perf_counter_rawcount"
                      detailLevel = "standard"/>

                    <counter id = "4"
                      uri = "Microsoft.Windows.System.PerfCounters.Typing.WordsContainingLetterA"
                      name = "$(string.CS1.Counter4.Name)" 
                      description = "$(string.CS1.Counter4.Description)" 
                      type = "perf_counter_rawcount"
                      detailLevel = "standard"/>

                    <counter id = "5"
                      uri = "Microsoft.Windows.System.PerfCounters.Typing.PercentOfWordsContainingLetterA"
                      name = "$(string.CS1.Counter5.Name)" 
                      description = "$(string.CS1.Counter5.Description)" 
                      type = "perf_sample_fraction"
                      baseID = "6"
                      detailLevel = "standard">
                      <counterAttributes>
                          <counterAttribute name = "displayAsReal" />
                      </counterAttributes>
                    </counter>

                    <counter id = "6"
                      uri = "Microsoft.Windows.System.PerfCounters.Typing.PercentBase"
                      type = "perf_sample_base"
                      detailLevel = "standard">
                      <counterAttributes>
                          <counterAttribute name = "noDisplay" />
                      </counterAttributes>
                    </counter>

                </counterSet>
            </provider>
        </counters>
    </instrumentation>

    <localization>
        <resources culture="en-US">
            <stringTable>

                <string id="CounterSet1.Name" value="Typing"/>
                <string id="CounterSet1.Description" value="Captures simple typing metrics."/>
                <string id="CS1.Counter1.Name" value="Total Words Typed"/> 
                <string id="CS1.Counter1.Description" value="The total number of words typed."/>
                <string id="CS1.Counter2.Name" value="Words Typed In Interval"/> 
                <string id="CS1.Counter2.Description" value="The total number of words typed in the interval."/>
                <string id="CS1.Counter3.Name" value="Letter A Pressed"/> 
                <string id="CS1.Counter3.Description" value="The number of times that the letter A is pressed."/>
                <string id="CS1.Counter4.Name" value="Words Containing A"/> 
                <string id="CS1.Counter4.Description" value="The number of words that contain the letter A."/>
                <string id="CS1.Counter5.Name" value="Percent of Words Containing A"/> 
                <string id="CS1.Counter5.Description" value="The percent of words that contain the letter A in the last interval."/>

            </stringTable>
        </resources>
    </localization>
</instrumentationManifest>

The following shows a simple provider implementation for the manifest:

using System.Diagnostics.PerformanceData;

        private static Guid providerId = new Guid("{51D1685C-35ED-45be-99FE-17261A4F27F3}");
        private static Guid typingCounterSetId = new Guid("{582803C9-AACD-45e5-8C30-571141A22092}");

        private static CounterSet typingCounterSet;         // Defines the counter set
        private static CounterSetInstance typingCsInstance; // Instance of the counter set

        private static int numberOfLetterAInWord = 0;

        . . .

            // Create the 'Typing' counter set.
            typingCounterSet = new CounterSet(providerId, typingCounterSetId, CounterSetInstanceType.Single);

            // Add the counters to the counter set definition.
            typingCounterSet.AddCounter(1, CounterType.RawData32, "Total Word Count");
            typingCounterSet.AddCounter(2, CounterType.Delta32, "Words Typed In Interval");
            typingCounterSet.AddCounter(3, CounterType.RawData32, "A Key Pressed");
            typingCounterSet.AddCounter(4, CounterType.RawData32, "Words Containing A");
            typingCounterSet.AddCounter(5, CounterType.SampleFraction, "Percent of Words Containg A");
            typingCounterSet.AddCounter(6, CounterType.SampleBase, "Percent Base");

            // Create an instance of the counter set (contains the counter data).
            typingCsInstance = typingCounterSet.CreateCounterSetInstance("Typing Instance");
            typingCsInstance.Counters[1].Value = 0;
            typingCsInstance.Counters[2].Value = 0;
            typingCsInstance.Counters[3].Value = 0;
            typingCsInstance.Counters[4].Value = 0;
            typingCsInstance.Counters[5].Value = 0;
            typingCsInstance.Counters[6].Value = 0;

        . . .

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            typingCounterSet.Dispose();
        }

        // Simple effort to capture letter A key press and words typed.
        private void textInput_KeyDown(object sender, KeyEventArgs e)
        {
            Keys keyData = e.KeyData;
            
            switch (e.KeyData)
            {
                case Keys.A :
                    // In the .NET 3.5 Framework, you had to use the
                    // Value property to set and increment the counter 
                    // value. Beginning with the .NET 4.0 Framework, 
                    // the Value property is safe to use in a multi-
                    // threaded application.
                    typingCsInstance.Counters["A Key Pressed"].Value++;
                    numberOfLetterAInWord++;

                    break;

                case Keys.Enter:
                case Keys.Space:
                case Keys.Tab:

                    if (numberOfLetterAInWord > 0)
                    {
                        // Beginning with the .NET 4.0 Framework, you 
                        // can use the Increment method to increment 
                        // the counter value by 1. The Increment method 
                        // is safe to use in a multi-threaded 
                        // application.
                        typingCsInstance.Counters["Words Containing A"].Increment();
                        typingCsInstance.Counters["Percent of Words Containg A"].Increment();
                        numberOfLetterAInWord = 0;
                    }

                    typingCsInstance.Counters["Percent Base"].Increment();
                    typingCsInstance.Counters["Total Word Count"].Increment();
                    typingCsInstance.Counters["Words Typed In Interval"].Increment();

                    break;
            }
        }
Did you find this helpful?
(1500 characters remaining)
Thank you for your feedback
Show:
© 2014 Microsoft. All rights reserved.