You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:26:06 UTC

[sling-org-apache-sling-commons-threads] 17/27: SLING-2564 - adding JMX monitoring of Sling Thread Pools

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.commons.threads-3.2.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-threads.git

commit 606bc12b8e7027eec074fc754fe0f38aeaa7d2b4
Author: Justin Edelson <ju...@apache.org>
AuthorDate: Thu Oct 18 21:53:20 2012 +0000

    SLING-2564 - adding JMX monitoring of Sling Thread Pools
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/threads@1399878 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |   3 +-
 .../threads/impl/DefaultThreadPoolManager.java     |  64 +++++++--
 .../commons/threads/impl/ThreadPoolMBeanImpl.java  | 147 +++++++++++++++++++
 .../sling/commons/threads/jmx/ThreadPoolMBean.java | 159 +++++++++++++++++++++
 4 files changed, 364 insertions(+), 9 deletions(-)

diff --git a/pom.xml b/pom.xml
index b9e5d2a..3b69b95 100644
--- a/pom.xml
+++ b/pom.xml
@@ -58,7 +58,8 @@
                             org.apache.sling.commons.threads.impl.Activator
                         </Bundle-Activator>
                         <Export-Package>
-                            org.apache.sling.commons.threads;version=3.2.0
+                            org.apache.sling.commons.threads;version=3.2.0,
+                            org.apache.sling.commons.threads.jmx;version=1.0.0
                         </Export-Package>
                         <Private-Package>
                             org.apache.sling.commons.threads.impl
diff --git a/src/main/java/org/apache/sling/commons/threads/impl/DefaultThreadPoolManager.java b/src/main/java/org/apache/sling/commons/threads/impl/DefaultThreadPoolManager.java
index ee86399..331d668 100644
--- a/src/main/java/org/apache/sling/commons/threads/impl/DefaultThreadPoolManager.java
+++ b/src/main/java/org/apache/sling/commons/threads/impl/DefaultThreadPoolManager.java
@@ -18,6 +18,7 @@ package org.apache.sling.commons.threads.impl;
 
 import java.util.Dictionary;
 import java.util.HashMap;
+import java.util.Hashtable;
 import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.ThreadPoolExecutor;
@@ -28,8 +29,10 @@ import org.apache.sling.commons.threads.ThreadPoolConfig;
 import org.apache.sling.commons.threads.ThreadPoolConfig.ThreadPoolPolicy;
 import org.apache.sling.commons.threads.ThreadPoolConfig.ThreadPriority;
 import org.apache.sling.commons.threads.ThreadPoolManager;
+import org.apache.sling.commons.threads.jmx.ThreadPoolMBean;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.cm.ManagedServiceFactory;
 import org.slf4j.Logger;
@@ -69,12 +72,15 @@ public class DefaultThreadPoolManager
     public void destroy() {
         this.logger.debug("Disposing all thread pools");
 
+        final Map<String, Entry> localCopy = new HashMap<String, Entry>(this.pools.size());
         synchronized ( this.pools ) {
-            for (final Entry entry : this.pools.values()) {
-                entry.shutdown();
-            }
+            localCopy.putAll(this.pools);
             this.pools.clear();
         }
+        for (final Entry entry : localCopy.values()) {
+            entry.unregisterMBean();
+            entry.shutdown();
+        }
         this.logger.info("Stopped Apache Sling Thread Pool Manager");
     }
 
