]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10112 add MBean to monitor queue and workers of AsyncExecution
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Wed, 22 Nov 2017 15:34:08 +0000 (16:34 +0100)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Fri, 24 Nov 2017 08:23:58 +0000 (09:23 +0100)
server/sonar-ce/src/test/java/org/sonar/ce/async/SynchronousAsyncExecutionTest.java
server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CeTasksMBeanImplTest.java
server/sonar-server/src/main/java/org/sonar/server/async/AsyncExecutionExecutorServiceImpl.java
server/sonar-server/src/main/java/org/sonar/server/async/AsyncExecutionMBean.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/async/AsyncExecutionMBeanImpl.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/async/AsyncExecutionModule.java
server/sonar-server/src/main/java/org/sonar/server/async/AsyncExecutionMonitoring.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/async/AsyncExecutionMBeanImplTest.java [new file with mode: 0644]

index 57f0a7163df6e3b61b37ac9dd9130d29093911e3..a8c6c4ee972a7e043b57c5aac03afc80325a8c8c 100644 (file)
@@ -1,3 +1,22 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
 package org.sonar.ce.async;
 
 import java.util.HashSet;
index c161c86d5a8438cab1a11b37ad665a8f5d207157..da5997c3f0074270f5ac1f880315df7f693c2df2 100644 (file)
@@ -52,6 +52,19 @@ public class CeTasksMBeanImplTest {
     assertThat(getMBean()).isNull();
   }
 
