Shared system timer and executor services - monitoring
Change-Id: Ieaa889447dbcb78e4d27fe7409fae463177372b8
diff --git a/core/net/src/main/java/org/onosproject/core/impl/CoreManager.java b/core/net/src/main/java/org/onosproject/core/impl/CoreManager.java
index a40ded6..eae8cf6 100644
--- a/core/net/src/main/java/org/onosproject/core/impl/CoreManager.java
+++ b/core/net/src/main/java/org/onosproject/core/impl/CoreManager.java
@@ -23,6 +23,7 @@
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
+import org.onlab.metrics.MetricsService;
import org.onlab.util.SharedExecutors;
import org.onosproject.app.ApplicationService;
import org.onosproject.cfg.ComponentConfigService;
@@ -80,6 +81,9 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected EventDeliveryService eventDeliveryService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected MetricsService metricsService;
+
private static final int DEFAULT_POOL_SIZE = 30;
@Property(name = "sharedThreadPoolSize", intValue = DEFAULT_POOL_SIZE,
label = "Configure shared pool maximum size ")
@@ -90,6 +94,12 @@
label = "Maximum number of millis an event sink has to process an event")
private int maxEventTimeLimit = DEFAULT_EVENT_TIME;
+ private static final boolean DEFAULT_PERFORMANCE_CHECK = false;
+ @Property(name = "sharedThreadPerformanceCheck", boolValue = DEFAULT_PERFORMANCE_CHECK,
+ label = "Enable queue performance check on shared pool")
+ private boolean calculatePoolPerformance = DEFAULT_PERFORMANCE_CHECK;
+
+
@Activate
public void activate() {
registerApplication(CORE_APP_NAME);
@@ -177,8 +187,14 @@
log.warn("maxEventTimeLimit must be greater than 1");
}
- log.info("Settings: sharedThreadPoolSize={}, maxEventTimeLimit={}",
- sharedThreadPoolSize, maxEventTimeLimit);
+ Boolean performanceCheck = isPropertyEnabled(properties, "sharedThreadPerformanceCheck");
+ if (performanceCheck != null) {
+ calculatePoolPerformance = performanceCheck;
+ SharedExecutors.setCalculatePoolPerformance(calculatePoolPerformance, metricsService);
+ }
+
+ log.info("Settings: sharedThreadPoolSize={}, maxEventTimeLimit={}, calculatePoolPerformance={}",
+ sharedThreadPoolSize, maxEventTimeLimit, calculatePoolPerformance);
}
@@ -202,5 +218,26 @@
return value;
}
+ /**
+ * Check property name is defined and set to true.
+ *
+ * @param properties properties to be looked up
+ * @param propertyName the name of the property to look up
+ * @return value when the propertyName is defined or return null
+ */
+ private static Boolean isPropertyEnabled(Dictionary<?, ?> properties,
+ String propertyName) {
+ Boolean value = null;
+ try {
+ String s = (String) properties.get(propertyName);
+ value = isNullOrEmpty(s) ? null : s.trim().equals("true");
+ } catch (ClassCastException e) {
+ // No propertyName defined.
+ value = null;
+ }
+ return value;
+ }
+
+
}
diff --git a/utils/misc/src/main/java/org/onlab/util/SharedExecutorService.java b/utils/misc/src/main/java/org/onlab/util/SharedExecutorService.java
index 051155c..d3c4534 100644
--- a/utils/misc/src/main/java/org/onlab/util/SharedExecutorService.java
+++ b/utils/misc/src/main/java/org/onlab/util/SharedExecutorService.java
@@ -15,6 +15,10 @@
*/
package org.onlab.util;
+import org.onlab.metrics.MetricsComponent;
+import org.onlab.metrics.MetricsFeature;
+import org.onlab.metrics.MetricsService;
+
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
@@ -23,6 +27,9 @@
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import com.codahale.metrics.Timer;
+
+
/**
* Executor service wrapper for shared executors with safeguards on shutdown
@@ -34,6 +41,13 @@
private ExecutorService executor;
+ private MetricsService metricsService = null;
+
+ private MetricsComponent executorMetrics;
+ private Timer queueMetrics = null;
+ private Timer delayMetrics = null;
+
+
/**
* Creates a wrapper for the given executor service.
*
@@ -63,6 +77,7 @@
oldExecutor.shutdown();
}
+
@Override
public void shutdown() {
throw new UnsupportedOperationException(NOT_ALLOWED);
@@ -91,7 +106,31 @@
@Override
public <T> Future<T> submit(Callable<T> task) {
- return executor.submit(task);
+ Counter taskCounter = new Counter();
+ taskCounter.reset();
+ return executor.submit(() -> {
+ T t = null;
+ long queueWaitTime = (long) taskCounter.duration();
+ String className;
+ if (task instanceof CallableExtended) {
+ className = ((CallableExtended) task).getRunnable().getClass().toString();
+ } else {
+ className = task.getClass().toString();
+ }
+ if (queueMetrics != null) {
+ queueMetrics.update(queueWaitTime, TimeUnit.SECONDS);
+ }
+ taskCounter.reset();
+ try {
+ t = task.call();
+ } catch (Exception e) { }
+ long taskwaittime = (long) taskCounter.duration();
+ if (delayMetrics != null) {
+ delayMetrics.update(taskwaittime, TimeUnit.SECONDS);
+ }
+ return t;
+ }
+ );
}
@Override
@@ -135,4 +174,47 @@
executor.execute(command);
}
+ public void setCalculatePoolPerformance(boolean calculatePoolPerformance, MetricsService metricsSrv) {
+ this.metricsService = metricsSrv;
+ if (calculatePoolPerformance) {
+ if (metricsService != null) {
+ executorMetrics = metricsService.registerComponent("SharedExecutor");
+ MetricsFeature mf = executorMetrics.registerFeature("*");
+ queueMetrics = metricsService.createTimer(executorMetrics, mf, "Queue");
+ delayMetrics = metricsService.createTimer(executorMetrics, mf, "Delay");
+ }
+ } else {
+ metricsService = null;
+ queueMetrics = null;
+ delayMetrics = null;
+ }
+ }
+
+ /**
+ * CallableExtended class is used to get Runnable Object
+ * from Callable Object.
+ *
+ */
+ class CallableExtended implements Callable {
+
+ private Runnable runnable;
+
+ /**
+ * Wrapper for Callable object .
+ * @param runnable Runnable object
+ */
+ public CallableExtended(Runnable runnable) {
+ this.runnable = runnable;
+ }
+ public Runnable getRunnable() {
+ return runnable;
+ }
+
+ @Override
+ public Object call() throws Exception {
+ runnable.run();
+ return null;
+ }
+ }
+
}
diff --git a/utils/misc/src/main/java/org/onlab/util/SharedExecutors.java b/utils/misc/src/main/java/org/onlab/util/SharedExecutors.java
index 0dadce8..b3e4879 100644
--- a/utils/misc/src/main/java/org/onlab/util/SharedExecutors.java
+++ b/utils/misc/src/main/java/org/onlab/util/SharedExecutors.java
@@ -16,6 +16,8 @@
package org.onlab.util;
+import org.onlab.metrics.MetricsService;
+
import java.util.Timer;
import java.util.concurrent.ExecutorService;
@@ -93,6 +95,11 @@
"onos-pool-executor-%d")));
}
+
+ public static void setCalculatePoolPerformance(boolean calculatePoolPerformance, MetricsService metricsService) {
+ poolThreadExecutor.setCalculatePoolPerformance(calculatePoolPerformance, metricsService);
+ }
+
/**
* Shuts down all shared timers and executors and therefore should be
* called only by the framework.