From 34882a731dbe65c971c612b56e982b9ed12a090b Mon Sep 17 00:00:00 2001 From: Tony Tkacik Date: Thu, 4 Sep 2014 13:48:08 +0200 Subject: [PATCH] Bug 222: Added basic Restconf operational statistics Added basic restconf statistics which counts incoming requests and exported it via Config subsystem. Export via config subsystem provides this statistics via JMX and Netconf. In distribution, where sal-netconf-connector is present and 99-sal-netconf-connector.xml is enabled, Restconf statistics are also available via restconf/operational/opendaylight-inventory:nodes/node/controller-config/yang-ext:mount/config:modules/module/rest-connector-default-impl Change-Id: Ibd0fb6875104d1a90eeaf62271c9a2f87d2f85f0 Signed-off-by: Tony Tkacik --- .../rest/connector/RestConnectorModule.java | 6 +- .../sal/rest/impl/RestconfApplication.java | 3 +- .../sal/restconf/impl/RestconfImpl.java | 9 ++ .../impl/RestconfProviderImpl.java | 48 +++++- .../StatisticsRestconfServiceWrapper.java | 150 ++++++++++++++++++ .../yang/opendaylight-rest-connector.yang | 35 ++++ 6 files changed, 245 insertions(+), 6 deletions(-) rename opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/{rest => restconf}/impl/RestconfProviderImpl.java (60%) create mode 100644 opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/StatisticsRestconfServiceWrapper.java diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/rest/connector/RestConnectorModule.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/rest/connector/RestConnectorModule.java index 52115a8f32..821290eca2 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/rest/connector/RestConnectorModule.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/rest/connector/RestConnectorModule.java @@ -1,6 +1,6 @@ package org.opendaylight.controller.config.yang.md.sal.rest.connector; -import org.opendaylight.controller.sal.rest.impl.RestconfProviderImpl; +import org.opendaylight.controller.sal.restconf.impl.RestconfProviderImpl; public class RestConnectorModule extends org.opendaylight.controller.config.yang.md.sal.rest.connector.AbstractRestConnectorModule { @@ -26,6 +26,10 @@ public class RestConnectorModule extends org.opendaylight.controller.config.yang instance.setWebsocketPort(getWebsocketPort()); // Register it with the Broker getDomBrokerDependency().registerProvider(instance); + + + getRootRuntimeBeanRegistratorWrapper().register(instance); + return instance; } } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfApplication.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfApplication.java index a298f4b093..c9496af4c8 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfApplication.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfApplication.java @@ -14,6 +14,7 @@ import javax.ws.rs.core.Application; import org.opendaylight.controller.sal.restconf.impl.BrokerFacade; import org.opendaylight.controller.sal.restconf.impl.ControllerContext; import org.opendaylight.controller.sal.restconf.impl.RestconfImpl; +import org.opendaylight.controller.sal.restconf.impl.StatisticsRestconfServiceWrapper; public class RestconfApplication extends Application { @@ -38,7 +39,7 @@ public class RestconfApplication extends Application { restconfImpl.setControllerContext(controllerContext); singletons.add(controllerContext); singletons.add(brokerFacade); - singletons.add(restconfImpl); + singletons.add(StatisticsRestconfServiceWrapper.getInstance()); singletons.add(StructuredDataToXmlProvider.INSTANCE); singletons.add(StructuredDataToJsonProvider.INSTANCE); singletons.add(JsonToCompositeNodeProvider.INSTANCE); diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java index adad26e141..5d8c910afc 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java @@ -15,6 +15,7 @@ import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import java.math.BigInteger; import java.net.URI; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -85,6 +86,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RestconfImpl implements RestconfService { + private enum UriParameters { PRETTY_PRINT("prettyPrint"), DEPTH("depth"); @@ -101,6 +103,8 @@ public class RestconfImpl implements RestconfService { } } + + private final static RestconfImpl INSTANCE = new RestconfImpl(); private static final int NOTIFICATION_PORT = 8181; @@ -1550,4 +1554,9 @@ public class RestconfImpl implements RestconfService { } return false; } + + public BigInteger getOperationalReceived() { + // TODO Auto-generated method stub + return null; + } } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfProviderImpl.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfProviderImpl.java similarity index 60% rename from opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfProviderImpl.java rename to opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfProviderImpl.java index 2fa99819d5..c7c9cc0dc5 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfProviderImpl.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfProviderImpl.java @@ -5,27 +5,34 @@ * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.controller.sal.rest.impl; +package org.opendaylight.controller.sal.restconf.impl; +import java.math.BigInteger; import java.util.Collection; import java.util.Collections; +import org.opendaylight.controller.config.yang.md.sal.rest.connector.Config; +import org.opendaylight.controller.config.yang.md.sal.rest.connector.Get; +import org.opendaylight.controller.config.yang.md.sal.rest.connector.Operational; +import org.opendaylight.controller.config.yang.md.sal.rest.connector.Post; +import org.opendaylight.controller.config.yang.md.sal.rest.connector.Put; +import org.opendaylight.controller.config.yang.md.sal.rest.connector.RestConnectorRuntimeMXBean; +import org.opendaylight.controller.config.yang.md.sal.rest.connector.Rpcs; import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService; import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; import org.opendaylight.controller.sal.core.api.Provider; import org.opendaylight.controller.sal.core.api.model.SchemaService; import org.opendaylight.controller.sal.rest.api.RestConnector; -import org.opendaylight.controller.sal.restconf.impl.BrokerFacade; -import org.opendaylight.controller.sal.restconf.impl.ControllerContext; import org.opendaylight.controller.sal.streams.websockets.WebSocketServer; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber; import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.model.api.SchemaContextListener; -public class RestconfProviderImpl implements Provider, AutoCloseable, RestConnector { +public class RestconfProviderImpl implements Provider, AutoCloseable, RestConnector, RestConnectorRuntimeMXBean { public final static String NOT_INITALIZED_MSG = "Restconf is not initialized yet. Please try again later"; + private final StatisticsRestconfServiceWrapper stats = StatisticsRestconfServiceWrapper.getInstance(); private ListenerRegistration listenerRegistration; private PortNumber port; public void setWebsocketPort(PortNumber port) { @@ -63,4 +70,37 @@ public class RestconfProviderImpl implements Provider, AutoCloseable, RestConnec } webSocketServerThread.interrupt(); } + + @Override + public Config getConfig() { + Config config = new Config(); + Get get = new Get(); + get.setReceivedRequests(stats.getConfigGet()); + config.setGet(get); + Post post = new Post(); + post.setReceivedRequests(stats.getConfigPost()); + config.setPost(post); + Put put = new Put(); + put.setReceivedRequests(stats.getConfigPut()); + config.setPut(put); + return config; + } + + @Override + public Operational getOperational() { + BigInteger opGet = stats.getOperationalGet(); + Operational operational = new Operational(); + Get get = new Get(); + get.setReceivedRequests(opGet); + operational.setGet(get); + return operational; + } + + @Override + public Rpcs getRpcs() { + BigInteger rpcInvoke = stats.getRpc(); + Rpcs rpcs = new Rpcs(); + rpcs.setReceivedRequests(rpcInvoke); + return rpcs ; + } } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/StatisticsRestconfServiceWrapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/StatisticsRestconfServiceWrapper.java new file mode 100644 index 0000000000..eafbb81c48 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/StatisticsRestconfServiceWrapper.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.restconf.impl; + +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicLong; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import org.opendaylight.controller.sal.rest.api.RestconfService; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.Node; + +public class StatisticsRestconfServiceWrapper implements RestconfService { + + AtomicLong operationalGet = new AtomicLong(); + AtomicLong configGet = new AtomicLong(); + AtomicLong rpc = new AtomicLong(); + AtomicLong configPost = new AtomicLong(); + AtomicLong configPut = new AtomicLong(); + AtomicLong configDelete = new AtomicLong(); + + private static final StatisticsRestconfServiceWrapper INSTANCE = new StatisticsRestconfServiceWrapper(RestconfImpl.getInstance()); + + final RestconfService delegate; + + private StatisticsRestconfServiceWrapper(RestconfService delegate) { + this.delegate = delegate; + } + + public static StatisticsRestconfServiceWrapper getInstance() { + return INSTANCE; + } + + @Override + public Object getRoot() { + return delegate.getRoot(); + } + + @Override + public StructuredData getModules(UriInfo uriInfo) { + return delegate.getModules(uriInfo); + } + + @Override + public StructuredData getModules(String identifier, UriInfo uriInfo) { + return delegate.getModules(identifier, uriInfo); + } + + @Override + public StructuredData getModule(String identifier, UriInfo uriInfo) { + return delegate.getModule(identifier, uriInfo); + } + + @Override + public StructuredData getOperations(UriInfo uriInfo) { + return delegate.getOperations(uriInfo); + } + + @Override + public StructuredData getOperations(String identifier, UriInfo uriInfo) { + return delegate.getOperations(identifier, uriInfo); + } + + @Override + public StructuredData invokeRpc(String identifier, CompositeNode payload, UriInfo uriInfo) { + rpc.incrementAndGet(); + return delegate.invokeRpc(identifier, payload, uriInfo); + } + + @Override + public StructuredData invokeRpc(String identifier, String noPayload, UriInfo uriInfo) { + rpc.incrementAndGet(); + return delegate.invokeRpc(identifier, noPayload, uriInfo); + } + + @Override + public NormalizedNodeContext readConfigurationData(String identifier, UriInfo uriInfo) { + configGet.incrementAndGet(); + return delegate.readConfigurationData(identifier, uriInfo); + } + + @Override + public NormalizedNodeContext readOperationalData(String identifier, UriInfo uriInfo) { + operationalGet.incrementAndGet(); + return delegate.readOperationalData(identifier, uriInfo); + } + + @Override + public Response updateConfigurationData(String identifier, Node payload) { + configPut.incrementAndGet(); + return delegate.updateConfigurationData(identifier, payload); + } + + @Override + public Response createConfigurationData(String identifier, Node payload) { + configPost.incrementAndGet(); + return delegate.createConfigurationData(identifier, payload); + } + + @Override + public Response createConfigurationData(Node payload) { + configPost.incrementAndGet(); + return delegate.createConfigurationData(payload); + } + + @Override + public Response deleteConfigurationData(String identifier) { + return delegate.deleteConfigurationData(identifier); + } + + @Override + public Response subscribeToStream(String identifier, UriInfo uriInfo) { + return delegate.subscribeToStream(identifier, uriInfo); + } + + @Override + public StructuredData getAvailableStreams(UriInfo uriInfo) { + return delegate.getAvailableStreams(uriInfo); + } + + public BigInteger getConfigDelete() { + return BigInteger.valueOf(configDelete.get()); + } + + public BigInteger getConfigGet() { + return BigInteger.valueOf(configGet.get()); + } + + public BigInteger getConfigPost() { + return BigInteger.valueOf(configPost.get()); + } + + public BigInteger getConfigPut() { + return BigInteger.valueOf(configPut.get()); + } + + public BigInteger getOperationalGet() { + return BigInteger.valueOf(operationalGet.get()); + } + + public BigInteger getRpc() { + return BigInteger.valueOf(rpc.get()); + } + +} diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/yang/opendaylight-rest-connector.yang b/opendaylight/md-sal/sal-rest-connector/src/main/yang/opendaylight-rest-connector.yang index a8fc8ff4d5..6d2add6ff1 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/yang/opendaylight-rest-connector.yang +++ b/opendaylight/md-sal/sal-rest-connector/src/main/yang/opendaylight-rest-connector.yang @@ -27,6 +27,12 @@ module opendaylight-rest-connector { config:java-name-prefix RestConnector; } + grouping statistics { + leaf received-requests { + type uint64; + } + } + augment "/config:modules/config:module/config:configuration" { case rest-connector-impl { when "/config:modules/config:module/config:type = 'rest-connector-impl'"; @@ -44,4 +50,33 @@ module opendaylight-rest-connector { } } } + + augment "/config:modules/config:module/config:state" { + case rest-connector-impl { + when "/config:modules/config:module/config:type = 'rest-connector-impl'"; + container rpcs { + uses statistics; + } + + container config { + container get { + uses statistics; + } + + container post { + uses statistics; + } + + container put { + uses statistics; + } + } + + container operational { + container get { + uses statistics; + } + } + } + } } \ No newline at end of file -- 2.36.6