Thomas Vachuska

Merge remote-tracking branch 'origin/master'

1 package org.onlab.onos.metrics.intent; 1 package org.onlab.onos.metrics.intent;
2 2
3 import java.util.List; 3 import java.util.List;
4 - 4 +import org.onlab.metrics.EventMetric;
5 -import com.codahale.metrics.Gauge;
6 -import com.codahale.metrics.Meter;
7 import org.onlab.onos.net.intent.IntentEvent; 5 import org.onlab.onos.net.intent.IntentEvent;
8 6
9 /** 7 /**
...@@ -18,68 +16,32 @@ public interface IntentMetricsService { ...@@ -18,68 +16,32 @@ public interface IntentMetricsService {
18 public List<IntentEvent> getEvents(); 16 public List<IntentEvent> getEvents();
19 17
20 /** 18 /**
21 - * Gets the Metrics' Gauge for the intent SUBMITTED event timestamp 19 + * Gets the Event Metric for the intent SUBMITTED events.
22 - * (ms from the epoch).
23 * 20 *
24 - * @return the Metrics' Gauge for the intent SUBMITTED event timestamp 21 + * @return the Event Metric for the intent SUBMITTED events.
25 - * (ms from the epoch)
26 */ 22 */
27 - public Gauge<Long> intentSubmittedTimestampEpochMsGauge(); 23 + public EventMetric intentSubmittedEventMetric();
28 24
29 /** 25 /**
30 - * Gets the Metrics' Gauge for the intent INSTALLED event timestamp 26 + * Gets the Event Metric for the intent INSTALLED events.
31 - * (ms from the epoch).
32 * 27 *
33 - * @return the Metrics' Gauge for the intent INSTALLED event timestamp 28 + * @return the Event Metric for the intent INSTALLED events.
34 - * (ms from the epoch)
35 */ 29 */
36 - public Gauge<Long> intentInstalledTimestampEpochMsGauge(); 30 + public EventMetric intentInstalledEventMetric();
37 31
38 /** 32 /**
39 - * Gets the Metrics' Gauge for the intent WITHDRAW_REQUESTED event 33 + * Gets the Event Metric for the intent WITHDRAW_REQUESTED events.
40 - * timestamp (ms from the epoch).
41 * 34 *
42 * TODO: This intent event is not implemented yet. 35 * TODO: This intent event is not implemented yet.
43 * 36 *
44 - * @return the Metrics' Gauge for the intent WITHDRAW_REQUESTED event 37 + * @return the Event Metric for the intent WITHDRAW_REQUESTED events.
45 - * timestamp (ms from the epoch)
46 - */
47 - public Gauge<Long> intentWithdrawRequestedTimestampEpochMsGauge();
48 -
49 - /**
50 - * Gets the Metrics' Gauge for the intent WITHDRAWN event timestamp
51 - * (ms from the epoch).
52 - *
53 - * @return the Metrics' Gauge for the intent WITHDRAWN event timestamp
54 - * (ms from the epoch)
55 - */
56 - public Gauge<Long> intentWithdrawnTimestampEpochMsGauge();
57 -
58 - /**
59 - * Gets the Metrics' Meter for the submitted intents event rate.
60 - *
61 - * @return the Metrics' Meter for the submitted intents event rate
62 - */
63 - public Meter intentSubmittedRateMeter();
64 -
65 - /**
66 - * Gets the Metrics' Meter for the installed intents event rate.
67 - *
68 - * @return the Metrics' Meter for the installed intent event rate
69 - */
70 - public Meter intentInstalledRateMeter();
71 -
72 - /**
73 - * Gets the Metrics' Meter for the withdraw requested intents event rate.
74 - *
75 - * @return the Metrics' Meter for the withdraw requested intents event rate
76 */ 38 */
77 - public Meter intentWithdrawRequestedRateMeter(); 39 + public EventMetric intentWithdrawRequestedEventMetric();
78 40
79 /** 41 /**
80 - * Gets the Metrics' Meter for the withdraw completed intents event rate. 42 + * Gets the Event Metric for the intent WITHDRAWN events.
81 * 43 *
82 - * @return the Metrics' Meter for the withdraw completed intents event rate 44 + * @return the Event Metric for the intent WITHDRAWN events.
83 */ 45 */
84 - public Meter intentWithdrawnRateMeter(); 46 + public EventMetric intentWithdrawnEventMetric();
85 } 47 }
......
...@@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.JsonNode; ...@@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.JsonNode;
11 import com.fasterxml.jackson.databind.ObjectMapper; 11 import com.fasterxml.jackson.databind.ObjectMapper;
12 import com.fasterxml.jackson.databind.node.ObjectNode; 12 import com.fasterxml.jackson.databind.node.ObjectNode;
13 import org.apache.karaf.shell.commands.Command; 13 import org.apache.karaf.shell.commands.Command;
14 +import org.onlab.metrics.EventMetric;
14 import org.onlab.onos.cli.AbstractShellCommand; 15 import org.onlab.onos.cli.AbstractShellCommand;
15 import org.onlab.onos.metrics.intent.IntentMetricsService; 16 import org.onlab.onos.metrics.intent.IntentMetricsService;
16 17
...@@ -29,8 +30,6 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand { ...@@ -29,8 +30,6 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand {
29 @Override 30 @Override
30 protected void execute() { 31 protected void execute() {
31 IntentMetricsService service = get(IntentMetricsService.class); 32 IntentMetricsService service = get(IntentMetricsService.class);
32 - Gauge<Long> gauge;
33 - Meter meter;
34 33
35 if (outputJson()) { 34 if (outputJson()) {
36 ObjectMapper mapper = new ObjectMapper() 35 ObjectMapper mapper = new ObjectMapper()
...@@ -38,49 +37,49 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand { ...@@ -38,49 +37,49 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand {
38 TimeUnit.MILLISECONDS, 37 TimeUnit.MILLISECONDS,
39 false)); 38 false));
40 ObjectNode result = mapper.createObjectNode(); 39 ObjectNode result = mapper.createObjectNode();
41 - // 40 + result = json(mapper, result, "intentSubmitted",
42 - gauge = service.intentSubmittedTimestampEpochMsGauge(); 41 + service.intentSubmittedEventMetric());
43 - result.put("intentSubmittedTimestamp", json(mapper, gauge)); 42 + result = json(mapper, result, "intentInstalled",
44 - gauge = service.intentInstalledTimestampEpochMsGauge(); 43 + service.intentInstalledEventMetric());
45 - result.put("intentInstalledTimestamp", json(mapper, gauge)); 44 + result = json(mapper, result, "intentWithdrawRequested",
46 - gauge = service.intentWithdrawRequestedTimestampEpochMsGauge(); 45 + service.intentWithdrawRequestedEventMetric());
47 - result.put("intentWithdrawRequestedTimestamp", 46 + result = json(mapper, result, "intentWithdrawn",
48 - json(mapper, gauge)); 47 + service.intentWithdrawnEventMetric());
49 - gauge = service.intentWithdrawnTimestampEpochMsGauge();
50 - result.put("intentWithdrawnTimestamp", json(mapper, gauge));
51 - //
52 - meter = service.intentSubmittedRateMeter();
53 - result.put("intentSubmittedRate", json(mapper, meter));
54 - meter = service.intentInstalledRateMeter();
55 - result.put("intentInstalledRate", json(mapper, meter));
56 - meter = service.intentWithdrawRequestedRateMeter();
57 - result.put("intentWithdrawRequestedRate", json(mapper, meter));
58 - meter = service.intentWithdrawnRateMeter();
59 - result.put("intentWithdrawnRate", json(mapper, meter));
60 - //
61 print("%s", result); 48 print("%s", result);
62 } else { 49 } else {
63 - gauge = service.intentSubmittedTimestampEpochMsGauge(); 50 + printEventMetric("Submitted",
64 - printGauge("Submitted", gauge); 51 + service.intentSubmittedEventMetric());
65 - gauge = service.intentInstalledTimestampEpochMsGauge(); 52 + printEventMetric("Installed",
66 - printGauge("Installed", gauge); 53 + service.intentInstalledEventMetric());
67 - gauge = service.intentWithdrawRequestedTimestampEpochMsGauge(); 54 + printEventMetric("Withdraw Requested",
68 - printGauge("Withdraw Requested", gauge); 55 + service.intentWithdrawRequestedEventMetric());
69 - gauge = service.intentWithdrawnTimestampEpochMsGauge(); 56 + printEventMetric("Withdrawn",
70 - printGauge("Withdrawn", gauge); 57 + service.intentWithdrawnEventMetric());
71 - //
72 - meter = service.intentSubmittedRateMeter();
73 - printMeter("Submitted", meter);
74 - meter = service.intentInstalledRateMeter();
75 - printMeter("Installed", meter);
76 - meter = service.intentWithdrawRequestedRateMeter();
77 - printMeter("Withdraw Requested", meter);
78 - meter = service.intentWithdrawnRateMeter();
79 - printMeter("Withdrawn", meter);
80 } 58 }
81 } 59 }
82 60
83 /** 61 /**
62 + * Produces JSON node for an Event Metric.
63 + *
64 + * @param mapper the JSON object mapper to use
65 + * @param objectNode the JSON object node to use
66 + * @param propertyPrefix the property prefix to use
67 + * @param eventMetric the Event Metric with the data
68 + * @return JSON object node for the Event Metric
69 + */
70 + private ObjectNode json(ObjectMapper mapper, ObjectNode objectNode,
71 + String propertyPrefix, EventMetric eventMetric) {
72 + String gaugeName = propertyPrefix + "Timestamp";
73 + String meterName = propertyPrefix + "Rate";
74 + Gauge<Long> gauge = eventMetric.lastEventTimestampGauge();
75 + Meter meter = eventMetric.eventRateMeter();
76 +
77 + objectNode.put(gaugeName, json(mapper, gauge));
78 + objectNode.put(meterName, json(mapper, meter));
79 + return objectNode;
80 + }
81 +
82 + /**
84 * Produces JSON node for an Object. 83 * Produces JSON node for an Object.
85 * 84 *
86 * @param mapper the JSON object mapper to use 85 * @param mapper the JSON object mapper to use
...@@ -94,8 +93,8 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand { ...@@ -94,8 +93,8 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand {
94 // 93 //
95 try { 94 try {
96 final String objectJson = mapper.writeValueAsString(object); 95 final String objectJson = mapper.writeValueAsString(object);
97 - JsonNode objectNode = mapper.readTree(objectJson); 96 + JsonNode jsonNode = mapper.readTree(objectJson);
98 - return objectNode; 97 + return jsonNode;
99 } catch (JsonProcessingException e) { 98 } catch (JsonProcessingException e) {
100 log.error("Error writing value as JSON string", e); 99 log.error("Error writing value as JSON string", e);
101 } catch (IOException e) { 100 } catch (IOException e) {
...@@ -105,28 +104,26 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand { ...@@ -105,28 +104,26 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand {
105 } 104 }
106 105
107 /** 106 /**
108 - * Prints a Gauge. 107 + * Prints an Event Metric.
109 * 108 *
110 * @param operationStr the string with the intent operation to print 109 * @param operationStr the string with the intent operation to print
111 - * @param gauge the Gauge to print 110 + * @param eventMetric the Event Metric to print
112 */ 111 */
113 - private void printGauge(String operationStr, Gauge<Long> gauge) { 112 + private void printEventMetric(String operationStr,
113 + EventMetric eventMetric) {
114 + Gauge<Long> gauge = eventMetric.lastEventTimestampGauge();
115 + Meter meter = eventMetric.eventRateMeter();
116 + TimeUnit rateUnit = TimeUnit.SECONDS;
117 + double rateFactor = rateUnit.toSeconds(1);
118 +
119 + // Print the Gauge
114 print(FORMAT_GAUGE, operationStr, gauge.getValue()); 120 print(FORMAT_GAUGE, operationStr, gauge.getValue());
115 - }
116 121
117 - /** 122 + // Print the Meter
118 - * Prints a Meter. 123 + print(FORMAT_METER, operationStr, meter.getCount(),
119 - * 124 + meter.getMeanRate() * rateFactor,
120 - * @param operationStr the string with the intent operation to print 125 + meter.getOneMinuteRate() * rateFactor,
121 - * @param meter the Meter to print 126 + meter.getFiveMinuteRate() * rateFactor,
122 - */ 127 + meter.getFifteenMinuteRate() * rateFactor);
123 - private void printMeter(String operationStr, Meter meter) {
124 - TimeUnit rateUnit = TimeUnit.SECONDS;
125 - double rateFactor = rateUnit.toSeconds(1);
126 - print(FORMAT_METER, operationStr, meter.getCount(),
127 - meter.getMeanRate() * rateFactor,
128 - meter.getOneMinuteRate() * rateFactor,
129 - meter.getFiveMinuteRate() * rateFactor,
130 - meter.getFifteenMinuteRate() * rateFactor);
131 } 128 }
132 } 129 }
......
...@@ -5,8 +5,6 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -5,8 +5,6 @@ import static org.slf4j.LoggerFactory.getLogger;
5 import java.util.LinkedList; 5 import java.util.LinkedList;
6 import java.util.List; 6 import java.util.List;
7 7
8 -import com.codahale.metrics.Gauge;
9 -import com.codahale.metrics.Meter;
10 import com.google.common.collect.ImmutableList; 8 import com.google.common.collect.ImmutableList;
11 import org.apache.felix.scr.annotations.Activate; 9 import org.apache.felix.scr.annotations.Activate;
12 import org.apache.felix.scr.annotations.Component; 10 import org.apache.felix.scr.annotations.Component;
...@@ -14,8 +12,7 @@ import org.apache.felix.scr.annotations.Deactivate; ...@@ -14,8 +12,7 @@ import org.apache.felix.scr.annotations.Deactivate;
14 import org.apache.felix.scr.annotations.Reference; 12 import org.apache.felix.scr.annotations.Reference;
15 import org.apache.felix.scr.annotations.ReferenceCardinality; 13 import org.apache.felix.scr.annotations.ReferenceCardinality;
16 import org.apache.felix.scr.annotations.Service; 14 import org.apache.felix.scr.annotations.Service;
17 -import org.onlab.metrics.MetricsComponent; 15 +import org.onlab.metrics.EventMetric;
18 -import org.onlab.metrics.MetricsFeature;
19 import org.onlab.metrics.MetricsService; 16 import org.onlab.metrics.MetricsService;
20 import org.onlab.onos.event.Event; 17 import org.onlab.onos.event.Event;
21 import org.onlab.onos.net.device.DeviceEvent; 18 import org.onlab.onos.net.device.DeviceEvent;
...@@ -48,6 +45,8 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -48,6 +45,8 @@ public class TopologyMetrics implements TopologyMetricsService {
48 protected LinkService linkService; 45 protected LinkService linkService;
49 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 46 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
50 protected TopologyService topologyService; 47 protected TopologyService topologyService;
48 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
49 + protected MetricsService metricsService;
51 50
52 private LinkedList<Event> lastEvents = new LinkedList<>(); 51 private LinkedList<Event> lastEvents = new LinkedList<>();
53 private static final int LAST_EVENTS_MAX_N = 100; 52 private static final int LAST_EVENTS_MAX_N = 100;
...@@ -61,22 +60,22 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -61,22 +60,22 @@ public class TopologyMetrics implements TopologyMetricsService {
61 // 60 //
62 // Metrics 61 // Metrics
63 // 62 //
64 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
65 - protected MetricsService metricsService;
66 - //
67 private static final String COMPONENT_NAME = "Topology"; 63 private static final String COMPONENT_NAME = "Topology";
68 - private static final String FEATURE_NAME = "EventNotification"; 64 + private static final String FEATURE_DEVICE_NAME = "DeviceEvent";
69 - private static final String GAUGE_NAME = "LastEventTimestamp.EpochMs"; 65 + private static final String FEATURE_HOST_NAME = "HostEvent";
70 - private static final String METER_NAME = "EventRate"; 66 + private static final String FEATURE_LINK_NAME = "LinkEvent";
67 + private static final String FEATURE_GRAPH_NAME = "GraphEvent";
71 // 68 //
72 - private MetricsComponent metricsComponent; 69 + // Event metrics:
73 - private MetricsFeature metricsFeatureEventNotification; 70 + // - Device events
71 + // - Host events
72 + // - Link events
73 + // - Topology Graph events
74 // 74 //
75 - // Timestamp of the last Topology event (ms from the Epoch) 75 + private EventMetric topologyDeviceEventMetric;
76 - private volatile long lastEventTimestampEpochMs = 0; 76 + private EventMetric topologyHostEventMetric;
77 - private Gauge<Long> lastEventTimestampEpochMsGauge; 77 + private EventMetric topologyLinkEventMetric;
78 - // Rate of the Topology events published to the Topology listeners 78 + private EventMetric topologyGraphEventMetric;
79 - private Meter eventRateMeter;
80 79
81 @Activate 80 @Activate
82 protected void activate() { 81 protected void activate() {
...@@ -113,27 +112,34 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -113,27 +112,34 @@ public class TopologyMetrics implements TopologyMetricsService {
113 } 112 }
114 113
115 @Override 114 @Override
116 - public Gauge<Long> lastEventTimestampEpochMsGauge() { 115 + public EventMetric topologyDeviceEventMetric() {
117 - return lastEventTimestampEpochMsGauge; 116 + return topologyDeviceEventMetric;
117 + }
118 +
119 + @Override
120 + public EventMetric topologyHostEventMetric() {
121 + return topologyHostEventMetric;
118 } 122 }
119 123
120 @Override 124 @Override
121 - public Meter eventRateMeter() { 125 + public EventMetric topologyLinkEventMetric() {
122 - return eventRateMeter; 126 + return topologyLinkEventMetric;
127 + }
128 +
129 + @Override
130 + public EventMetric topologyGraphEventMetric() {
131 + return topologyGraphEventMetric;
123 } 132 }
124 133
125 /** 134 /**
126 * Records an event. 135 * Records an event.
127 * 136 *
128 * @param event the event to record 137 * @param event the event to record
129 - * @param updateEventRateMeter if true, update the Event Rate Meter 138 + * @param eventMetric the Event Metric to use
130 */ 139 */
131 - private void recordEvent(Event event, boolean updateEventRateMeter) { 140 + private void recordEvent(Event event, EventMetric eventMetric) {
132 synchronized (lastEvents) { 141 synchronized (lastEvents) {
133 - lastEventTimestampEpochMs = System.currentTimeMillis(); 142 + eventMetric.eventReceived();
134 - if (updateEventRateMeter) {
135 - eventRateMeter.mark(1);
136 - }
137 143
138 // 144 //
139 // Keep only the last N events, where N = LAST_EVENTS_MAX_N 145 // Keep only the last N events, where N = LAST_EVENTS_MAX_N
...@@ -151,7 +157,7 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -151,7 +157,7 @@ public class TopologyMetrics implements TopologyMetricsService {
151 private class InnerDeviceListener implements DeviceListener { 157 private class InnerDeviceListener implements DeviceListener {
152 @Override 158 @Override
153 public void event(DeviceEvent event) { 159 public void event(DeviceEvent event) {
154 - recordEvent(event, true); 160 + recordEvent(event, topologyDeviceEventMetric);
155 log.debug("Device Event: time = {} type = {} event = {}", 161 log.debug("Device Event: time = {} type = {} event = {}",
156 event.time(), event.type(), event); 162 event.time(), event.type(), event);
157 } 163 }
...@@ -163,7 +169,7 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -163,7 +169,7 @@ public class TopologyMetrics implements TopologyMetricsService {
163 private class InnerHostListener implements HostListener { 169 private class InnerHostListener implements HostListener {
164 @Override 170 @Override
165 public void event(HostEvent event) { 171 public void event(HostEvent event) {
166 - recordEvent(event, true); 172 + recordEvent(event, topologyHostEventMetric);
167 log.debug("Host Event: time = {} type = {} event = {}", 173 log.debug("Host Event: time = {} type = {} event = {}",
168 event.time(), event.type(), event); 174 event.time(), event.type(), event);
169 } 175 }
...@@ -175,7 +181,7 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -175,7 +181,7 @@ public class TopologyMetrics implements TopologyMetricsService {
175 private class InnerLinkListener implements LinkListener { 181 private class InnerLinkListener implements LinkListener {
176 @Override 182 @Override
177 public void event(LinkEvent event) { 183 public void event(LinkEvent event) {
178 - recordEvent(event, true); 184 + recordEvent(event, topologyLinkEventMetric);
179 log.debug("Link Event: time = {} type = {} event = {}", 185 log.debug("Link Event: time = {} type = {} event = {}",
180 event.time(), event.type(), event); 186 event.time(), event.type(), event);
181 } 187 }
...@@ -187,11 +193,7 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -187,11 +193,7 @@ public class TopologyMetrics implements TopologyMetricsService {
187 private class InnerTopologyListener implements TopologyListener { 193 private class InnerTopologyListener implements TopologyListener {
188 @Override 194 @Override
189 public void event(TopologyEvent event) { 195 public void event(TopologyEvent event) {
190 - // 196 + recordEvent(event, topologyGraphEventMetric);
191 - // NOTE: Don't update the eventRateMeter, because the real
192 - // events are already captured/counted.
193 - //
194 - recordEvent(event, false);
195 log.debug("Topology Event: time = {} type = {} event = {}", 197 log.debug("Topology Event: time = {} type = {} event = {}",
196 event.time(), event.type(), event); 198 event.time(), event.type(), event);
197 for (Event reason : event.reasons()) { 199 for (Event reason : event.reasons()) {
...@@ -206,7 +208,6 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -206,7 +208,6 @@ public class TopologyMetrics implements TopologyMetricsService {
206 */ 208 */
207 private void clear() { 209 private void clear() {
208 synchronized (lastEvents) { 210 synchronized (lastEvents) {
209 - lastEventTimestampEpochMs = 0;
210 lastEvents.clear(); 211 lastEvents.clear();
211 } 212 }
212 } 213 }
...@@ -215,35 +216,32 @@ public class TopologyMetrics implements TopologyMetricsService { ...@@ -215,35 +216,32 @@ public class TopologyMetrics implements TopologyMetricsService {
215 * Registers the metrics. 216 * Registers the metrics.
216 */ 217 */
217 private void registerMetrics() { 218 private void registerMetrics() {
218 - metricsComponent = metricsService.registerComponent(COMPONENT_NAME); 219 + topologyDeviceEventMetric =
219 - metricsFeatureEventNotification = 220 + new EventMetric(metricsService, COMPONENT_NAME,
220 - metricsComponent.registerFeature(FEATURE_NAME); 221 + FEATURE_DEVICE_NAME);
221 - lastEventTimestampEpochMsGauge = 222 + topologyHostEventMetric =
222 - metricsService.registerMetric(metricsComponent, 223 + new EventMetric(metricsService, COMPONENT_NAME,
223 - metricsFeatureEventNotification, 224 + FEATURE_HOST_NAME);
224 - GAUGE_NAME, 225 + topologyLinkEventMetric =
225 - new Gauge<Long>() { 226 + new EventMetric(metricsService, COMPONENT_NAME,
226 - @Override 227 + FEATURE_LINK_NAME);
227 - public Long getValue() { 228 + topologyGraphEventMetric =
228 - return lastEventTimestampEpochMs; 229 + new EventMetric(metricsService, COMPONENT_NAME,
229 - } 230 + FEATURE_GRAPH_NAME);
230 - }); 231 +
231 - eventRateMeter = 232 + topologyDeviceEventMetric.registerMetrics();
232 - metricsService.createMeter(metricsComponent, 233 + topologyHostEventMetric.registerMetrics();
233 - metricsFeatureEventNotification, 234 + topologyLinkEventMetric.registerMetrics();
234 - METER_NAME); 235 + topologyGraphEventMetric.registerMetrics();
235 -
236 } 236 }
237 237
238 /** 238 /**
239 * Removes the metrics. 239 * Removes the metrics.
240 */ 240 */
241 private void removeMetrics() { 241 private void removeMetrics() {
242 - metricsService.removeMetric(metricsComponent, 242 + topologyDeviceEventMetric.removeMetrics();
243 - metricsFeatureEventNotification, 243 + topologyHostEventMetric.removeMetrics();
244 - GAUGE_NAME); 244 + topologyLinkEventMetric.removeMetrics();
245 - metricsService.removeMetric(metricsComponent, 245 + topologyGraphEventMetric.removeMetrics();
246 - metricsFeatureEventNotification,
247 - METER_NAME);
248 } 246 }
249 } 247 }
......
1 package org.onlab.onos.metrics.topology; 1 package org.onlab.onos.metrics.topology;
2 2
3 import java.util.List; 3 import java.util.List;
4 - 4 +import org.onlab.metrics.EventMetric;
5 -import com.codahale.metrics.Gauge;
6 -import com.codahale.metrics.Meter;
7 import org.onlab.onos.event.Event; 5 import org.onlab.onos.event.Event;
8 6
9 /** 7 /**
...@@ -18,18 +16,30 @@ public interface TopologyMetricsService { ...@@ -18,18 +16,30 @@ public interface TopologyMetricsService {
18 public List<Event> getEvents(); 16 public List<Event> getEvents();
19 17
20 /** 18 /**
21 - * Gets the Metrics' Gauge for the last topology event timestamp 19 + * Gets the Event Metric for the Device Events.
22 - * (ms from the epoch). 20 + *
21 + * @return the Event Metric for the Device Events.
22 + */
23 + public EventMetric topologyDeviceEventMetric();
24 +
25 + /**
26 + * Gets the Event Metric for the Host Events.
27 + *
28 + * @return the Event Metric for the Host Events.
29 + */
30 + public EventMetric topologyHostEventMetric();
31 +
32 + /**
33 + * Gets the Event Metric for the Link Events.
23 * 34 *
24 - * @return the Metrics' Gauge for the last topology event timestamp 35 + * @return the Event Metric for the Link Events.
25 - * (ms from the epoch)
26 */ 36 */
27 - public Gauge<Long> lastEventTimestampEpochMsGauge(); 37 + public EventMetric topologyLinkEventMetric();
28 38
29 /** 39 /**
30 - * Gets the Metrics' Meter for the topology events rate. 40 + * Gets the Event Metric for the Topology Graph Events.
31 * 41 *
32 - * @return the Metrics' Meter for the topology events rate 42 + * @return the Event Metric for the Topology Graph Events.
33 */ 43 */
34 - public Meter eventRateMeter(); 44 + public EventMetric topologyGraphEventMetric();
35 } 45 }
......
...@@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.JsonNode; ...@@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.JsonNode;
11 import com.fasterxml.jackson.databind.ObjectMapper; 11 import com.fasterxml.jackson.databind.ObjectMapper;
12 import com.fasterxml.jackson.databind.node.ObjectNode; 12 import com.fasterxml.jackson.databind.node.ObjectNode;
13 import org.apache.karaf.shell.commands.Command; 13 import org.apache.karaf.shell.commands.Command;
14 +import org.onlab.metrics.EventMetric;
14 import org.onlab.onos.cli.AbstractShellCommand; 15 import org.onlab.onos.cli.AbstractShellCommand;
15 import org.onlab.onos.metrics.topology.TopologyMetricsService; 16 import org.onlab.onos.metrics.topology.TopologyMetricsService;
16 17
...@@ -22,15 +23,13 @@ import org.onlab.onos.metrics.topology.TopologyMetricsService; ...@@ -22,15 +23,13 @@ import org.onlab.onos.metrics.topology.TopologyMetricsService;
22 public class TopologyEventsMetricsCommand extends AbstractShellCommand { 23 public class TopologyEventsMetricsCommand extends AbstractShellCommand {
23 24
24 private static final String FORMAT_GAUGE = 25 private static final String FORMAT_GAUGE =
25 - "Last Topology Event Timestamp (ms from epoch)=%d"; 26 + "Topology %s Event Timestamp (ms from epoch)=%d";
26 private static final String FORMAT_METER = 27 private static final String FORMAT_METER =
27 - "Topology Events count=%d rate(events/sec) mean=%f m1=%f m5=%f m15=%f"; 28 + "Topology %s Events count=%d rate(events/sec) mean=%f m1=%f m5=%f m15=%f";
28 29
29 @Override 30 @Override
30 protected void execute() { 31 protected void execute() {
31 TopologyMetricsService service = get(TopologyMetricsService.class); 32 TopologyMetricsService service = get(TopologyMetricsService.class);
32 - Gauge<Long> gauge = service.lastEventTimestampEpochMsGauge();
33 - Meter meter = service.eventRateMeter();
34 33
35 if (outputJson()) { 34 if (outputJson()) {
36 ObjectMapper mapper = new ObjectMapper() 35 ObjectMapper mapper = new ObjectMapper()
...@@ -38,32 +37,89 @@ public class TopologyEventsMetricsCommand extends AbstractShellCommand { ...@@ -38,32 +37,89 @@ public class TopologyEventsMetricsCommand extends AbstractShellCommand {
38 TimeUnit.MILLISECONDS, 37 TimeUnit.MILLISECONDS,
39 false)); 38 false));
40 ObjectNode result = mapper.createObjectNode(); 39 ObjectNode result = mapper.createObjectNode();
41 - try { 40 + result = json(mapper, result, "topologyDeviceEvent",
42 - // 41 + service.topologyDeviceEventMetric());
43 - // NOTE: The API for custom serializers is incomplete, 42 + result = json(mapper, result, "topologyHostEvent",
44 - // hence we have to parse the JSON string to create JsonNode. 43 + service.topologyHostEventMetric());
45 - // 44 + result = json(mapper, result, "topologyLinkEvent",
46 - final String gaugeJson = mapper.writeValueAsString(gauge); 45 + service.topologyLinkEventMetric());
47 - final String meterJson = mapper.writeValueAsString(meter); 46 + result = json(mapper, result, "topologyGraphEvent",
48 - JsonNode gaugeNode = mapper.readTree(gaugeJson); 47 + service.topologyGraphEventMetric());
49 - JsonNode meterNode = mapper.readTree(meterJson);
50 - result.put("lastTopologyEventTimestamp", gaugeNode);
51 - result.put("topologyEventRate", meterNode);
52 - } catch (JsonProcessingException e) {
53 - log.error("Error writing value as JSON string", e);
54 - } catch (IOException e) {
55 - log.error("Error writing value as JSON string", e);
56 - }
57 print("%s", result); 48 print("%s", result);
58 } else { 49 } else {
59 - TimeUnit rateUnit = TimeUnit.SECONDS; 50 + printEventMetric("Device", service.topologyDeviceEventMetric());
60 - double rateFactor = rateUnit.toSeconds(1); 51 + printEventMetric("Host", service.topologyHostEventMetric());
61 - print(FORMAT_GAUGE, gauge.getValue()); 52 + printEventMetric("Link", service.topologyLinkEventMetric());
62 - print(FORMAT_METER, meter.getCount(), 53 + printEventMetric("Graph", service.topologyGraphEventMetric());
63 - meter.getMeanRate() * rateFactor,
64 - meter.getOneMinuteRate() * rateFactor,
65 - meter.getFiveMinuteRate() * rateFactor,
66 - meter.getFifteenMinuteRate() * rateFactor);
67 } 54 }
68 } 55 }
56 +
57 + /**
58 + * Produces JSON node for an Event Metric.
59 + *
60 + * @param mapper the JSON object mapper to use
61 + * @param objectNode the JSON object node to use
62 + * @param propertyPrefix the property prefix to use
63 + * @param eventMetric the Event Metric with the data
64 + * @return JSON object node for the Event Metric
65 + */
66 + private ObjectNode json(ObjectMapper mapper, ObjectNode objectNode,
67 + String propertyPrefix, EventMetric eventMetric) {
68 + String gaugeName = propertyPrefix + "Timestamp";
69 + String meterName = propertyPrefix + "Rate";
70 + Gauge<Long> gauge = eventMetric.lastEventTimestampGauge();
71 + Meter meter = eventMetric.eventRateMeter();
72 +
73 + objectNode.put(gaugeName, json(mapper, gauge));
74 + objectNode.put(meterName, json(mapper, meter));
75 + return objectNode;
76 + }
77 +
78 + /**
79 + * Produces JSON node for an Object.
80 + *
81 + * @param mapper the JSON object mapper to use
82 + * @param object the Object with the data
83 + * @return JSON node for the Object
84 + */
85 + private JsonNode json(ObjectMapper mapper, Object object) {
86 + //
87 + // NOTE: The API for custom serializers is incomplete,
88 + // hence we have to parse the JSON string to create JsonNode.
89 + //
90 + try {
91 + final String objectJson = mapper.writeValueAsString(object);
92 + JsonNode jsonNode = mapper.readTree(objectJson);
93 + return jsonNode;
94 + } catch (JsonProcessingException e) {
95 + log.error("Error writing value as JSON string", e);
96 + } catch (IOException e) {
97 + log.error("Error writing value as JSON string", e);
98 + }
99 + return null;
100 + }
101 +
102 + /**
103 + * Prints an Event Metric.
104 + *
105 + * @param operationStr the string with the intent operation to print
106 + * @param eventMetric the Event Metric to print
107 + */
108 + private void printEventMetric(String operationStr,
109 + EventMetric eventMetric) {
110 + Gauge<Long> gauge = eventMetric.lastEventTimestampGauge();
111 + Meter meter = eventMetric.eventRateMeter();
112 + TimeUnit rateUnit = TimeUnit.SECONDS;
113 + double rateFactor = rateUnit.toSeconds(1);
114 +
115 + // Print the Gauge
116 + print(FORMAT_GAUGE, operationStr, gauge.getValue());
117 +
118 + // Print the Meter
119 + print(FORMAT_METER, operationStr, meter.getCount(),
120 + meter.getMeanRate() * rateFactor,
121 + meter.getOneMinuteRate() * rateFactor,
122 + meter.getFiveMinuteRate() * rateFactor,
123 + meter.getFifteenMinuteRate() * rateFactor);
124 + }
69 } 125 }
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
35 <bundle>mvn:io.netty/netty-transport-native-epoll/4.0.23.Final</bundle> 35 <bundle>mvn:io.netty/netty-transport-native-epoll/4.0.23.Final</bundle>
36 <bundle>mvn:commons-pool/commons-pool/1.6</bundle> 36 <bundle>mvn:commons-pool/commons-pool/1.6</bundle>
37 37
38 - <bundle>mvn:com.hazelcast/hazelcast/3.3</bundle> 38 + <bundle>mvn:com.hazelcast/hazelcast/3.3.2</bundle>
39 <bundle>mvn:io.dropwizard.metrics/metrics-core/3.1.0</bundle> 39 <bundle>mvn:io.dropwizard.metrics/metrics-core/3.1.0</bundle>
40 <bundle>mvn:io.dropwizard.metrics/metrics-json/3.1.0</bundle> 40 <bundle>mvn:io.dropwizard.metrics/metrics-json/3.1.0</bundle>
41 <bundle>mvn:com.eclipsesource.minimal-json/minimal-json/0.9.1</bundle> 41 <bundle>mvn:com.eclipsesource.minimal-json/minimal-json/0.9.1</bundle>
......
...@@ -192,7 +192,7 @@ ...@@ -192,7 +192,7 @@
192 <dependency> 192 <dependency>
193 <groupId>com.hazelcast</groupId> 193 <groupId>com.hazelcast</groupId>
194 <artifactId>hazelcast</artifactId> 194 <artifactId>hazelcast</artifactId>
195 - <version>3.3</version> 195 + <version>3.3.2</version>
196 </dependency> 196 </dependency>
197 <dependency> 197 <dependency>
198 <groupId>com.eclipsesource.minimal-json</groupId> 198 <groupId>com.eclipsesource.minimal-json</groupId>
......
1 +package org.onlab.metrics;
2 +
3 +import com.codahale.metrics.Gauge;
4 +import com.codahale.metrics.Meter;
5 +
6 +/**
7 + * Metric measurements for events.
8 + */
9 +public class EventMetric {
10 + private static final String GAUGE_TIMESTAMP_NAME = "Timestamp.EpochMs";
11 + private static final String METER_RATE_NAME = "Rate";
12 +
13 + private final MetricsService metricsService;
14 + private final String componentName;
15 + private final String featureName;
16 +
17 + private MetricsComponent metricsComponent;
18 + private MetricsFeature metricsFeature;
19 +
20 + private volatile long lastEventTimestampEpochMs = 0;
21 + private Gauge<Long> lastEventTimestampGauge;
22 + private Meter eventRateMeter;
23 +
24 + /**
25 + * Constructor.
26 + *
27 + * @param metricsService the Metrics Service to use for Metrics
28 + * registration and deregistration
29 + * @param componentName the Metrics Component Name to use for Metrics
30 + * registration and deregistration
31 + * @param featureName the Metrics Feature Name to use for Metrics
32 + * registration and deregistration
33 + */
34 + public EventMetric(MetricsService metricsService, String componentName,
35 + String featureName) {
36 + this.metricsService = metricsService;
37 + this.componentName = componentName;
38 + this.featureName = featureName;
39 + }
40 +
41 + /**
42 + * Registers the metrics.
43 + */
44 + public void registerMetrics() {
45 + metricsComponent = metricsService.registerComponent(componentName);
46 + metricsFeature = metricsComponent.registerFeature(featureName);
47 +
48 + lastEventTimestampEpochMs = 0;
49 + lastEventTimestampGauge =
50 + metricsService.registerMetric(metricsComponent,
51 + metricsFeature,
52 + GAUGE_TIMESTAMP_NAME,
53 + new Gauge<Long>() {
54 + @Override
55 + public Long getValue() {
56 + return lastEventTimestampEpochMs;
57 + }
58 + });
59 +
60 + eventRateMeter = metricsService.createMeter(metricsComponent,
61 + metricsFeature,
62 + METER_RATE_NAME);
63 + }
64 +
65 + /**
66 + * Removes the metrics.
67 + */
68 + public void removeMetrics() {
69 + lastEventTimestampEpochMs = 0;
70 + metricsService.removeMetric(metricsComponent,
71 + metricsFeature,
72 + GAUGE_TIMESTAMP_NAME);
73 + metricsService.removeMetric(metricsComponent,
74 + metricsFeature,
75 + METER_RATE_NAME);
76 + }
77 +
78 + /**
79 + * Updates the metric measurements for a single event.
80 + */
81 + public void eventReceived() {
82 + lastEventTimestampEpochMs = System.currentTimeMillis();
83 + eventRateMeter.mark(1);
84 + }
85 +
86 + /**
87 + * Gets the last event timestamp Gauge (ms from the Epoch).
88 + *
89 + * @return the last event timestamp Gauge (ms from the Epoch)
90 + */
91 + public Gauge<Long> lastEventTimestampGauge() {
92 + return lastEventTimestampGauge;
93 + }
94 +
95 + /**
96 + * Gets the event rate meter.
97 + *
98 + * @return the event rate meter
99 + */
100 + public Meter eventRateMeter() {
101 + return eventRateMeter;
102 + }
103 +}