private Map<String, Map<String, List<MetricDefinition>>> processMetricDefinition(
    Map<String, Map<String, List<MetricDefinition>>> metricMap) {

    if (!metricMap.isEmpty()) {
        // For every Component
      for (Map.Entry<String, Map<String, List<MetricDefinition>>> componentMetricDefEntry : metricMap.entrySet()) {
        String componentName = componentMetricDefEntry.getKey();
        // For every Component / HostComponent category
        for (Map.Entry<String, List<MetricDefinition>> metricDefEntry : componentMetricDefEntry.getValue().entrySet()) {
          //For every metric definition
          for (MetricDefinition metricDefinition : metricDefEntry.getValue()) {
            for (Map.Entry<String, Map<String, Metric>> metricByCategory : metricDefinition.getMetricsByCategory().entrySet()) {
              Iterator<Map.Entry<String, Metric>> iterator = metricByCategory.getValue().entrySet().iterator();
              Map<String, Metric> newMetricsToAdd = new HashMap<>();

              while (iterator.hasNext()) {
                Map.Entry<String, Metric> metricEntry = iterator.next();
                // Process Namenode rpc metrics
                Map<String, Metric> processedMetrics = PropertyHelper.processRpcMetricDefinition(metricDefinition.getType(),
                  componentName, metricEntry.getKey(), metricEntry.getValue());
                if (processedMetrics != null) {
                  iterator.remove(); // Remove current metric entry
                  newMetricsToAdd.putAll(processedMetrics);
                } else {
                  processedMetrics = Collections.singletonMap(metricEntry.getKey(), metricEntry.getValue());
                }

                // NOTE: Only Component aggregates for AMS supported for now.
                if (metricDefinition.getType().equals("ganglia") &&
                  (metricDefEntry.getKey().equals(Component.name()) ||
                    metricDefEntry.getKey().equals(HostComponent.name()))) {
                  for (Map.Entry<String, Metric> processedMetric : processedMetrics.entrySet()) {
                    newMetricsToAdd.putAll(getAggregateFunctionMetrics(processedMetric.getKey(),
                      processedMetric.getValue()));
                  }
                }
              }
              metricByCategory.getValue().putAll(newMetricsToAdd);
            }
          }
        }
      }
    }

    return metricMap;
  }
Add aggregate function support for all stack defined metrics.

Refactor Namenode RPC metrics for different kinds of ports.
ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java