+  /**
+   * Dumb implementation of CEQueueStatus which returns constant values for get methods and throws UnsupportedOperationException
+   * for other methods.
+   */
+  @CheckForNull
+  private ObjectInstance getMBean() throws Exception {
+    try {
+      return ManagementFactory.getPlatformMBeanServer().getObjectInstance(new ObjectName(CeTasksMBean.OBJECT_NAME));
+    } catch (InstanceNotFoundException e) {
+      return null;
+    }
+  }
+
   @Test
   public void get_methods_delegate_to_the_CEQueueStatus_instance() {
     assertThat(underTest.getPendingCount()).isEqualTo(PENDING_COUNT);
@@ -77,13 +90,9 @@ public class CeTasksMBeanImplTest {
     assertThat(section.getName()).isEqualTo("Compute Engine Tasks");
     assertThat(section.getAttributesCount()).isEqualTo(7);
   }
-
-  /**
-   * Dumb implementation of CEQueueStatus which returns constant values for get methods and throws UnsupportedOperationException
-   * for other methods.
-   */
   private static class DumbCEQueueStatus implements CEQueueStatus {
 
+
     @Override
     public long getPendingCount() {
       return PENDING_COUNT;
@@ -123,13 +132,13 @@ public class CeTasksMBeanImplTest {
     public long getProcessingTime() {
       return PROCESSING_TIME;
     }
-
     private long methodNotImplemented() {
       throw new UnsupportedOperationException("Not Implemented");
     }
-  }
 
+  }
   private static class DumbCeConfiguration implements CeConfiguration {
+
     @Override
     public void refresh() {
       throw new UnsupportedOperationException("Refresh is not implemented");
@@ -166,13 +175,4 @@ public class CeTasksMBeanImplTest {
     }
 
   }
-
-  @CheckForNull
-  private ObjectInstance getMBean() throws Exception {
-    try {
-      return ManagementFactory.getPlatformMBeanServer().getObjectInstance(new ObjectName(CeTasksMBean.OBJECT_NAME));
-    } catch (InstanceNotFoundException e) {
-      return null;
-    }
-  }
 }
index 60c87fc9fa6b3e3312e37307687fcc6f91b47647..f329d52ec4029d72444950161273ee30f40e5ab5 100644 (file)
@@ -20,7 +20,6 @@
 package org.sonar.server.async;
 
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
-import java.util.concurrent.ExecutorService;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
 import org.sonar.api.utils.log.Logger;
@@ -30,8 +29,8 @@ import org.sonar.server.util.AbstractStoppableExecutorService;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
 public class AsyncExecutionExecutorServiceImpl
-  extends AbstractStoppableExecutorService<ExecutorService>
-  implements AsyncExecutionExecutorService {
+  extends AbstractStoppableExecutorService<ThreadPoolExecutor>
+  implements AsyncExecutionExecutorService, AsyncExecutionMonitoring {
   private static final Logger LOG = Loggers.get(AsyncExecutionExecutorServiceImpl.class);
 
   private static final int MIN_THREAD_COUNT = 1;
@@ -56,4 +55,19 @@ public class AsyncExecutionExecutorServiceImpl
   public void addToQueue(Runnable r) {
     this.submit(r);
   }
+
+  @Override
+  public int getQueueSize() {
+    return delegate.getQueue().size();
+  }
+
+  @Override
+  public int getWorkerCount() {
+    return delegate.getPoolSize();
+  }
+
+  @Override
+  public int getLargestWorkerCount() {
+    return delegate.getLargestPoolSize();
+  }
 }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/async/AsyncExecutionMBean.java b/server/sonar-server/src/main/java/org/sonar/server/async/AsyncExecutionMBean.java
new file mode 100644 (file)
index 0000000..08de7ef
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.async;
+
+public interface AsyncExecutionMBean {
+
+  String OBJECT_NAME = "SonarQube:name=AsyncExecution";
+
+  long getQueueSize();
+
+  long getWorkerCount();
+
+  long getLargestWorkerCount();
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/async/AsyncExecutionMBeanImpl.java b/server/sonar-server/src/main/java/org/sonar/server/async/AsyncExecutionMBeanImpl.java
new file mode 100644 (file)
index 0000000..b562fa8
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.async;
+
+import org.picocontainer.Startable;
+import org.sonar.process.Jmx;
+
+public class AsyncExecutionMBeanImpl implements AsyncExecutionMBean, Startable {
+
+  private final AsyncExecutionMonitoring asyncExecutionMonitoring;
+
+  public AsyncExecutionMBeanImpl(AsyncExecutionMonitoring asyncExecutionMonitoring) {
+    this.asyncExecutionMonitoring = asyncExecutionMonitoring;
+  }
+
+  @Override
+  public void start() {
+    Jmx.register(OBJECT_NAME, this);
+  }
+
+  @Override
+  public void stop() {
+    Jmx.unregister(OBJECT_NAME);
+  }
+
+  @Override
+  public long getQueueSize() {
+    return asyncExecutionMonitoring.getQueueSize();
+  }
+
+  @Override
+  public long getWorkerCount() {
+    return asyncExecutionMonitoring.getWorkerCount();
+  }
+
+  @Override
+  public long getLargestWorkerCount() {
+    return asyncExecutionMonitoring.getLargestWorkerCount();
+  }
+}
index 1e5673c45ee8a30b3ebd48eac2fa56ddecce48b7..2d16d0bac767d43d0802f1797934fb757dedf147 100644 (file)
@@ -25,6 +25,7 @@ public class AsyncExecutionModule extends Module {
   @Override
   protected void configureModule() {
     add(
+      AsyncExecutionMBeanImpl.class,
       AsyncExecutionExecutorServiceImpl.class,
       AsyncExecutionImpl.class);
   }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/async/AsyncExecutionMonitoring.java b/server/sonar-server/src/main/java/org/sonar/server/async/AsyncExecutionMonitoring.java
new file mode 100644 (file)
index 0000000..f65a509
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.async;
+
+public interface AsyncExecutionMonitoring {
+  int getQueueSize();
+
+  int getWorkerCount();
+
+  int getLargestWorkerCount();
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/async/AsyncExecutionMBeanImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/async/AsyncExecutionMBeanImplTest.java
new file mode 100644 (file)
index 0000000..d4cbeb3
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.async;
+
+import java.lang.management.ManagementFactory;
+import javax.annotation.CheckForNull;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class AsyncExecutionMBeanImplTest {
+  private AsyncExecutionMonitoring asyncExecutionMonitoring = Mockito.mock(AsyncExecutionMonitoring.class);
+
+  private AsyncExecutionMBeanImpl underTest = new AsyncExecutionMBeanImpl(asyncExecutionMonitoring);
+
+  @Test
+  public void register_and_unregister() throws Exception {
+    assertThat(getMBean()).isNull();
+
+    underTest.start();
+    assertThat(getMBean()).isNotNull();
+
+    underTest.stop();
+    assertThat(getMBean()).isNull();
+  }
+
+  @Test
+  public void getQueueSize_delegates_to_AsyncExecutionMonitoring() {
+    when(asyncExecutionMonitoring.getQueueSize()).thenReturn(12);
+
+    assertThat(underTest.getQueueSize()).isEqualTo(12);
+
+    verify(asyncExecutionMonitoring).getQueueSize();
+  }
+
+  @Test
+  public void getWorkerCount_delegates_to_AsyncExecutionMonitoring() {
+    when(asyncExecutionMonitoring.getWorkerCount()).thenReturn(12);
+
+    assertThat(underTest.getWorkerCount()).isEqualTo(12);
+
+    verify(asyncExecutionMonitoring).getWorkerCount();
+  }
+
+  @Test
+  public void getLargestWorkerCount_delegates_to_AsyncExecutionMonitoring() {
+    when(asyncExecutionMonitoring.getLargestWorkerCount()).thenReturn(12);
+
+    assertThat(underTest.getLargestWorkerCount()).isEqualTo(12);
+
+    verify(asyncExecutionMonitoring).getLargestWorkerCount();
+  }
+
+  @CheckForNull
+  private ObjectInstance getMBean() throws Exception {
+    try {
+      return ManagementFactory.getPlatformMBeanServer().getObjectInstance(new ObjectName(AsyncExecutionMBean.OBJECT_NAME));
+    } catch (InstanceNotFoundException e) {
+      return null;
+    }
+  }
+
+
+}