@@ -119,17 +125,22 @@ public class DefaultThreadPoolManager
     public ThreadPool get(final String name) {
         final String poolName = (name == null ? DEFAULT_THREADPOOL_NAME : name);
         Entry entry = null;
+        boolean created = false;
         synchronized (this.pools) {
             entry = this.pools.get(poolName);
             if ( entry == null ) {
                 this.logger.debug("Creating new pool with name {}", poolName);
                 final ModifiableThreadPoolConfig config = new ModifiableThreadPoolConfig();
-                entry = new Entry(null, config, poolName);
+                entry = new Entry(null, config, poolName, bundleContext);
+                created = true;
 
                 this.pools.put(poolName, entry);
             }
-            return entry.incUsage();
         }
+        if (created) {
+            entry.registerMBean();
+        }
+        return entry.incUsage();
     }
 
     /**
@@ -137,15 +148,20 @@ public class DefaultThreadPoolManager
      */
     public void release(ThreadPool pool) {
         if ( pool instanceof ThreadPoolFacade ) {
+            Entry removedEntry = null;
             synchronized ( this.pools ) {
                 final Entry entry = this.pools.get(pool.getName());
                 if ( entry != null ) {
                     entry.decUsage();
                     if ( !entry.isUsed() ) {
+                        removedEntry = entry;
                         this.pools.remove(pool.getName());
                     }
                 }
             }
+            if ( removedEntry != null ) {
+                removedEntry.unregisterMBean();
+            }
         }
 
     }
@@ -176,10 +192,11 @@ public class DefaultThreadPoolManager
 
         final String name = "ThreadPool-" + UUID.randomUUID().toString() +
              (label == null ? "" : " (" + label + ")");
-        final Entry entry = new Entry(null, config, name);
+        final Entry entry = new Entry(null, config, name, bundleContext);
         synchronized ( this.pools ) {
             this.pools.put(name, entry);
         }
+        entry.registerMBean();
         return entry.incUsage();
     }
 
@@ -210,6 +227,7 @@ public class DefaultThreadPoolManager
             throw new ConfigurationException(ModifiableThreadPoolConfig.PROPERTY_NAME, "Property is missing or empty.");
         }
         this.logger.debug("Updating {} with {}", pid, properties);
+        Entry createdEntry = null;
         synchronized ( this.pools ) {
             final ThreadPoolConfig config = this.createConfig(properties);
 
@@ -241,9 +259,13 @@ public class DefaultThreadPoolManager
                 foundEntry.update(config, name, pid);
             } else {
                 // create
-                this.pools.put(name, new Entry(pid, config, name));
+                createdEntry = new Entry(pid, config, name, bundleContext);
+                this.pools.put(name, createdEntry);
             }
         }
+        if ( createdEntry != null ) {
+            createdEntry.registerMBean(); 
+        }
     }
 
     /**
@@ -275,6 +297,8 @@ public class DefaultThreadPoolManager
     }
 
     protected static final class Entry {
+        private static final Logger logger = LoggerFactory.getLogger(Entry.class);
+
         /** The configuration pid. (might be null for anonymous pools.*/
         private volatile String pid;
 
@@ -290,10 +314,15 @@ public class DefaultThreadPoolManager
         /** The corresponding pool - might be null if unused. */
         private volatile ThreadPoolFacade pool;
 
-        public Entry(final String pid, final ThreadPoolConfig config, final String name) {
+        private ServiceRegistration mbeanRegistration;
+
+        private BundleContext bundleContext;
+
+        public Entry(final String pid, final ThreadPoolConfig config, final String name, final BundleContext bundleContext) {
             this.pid = pid;
             this.config = config;
             this.name = name;
+            this.bundleContext = bundleContext;
         }
 
         public String getPid() {
@@ -352,5 +381,24 @@ public class DefaultThreadPoolManager
             }
             return null;
         }
+
+        protected void unregisterMBean() {
+            if ( this.mbeanRegistration != null ) {
+                this.mbeanRegistration.unregister();
+                this.mbeanRegistration = null;
+            }
+        }
+
+        protected void registerMBean() {
+            try {
+                final Dictionary<String, String> mbeanProps = new Hashtable<String, String>();
+                mbeanProps.put("jmx.objectname", "org.apache.sling:type=threads,service=ThreadPool,name=" + this.name);
+
+                final ThreadPoolMBeanImpl mbean = new ThreadPoolMBeanImpl(this);
+                this.mbeanRegistration = bundleContext.registerService(ThreadPoolMBean.class.getName(), mbean, mbeanProps);
+            } catch (Throwable t) {
+                logger.warn("Unable to register Thread Pool MBean", t);
+            }
+        }
     }
 }
