/* * Copyright 2015-present Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onosproject.intentperf; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; 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.osgi.ServiceDirectory; import org.onosproject.intentperf.IntentPerfCollector.Sample; import org.onosproject.ui.RequestHandler; import org.onosproject.ui.UiConnection; import org.onosproject.ui.UiExtension; import org.onosproject.ui.UiExtensionService; import org.onosproject.ui.UiMessageHandler; import org.onosproject.ui.UiView; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import static java.util.Collections.synchronizedSet; import static org.onosproject.ui.UiView.Category.OTHER; /** * Mechanism to stream data to the GUI. */ @Component(immediate = true, enabled = true) @Service(value = IntentPerfUi.class) public class IntentPerfUi { private static final String INTENT_PERF_START = "intentPerfStart"; private static final String INTENT_PERF_STOP = "intentPerfStop"; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected UiExtensionService uiExtensionService; private final Set<StreamingControl> handlers = synchronizedSet(new HashSet<>()); private List<UiView> views = ImmutableList.of( new UiView(OTHER, "intentPerf", "Intent Performance") ); private UiExtension uiExtension = new UiExtension.Builder(getClass().getClassLoader(), views) .messageHandlerFactory(this::newHandlers) .build(); private IntentPerfCollector collector; @Activate protected void activate() { uiExtensionService.register(uiExtension); } @Deactivate protected void deactivate() { uiExtensionService.unregister(uiExtension); } /** * Reports a single sample of performance data. * * @param sample performance sample */ public void reportSample(Sample sample) { synchronized (handlers) { handlers.forEach(h -> h.send(sample)); } } /** * Binds the sample collector. * * @param collector list of headers for future samples */ public void setCollector(IntentPerfCollector collector) { this.collector = collector; } // Creates and returns session specific message handler. private Collection<UiMessageHandler> newHandlers() { return ImmutableList.of(new StreamingControl()); } // UI Message handlers for turning on/off reporting to a session. private class StreamingControl extends UiMessageHandler { private boolean streamingEnabled = false; @Override protected Collection<RequestHandler> createRequestHandlers() { return ImmutableSet.of( new IntentPerfStart(), new IntentPerfStop() ); } @Override public void init(UiConnection connection, ServiceDirectory directory) { super.init(connection, directory); handlers.add(this); } @Override public void destroy() { super.destroy(); handlers.remove(this); } private void send(Sample sample) { if (streamingEnabled) { connection().sendMessage("intentPerfSample", sampleNode(sample)); } } private ObjectNode sampleNode(Sample sample) { ObjectNode sampleNode = objectNode(); ArrayNode an = arrayNode(); sampleNode.put("time", sample.time); sampleNode.set("data", an); for (double d : sample.data) { an.add(d); } return sampleNode; } // ====================================================================== private final class IntentPerfStart extends RequestHandler { private IntentPerfStart() { super(INTENT_PERF_START); } @Override public void process(ObjectNode payload) { streamingEnabled = true; sendInitData(); } private void sendInitData() { ObjectNode rootNode = MAPPER.createObjectNode(); ArrayNode an = MAPPER.createArrayNode(); ArrayNode sn = MAPPER.createArrayNode(); rootNode.set("headers", an); rootNode.set("samples", sn); collector.getSampleHeaders().forEach(an::add); collector.getSamples().forEach(s -> sn.add(sampleNode(s))); sendMessage("intentPerfInit", rootNode); } } // ====================================================================== private final class IntentPerfStop extends RequestHandler { private IntentPerfStop() { super(INTENT_PERF_STOP); } @Override public void process(ObjectNode payload) { streamingEnabled = false; } } } }