Use registered strings for Component/feature names in Metrics

Removed the enumerated values for Component and Feature names
and replaced them with a way to register names.

Change-Id: Iecf58bd96ee6b04b2e668574e73533512cfac2ef
diff --git a/src/main/java/net/onrc/onos/core/metrics/OnosMetrics.java b/src/main/java/net/onrc/onos/core/metrics/OnosMetrics.java
index 62d9038..6c8cad2 100644
--- a/src/main/java/net/onrc/onos/core/metrics/OnosMetrics.java
+++ b/src/main/java/net/onrc/onos/core/metrics/OnosMetrics.java
@@ -10,9 +10,40 @@
 import com.codahale.metrics.Timer;
 
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 /**
  * This class acts a singleton to hold the Metrics registry for ONOS.
+ * All metrics (Counter, Histogram, Timer, Meter, Gauge) use a hierarchical
+ * string-based naming scheme: COMPONENT.FEATURE.NAME.
+ * Example: "Topology.Counters.TopologyUpdates".
+ * The COMPONENT and FEATURE names have to be registered in advance before
+ * a metric can be created. Example:
+ * <pre>
+ *   <code>
+ *     private static final OnosMetrics.MetricsComponent COMPONENT =
+ *         OnosMetrics.registerComponent("Topology");
+ *     private static final OnosMetrics.MetricsFeature FEATURE =
+ *         COMPONENT.registerFeature("Counters");
+ *     private final Counter counterTopologyUpdates =
+ *         OnosMetrics.createCounter(COMPONENT, FEATURE, "TopologyUpdates");
+ *   </code>
+ * </pre>
+ * Gauges are slightly different because they are not created directly in
+ * this class, but are allocated by the caller and passed in for registration:
+ * <pre>
+ *   <code>
+ *     private final Gauge<Long> gauge =
+ *         new {@literal Gauge<Long>}() {
+ *             {@literal @}Override
+ *             public Long getValue() {
+ *                 return gaugeValue;
+ *             }
+ *         };
+ *     OnosMetrics.registerMetric(COMPONENT, FEATURE, GAUGE_NAME, gauge);
+ *   </code>
+ * </pre>
  */
 public final class OnosMetrics {
 
@@ -26,66 +57,126 @@
      * Components that can hold Metrics.  This is used as the first part of
      * a Metric's name.
      */
-    public enum MetricsComponents {
+    public interface MetricsComponent {
         /**
-         * Global scope, not associated with a particular component.
-         */
-        GLOBAL("Global"),
-
-        /**
-         * Topology component.
-         */
-        TOPOLOGY("Topology");
-
-        private final String name;
-
-        /**
-         * Constructor allows specifying an alternate string name.
+         * Fetches the name of the Component.
          *
-         * @param name string for the name of the component
+         * @return name of the Component
          */
-        private MetricsComponents(String name) {
-            this.name = name;
-        }
+        public String getName();
 
-        @Override
-        public String toString() {
-            return name;
-        }
+        /**
+         * Registers a Feature for this component.
+         *
+         * @param featureName name of the Feature to register
+         * @return Feature object that can be used when creating Metrics
+         */
+        public MetricsFeature registerFeature(final String featureName);
     }
 
     /**
      * Features that can hold Metrics.  This is used as the second part of
      * a Metric's name.
      */
-    public enum MetricsFeatures {
+    public interface MetricsFeature {
         /**
-         * Global scope, not associated with a particular feature.
+         * Fetches the name of the Feature.
+         *
+         * @return name of the Feature
          */
-        GLOBAL("Global"),
+        public String getName();
+    }
 
-        /**
-         * Topology Intents Framework feature. (example)
-         */
-        TOPOLOGY_INTENTS("IntentsFramework");
-
+    /**
+     * Implementation of a class to represent the Component portion of a
+     * Metric's name.
+     */
+    private static final class Component implements MetricsComponent {
         private final String name;
 
         /**
-         * Constructor allows specifying an alternate string name.
+         * Constructs a component from a name.
          *
-         * @param name string for the name of the component
+         * @param newName name of the component
          */
-        private MetricsFeatures(String name) {
-            this.name = name;
+        private Component(final String newName) {
+            name = newName;
         }
 
         @Override
-        public String toString() {
+        public String getName() {
+            return name;
+        }
+
+        /**
+         * Registry to hold the Features defined in this Component.
+         */
+        private ConcurrentMap<String, MetricsFeature> featuresRegistry =
+                new ConcurrentHashMap<>();
+
+        @Override
+        public MetricsFeature registerFeature(final String featureName) {
+            MetricsFeature feature = featuresRegistry.get(featureName);
+            if (feature == null) {
+                final MetricsFeature createdFeature = new Feature(featureName);
+                feature = featuresRegistry.putIfAbsent(featureName, createdFeature);
+                if (feature == null) {
+                    feature = createdFeature;
+                }
+            }
+            return feature;
+        }
+    }
+
+    /**
+     * Implementation of a class to represent the Feature portion of a Metric's
+     * name.
+     */
+    private static final class Feature implements MetricsFeature {
+        private final String name;
+
+        /**
+         * Constructs a Feature from a name.
+         *
+         * @param newName name of the Feature
+         */
+        private Feature(final String newName) {
+            name = newName;
+        }
+
+        @Override
+        public String getName() {
             return name;
         }
     }
 
+    /**
+     * Registry to hold the Components defined in the system.
+     */
+    private static ConcurrentMap<String, MetricsComponent> componentsRegistry =
+            new ConcurrentHashMap<>();
+
+    /**
+     * Registers a component.
+     *
+     * @param name name of the Component to register
+     * @return MetricsComponent object that can be used to create Metrics.
+     */
+    public static MetricsComponent registerComponent(final String name) {
+        MetricsComponent component = componentsRegistry.get(name);
+        if (component == null) {
+            final MetricsComponent createdComponent = new Component(name);
+            component = componentsRegistry.putIfAbsent(name, createdComponent);
+            if (component == null) {
+                component = createdComponent;
+            }
+        }
+        return component;
+    }
+
+    /**
+     * Registry for the Metrics objects created in the system.
+     */
     private static final MetricRegistry METRICS_REGISTRY = new MetricRegistry();
 
     /**
@@ -97,12 +188,12 @@
      *
      * @return full name of the metric
      */
-    public static String generateName(final MetricsComponents component,
-                                      final MetricsFeatures feature,
+    public static String generateName(final MetricsComponent component,
+                                      final MetricsFeature feature,
                                       final String metricName) {
-        return MetricRegistry.name(component.toString(),
-                feature.toString(),
-                metricName);
+        return MetricRegistry.name(component.getName(),
+                                   feature.getName(),
+                                   metricName);
     }
 
     /**
@@ -113,8 +204,8 @@
      * @param metricName local name of the metric
      * @return Counter Meteric
      */
-    public static Counter createCounter(final MetricsComponents component,
-                                        final MetricsFeatures feature,
+    public static Counter createCounter(final MetricsComponent component,
+                                        final MetricsFeature feature,
                                         final String metricName) {
         final String name = generateName(component, feature, metricName);
         return METRICS_REGISTRY.counter(name);
@@ -128,8 +219,8 @@
      * @param metricName local name of the metric
      * @return Histogram Metric
      */
-    public static Histogram createHistogram(final MetricsComponents component,
-                                            final MetricsFeatures feature,
+    public static Histogram createHistogram(final MetricsComponent component,
+                                            final MetricsFeature feature,
                                             final String metricName) {
         final String name = generateName(component, feature, metricName);
         return METRICS_REGISTRY.histogram(name);
@@ -143,8 +234,8 @@
      * @param metricName local name of the metric
      * @return Timer Metric
      */
-    public static Timer createTimer(final MetricsComponents component,
-                                    final MetricsFeatures feature,
+    public static Timer createTimer(final MetricsComponent component,
+                                    final MetricsFeature feature,
                                     final String metricName) {
         final String name = generateName(component, feature, metricName);
         return METRICS_REGISTRY.timer(name);
@@ -158,8 +249,8 @@
      * @param metricName local name of the metric
      * @return Meter Metric
      */
-    public static Meter createMeter(final MetricsComponents component,
-                                    final MetricsFeatures feature,
+    public static Meter createMeter(final MetricsComponent component,
+                                    final MetricsFeature feature,
                                     final String metricName) {
         final String name = generateName(component, feature, metricName);
         return METRICS_REGISTRY.meter(name);
@@ -175,8 +266,8 @@
      * @param metricName local name of the metric
      * @param metric Metric to register
      */
-    public static void registerMetric(final MetricsComponents component,
-                                      final MetricsFeatures feature,
+    public static void registerMetric(final MetricsComponent component,
+                                      final MetricsFeature feature,
                                       final String metricName,
                                       final Metric metric) {
         final String name = generateName(component, feature, metricName);
diff --git a/src/test/java/net/onrc/onos/api/rest/TestRestMetricsCounters.java b/src/test/java/net/onrc/onos/api/rest/TestRestMetricsCounters.java
index 86523c0..148fd85 100644
--- a/src/test/java/net/onrc/onos/api/rest/TestRestMetricsCounters.java
+++ b/src/test/java/net/onrc/onos/api/rest/TestRestMetricsCounters.java
@@ -48,35 +48,40 @@
     }
 
     //  Test Counter data objects
+    private static final OnosMetrics.MetricsComponent COMPONENT =
+            OnosMetrics.registerComponent("MetricsUnitTests");
+    private static final OnosMetrics.MetricsFeature FEATURE =
+            COMPONENT.registerFeature("Counters");
+
     private static final String COUNTER1_NAME = "COUNTER1";
-    private static final String COUNTER1_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-                                                     OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String COUNTER1_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+                                                     FEATURE,
                                                      COUNTER1_NAME);
     private static final int COUNTER1_COUNT = 0;
 
     private static final String COUNTER2_NAME = "COUNTER2";
-    private static final String COUNTER2_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-                                                     OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String COUNTER2_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+                                                     FEATURE,
                                                      COUNTER2_NAME);
     private static final int COUNTER2_COUNT = -1;
 
     private static final String COUNTER3_NAME = "COUNTER3";
-    private static final String COUNTER3_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-                                                     OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String COUNTER3_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+                                                     FEATURE,
                                                      COUNTER3_NAME);
     private static final int COUNTER3_COUNT = 5;
 
     private final Counter counter1 =
-            OnosMetrics.createCounter(OnosMetrics.MetricsComponents.GLOBAL,
-                                      OnosMetrics.MetricsFeatures.GLOBAL,
+            OnosMetrics.createCounter(COMPONENT,
+                                      FEATURE,
                                       COUNTER1_NAME);
     private final Counter counter2 =
-            OnosMetrics.createCounter(OnosMetrics.MetricsComponents.GLOBAL,
-                                      OnosMetrics.MetricsFeatures.GLOBAL,
+            OnosMetrics.createCounter(COMPONENT,
+                                      FEATURE,
                                       COUNTER2_NAME);
     private final Counter counter3 =
-            OnosMetrics.createCounter(OnosMetrics.MetricsComponents.GLOBAL,
-                                      OnosMetrics.MetricsFeatures.GLOBAL,
+            OnosMetrics.createCounter(COMPONENT,
+                                      FEATURE,
                                       COUNTER3_NAME);
 
     /**
diff --git a/src/test/java/net/onrc/onos/api/rest/TestRestMetricsFilters.java b/src/test/java/net/onrc/onos/api/rest/TestRestMetricsFilters.java
index ccf1908..7e65a55 100644
--- a/src/test/java/net/onrc/onos/api/rest/TestRestMetricsFilters.java
+++ b/src/test/java/net/onrc/onos/api/rest/TestRestMetricsFilters.java
@@ -53,69 +53,74 @@
     }
 
     //  Test data objects
+    private static final OnosMetrics.MetricsComponent COMPONENT =
+            OnosMetrics.registerComponent("MetricsUnitTests");
+    private static final OnosMetrics.MetricsFeature FEATURE =
+            COMPONENT.registerFeature("Filters");
+
     private static final String TIMER1_NAME = "timer1";
-    private static final String TIMER1_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-            OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String TIMER1_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+            FEATURE,
             "timer1");
     private static final String TIMER2_NAME = "timer2";
-    private static final String TIMER2_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-            OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String TIMER2_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+            FEATURE,
             "timer2");
     private static final String TIMER3_NAME = "timer3";
-    private static final String TIMER3_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-            OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String TIMER3_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+            FEATURE,
             "timer3");
 
     private static final String GAUGE1_NAME = "gauge1";
-    private static final String GAUGE1_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-            OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String GAUGE1_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+            FEATURE,
             "gauge1");
     private static final String GAUGE2_NAME = "gauge2";
-    private static final String GAUGE2_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-            OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String GAUGE2_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+            FEATURE,
             "gauge2");
     private static final String GAUGE3_NAME = "gauge3";
-    private static final String GAUGE3_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-            OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String GAUGE3_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+            FEATURE,
             "gauge3");
 
     private static final String COUNTER1_NAME = "counter1";
-    private static final String COUNTER1_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-            OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String COUNTER1_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+            FEATURE,
             "counter1");
     private static final String COUNTER2_NAME = "counter2";
-    private static final String COUNTER2_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-            OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String COUNTER2_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+            FEATURE,
             "counter2");
     private static final String COUNTER3_NAME = "counter3";
-    private static final String COUNTER3_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-            OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String COUNTER3_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+            FEATURE,
             "counter3");
 
     private static final String METER1_NAME = "meter1";
-    private static final String METER1_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-            OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String METER1_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+            FEATURE,
             "meter1");
     private static final String METER2_NAME = "meter2";
-    private static final String METER2_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-            OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String METER2_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+            FEATURE,
             "meter2");
     private static final String METER3_NAME = "meter3";
-    private static final String METER3_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-            OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String METER3_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+            FEATURE,
             "meter3");
 
     private static final String HISTOGRAM1_NAME = "histogram1";
-    private static final String HISTOGRAM1_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-            OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String HISTOGRAM1_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+            FEATURE,
             "histogram1");
     private static final String HISTOGRAM2_NAME = "histogram2";
-    private static final String HISTOGRAM2_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-            OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String HISTOGRAM2_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+            FEATURE,
             "histogram2");
     private static final String HISTOGRAM3_NAME = "histogram3";
-    private static final String HISTOGRAM3_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-            OnosMetrics.MetricsFeatures.GLOBAL,
+    private static final String HISTOGRAM3_FULL_NAME = OnosMetrics.generateName(COMPONENT,
+            FEATURE,
             "histogram3");
 
     private final Gauge<Integer> testGauge = new Gauge<Integer>() {
@@ -129,56 +134,56 @@
      * Creates Metrics objects for test.
      */
     private void createMetrics() {
-        OnosMetrics.createTimer(OnosMetrics.MetricsComponents.GLOBAL,
-                OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.createTimer(COMPONENT,
+                FEATURE,
                 TIMER1_NAME);
-        OnosMetrics.createTimer(OnosMetrics.MetricsComponents.GLOBAL,
-                OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.createTimer(COMPONENT,
+                FEATURE,
                 TIMER2_NAME);
-        OnosMetrics.createTimer(OnosMetrics.MetricsComponents.GLOBAL,
-                OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.createTimer(COMPONENT,
+                FEATURE,
                 TIMER3_NAME);
 
-        OnosMetrics.createCounter(OnosMetrics.MetricsComponents.GLOBAL,
-                OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.createCounter(COMPONENT,
+                FEATURE,
                 COUNTER1_NAME);
-        OnosMetrics.createCounter(OnosMetrics.MetricsComponents.GLOBAL,
-                OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.createCounter(COMPONENT,
+                FEATURE,
                 COUNTER2_NAME);
-        OnosMetrics.createCounter(OnosMetrics.MetricsComponents.GLOBAL,
-                OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.createCounter(COMPONENT,
+                FEATURE,
                 COUNTER3_NAME);
 
-        OnosMetrics.createMeter(OnosMetrics.MetricsComponents.GLOBAL,
-                OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.createMeter(COMPONENT,
+                FEATURE,
                 METER1_NAME);
-        OnosMetrics.createMeter(OnosMetrics.MetricsComponents.GLOBAL,
-                OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.createMeter(COMPONENT,
+                FEATURE,
                 METER2_NAME);
-        OnosMetrics.createMeter(OnosMetrics.MetricsComponents.GLOBAL,
-                OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.createMeter(COMPONENT,
+                FEATURE,
                 METER3_NAME);
 
-        OnosMetrics.createHistogram(OnosMetrics.MetricsComponents.GLOBAL,
-                OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.createHistogram(COMPONENT,
+                FEATURE,
                 HISTOGRAM1_NAME);
-        OnosMetrics.createHistogram(OnosMetrics.MetricsComponents.GLOBAL,
-                OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.createHistogram(COMPONENT,
+                FEATURE,
                 HISTOGRAM2_NAME);
-        OnosMetrics.createHistogram(OnosMetrics.MetricsComponents.GLOBAL,
-                OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.createHistogram(COMPONENT,
+                FEATURE,
                 HISTOGRAM3_NAME);
 
-        OnosMetrics.registerMetric(OnosMetrics.MetricsComponents.GLOBAL,
-                OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.registerMetric(COMPONENT,
+                FEATURE,
                 GAUGE1_NAME,
                 testGauge);
-        OnosMetrics.registerMetric(OnosMetrics.MetricsComponents.GLOBAL,
-                OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.registerMetric(COMPONENT,
+                FEATURE,
                 GAUGE2_NAME,
                 testGauge);
-        OnosMetrics.registerMetric(OnosMetrics.MetricsComponents.GLOBAL,
-                OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.registerMetric(COMPONENT,
+                FEATURE,
                 GAUGE3_NAME,
                 testGauge);
     }
diff --git a/src/test/java/net/onrc/onos/api/rest/TestRestMetricsGauges.java b/src/test/java/net/onrc/onos/api/rest/TestRestMetricsGauges.java
index c7b0e96..b6c5cab 100644
--- a/src/test/java/net/onrc/onos/api/rest/TestRestMetricsGauges.java
+++ b/src/test/java/net/onrc/onos/api/rest/TestRestMetricsGauges.java
@@ -48,22 +48,25 @@
     }
 
     // Test data for Gauges
+
+    private static final OnosMetrics.MetricsComponent COMPONENT =
+            OnosMetrics.registerComponent("MetricsUnitTests");
+    private static final OnosMetrics.MetricsFeature FEATURE =
+            COMPONENT.registerFeature("Gauges");
+
     private static final String GAUGE1_NAME = "gauge1";
-    private static final String GAUGE1_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-                                                   OnosMetrics.MetricsFeatures.GLOBAL,
-                                                   GAUGE1_NAME);
+    private static final String GAUGE1_FULL_NAME =
+            OnosMetrics.generateName(COMPONENT, FEATURE, GAUGE1_NAME);
     private static final int GAUGE1_VALUE = 0;
 
     private static final String GAUGE2_NAME = "gauge2";
-    private static final String GAUGE2_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-                                                   OnosMetrics.MetricsFeatures.GLOBAL,
-                                                   GAUGE2_NAME);
+    private static final String GAUGE2_FULL_NAME =
+            OnosMetrics.generateName(COMPONENT, FEATURE, GAUGE2_NAME);
     private static final int GAUGE2_VALUE = -1;
 
     private static final String GAUGE3_NAME = "gauge3";
-    private static final String GAUGE3_FULL_NAME = OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-                                                   OnosMetrics.MetricsFeatures.GLOBAL,
-                                                   GAUGE3_NAME);
+    private static final String GAUGE3_FULL_NAME =
+            OnosMetrics.generateName(COMPONENT, FEATURE, GAUGE3_NAME);
     private static final int GAUGE3_VALUE = 123456789;
 
     private final Gauge<Integer> gauge1 =
@@ -91,18 +94,18 @@
                     };
 
     private void registerGauges() {
-        OnosMetrics.registerMetric(OnosMetrics.MetricsComponents.GLOBAL,
-                                   OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.registerMetric(COMPONENT,
+                                   FEATURE,
                                    GAUGE1_NAME,
                                    gauge1);
 
-        OnosMetrics.registerMetric(OnosMetrics.MetricsComponents.GLOBAL,
-                                   OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.registerMetric(COMPONENT,
+                                   FEATURE,
                                    GAUGE2_NAME,
                                    gauge2);
 
-        OnosMetrics.registerMetric(OnosMetrics.MetricsComponents.GLOBAL,
-                                   OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.registerMetric(COMPONENT,
+                                   FEATURE,
                                    GAUGE3_NAME,
                                    gauge3);
     }
diff --git a/src/test/java/net/onrc/onos/api/rest/TestRestMetricsHistograms.java b/src/test/java/net/onrc/onos/api/rest/TestRestMetricsHistograms.java
index 772174e..108cd73 100644
--- a/src/test/java/net/onrc/onos/api/rest/TestRestMetricsHistograms.java
+++ b/src/test/java/net/onrc/onos/api/rest/TestRestMetricsHistograms.java
@@ -55,46 +55,46 @@
 
     // Test data for Histograms
 
+    private static final OnosMetrics.MetricsComponent COMPONENT =
+            OnosMetrics.registerComponent("MetricsUnitTests");
+    private static final OnosMetrics.MetricsFeature FEATURE =
+            COMPONENT.registerFeature("Histograms");
+
     private static final String HISTOGRAM1_NAME = "HISTOGRAM1";
     private static final String HISTOGRAM1_FULL_NAME =
-            OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-                    OnosMetrics.MetricsFeatures.GLOBAL,
-                    HISTOGRAM1_NAME);
+            OnosMetrics.generateName(COMPONENT, FEATURE, HISTOGRAM1_NAME);
+
     private static final int[] HISTOGRAM1_VALUES =
             {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
 
     private static final String HISTOGRAM2_NAME = "HISTOGRAM2";
     private static final String HISTOGRAM2_FULL_NAME =
-            OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-                    OnosMetrics.MetricsFeatures.GLOBAL,
-                    HISTOGRAM2_NAME);
+            OnosMetrics.generateName(COMPONENT, FEATURE, HISTOGRAM2_NAME);
     private static final int[] HISTOGRAM2_VALUES =
             {100, 100, 100, 100, 100, 100, 100};
 
     private static final String HISTOGRAM3_NAME = "HISTOGRAM3";
     private static final String HISTOGRAM3_FULL_NAME =
-            OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-                    OnosMetrics.MetricsFeatures.GLOBAL,
-                    HISTOGRAM3_NAME);
+            OnosMetrics.generateName(COMPONENT, FEATURE, HISTOGRAM3_NAME);
     private static final int[] HISTOGRAM3_VALUES =
             {555};
 
     private final Histogram histogram1 =
             OnosMetrics.createHistogram(
-                    OnosMetrics.MetricsComponents.GLOBAL,
-                    OnosMetrics.MetricsFeatures.GLOBAL,
+                    COMPONENT,
+                    FEATURE,
                     HISTOGRAM1_NAME);
 
     private final Histogram histogram2 =
             OnosMetrics.createHistogram(
-                    OnosMetrics.MetricsComponents.GLOBAL,
-                    OnosMetrics.MetricsFeatures.GLOBAL,
+                    COMPONENT,
+                    FEATURE,
                     HISTOGRAM2_NAME);
 
     private final Histogram histogram3 =
             OnosMetrics.createHistogram(
-                    OnosMetrics.MetricsComponents.GLOBAL,
-                    OnosMetrics.MetricsFeatures.GLOBAL,
+                    COMPONENT,
+                    FEATURE,
                     HISTOGRAM3_NAME);
 
     /**
diff --git a/src/test/java/net/onrc/onos/api/rest/TestRestMetricsMeters.java b/src/test/java/net/onrc/onos/api/rest/TestRestMetricsMeters.java
index 4cfb631..da046fd 100644
--- a/src/test/java/net/onrc/onos/api/rest/TestRestMetricsMeters.java
+++ b/src/test/java/net/onrc/onos/api/rest/TestRestMetricsMeters.java
@@ -52,28 +52,25 @@
 
     //  Test data for Meters
 
+
+    private static final OnosMetrics.MetricsComponent COMPONENT =
+            OnosMetrics.registerComponent("MetricsUnitTest");
+    private static final OnosMetrics.MetricsFeature FEATURE =
+            COMPONENT.registerFeature("Meters");
+
     private static final String METER1_NAME = "METER1";
     private static final String METER1_FULL_NAME =
-            OnosMetrics.generateName(
-                    OnosMetrics.MetricsComponents.GLOBAL,
-                    OnosMetrics.MetricsFeatures.GLOBAL,
-                    METER1_NAME);
+            OnosMetrics.generateName(COMPONENT, FEATURE, METER1_NAME);
     private static final int METER1_ITERATIONS = 1;
 
     private static final String METER2_NAME = "METER2";
     private static final String METER2_FULL_NAME =
-            OnosMetrics.generateName(
-                    OnosMetrics.MetricsComponents.GLOBAL,
-                    OnosMetrics.MetricsFeatures.GLOBAL,
-                    METER2_NAME);
+            OnosMetrics.generateName(COMPONENT, FEATURE, METER2_NAME);
     private static final int METER2_ITERATIONS = 10;
 
     private static final String METER3_NAME = "METER3";
     private static final String METER3_FULL_NAME =
-            OnosMetrics.generateName(
-                    OnosMetrics.MetricsComponents.GLOBAL,
-                    OnosMetrics.MetricsFeatures.GLOBAL,
-                    METER3_NAME);
+            OnosMetrics.generateName(COMPONENT, FEATURE, METER3_NAME);
     private static final int METER3_ITERATIONS = 100;
 
     private final Meter meter1 = new Meter(mockClock);
@@ -101,20 +98,20 @@
         fillMeter(meter2, METER2_ITERATIONS);
         fillMeter(meter3, METER3_ITERATIONS);
 
-        OnosMetrics.registerMetric(OnosMetrics.MetricsComponents.GLOBAL,
-                                   OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.registerMetric(COMPONENT,
+                                   FEATURE,
                                    METER1_NAME,
                                    meter1);
 
-        OnosMetrics.registerMetric(OnosMetrics.MetricsComponents.GLOBAL,
-                                   OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.registerMetric(COMPONENT,
+                                   FEATURE,
                                    METER2_NAME,
                                    meter2);
 
-        OnosMetrics.registerMetric(OnosMetrics.MetricsComponents.GLOBAL,
-                OnosMetrics.MetricsFeatures.GLOBAL,
-                METER3_NAME,
-                meter3);
+        OnosMetrics.registerMetric(COMPONENT,
+                                   FEATURE,
+                                   METER3_NAME,
+                                   meter3);
     }
 
     /**
diff --git a/src/test/java/net/onrc/onos/api/rest/TestRestMetricsTimers.java b/src/test/java/net/onrc/onos/api/rest/TestRestMetricsTimers.java
index af0e7f8..dd8cf8c 100644
--- a/src/test/java/net/onrc/onos/api/rest/TestRestMetricsTimers.java
+++ b/src/test/java/net/onrc/onos/api/rest/TestRestMetricsTimers.java
@@ -45,20 +45,25 @@
 
     //  Test data objects for Timers
 
+    private static final OnosMetrics.MetricsComponent COMPONENT =
+            OnosMetrics.registerComponent("MetricsUnitTests");
+    private static final OnosMetrics.MetricsFeature FEATURE =
+            COMPONENT.registerFeature("Timers");
+
     //  timer1 will be called 3 times
     private static final String TIMER1_NAME = "timer1";
     private static final String TIMER1_FULL_NAME =
-            OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-                                     OnosMetrics.MetricsFeatures.GLOBAL,
+            OnosMetrics.generateName(COMPONENT,
+                                     FEATURE,
                                      TIMER1_NAME);
     private static final int TIMER1_COUNT = 3;
 
     //  timer2 will be called 10 times
     private static final String TIMER2_NAME = "timer2";
     private static final String TIMER2_FULL_NAME =
-            OnosMetrics.generateName(OnosMetrics.MetricsComponents.GLOBAL,
-                    OnosMetrics.MetricsFeatures.GLOBAL,
-                    TIMER2_NAME);
+            OnosMetrics.generateName(COMPONENT,
+                                     FEATURE,
+                                     TIMER2_NAME);
     private static final int TIMER2_COUNT = 10;
 
     private static final int RESERVOIR_SIZE = 100;
@@ -90,13 +95,13 @@
         // add the two timers to the registry so the REST APIs will pick them
         // up
 
-        OnosMetrics.registerMetric(OnosMetrics.MetricsComponents.GLOBAL,
-                                   OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.registerMetric(COMPONENT,
+                                   FEATURE,
                                    TIMER1_NAME,
                                    timer1);
 
-        OnosMetrics.registerMetric(OnosMetrics.MetricsComponents.GLOBAL,
-                                   OnosMetrics.MetricsFeatures.GLOBAL,
+        OnosMetrics.registerMetric(COMPONENT,
+                                   FEATURE,
                                    TIMER2_NAME,
                                    timer2);
     }