Bug 222: Added basic Restconf operational statistics 62/10762/2
authorTony Tkacik <ttkacik@cisco.com>
Thu, 4 Sep 2014 11:48:08 +0000 (13:48 +0200)
committerTony Tkacik <ttkacik@cisco.com>
Thu, 4 Sep 2014 15:16:17 +0000 (15:16 +0000)
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 <ttkacik@cisco.com>
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/rest/connector/RestConnectorModule.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfApplication.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfProviderImpl.java [moved from opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfProviderImpl.java with 60% similarity]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/StatisticsRestconfServiceWrapper.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/yang/opendaylight-rest-connector.yang

index 52115a8..821290e 100644 (file)
@@ -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;
     }
 }
index a298f4b..c9496af 100644 (file)
@@ -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);
index adad26e..5d8c910 100644 (file)
@@ -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;
+    }
 }
@@ -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<SchemaContextListener> 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 (file)
index 0000000..eafbb81
--- /dev/null
@@ -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());
+    }
+
+}
index a8fc8ff..6d2add6 100644 (file)
@@ -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