Refeactor the Topology Events and Intent Events Metrics modules:
* Use the new class EventMetric to cleanup and simplify the implementation
* Replaced the single metric for Topology Events with four metrics
(last event timestamp and event rate):
- Device Event metrics
- Host Event metrics
- Link Event metrics
- Topology Graph metrics
Change-Id: I2acc06ab84ef3ca06d0d383983dfcff9774ff341
diff --git a/apps/metrics/topology/src/main/java/org/onlab/onos/metrics/topology/TopologyMetrics.java b/apps/metrics/topology/src/main/java/org/onlab/onos/metrics/topology/TopologyMetrics.java
index 32cf0cf..814e178 100644
--- a/apps/metrics/topology/src/main/java/org/onlab/onos/metrics/topology/TopologyMetrics.java
+++ b/apps/metrics/topology/src/main/java/org/onlab/onos/metrics/topology/TopologyMetrics.java
@@ -5,8 +5,6 @@
import java.util.LinkedList;
import java.util.List;
-import com.codahale.metrics.Gauge;
-import com.codahale.metrics.Meter;
import com.google.common.collect.ImmutableList;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -14,8 +12,7 @@
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
-import org.onlab.metrics.MetricsComponent;
-import org.onlab.metrics.MetricsFeature;
+import org.onlab.metrics.EventMetric;
import org.onlab.metrics.MetricsService;
import org.onlab.onos.event.Event;
import org.onlab.onos.net.device.DeviceEvent;
@@ -48,6 +45,8 @@
protected LinkService linkService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected TopologyService topologyService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected MetricsService metricsService;
private LinkedList<Event> lastEvents = new LinkedList<>();
private static final int LAST_EVENTS_MAX_N = 100;
@@ -61,22 +60,22 @@
//
// Metrics
//
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected MetricsService metricsService;
- //
private static final String COMPONENT_NAME = "Topology";
- private static final String FEATURE_NAME = "EventNotification";
- private static final String GAUGE_NAME = "LastEventTimestamp.EpochMs";
- private static final String METER_NAME = "EventRate";
+ private static final String FEATURE_DEVICE_NAME = "DeviceEvent";
+ private static final String FEATURE_HOST_NAME = "HostEvent";
+ private static final String FEATURE_LINK_NAME = "LinkEvent";
+ private static final String FEATURE_GRAPH_NAME = "GraphEvent";
//
- private MetricsComponent metricsComponent;
- private MetricsFeature metricsFeatureEventNotification;
+ // Event metrics:
+ // - Device events
+ // - Host events
+ // - Link events
+ // - Topology Graph events
//
- // Timestamp of the last Topology event (ms from the Epoch)
- private volatile long lastEventTimestampEpochMs = 0;
- private Gauge<Long> lastEventTimestampEpochMsGauge;
- // Rate of the Topology events published to the Topology listeners
- private Meter eventRateMeter;
+ private EventMetric topologyDeviceEventMetric;
+ private EventMetric topologyHostEventMetric;
+ private EventMetric topologyLinkEventMetric;
+ private EventMetric topologyGraphEventMetric;
@Activate
protected void activate() {
@@ -113,27 +112,34 @@
}
@Override
- public Gauge<Long> lastEventTimestampEpochMsGauge() {
- return lastEventTimestampEpochMsGauge;
+ public EventMetric topologyDeviceEventMetric() {
+ return topologyDeviceEventMetric;
}
@Override
- public Meter eventRateMeter() {
- return eventRateMeter;
+ public EventMetric topologyHostEventMetric() {
+ return topologyHostEventMetric;
+ }
+
+ @Override
+ public EventMetric topologyLinkEventMetric() {
+ return topologyLinkEventMetric;
+ }
+
+ @Override
+ public EventMetric topologyGraphEventMetric() {
+ return topologyGraphEventMetric;
}
/**
* Records an event.
*
* @param event the event to record
- * @param updateEventRateMeter if true, update the Event Rate Meter
+ * @param eventMetric the Event Metric to use
*/
- private void recordEvent(Event event, boolean updateEventRateMeter) {
+ private void recordEvent(Event event, EventMetric eventMetric) {
synchronized (lastEvents) {
- lastEventTimestampEpochMs = System.currentTimeMillis();
- if (updateEventRateMeter) {
- eventRateMeter.mark(1);
- }
+ eventMetric.eventReceived();
//
// Keep only the last N events, where N = LAST_EVENTS_MAX_N
@@ -151,7 +157,7 @@
private class InnerDeviceListener implements DeviceListener {
@Override
public void event(DeviceEvent event) {
- recordEvent(event, true);
+ recordEvent(event, topologyDeviceEventMetric);
log.debug("Device Event: time = {} type = {} event = {}",
event.time(), event.type(), event);
}
@@ -163,7 +169,7 @@
private class InnerHostListener implements HostListener {
@Override
public void event(HostEvent event) {
- recordEvent(event, true);
+ recordEvent(event, topologyHostEventMetric);
log.debug("Host Event: time = {} type = {} event = {}",
event.time(), event.type(), event);
}
@@ -175,7 +181,7 @@
private class InnerLinkListener implements LinkListener {
@Override
public void event(LinkEvent event) {
- recordEvent(event, true);
+ recordEvent(event, topologyLinkEventMetric);
log.debug("Link Event: time = {} type = {} event = {}",
event.time(), event.type(), event);
}
@@ -187,11 +193,7 @@
private class InnerTopologyListener implements TopologyListener {
@Override
public void event(TopologyEvent event) {
- //
- // NOTE: Don't update the eventRateMeter, because the real
- // events are already captured/counted.
- //
- recordEvent(event, false);
+ recordEvent(event, topologyGraphEventMetric);
log.debug("Topology Event: time = {} type = {} event = {}",
event.time(), event.type(), event);
for (Event reason : event.reasons()) {
@@ -206,7 +208,6 @@
*/
private void clear() {
synchronized (lastEvents) {
- lastEventTimestampEpochMs = 0;
lastEvents.clear();
}
}
@@ -215,35 +216,32 @@
* Registers the metrics.
*/
private void registerMetrics() {
- metricsComponent = metricsService.registerComponent(COMPONENT_NAME);
- metricsFeatureEventNotification =
- metricsComponent.registerFeature(FEATURE_NAME);
- lastEventTimestampEpochMsGauge =
- metricsService.registerMetric(metricsComponent,
- metricsFeatureEventNotification,
- GAUGE_NAME,
- new Gauge<Long>() {
- @Override
- public Long getValue() {
- return lastEventTimestampEpochMs;
- }
- });
- eventRateMeter =
- metricsService.createMeter(metricsComponent,
- metricsFeatureEventNotification,
- METER_NAME);
+ topologyDeviceEventMetric =
+ new EventMetric(metricsService, COMPONENT_NAME,
+ FEATURE_DEVICE_NAME);
+ topologyHostEventMetric =
+ new EventMetric(metricsService, COMPONENT_NAME,
+ FEATURE_HOST_NAME);
+ topologyLinkEventMetric =
+ new EventMetric(metricsService, COMPONENT_NAME,
+ FEATURE_LINK_NAME);
+ topologyGraphEventMetric =
+ new EventMetric(metricsService, COMPONENT_NAME,
+ FEATURE_GRAPH_NAME);
+ topologyDeviceEventMetric.registerMetrics();
+ topologyHostEventMetric.registerMetrics();
+ topologyLinkEventMetric.registerMetrics();
+ topologyGraphEventMetric.registerMetrics();
}
/**
* Removes the metrics.
*/
private void removeMetrics() {
- metricsService.removeMetric(metricsComponent,
- metricsFeatureEventNotification,
- GAUGE_NAME);
- metricsService.removeMetric(metricsComponent,
- metricsFeatureEventNotification,
- METER_NAME);
+ topologyDeviceEventMetric.removeMetrics();
+ topologyHostEventMetric.removeMetrics();
+ topologyLinkEventMetric.removeMetrics();
+ topologyGraphEventMetric.removeMetrics();
}
}
diff --git a/apps/metrics/topology/src/main/java/org/onlab/onos/metrics/topology/TopologyMetricsService.java b/apps/metrics/topology/src/main/java/org/onlab/onos/metrics/topology/TopologyMetricsService.java
index aeb2e32..9203d9b 100644
--- a/apps/metrics/topology/src/main/java/org/onlab/onos/metrics/topology/TopologyMetricsService.java
+++ b/apps/metrics/topology/src/main/java/org/onlab/onos/metrics/topology/TopologyMetricsService.java
@@ -1,9 +1,7 @@
package org.onlab.onos.metrics.topology;
import java.util.List;
-
-import com.codahale.metrics.Gauge;
-import com.codahale.metrics.Meter;
+import org.onlab.metrics.EventMetric;
import org.onlab.onos.event.Event;
/**
@@ -18,18 +16,30 @@
public List<Event> getEvents();
/**
- * Gets the Metrics' Gauge for the last topology event timestamp
- * (ms from the epoch).
+ * Gets the Event Metric for the Device Events.
*
- * @return the Metrics' Gauge for the last topology event timestamp
- * (ms from the epoch)
+ * @return the Event Metric for the Device Events.
*/
- public Gauge<Long> lastEventTimestampEpochMsGauge();
+ public EventMetric topologyDeviceEventMetric();
/**
- * Gets the Metrics' Meter for the topology events rate.
+ * Gets the Event Metric for the Host Events.
*
- * @return the Metrics' Meter for the topology events rate
+ * @return the Event Metric for the Host Events.
*/
- public Meter eventRateMeter();
+ public EventMetric topologyHostEventMetric();
+
+ /**
+ * Gets the Event Metric for the Link Events.
+ *
+ * @return the Event Metric for the Link Events.
+ */
+ public EventMetric topologyLinkEventMetric();
+
+ /**
+ * Gets the Event Metric for the Topology Graph Events.
+ *
+ * @return the Event Metric for the Topology Graph Events.
+ */
+ public EventMetric topologyGraphEventMetric();
}
diff --git a/apps/metrics/topology/src/main/java/org/onlab/onos/metrics/topology/cli/TopologyEventsMetricsCommand.java b/apps/metrics/topology/src/main/java/org/onlab/onos/metrics/topology/cli/TopologyEventsMetricsCommand.java
index 54d3a95..b7e0401 100644
--- a/apps/metrics/topology/src/main/java/org/onlab/onos/metrics/topology/cli/TopologyEventsMetricsCommand.java
+++ b/apps/metrics/topology/src/main/java/org/onlab/onos/metrics/topology/cli/TopologyEventsMetricsCommand.java
@@ -11,6 +11,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.karaf.shell.commands.Command;
+import org.onlab.metrics.EventMetric;
import org.onlab.onos.cli.AbstractShellCommand;
import org.onlab.onos.metrics.topology.TopologyMetricsService;
@@ -22,15 +23,13 @@
public class TopologyEventsMetricsCommand extends AbstractShellCommand {
private static final String FORMAT_GAUGE =
- "Last Topology Event Timestamp (ms from epoch)=%d";
+ "Topology %s Event Timestamp (ms from epoch)=%d";
private static final String FORMAT_METER =
- "Topology Events count=%d rate(events/sec) mean=%f m1=%f m5=%f m15=%f";
+ "Topology %s Events count=%d rate(events/sec) mean=%f m1=%f m5=%f m15=%f";
@Override
protected void execute() {
TopologyMetricsService service = get(TopologyMetricsService.class);
- Gauge<Long> gauge = service.lastEventTimestampEpochMsGauge();
- Meter meter = service.eventRateMeter();
if (outputJson()) {
ObjectMapper mapper = new ObjectMapper()
@@ -38,32 +37,89 @@
TimeUnit.MILLISECONDS,
false));
ObjectNode result = mapper.createObjectNode();
- try {
- //
- // NOTE: The API for custom serializers is incomplete,
- // hence we have to parse the JSON string to create JsonNode.
- //
- final String gaugeJson = mapper.writeValueAsString(gauge);
- final String meterJson = mapper.writeValueAsString(meter);
- JsonNode gaugeNode = mapper.readTree(gaugeJson);
- JsonNode meterNode = mapper.readTree(meterJson);
- result.put("lastTopologyEventTimestamp", gaugeNode);
- result.put("topologyEventRate", meterNode);
- } catch (JsonProcessingException e) {
- log.error("Error writing value as JSON string", e);
- } catch (IOException e) {
- log.error("Error writing value as JSON string", e);
- }
+ result = json(mapper, result, "topologyDeviceEvent",
+ service.topologyDeviceEventMetric());
+ result = json(mapper, result, "topologyHostEvent",
+ service.topologyHostEventMetric());
+ result = json(mapper, result, "topologyLinkEvent",
+ service.topologyLinkEventMetric());
+ result = json(mapper, result, "topologyGraphEvent",
+ service.topologyGraphEventMetric());
print("%s", result);
} else {
- TimeUnit rateUnit = TimeUnit.SECONDS;
- double rateFactor = rateUnit.toSeconds(1);
- print(FORMAT_GAUGE, gauge.getValue());
- print(FORMAT_METER, meter.getCount(),
- meter.getMeanRate() * rateFactor,
- meter.getOneMinuteRate() * rateFactor,
- meter.getFiveMinuteRate() * rateFactor,
- meter.getFifteenMinuteRate() * rateFactor);
+ printEventMetric("Device", service.topologyDeviceEventMetric());
+ printEventMetric("Host", service.topologyHostEventMetric());
+ printEventMetric("Link", service.topologyLinkEventMetric());
+ printEventMetric("Graph", service.topologyGraphEventMetric());
}
}
+
+ /**
+ * Produces JSON node for an Event Metric.
+ *
+ * @param mapper the JSON object mapper to use
+ * @param objectNode the JSON object node to use
+ * @param propertyPrefix the property prefix to use
+ * @param eventMetric the Event Metric with the data
+ * @return JSON object node for the Event Metric
+ */
+ private ObjectNode json(ObjectMapper mapper, ObjectNode objectNode,
+ String propertyPrefix, EventMetric eventMetric) {
+ String gaugeName = propertyPrefix + "Timestamp";
+ String meterName = propertyPrefix + "Rate";
+ Gauge<Long> gauge = eventMetric.lastEventTimestampGauge();
+ Meter meter = eventMetric.eventRateMeter();
+
+ objectNode.put(gaugeName, json(mapper, gauge));
+ objectNode.put(meterName, json(mapper, meter));
+ return objectNode;
+ }
+
+ /**
+ * Produces JSON node for an Object.
+ *
+ * @param mapper the JSON object mapper to use
+ * @param object the Object with the data
+ * @return JSON node for the Object
+ */
+ private JsonNode json(ObjectMapper mapper, Object object) {
+ //
+ // NOTE: The API for custom serializers is incomplete,
+ // hence we have to parse the JSON string to create JsonNode.
+ //
+ try {
+ final String objectJson = mapper.writeValueAsString(object);
+ JsonNode jsonNode = mapper.readTree(objectJson);
+ return jsonNode;
+ } catch (JsonProcessingException e) {
+ log.error("Error writing value as JSON string", e);
+ } catch (IOException e) {
+ log.error("Error writing value as JSON string", e);
+ }
+ return null;
+ }
+
+ /**
+ * Prints an Event Metric.
+ *
+ * @param operationStr the string with the intent operation to print
+ * @param eventMetric the Event Metric to print
+ */
+ private void printEventMetric(String operationStr,
+ EventMetric eventMetric) {
+ Gauge<Long> gauge = eventMetric.lastEventTimestampGauge();
+ Meter meter = eventMetric.eventRateMeter();
+ TimeUnit rateUnit = TimeUnit.SECONDS;
+ double rateFactor = rateUnit.toSeconds(1);
+
+ // Print the Gauge
+ print(FORMAT_GAUGE, operationStr, gauge.getValue());
+
+ // Print the Meter
+ print(FORMAT_METER, operationStr, meter.getCount(),
+ meter.getMeanRate() * rateFactor,
+ meter.getOneMinuteRate() * rateFactor,
+ meter.getFiveMinuteRate() * rateFactor,
+ meter.getFifteenMinuteRate() * rateFactor);
+ }
}