mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-24 13:51:27 +02:00
Update the TopologyMetrics module to listen for all topology-related events:
Devices, Hosts, Links, TopologyEvent Now the semantics for updating the metrics are: * Any topology-related event (DeviceEvent, HostEvent, LinkEvent, TopologyEvent) will update the Lost Topology Event Timestamp * Only the DeviceEvent, HostEvent and LinkEvent will be counted in measuring the event rate; TopologyEvent is excluded, because it is generated as a result of some of those events Also, increased the number of saved events from 10 to 100. Change-Id: Ie759ee69869cddc617d7ad5b8b75a622e2571620
This commit is contained in:
parent
558e893766
commit
5ba8b28e76
@ -18,6 +18,15 @@ import org.onlab.metrics.MetricsComponent;
|
||||
import org.onlab.metrics.MetricsFeature;
|
||||
import org.onlab.metrics.MetricsService;
|
||||
import org.onlab.onos.event.Event;
|
||||
import org.onlab.onos.net.device.DeviceEvent;
|
||||
import org.onlab.onos.net.device.DeviceListener;
|
||||
import org.onlab.onos.net.device.DeviceService;
|
||||
import org.onlab.onos.net.host.HostEvent;
|
||||
import org.onlab.onos.net.host.HostListener;
|
||||
import org.onlab.onos.net.host.HostService;
|
||||
import org.onlab.onos.net.link.LinkEvent;
|
||||
import org.onlab.onos.net.link.LinkListener;
|
||||
import org.onlab.onos.net.link.LinkService;
|
||||
import org.onlab.onos.net.topology.TopologyEvent;
|
||||
import org.onlab.onos.net.topology.TopologyListener;
|
||||
import org.onlab.onos.net.topology.TopologyService;
|
||||
@ -28,14 +37,26 @@ import org.slf4j.Logger;
|
||||
*/
|
||||
@Component(immediate = true)
|
||||
@Service
|
||||
public class TopologyMetrics implements TopologyMetricsService,
|
||||
TopologyListener {
|
||||
public class TopologyMetrics implements TopologyMetricsService {
|
||||
private static final Logger log = getLogger(TopologyMetrics.class);
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected DeviceService deviceService;
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected HostService hostService;
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected LinkService linkService;
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected TopologyService topologyService;
|
||||
private LinkedList<TopologyEvent> lastEvents = new LinkedList<>();
|
||||
private static final int LAST_EVENTS_MAX_N = 10;
|
||||
|
||||
private LinkedList<Event> lastEvents = new LinkedList<>();
|
||||
private static final int LAST_EVENTS_MAX_N = 100;
|
||||
|
||||
private final DeviceListener deviceListener = new InnerDeviceListener();
|
||||
private final HostListener hostListener = new InnerHostListener();
|
||||
private final LinkListener linkListener = new InnerLinkListener();
|
||||
private final TopologyListener topologyListener =
|
||||
new InnerTopologyListener();
|
||||
|
||||
//
|
||||
// Metrics
|
||||
@ -61,22 +82,33 @@ public class TopologyMetrics implements TopologyMetricsService,
|
||||
protected void activate() {
|
||||
clear();
|
||||
registerMetrics();
|
||||
topologyService.addListener(this);
|
||||
|
||||
// Register for all topology-related events
|
||||
deviceService.addListener(deviceListener);
|
||||
hostService.addListener(hostListener);
|
||||
linkService.addListener(linkListener);
|
||||
topologyService.addListener(topologyListener);
|
||||
|
||||
log.info("ONOS Topology Metrics started.");
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
topologyService.removeListener(this);
|
||||
// De-register from all topology-related events
|
||||
deviceService.removeListener(deviceListener);
|
||||
hostService.removeListener(hostListener);
|
||||
linkService.removeListener(linkListener);
|
||||
topologyService.removeListener(topologyListener);
|
||||
|
||||
removeMetrics();
|
||||
clear();
|
||||
log.info("ONOS Topology Metrics stopped.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TopologyEvent> getEvents() {
|
||||
public List<Event> getEvents() {
|
||||
synchronized (lastEvents) {
|
||||
return ImmutableList.<TopologyEvent>copyOf(lastEvents);
|
||||
return ImmutableList.<Event>copyOf(lastEvents);
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,27 +122,22 @@ public class TopologyMetrics implements TopologyMetricsService,
|
||||
return eventRateMeter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void event(TopologyEvent event) {
|
||||
lastEventTimestampEpochMs = System.currentTimeMillis();
|
||||
//
|
||||
// NOTE: If we want to count each "reason" as a separate event,
|
||||
// then we should use 'event.reason().size()' instead of '1' to
|
||||
// mark the meter below.
|
||||
//
|
||||
eventRateMeter.mark(1);
|
||||
|
||||
log.debug("Topology Event: time = {} type = {} subject = {}",
|
||||
event.time(), event.type(), event.subject());
|
||||
for (Event reason : event.reasons()) {
|
||||
log.debug("Topology Event Reason: time = {} type = {} subject = {}",
|
||||
reason.time(), reason.type(), reason.subject());
|
||||
}
|
||||
|
||||
//
|
||||
// Keep only the last N events, where N = LAST_EVENTS_MAX_N
|
||||
//
|
||||
/**
|
||||
* Records an event.
|
||||
*
|
||||
* @param event the event to record
|
||||
* @param updateEventRateMeter if true, update the Event Rate Meter
|
||||
*/
|
||||
private void recordEvent(Event event, boolean updateEventRateMeter) {
|
||||
synchronized (lastEvents) {
|
||||
lastEventTimestampEpochMs = System.currentTimeMillis();
|
||||
if (updateEventRateMeter) {
|
||||
eventRateMeter.mark(1);
|
||||
}
|
||||
|
||||
//
|
||||
// Keep only the last N events, where N = LAST_EVENTS_MAX_N
|
||||
//
|
||||
while (lastEvents.size() >= LAST_EVENTS_MAX_N) {
|
||||
lastEvents.remove();
|
||||
}
|
||||
@ -118,12 +145,68 @@ public class TopologyMetrics implements TopologyMetricsService,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner Device Event Listener class.
|
||||
*/
|
||||
private class InnerDeviceListener implements DeviceListener {
|
||||
@Override
|
||||
public void event(DeviceEvent event) {
|
||||
recordEvent(event, true);
|
||||
log.debug("Device Event: time = {} type = {} event = {}",
|
||||
event.time(), event.type(), event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner Host Event Listener class.
|
||||
*/
|
||||
private class InnerHostListener implements HostListener {
|
||||
@Override
|
||||
public void event(HostEvent event) {
|
||||
recordEvent(event, true);
|
||||
log.debug("Host Event: time = {} type = {} event = {}",
|
||||
event.time(), event.type(), event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner Link Event Listener class.
|
||||
*/
|
||||
private class InnerLinkListener implements LinkListener {
|
||||
@Override
|
||||
public void event(LinkEvent event) {
|
||||
recordEvent(event, true);
|
||||
log.debug("Link Event: time = {} type = {} event = {}",
|
||||
event.time(), event.type(), event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner Topology Event Listener class.
|
||||
*/
|
||||
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);
|
||||
log.debug("Topology Event: time = {} type = {} event = {}",
|
||||
event.time(), event.type(), event);
|
||||
for (Event reason : event.reasons()) {
|
||||
log.debug("Topology Event Reason: time = {} type = {} event = {}",
|
||||
reason.time(), reason.type(), reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the internal state.
|
||||
*/
|
||||
private void clear() {
|
||||
lastEventTimestampEpochMs = 0;
|
||||
synchronized (lastEvents) {
|
||||
lastEventTimestampEpochMs = 0;
|
||||
lastEvents.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import java.util.List;
|
||||
|
||||
import com.codahale.metrics.Gauge;
|
||||
import com.codahale.metrics.Meter;
|
||||
import org.onlab.onos.net.topology.TopologyEvent;
|
||||
import org.onlab.onos.event.Event;
|
||||
|
||||
/**
|
||||
* Service interface exported by TopologyMetrics.
|
||||
@ -15,7 +15,7 @@ public interface TopologyMetricsService {
|
||||
*
|
||||
* @return the last saved topology events.
|
||||
*/
|
||||
public List<TopologyEvent> getEvents();
|
||||
public List<Event> getEvents();
|
||||
|
||||
/**
|
||||
* Gets the Metrics' Gauge for the last topology event timestamp
|
||||
|
||||
@ -19,10 +19,8 @@ import org.onlab.onos.net.topology.TopologyEvent;
|
||||
description = "Lists the last topology events")
|
||||
public class TopologyEventsListCommand extends AbstractShellCommand {
|
||||
|
||||
private static final String FORMAT_EVENT =
|
||||
"Topology Event time=%d type=%s subject=%s";
|
||||
private static final String FORMAT_REASON =
|
||||
" Reason time=%d type=%s subject=%s";
|
||||
private static final String FORMAT_EVENT = "Event=%s";
|
||||
private static final String FORMAT_REASON = " Reason=%s";
|
||||
|
||||
@Override
|
||||
protected void execute() {
|
||||
@ -31,12 +29,13 @@ public class TopologyEventsListCommand extends AbstractShellCommand {
|
||||
if (outputJson()) {
|
||||
print("%s", json(service.getEvents()));
|
||||
} else {
|
||||
for (TopologyEvent event : service.getEvents()) {
|
||||
print(FORMAT_EVENT, event.time(), event.type(),
|
||||
event.subject());
|
||||
for (Event reason : event.reasons()) {
|
||||
print(FORMAT_REASON, reason.time(), reason.type(),
|
||||
reason.subject());
|
||||
for (Event event : service.getEvents()) {
|
||||
print(FORMAT_EVENT, event);
|
||||
if (event instanceof TopologyEvent) {
|
||||
TopologyEvent topologyEvent = (TopologyEvent) event;
|
||||
for (Event reason : topologyEvent.reasons()) {
|
||||
print(FORMAT_REASON, reason);
|
||||
}
|
||||
}
|
||||
print(""); // Extra empty line for clarity
|
||||
}
|
||||
@ -46,14 +45,14 @@ public class TopologyEventsListCommand extends AbstractShellCommand {
|
||||
/**
|
||||
* Produces a JSON array of topology events.
|
||||
*
|
||||
* @param topologyEvents the topology events with the data
|
||||
* @param events the topology events with the data
|
||||
* @return JSON array with the topology events
|
||||
*/
|
||||
private JsonNode json(List<TopologyEvent> topologyEvents) {
|
||||
private JsonNode json(List<Event> events) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
ArrayNode result = mapper.createArrayNode();
|
||||
|
||||
for (TopologyEvent event : topologyEvents) {
|
||||
for (Event event : events) {
|
||||
result.add(json(mapper, event));
|
||||
}
|
||||
return result;
|
||||
@ -66,32 +65,23 @@ public class TopologyEventsListCommand extends AbstractShellCommand {
|
||||
* @param topologyEvent the topology event with the data
|
||||
* @return JSON object for the topology event
|
||||
*/
|
||||
private ObjectNode json(ObjectMapper mapper, TopologyEvent topologyEvent) {
|
||||
ObjectNode result = mapper.createObjectNode();
|
||||
ArrayNode reasons = mapper.createArrayNode();
|
||||
|
||||
for (Event reason : topologyEvent.reasons()) {
|
||||
reasons.add(json(mapper, reason));
|
||||
}
|
||||
result.put("time", topologyEvent.time())
|
||||
.put("type", topologyEvent.type().toString())
|
||||
.put("subject", topologyEvent.subject().toString())
|
||||
.put("reasons", reasons);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces JSON object for a generic event.
|
||||
*
|
||||
* @param event the generic event with the data
|
||||
* @return JSON object for the generic event
|
||||
*/
|
||||
private ObjectNode json(ObjectMapper mapper, Event event) {
|
||||
ObjectNode result = mapper.createObjectNode();
|
||||
|
||||
result.put("time", event.time())
|
||||
.put("type", event.type().toString())
|
||||
.put("subject", event.subject().toString());
|
||||
.put("event", event.toString());
|
||||
|
||||
// Add the reasons if a TopologyEvent
|
||||
if (event instanceof TopologyEvent) {
|
||||
TopologyEvent topologyEvent = (TopologyEvent) event;
|
||||
ArrayNode reasons = mapper.createArrayNode();
|
||||
for (Event reason : topologyEvent.reasons()) {
|
||||
reasons.add(json(mapper, reason));
|
||||
}
|
||||
result.put("reasons", reasons);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user