mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-25 22:31:07 +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.MetricsFeature;
|
||||||
import org.onlab.metrics.MetricsService;
|
import org.onlab.metrics.MetricsService;
|
||||||
import org.onlab.onos.event.Event;
|
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.TopologyEvent;
|
||||||
import org.onlab.onos.net.topology.TopologyListener;
|
import org.onlab.onos.net.topology.TopologyListener;
|
||||||
import org.onlab.onos.net.topology.TopologyService;
|
import org.onlab.onos.net.topology.TopologyService;
|
||||||
@ -28,14 +37,26 @@ import org.slf4j.Logger;
|
|||||||
*/
|
*/
|
||||||
@Component(immediate = true)
|
@Component(immediate = true)
|
||||||
@Service
|
@Service
|
||||||
public class TopologyMetrics implements TopologyMetricsService,
|
public class TopologyMetrics implements TopologyMetricsService {
|
||||||
TopologyListener {
|
|
||||||
private static final Logger log = getLogger(TopologyMetrics.class);
|
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)
|
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||||
protected TopologyService topologyService;
|
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
|
// Metrics
|
||||||
@ -61,22 +82,33 @@ public class TopologyMetrics implements TopologyMetricsService,
|
|||||||
protected void activate() {
|
protected void activate() {
|
||||||
clear();
|
clear();
|
||||||
registerMetrics();
|
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.");
|
log.info("ONOS Topology Metrics started.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deactivate
|
@Deactivate
|
||||||
public void 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();
|
removeMetrics();
|
||||||
clear();
|
clear();
|
||||||
log.info("ONOS Topology Metrics stopped.");
|
log.info("ONOS Topology Metrics stopped.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<TopologyEvent> getEvents() {
|
public List<Event> getEvents() {
|
||||||
synchronized (lastEvents) {
|
synchronized (lastEvents) {
|
||||||
return ImmutableList.<TopologyEvent>copyOf(lastEvents);
|
return ImmutableList.<Event>copyOf(lastEvents);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,27 +122,22 @@ public class TopologyMetrics implements TopologyMetricsService,
|
|||||||
return eventRateMeter;
|
return eventRateMeter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void event(TopologyEvent event) {
|
* 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();
|
lastEventTimestampEpochMs = System.currentTimeMillis();
|
||||||
//
|
if (updateEventRateMeter) {
|
||||||
// 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);
|
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
|
// Keep only the last N events, where N = LAST_EVENTS_MAX_N
|
||||||
//
|
//
|
||||||
synchronized (lastEvents) {
|
|
||||||
while (lastEvents.size() >= LAST_EVENTS_MAX_N) {
|
while (lastEvents.size() >= LAST_EVENTS_MAX_N) {
|
||||||
lastEvents.remove();
|
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.
|
* Clears the internal state.
|
||||||
*/
|
*/
|
||||||
private void clear() {
|
private void clear() {
|
||||||
lastEventTimestampEpochMs = 0;
|
|
||||||
synchronized (lastEvents) {
|
synchronized (lastEvents) {
|
||||||
|
lastEventTimestampEpochMs = 0;
|
||||||
lastEvents.clear();
|
lastEvents.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import com.codahale.metrics.Gauge;
|
import com.codahale.metrics.Gauge;
|
||||||
import com.codahale.metrics.Meter;
|
import com.codahale.metrics.Meter;
|
||||||
import org.onlab.onos.net.topology.TopologyEvent;
|
import org.onlab.onos.event.Event;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service interface exported by TopologyMetrics.
|
* Service interface exported by TopologyMetrics.
|
||||||
@ -15,7 +15,7 @@ public interface TopologyMetricsService {
|
|||||||
*
|
*
|
||||||
* @return the last saved topology events.
|
* @return the last saved topology events.
|
||||||
*/
|
*/
|
||||||
public List<TopologyEvent> getEvents();
|
public List<Event> getEvents();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the Metrics' Gauge for the last topology event timestamp
|
* 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")
|
description = "Lists the last topology events")
|
||||||
public class TopologyEventsListCommand extends AbstractShellCommand {
|
public class TopologyEventsListCommand extends AbstractShellCommand {
|
||||||
|
|
||||||
private static final String FORMAT_EVENT =
|
private static final String FORMAT_EVENT = "Event=%s";
|
||||||
"Topology Event time=%d type=%s subject=%s";
|
private static final String FORMAT_REASON = " Reason=%s";
|
||||||
private static final String FORMAT_REASON =
|
|
||||||
" Reason time=%d type=%s subject=%s";
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void execute() {
|
protected void execute() {
|
||||||
@ -31,12 +29,13 @@ public class TopologyEventsListCommand extends AbstractShellCommand {
|
|||||||
if (outputJson()) {
|
if (outputJson()) {
|
||||||
print("%s", json(service.getEvents()));
|
print("%s", json(service.getEvents()));
|
||||||
} else {
|
} else {
|
||||||
for (TopologyEvent event : service.getEvents()) {
|
for (Event event : service.getEvents()) {
|
||||||
print(FORMAT_EVENT, event.time(), event.type(),
|
print(FORMAT_EVENT, event);
|
||||||
event.subject());
|
if (event instanceof TopologyEvent) {
|
||||||
for (Event reason : event.reasons()) {
|
TopologyEvent topologyEvent = (TopologyEvent) event;
|
||||||
print(FORMAT_REASON, reason.time(), reason.type(),
|
for (Event reason : topologyEvent.reasons()) {
|
||||||
reason.subject());
|
print(FORMAT_REASON, reason);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
print(""); // Extra empty line for clarity
|
print(""); // Extra empty line for clarity
|
||||||
}
|
}
|
||||||
@ -46,14 +45,14 @@ public class TopologyEventsListCommand extends AbstractShellCommand {
|
|||||||
/**
|
/**
|
||||||
* Produces a JSON array of topology events.
|
* 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
|
* @return JSON array with the topology events
|
||||||
*/
|
*/
|
||||||
private JsonNode json(List<TopologyEvent> topologyEvents) {
|
private JsonNode json(List<Event> events) {
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
ArrayNode result = mapper.createArrayNode();
|
ArrayNode result = mapper.createArrayNode();
|
||||||
|
|
||||||
for (TopologyEvent event : topologyEvents) {
|
for (Event event : events) {
|
||||||
result.add(json(mapper, event));
|
result.add(json(mapper, event));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -66,32 +65,23 @@ public class TopologyEventsListCommand extends AbstractShellCommand {
|
|||||||
* @param topologyEvent the topology event with the data
|
* @param topologyEvent the topology event with the data
|
||||||
* @return JSON object for the topology event
|
* @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) {
|
private ObjectNode json(ObjectMapper mapper, Event event) {
|
||||||
ObjectNode result = mapper.createObjectNode();
|
ObjectNode result = mapper.createObjectNode();
|
||||||
|
|
||||||
result.put("time", event.time())
|
result.put("time", event.time())
|
||||||
.put("type", event.type().toString())
|
.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;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user