diff --git a/src/main/java/org/apache/sling/commons/threads/impl/ThreadPoolMBeanImpl.java b/src/main/java/org/apache/sling/commons/threads/impl/ThreadPoolMBeanImpl.java
new file mode 100644
index 0000000..fe96b97
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/threads/impl/ThreadPoolMBeanImpl.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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.apache.sling.commons.threads.impl;
+
+import java.util.concurrent.ThreadPoolExecutor;
+
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+
+import org.apache.sling.commons.threads.impl.DefaultThreadPoolManager.Entry;
+import org.apache.sling.commons.threads.jmx.ThreadPoolMBean;
+
+class ThreadPoolMBeanImpl extends StandardMBean implements ThreadPoolMBean {
+    
+    private final Entry entry;
+
+    ThreadPoolMBeanImpl(Entry entry) throws NotCompliantMBeanException {
+        super(ThreadPoolMBean.class);
+        this.entry = entry;
+    }
+
+    public String getBlockPolicy() {
+        return this.entry.getConfig().getBlockPolicy().name();
+    }
+
+    public int getExecutorActiveCount() {
+        final ThreadPoolExecutor tpe = this.entry.getExecutor();
+        if ( tpe != null ) {
+            return tpe.getActiveCount();
+        } else {
+            return -1;
+        }
+    }
+
+    public long getExecutorCompletedTaskCount() {
+        final ThreadPoolExecutor tpe = this.entry.getExecutor();
+        if ( tpe != null ) {
+            return tpe.getCompletedTaskCount();
+        } else {
+            return -1;
+        }
+    }
+
+    public int getExecutorCorePoolSize() {
+        final ThreadPoolExecutor tpe = this.entry.getExecutor();
+        if ( tpe != null ) {
+            return tpe.getCorePoolSize();
+        } else {
+            return -1;
+        }
+    }
+
+    public int getExecutorLargestPoolSize() {
+        final ThreadPoolExecutor tpe = this.entry.getExecutor();
+        if ( tpe != null ) {
+            return tpe.getLargestPoolSize();
+        } else {
+            return -1;
+        }
+    }
+
+    public int getExecutorMaximumPoolSize() {
+        final ThreadPoolExecutor tpe = this.entry.getExecutor();
+        if ( tpe != null ) {
+            return tpe.getMaximumPoolSize();
+        } else {
+            return -1;
+        }
+    }
+
+    public int getExecutorPoolSize() {
+        final ThreadPoolExecutor tpe = this.entry.getExecutor();
+        if ( tpe != null ) {
+            return tpe.getPoolSize();
+        } else {
+            return -1;
+        }
+    }
+
+    public long getExecutorTaskCount() {
+        final ThreadPoolExecutor tpe = this.entry.getExecutor();
+        if ( tpe != null ) {
+            return tpe.getTaskCount();
+        } else {
+            return -1;
+        }
+    }
+
+    public long getKeepAliveTime() {
+        return this.entry.getConfig().getKeepAliveTime();
+    }
+
+    public int getMaxPoolSize() {
+        return this.entry.getConfig().getMaxPoolSize();
+    }
+
+    public int getMinPoolSize() {
+        return this.entry.getConfig().getMinPoolSize();
+    }
+
+    public String getName() {
+        return this.entry.getName();
+    }
+
+    public String getPid() {
+        return this.entry.getPid();
+    }
+
+    public String getPriority() {
+        return this.entry.getConfig().getPriority().name();
+    }
+
+    public int getQueueSize() {
+        return this.entry.getConfig().getQueueSize();
+    }
+
+    public int getShutdownWaitTimeMs() {
+        return this.entry.getConfig().getShutdownWaitTimeMs();
+    }
+
+    public boolean isDaemon() {
+        return this.entry.getConfig().isDaemon();
+    }
+
+    public boolean isShutdownGraceful() {
+        return this.entry.getConfig().isShutdownGraceful();
+    }
+
+    public boolean isUsed() {
+        return this.entry.isUsed();
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/commons/threads/jmx/ThreadPoolMBean.java b/src/main/java/org/apache/sling/commons/threads/jmx/ThreadPoolMBean.java
new file mode 100644
index 0000000..bdee6b3
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/threads/jmx/ThreadPoolMBean.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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.apache.sling.commons.threads.jmx;
+
+/**
+ * This is the management interface for a Sling Thread Pool.
+ */
+public interface ThreadPoolMBean {
+
+    /**
+     * Retrieve the block policy of the thread pool.
+     * 
+     * @return the block policy
+     */
+    String getBlockPolicy();
+
+    /**
+     * Retrieve the active count from the pool's Executor.
+     * 
+     * @return the active count or -1 if the thread pool does not have an Executor
+     */
+    int getExecutorActiveCount();
+
+    /**
+     * Retrieve the completed task count from the pool's Executor.
+     * 
+     * @return the completed task count or -1 if the thread pool does not have an Executor
+     */
+    long getExecutorCompletedTaskCount();
+
+    /**
+     * Retrieve the core pool size from the pool's Executor.
+     * 
+     * @return the core pool size or -1 if the thread pool does not have an Executor
+     */
+    int getExecutorCorePoolSize();
+
+    /**
+     * Retrieve the largest pool size from the pool's Executor.
+     * 
+     * @return the largest pool size or -1 if the thread pool does not have an Executor
+     */
+    int getExecutorLargestPoolSize();
+
+    /**
+     * Retrieve the maximum pool size from the pool's Executor.
+     * 
+     * @return the maximum pool size or -1 if the thread pool does not have an Executor
+     */
+    int getExecutorMaximumPoolSize();
+
+
+    /**
+     * Retrieve the pool size from the pool's Executor.
+     * 
+     * @return the pool size or -1 if the thread pool does not have an Executor
+     */
+    int getExecutorPoolSize();
+
+
+    /**
+     * Retrieve the task count from the pool's Executor.
+     * 
+     * @return the task count or -1 if the thread pool does not have an Executor
+     */
+    long getExecutorTaskCount();
+
+    /**
+     * Return the configured keep alive time.
+     * 
+     * @return The configured keep alive time.
+     */
+    long getKeepAliveTime();
+
+    /**
+     * Return the configured maximum pool size.
+     * 
+     * @return The configured maximum pool size.
+     */
+    int getMaxPoolSize();
+
+    /**
+     * Return the minimum pool size.
+     * 
+     * @return The minimum pool size.
+     */
+    int getMinPoolSize();
+
+    /**
+     * Return the name of the thread pool
+     * 
+     * @return the name
+     */
+    String getName();
+
+    /**
+     * Return the configuration pid of the thread pool.
+     * 
+     * @return the pid
+     */
+    String getPid();
+
+    /**
+     * Return the configured priority of the thread pool.
+     * 
+     * @return the priority
+     */
+    String getPriority();
+
+    /**
+     * Return the configured queue size.
+     * 
+     * @return The configured queue size.
+     */
+    int getQueueSize();
+
+    /**
+     * Return the configured shutdown wait time in milliseconds.
+     * 
+     * @return The configured shutdown wait time.
+     */
+    int getShutdownWaitTimeMs();
+
+    /**
+     * Return whether or not the thread pool creates daemon threads.
+     * 
+     * @return The daemon configuration.
+     */
+    boolean isDaemon();
+
+    /**
+     * Return whether or not the thread pool is configured to shutdown gracefully.
+     * 
+     * @return The graceful shutdown configuration.
+     */
+    boolean isShutdownGraceful();
+
+    /**
+     * Return whether or not the thread pool is in use.
+     * 
+     * @return The used state of the pool.
+     */
+    boolean isUsed();
+
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.