Thomas Vachuska

Merge remote-tracking branch 'origin/master'

......@@ -5,8 +5,6 @@ import static org.slf4j.LoggerFactory.getLogger;
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.Deactivate;
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.net.intent.IntentEvent;
import org.onlab.onos.net.intent.IntentListener;
......@@ -33,56 +30,32 @@ public class IntentMetrics implements IntentMetricsService,
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentService intentService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected MetricsService metricsService;
private LinkedList<IntentEvent> lastEvents = new LinkedList<>();
private static final int LAST_EVENTS_MAX_N = 100;
//
// Metrics
//
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected MetricsService metricsService;
//
private static final String COMPONENT_NAME = "Intent";
private static final String FEATURE_SUBMITTED_NAME = "Submitted";
private static final String FEATURE_INSTALLED_NAME = "Installed";
private static final String FEATURE_WITHDRAW_REQUESTED_NAME =
"WithdrawRequested";
private static final String FEATURE_WITHDRAWN_NAME = "Withdrawn";
private static final String GAUGE_TIMESTAMP_NAME = "Timestamp.EpochMs";
private static final String METER_RATE_NAME = "Rate";
//
private MetricsComponent metricsComponent;
private MetricsFeature metricsFeatureSubmitted;
private MetricsFeature metricsFeatureInstalled;
private MetricsFeature metricsFeatureWithdrawRequested;
private MetricsFeature metricsFeatureWithdrawn;
// Event metrics:
// - Intent Submitted API operation
// - Intent Installed operation completion
// - Intent Withdraw Requested API operation
// - Intent Withdrawn operation completion
//
// Timestamps:
// - Intent Submitted API operation (ms from the Epoch)
// - Intent Installed operation completion (ms from the Epoch)
// - Intent Withdraw Requested API operation (ms from the Epoch)
// - Intent Withdrawn operation completion (ms from the Epoch)
//
private volatile long intentSubmittedTimestampEpochMs = 0;
private volatile long intentInstalledTimestampEpochMs = 0;
private volatile long intentWithdrawRequestedTimestampEpochMs = 0;
private volatile long intentWithdrawnTimestampEpochMs = 0;
//
private Gauge<Long> intentSubmittedTimestampEpochMsGauge;
private Gauge<Long> intentInstalledTimestampEpochMsGauge;
private Gauge<Long> intentWithdrawRequestedTimestampEpochMsGauge;
private Gauge<Long> intentWithdrawnTimestampEpochMsGauge;
//
// Rate meters:
// - Rate of the Submitted Intent API operations
// - Rate of the Installed Intent operations
// - Rate of the Withdrawn Requested Intent API operations
// - Rate of the Withdrawn Intent operations
//
private Meter intentSubmittedRateMeter;
private Meter intentInstalledRateMeter;
private Meter intentWithdrawRequestedRateMeter;
private Meter intentWithdrawnRateMeter;
private EventMetric intentSubmittedEventMetric;
private EventMetric intentInstalledEventMetric;
private EventMetric intentWithdrawRequestedEventMetric;
private EventMetric intentWithdrawnEventMetric;
@Activate
protected void activate() {
......@@ -108,43 +81,23 @@ public class IntentMetrics implements IntentMetricsService,
}
@Override
public Gauge<Long> intentSubmittedTimestampEpochMsGauge() {
return intentSubmittedTimestampEpochMsGauge;
}
@Override
public Gauge<Long> intentInstalledTimestampEpochMsGauge() {
return intentInstalledTimestampEpochMsGauge;
}
@Override
public Gauge<Long> intentWithdrawRequestedTimestampEpochMsGauge() {
return intentWithdrawRequestedTimestampEpochMsGauge;
}
@Override
public Gauge<Long> intentWithdrawnTimestampEpochMsGauge() {
return intentWithdrawnTimestampEpochMsGauge;
}
@Override
public Meter intentSubmittedRateMeter() {
return intentSubmittedRateMeter;
public EventMetric intentSubmittedEventMetric() {
return intentSubmittedEventMetric;
}
@Override
public Meter intentInstalledRateMeter() {
return intentInstalledRateMeter;
public EventMetric intentInstalledEventMetric() {
return intentInstalledEventMetric;
}
@Override
public Meter intentWithdrawRequestedRateMeter() {
return intentWithdrawRequestedRateMeter;
public EventMetric intentWithdrawRequestedEventMetric() {
return intentWithdrawRequestedEventMetric;
}
@Override
public Meter intentWithdrawnRateMeter() {
return intentWithdrawnRateMeter;
public EventMetric intentWithdrawnEventMetric() {
return intentWithdrawnEventMetric;
}
@Override
......@@ -156,26 +109,21 @@ public class IntentMetrics implements IntentMetricsService,
//
switch (event.type()) {
case SUBMITTED:
intentSubmittedTimestampEpochMs = System.currentTimeMillis();
intentSubmittedRateMeter.mark(1);
intentSubmittedEventMetric.eventReceived();
break;
case INSTALLED:
intentInstalledTimestampEpochMs = System.currentTimeMillis();
intentInstalledRateMeter.mark(1);
intentInstalledEventMetric.eventReceived();
break;
case FAILED:
// TODO: Just ignore?
break;
/*
case WITHDRAW_REQUESTED:
intentWithdrawRequestedTimestampEpochMs =
System.currentTimeMillis();
intentWithdrawRequestedRateMeter.mark(1);
intentWithdrawRequestedEventMetric.eventReceived();
break;
*/
case WITHDRAWN:
intentWithdrawnTimestampEpochMs = System.currentTimeMillis();
intentWithdrawnRateMeter.mark(1);
intentWithdrawnEventMetric.eventReceived();
break;
default:
break;
......@@ -199,10 +147,6 @@ public class IntentMetrics implements IntentMetricsService,
*/
private void clear() {
synchronized (lastEvents) {
intentSubmittedTimestampEpochMs = 0;
intentInstalledTimestampEpochMs = 0;
intentWithdrawRequestedTimestampEpochMs = 0;
intentWithdrawnTimestampEpochMs = 0;
lastEvents.clear();
}
}
......@@ -211,109 +155,32 @@ public class IntentMetrics implements IntentMetricsService,
* Registers the metrics.
*/
private void registerMetrics() {
metricsComponent = metricsService.registerComponent(COMPONENT_NAME);
//
metricsFeatureSubmitted =
metricsComponent.registerFeature(FEATURE_SUBMITTED_NAME);
metricsFeatureInstalled =
metricsComponent.registerFeature(FEATURE_INSTALLED_NAME);
metricsFeatureWithdrawRequested =
metricsComponent.registerFeature(FEATURE_WITHDRAW_REQUESTED_NAME);
metricsFeatureWithdrawn =
metricsComponent.registerFeature(FEATURE_WITHDRAWN_NAME);
//
intentSubmittedTimestampEpochMsGauge =
metricsService.registerMetric(metricsComponent,
metricsFeatureSubmitted,
GAUGE_TIMESTAMP_NAME,
new Gauge<Long>() {
@Override
public Long getValue() {
return intentSubmittedTimestampEpochMs;
}
});
//
intentInstalledTimestampEpochMsGauge =
metricsService.registerMetric(metricsComponent,
metricsFeatureInstalled,
GAUGE_TIMESTAMP_NAME,
new Gauge<Long>() {
@Override
public Long getValue() {
return intentInstalledTimestampEpochMs;
}
});
//
intentWithdrawRequestedTimestampEpochMsGauge =
metricsService.registerMetric(metricsComponent,
metricsFeatureWithdrawRequested,
GAUGE_TIMESTAMP_NAME,
new Gauge<Long>() {
@Override
public Long getValue() {
return intentWithdrawRequestedTimestampEpochMs;
}
});
//
intentWithdrawnTimestampEpochMsGauge =
metricsService.registerMetric(metricsComponent,
metricsFeatureWithdrawn,
GAUGE_TIMESTAMP_NAME,
new Gauge<Long>() {
@Override
public Long getValue() {
return intentWithdrawnTimestampEpochMs;
}
});
//
intentSubmittedRateMeter =
metricsService.createMeter(metricsComponent,
metricsFeatureSubmitted,
METER_RATE_NAME);
//
intentInstalledRateMeter =
metricsService.createMeter(metricsComponent,
metricsFeatureInstalled,
METER_RATE_NAME);
//
intentWithdrawRequestedRateMeter =
metricsService.createMeter(metricsComponent,
metricsFeatureWithdrawRequested,
METER_RATE_NAME);
//
intentWithdrawnRateMeter =
metricsService.createMeter(metricsComponent,
metricsFeatureWithdrawn,
METER_RATE_NAME);
intentSubmittedEventMetric =
new EventMetric(metricsService, COMPONENT_NAME,
FEATURE_SUBMITTED_NAME);
intentInstalledEventMetric =
new EventMetric(metricsService, COMPONENT_NAME,
FEATURE_INSTALLED_NAME);
intentWithdrawRequestedEventMetric =
new EventMetric(metricsService, COMPONENT_NAME,
FEATURE_WITHDRAW_REQUESTED_NAME);
intentWithdrawnEventMetric =
new EventMetric(metricsService, COMPONENT_NAME,
FEATURE_WITHDRAWN_NAME);
intentSubmittedEventMetric.registerMetrics();
intentInstalledEventMetric.registerMetrics();
intentWithdrawRequestedEventMetric.registerMetrics();
intentWithdrawnEventMetric.registerMetrics();
}
/**
* Removes the metrics.
*/
private void removeMetrics() {
metricsService.removeMetric(metricsComponent,
metricsFeatureSubmitted,
GAUGE_TIMESTAMP_NAME);
metricsService.removeMetric(metricsComponent,
metricsFeatureInstalled,
GAUGE_TIMESTAMP_NAME);
metricsService.removeMetric(metricsComponent,
metricsFeatureWithdrawRequested,
GAUGE_TIMESTAMP_NAME);
metricsService.removeMetric(metricsComponent,
metricsFeatureWithdrawn,
GAUGE_TIMESTAMP_NAME);
metricsService.removeMetric(metricsComponent,
metricsFeatureSubmitted,
METER_RATE_NAME);
metricsService.removeMetric(metricsComponent,
metricsFeatureInstalled,
METER_RATE_NAME);
metricsService.removeMetric(metricsComponent,
metricsFeatureWithdrawRequested,
METER_RATE_NAME);
metricsService.removeMetric(metricsComponent,
metricsFeatureWithdrawn,
METER_RATE_NAME);
intentSubmittedEventMetric.removeMetrics();
intentInstalledEventMetric.removeMetrics();
intentWithdrawRequestedEventMetric.removeMetrics();
intentWithdrawnEventMetric.removeMetrics();
}
}
......
package org.onlab.onos.metrics.intent;
import java.util.List;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.Meter;
import org.onlab.metrics.EventMetric;
import org.onlab.onos.net.intent.IntentEvent;
/**
......@@ -18,68 +16,32 @@ public interface IntentMetricsService {
public List<IntentEvent> getEvents();
/**
* Gets the Metrics' Gauge for the intent SUBMITTED event timestamp
* (ms from the epoch).
* Gets the Event Metric for the intent SUBMITTED events.
*
* @return the Metrics' Gauge for the intent SUBMITTED event timestamp
* (ms from the epoch)
* @return the Event Metric for the intent SUBMITTED events.
*/
public Gauge<Long> intentSubmittedTimestampEpochMsGauge();
public EventMetric intentSubmittedEventMetric();
/**
* Gets the Metrics' Gauge for the intent INSTALLED event timestamp
* (ms from the epoch).
* Gets the Event Metric for the intent INSTALLED events.
*
* @return the Metrics' Gauge for the intent INSTALLED event timestamp
* (ms from the epoch)
* @return the Event Metric for the intent INSTALLED events.
*/
public Gauge<Long> intentInstalledTimestampEpochMsGauge();
public EventMetric intentInstalledEventMetric();
/**
* Gets the Metrics' Gauge for the intent WITHDRAW_REQUESTED event
* timestamp (ms from the epoch).
* Gets the Event Metric for the intent WITHDRAW_REQUESTED events.
*
* TODO: This intent event is not implemented yet.
*
* @return the Metrics' Gauge for the intent WITHDRAW_REQUESTED event
* timestamp (ms from the epoch)
*/
public Gauge<Long> intentWithdrawRequestedTimestampEpochMsGauge();
/**
* Gets the Metrics' Gauge for the intent WITHDRAWN event timestamp
* (ms from the epoch).
*
* @return the Metrics' Gauge for the intent WITHDRAWN event timestamp
* (ms from the epoch)
*/
public Gauge<Long> intentWithdrawnTimestampEpochMsGauge();
/**
* Gets the Metrics' Meter for the submitted intents event rate.
*
* @return the Metrics' Meter for the submitted intents event rate
*/
public Meter intentSubmittedRateMeter();
/**
* Gets the Metrics' Meter for the installed intents event rate.
*
* @return the Metrics' Meter for the installed intent event rate
*/
public Meter intentInstalledRateMeter();
/**
* Gets the Metrics' Meter for the withdraw requested intents event rate.
*
* @return the Metrics' Meter for the withdraw requested intents event rate
* @return the Event Metric for the intent WITHDRAW_REQUESTED events.
*/
public Meter intentWithdrawRequestedRateMeter();
public EventMetric intentWithdrawRequestedEventMetric();
/**
* Gets the Metrics' Meter for the withdraw completed intents event rate.
* Gets the Event Metric for the intent WITHDRAWN events.
*
* @return the Metrics' Meter for the withdraw completed intents event rate
* @return the Event Metric for the intent WITHDRAWN events.
*/
public Meter intentWithdrawnRateMeter();
public EventMetric intentWithdrawnEventMetric();
}
......
......@@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.JsonNode;
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.intent.IntentMetricsService;
......@@ -29,8 +30,6 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand {
@Override
protected void execute() {
IntentMetricsService service = get(IntentMetricsService.class);
Gauge<Long> gauge;
Meter meter;
if (outputJson()) {
ObjectMapper mapper = new ObjectMapper()
......@@ -38,49 +37,49 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand {
TimeUnit.MILLISECONDS,
false));
ObjectNode result = mapper.createObjectNode();
//
gauge = service.intentSubmittedTimestampEpochMsGauge();
result.put("intentSubmittedTimestamp", json(mapper, gauge));
gauge = service.intentInstalledTimestampEpochMsGauge();
result.put("intentInstalledTimestamp", json(mapper, gauge));
gauge = service.intentWithdrawRequestedTimestampEpochMsGauge();
result.put("intentWithdrawRequestedTimestamp",
json(mapper, gauge));
gauge = service.intentWithdrawnTimestampEpochMsGauge();
result.put("intentWithdrawnTimestamp", json(mapper, gauge));
//
meter = service.intentSubmittedRateMeter();
result.put("intentSubmittedRate", json(mapper, meter));
meter = service.intentInstalledRateMeter();
result.put("intentInstalledRate", json(mapper, meter));
meter = service.intentWithdrawRequestedRateMeter();
result.put("intentWithdrawRequestedRate", json(mapper, meter));
meter = service.intentWithdrawnRateMeter();
result.put("intentWithdrawnRate", json(mapper, meter));
//
result = json(mapper, result, "intentSubmitted",
service.intentSubmittedEventMetric());
result = json(mapper, result, "intentInstalled",
service.intentInstalledEventMetric());
result = json(mapper, result, "intentWithdrawRequested",
service.intentWithdrawRequestedEventMetric());
result = json(mapper, result, "intentWithdrawn",
service.intentWithdrawnEventMetric());
print("%s", result);
} else {
gauge = service.intentSubmittedTimestampEpochMsGauge();
printGauge("Submitted", gauge);
gauge = service.intentInstalledTimestampEpochMsGauge();
printGauge("Installed", gauge);
gauge = service.intentWithdrawRequestedTimestampEpochMsGauge();
printGauge("Withdraw Requested", gauge);
gauge = service.intentWithdrawnTimestampEpochMsGauge();
printGauge("Withdrawn", gauge);
//
meter = service.intentSubmittedRateMeter();
printMeter("Submitted", meter);
meter = service.intentInstalledRateMeter();
printMeter("Installed", meter);
meter = service.intentWithdrawRequestedRateMeter();
printMeter("Withdraw Requested", meter);
meter = service.intentWithdrawnRateMeter();
printMeter("Withdrawn", meter);
printEventMetric("Submitted",
service.intentSubmittedEventMetric());
printEventMetric("Installed",
service.intentInstalledEventMetric());
printEventMetric("Withdraw Requested",
service.intentWithdrawRequestedEventMetric());
printEventMetric("Withdrawn",
service.intentWithdrawnEventMetric());
}
}
/**
* 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
......@@ -94,8 +93,8 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand {
//
try {
final String objectJson = mapper.writeValueAsString(object);
JsonNode objectNode = mapper.readTree(objectJson);
return objectNode;
JsonNode jsonNode = mapper.readTree(objectJson);
return jsonNode;
} catch (JsonProcessingException e) {
log.error("Error writing value as JSON string", e);
} catch (IOException e) {
......@@ -105,28 +104,26 @@ public class IntentEventsMetricsCommand extends AbstractShellCommand {
}
/**
* Prints a Gauge.
* Prints an Event Metric.
*
* @param operationStr the string with the intent operation to print
* @param gauge the Gauge to print
* @param eventMetric the Event Metric to print
*/
private void printGauge(String operationStr, Gauge<Long> gauge) {
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());
}
/**
* Prints a Meter.
*
* @param operationStr the string with the intent operation to print
* @param meter the Meter to print
*/
private void printMeter(String operationStr, Meter meter) {
TimeUnit rateUnit = TimeUnit.SECONDS;
double rateFactor = rateUnit.toSeconds(1);
print(FORMAT_METER, operationStr, meter.getCount(),
meter.getMeanRate() * rateFactor,
meter.getOneMinuteRate() * rateFactor,
meter.getFiveMinuteRate() * rateFactor,
meter.getFifteenMinuteRate() * rateFactor);
// Print the Meter
print(FORMAT_METER, operationStr, meter.getCount(),
meter.getMeanRate() * rateFactor,
meter.getOneMinuteRate() * rateFactor,
meter.getFiveMinuteRate() * rateFactor,
meter.getFifteenMinuteRate() * rateFactor);
}
}
......
......@@ -5,8 +5,6 @@ import static org.slf4j.LoggerFactory.getLogger;
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.Deactivate;
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 @@ public class TopologyMetrics implements TopologyMetricsService {
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 @@ public class TopologyMetrics implements TopologyMetricsService {
//
// 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 @@ public class TopologyMetrics implements TopologyMetricsService {
}
@Override
public Gauge<Long> lastEventTimestampEpochMsGauge() {
return lastEventTimestampEpochMsGauge;
public EventMetric topologyDeviceEventMetric() {
return topologyDeviceEventMetric;
}
@Override
public EventMetric topologyHostEventMetric() {
return topologyHostEventMetric;
}
@Override
public Meter eventRateMeter() {
return eventRateMeter;
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 @@ public class TopologyMetrics implements TopologyMetricsService {
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 @@ public class TopologyMetrics implements TopologyMetricsService {
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 @@ public class TopologyMetrics implements TopologyMetricsService {
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 @@ public class TopologyMetrics implements TopologyMetricsService {
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 @@ public class TopologyMetrics implements TopologyMetricsService {
*/
private void clear() {
synchronized (lastEvents) {
lastEventTimestampEpochMs = 0;
lastEvents.clear();
}
}
......@@ -215,35 +216,32 @@ public class TopologyMetrics implements TopologyMetricsService {
* 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();
}
}
......
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 interface TopologyMetricsService {
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 Event Metric for the Device Events.
*/
public EventMetric topologyDeviceEventMetric();
/**
* Gets the Event Metric for the Host Events.
*
* @return the Event Metric for the Host Events.
*/
public EventMetric topologyHostEventMetric();
/**
* Gets the Event Metric for the Link Events.
*
* @return the Metrics' Gauge for the last topology event timestamp
* (ms from the epoch)
* @return the Event Metric for the Link Events.
*/
public Gauge<Long> lastEventTimestampEpochMsGauge();
public EventMetric topologyLinkEventMetric();
/**
* Gets the Metrics' Meter for the topology events rate.
* Gets the Event Metric for the Topology Graph Events.
*
* @return the Metrics' Meter for the topology events rate
* @return the Event Metric for the Topology Graph Events.
*/
public Meter eventRateMeter();
public EventMetric topologyGraphEventMetric();
}
......
......@@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.JsonNode;
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 @@ import org.onlab.onos.metrics.topology.TopologyMetricsService;
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 @@ public class TopologyEventsMetricsCommand extends AbstractShellCommand {
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);
}
}
......
......@@ -35,7 +35,7 @@
<bundle>mvn:io.netty/netty-transport-native-epoll/4.0.23.Final</bundle>
<bundle>mvn:commons-pool/commons-pool/1.6</bundle>
<bundle>mvn:com.hazelcast/hazelcast/3.3</bundle>
<bundle>mvn:com.hazelcast/hazelcast/3.3.2</bundle>
<bundle>mvn:io.dropwizard.metrics/metrics-core/3.1.0</bundle>
<bundle>mvn:io.dropwizard.metrics/metrics-json/3.1.0</bundle>
<bundle>mvn:com.eclipsesource.minimal-json/minimal-json/0.9.1</bundle>
......
......@@ -192,7 +192,7 @@
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId>
<version>3.3</version>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>com.eclipsesource.minimal-json</groupId>
......
package org.onlab.metrics;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.Meter;
/**
* Metric measurements for events.
*/
public class EventMetric {
private static final String GAUGE_TIMESTAMP_NAME = "Timestamp.EpochMs";
private static final String METER_RATE_NAME = "Rate";
private final MetricsService metricsService;
private final String componentName;
private final String featureName;
private MetricsComponent metricsComponent;
private MetricsFeature metricsFeature;
private volatile long lastEventTimestampEpochMs = 0;
private Gauge<Long> lastEventTimestampGauge;
private Meter eventRateMeter;
/**
* Constructor.
*
* @param metricsService the Metrics Service to use for Metrics
* registration and deregistration
* @param componentName the Metrics Component Name to use for Metrics
* registration and deregistration
* @param featureName the Metrics Feature Name to use for Metrics
* registration and deregistration
*/
public EventMetric(MetricsService metricsService, String componentName,
String featureName) {
this.metricsService = metricsService;
this.componentName = componentName;
this.featureName = featureName;
}
/**
* Registers the metrics.
*/
public void registerMetrics() {
metricsComponent = metricsService.registerComponent(componentName);
metricsFeature = metricsComponent.registerFeature(featureName);
lastEventTimestampEpochMs = 0;
lastEventTimestampGauge =
metricsService.registerMetric(metricsComponent,
metricsFeature,
GAUGE_TIMESTAMP_NAME,
new Gauge<Long>() {
@Override
public Long getValue() {
return lastEventTimestampEpochMs;
}
});
eventRateMeter = metricsService.createMeter(metricsComponent,
metricsFeature,
METER_RATE_NAME);
}
/**
* Removes the metrics.
*/
public void removeMetrics() {
lastEventTimestampEpochMs = 0;
metricsService.removeMetric(metricsComponent,
metricsFeature,
GAUGE_TIMESTAMP_NAME);
metricsService.removeMetric(metricsComponent,
metricsFeature,
METER_RATE_NAME);
}
/**
* Updates the metric measurements for a single event.
*/
public void eventReceived() {
lastEventTimestampEpochMs = System.currentTimeMillis();
eventRateMeter.mark(1);
}
/**
* Gets the last event timestamp Gauge (ms from the Epoch).
*
* @return the last event timestamp Gauge (ms from the Epoch)
*/
public Gauge<Long> lastEventTimestampGauge() {
return lastEventTimestampGauge;
}
/**
* Gets the event rate meter.
*
* @return the event rate meter
*/
public Meter eventRateMeter() {
return eventRateMeter;
}
}