Mapping Performance Counters (Counter Ids and Metadata)

Performance counters are represented by string names, for example disk.provisioned.LATEST or mem.granted.AVERAGE. A vSphere server tracks performance counters by using system-generated counter IDs. When you create a performance query, you use counter IDs to specify the statistics to be retrieved, so it is useful to map the names to IDs.

The example must specify counter IDs in the calls to QueryPerf, and it will use performance counter metadata when it prints information about the returned data. To obtain performance counter IDs and the corresponding performance counter metadata, the example creates two hash maps. This example maps the entire set of performance counters to support retrieval of any counter.

HashMap Declarations

The following code fragment declares two hash maps.

  • countersIdMap – Uses full counter names to index performance counter IDs. A full counter name is the combination of counter group, name, and rollup type. The example uses this map to obtain counter IDs when it builds the performance query specification.
  • countersInfoMap – Uses performance counter IDs to index PerformanceCounterInfo data objects. The example uses this map to obtain metadata when it prints the returned performance data.
/*
 * Map of counter IDs indexed by counter name.
 * The full counter name is the hash key - group.name.ROLLUP-TYPE.
 */
private static HashMap<String, Integer> countersIdMap = new HashMap<String, Integer>();

/* 
 * Map of performance counter data (PerfCounterInfo) indexed by counter ID 
 * (PerfCounterInfo.key property). 
 */
private static HashMap<Integer, PerfCounterInfo> countersInfoMap = 
    new HashMap<Integer, PerfCounterInfo>();

The following figure shows a representation of the hash maps.

Figure 1. Performance Counter Hash Maps
Visualizes the hash maps for vSphere performance counters.

Creating the Map

The example uses the Property Collector to retrieve the array of performance counters (PerfCounterInfo) known to the vCenter Server (PerformanceManager.perfCounter[]). It then uses the data to create the maps. The code fragment uses the variable apiMethods, which is a VimPortType object that provides access to the vSphere API methods. For information about the VimPortType object, see Overview of a Java Sample Application for the Web Services SDK.

The following code fragment performs these steps:

  1. Create an ObjectSpec to define the property collector context. This example specifies the Performance Manager.
  2. Create a PropertySpec to identify the property to be retrieved. This example retrieves the perfCounter property, which is an array of PerfCounterInfo objects.
  3. Create a PropertyFilterSpec for the call to the PropertyCollector. The PropertyFilterSpec creates the association between the ObjectSpec and PropertySpec for the operation.
  4. Call the PropertyCollector.RetrievePropertiesEx method. This method blocks until the server returns the requested property data.
  5. Cast the returned xsd:anyType value into the array of PerfCounterInfo objects.
  6. Cycle through the returned array and load the maps. The counter-name to counter-ID map uses a fully qualified counter name. The qualified name is a path consisting of counter group, counter name, and rollup type – group.counter.ROLLUP-TYPE The rollup type must be coded in uppercase letters. Examples of qualified names are disk.provisioned.LATEST and mem.granted.AVERAGE.
/*
 * Create an object spec to define the context to retrieve the PerformanceManager property.
 */
ObjectSpec oSpec = new ObjectSpec();
oSpec.setObj(performanceMgrRef);
        
/* 
 * Specify the property for retrieval
 * (PerformanceManager.perfCounter is the list of counters the vCenter Server is aware of.)
 */
PropertySpec pSpec = new PropertySpec();
pSpec.setType("PerformanceManager");
pSpec.getPathSet().add("perfCounter");

/*
 * Create a PropertyFilterSpec and add the object and property specs to it.
 */
PropertyFilterSpec fSpec = new PropertyFilterSpec();
fSpec.getObjectSet().add(oSpec);
fSpec.getPropSet().add(pSpec);
        
/*
 * Create a list for the filter and add the spec to it.
 */
List<PropertyFilterSpec> fSpecList = new ArrayList<PropertyFilterSpec>();
fSpecList.add(fSpec);

/*
 * Get the performance counters from the server.
 */
RetrieveOptions ro = new RetrieveOptions();
RetrieveResult props = apiMethods.retrievePropertiesEx(pCollectorRef,fSpecList,ro);

/*
 * Turn the retrieved results into an array of PerfCounterInfo.
 */
List<PerfCounterInfo> perfCounters = new ArrayList<PerfCounterInfo>();
if (props != null) {
   for (ObjectContent oc : props.getObjects()) {
      List<DynamicProperty> dps = oc.getPropSet();
      if (dps != null) {
         for (DynamicProperty dp : dps) {
            /*

/*
 * Cycle through the PerfCounterInfo objects and load the maps.
 */
             *  DynamicProperty.val is an xsd:anyType value to be cast
             *  to an ArrayOfPerfCounterInfo and assigned to a List<PerfCounterInfo>.
             */
            perfCounters = ((ArrayOfPerfCounterInfo)dp.getVal()).getPerfCounterInfo();
         }
      }
   }
}
for(PerfCounterInfo perfCounter : perfCounters) {
   Integer counterId = new Integer(perfCounter.getKey());

   /*
    * This map uses the counter ID to index performance counter metadata.
    */
   countersInfoMap.put(counterId, perfCounter);

   /*
    * Obtain the name components and construct the full counter name,
    * for example – power.power.AVERAGE.
    * This map uses the full counter name to index counter IDs.
    */
   String counterGroup = perfCounter.getGroupInfo().getKey();
   String counterName = perfCounter.getNameInfo().getKey();
   String counterRollupType = perfCounter.getRollupType().toString();
   String fullCounterName = counterGroup + "." + counterName + "." + counterRollupType;

   /*
    * Store the counter ID in a map indexed by the full counter name.
    */
   countersIdMap.put(fullCounterName, counterId);

}