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);