aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-ce
diff options
context:
space:
mode:
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>2017-03-31 14:40:30 +0200
committerEric Hartmann <hartmann.eric@gmail.Com>2017-04-27 09:23:18 +0200
commite62b51e3812f640230c0d0dc191a54e8db76b949 (patch)
treed6fcd5facf744d3b3c2ac1dc7c037c7efa1a1069 /server/sonar-ce
parent47e4a68f20bc29ed48cdb177b5cf9f698d6af8ad (diff)
downloadsonarqube-e62b51e3812f640230c0d0dc191a54e8db76b949.tar.gz
sonarqube-e62b51e3812f640230c0d0dc191a54e8db76b949.zip
SONAR-9041 move computation.monitoring package to sonar-ce
Diffstat (limited to 'server/sonar-ce')
-rw-r--r--server/sonar-ce/src/main/java/org/sonar/ce/CeConfigurationModule.java2
-rw-r--r--server/sonar-ce/src/main/java/org/sonar/ce/CeQueueModule.java6
-rw-r--r--server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CEQueueStatus.java88
-rw-r--r--server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CEQueueStatusImpl.java91
-rw-r--r--server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeDatabaseMBean.java43
-rw-r--r--server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeDatabaseMBeanImpl.java113
-rw-r--r--server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeTasksMBean.java55
-rw-r--r--server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeTasksMBeanImpl.java92
-rw-r--r--server/sonar-ce/src/main/java/org/sonar/ce/monitoring/package-info.java23
-rw-r--r--server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CEQueueStatusImplConcurrentTest.java101
-rw-r--r--server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CEQueueStatusImplTest.java142
-rw-r--r--server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CeDatabaseMBeanImplTest.java70
-rw-r--r--server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CeTasksMBeanImplTest.java156
-rw-r--r--server/sonar-ce/src/test/java/org/sonar/ce/queue/InternalCeQueueImplTest.java4
14 files changed, 980 insertions, 6 deletions
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/CeConfigurationModule.java b/server/sonar-ce/src/main/java/org/sonar/ce/CeConfigurationModule.java
index f89cf4efd39..cb61583ff06 100644
--- a/server/sonar-ce/src/main/java/org/sonar/ce/CeConfigurationModule.java
+++ b/server/sonar-ce/src/main/java/org/sonar/ce/CeConfigurationModule.java
@@ -23,7 +23,7 @@ import org.sonar.ce.configuration.CeConfigurationImpl;
import org.sonar.ce.log.CeLogging;
import org.sonar.core.platform.Module;
import org.sonar.process.systeminfo.ProcessStateSystemInfo;
-import org.sonar.server.computation.monitoring.CeDatabaseMBeanImpl;
+import org.sonar.ce.monitoring.CeDatabaseMBeanImpl;
public class CeConfigurationModule extends Module {
@Override
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/CeQueueModule.java b/server/sonar-ce/src/main/java/org/sonar/ce/CeQueueModule.java
index 159e0d53687..d8f37cd5e11 100644
--- a/server/sonar-ce/src/main/java/org/sonar/ce/CeQueueModule.java
+++ b/server/sonar-ce/src/main/java/org/sonar/ce/CeQueueModule.java
@@ -19,11 +19,11 @@
*/
package org.sonar.ce;
-import org.sonar.core.platform.Module;
-import org.sonar.server.computation.monitoring.CEQueueStatusImpl;
-import org.sonar.server.computation.monitoring.CeTasksMBeanImpl;
+import org.sonar.ce.monitoring.CEQueueStatusImpl;
+import org.sonar.ce.monitoring.CeTasksMBeanImpl;
import org.sonar.ce.queue.CeQueueInitializer;
import org.sonar.ce.queue.InternalCeQueueImpl;
+import org.sonar.core.platform.Module;
public class CeQueueModule extends Module {
@Override
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CEQueueStatus.java b/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CEQueueStatus.java
new file mode 100644
index 00000000000..bc652ea9871
--- /dev/null
+++ b/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CEQueueStatus.java
@@ -0,0 +1,88 @@
+/*
+ * 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.monitoring;
+
+public interface CEQueueStatus {
+
+ /**
+ * Adds 1 to the count of batch reports under processing and removes 1 from the count of batch reports waiting for
+ * processing.
+ *
+ * @return the new count of batch reports under processing
+ *
+ * @see #getInProgressCount()
+ */
+ long addInProgress();
+
+ /**
+ * Adds 1 to the count of batch reports which processing ended successfully and removes 1 from the count of batch
+ * reports under processing. Adds the specified time to the processing time counter.
+ *
+ * @param processingTime duration of processing in ms
+ *
+ * @return the new count of batch reports which processing ended successfully
+ *
+ * @see #getSuccessCount()
+ * @see #getInProgressCount()
+ *
+ * @throws IllegalArgumentException if processingTime is < 0
+ */
+ long addSuccess(long processingTime);
+
+ /**
+ * Adds 1 to the count of batch reports which processing ended with an error and removes 1 from the count of batch
+ * reports under processing. Adds the specified time to the processing time counter.
+ *
+ * @param processingTime duration of processing in ms
+ *
+ * @return the new count of batch reports which processing ended with an error
+ *
+ * @see #getErrorCount()
+ * @see #getInProgressCount()
+ *
+ * @throws IllegalArgumentException if processingTime is < 0
+ */
+ long addError(long processingTime);
+
+ /**
+ * Count of batch reports waiting for processing since startup, including reports received before instance startup.
+ */
+ long getPendingCount();
+
+ /**
+ * Count of batch reports under processing.
+ */
+ long getInProgressCount();
+
+ /**
+ * Count of batch reports which processing ended with an error since instance startup.
+ */
+ long getErrorCount();
+
+ /**
+ * Count of batch reports which processing ended successfully since instance startup.
+ */
+ long getSuccessCount();
+
+ /**
+ * Time spent processing batch reports since startup, in milliseconds.
+ */
+ long getProcessingTime();
+}
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CEQueueStatusImpl.java b/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CEQueueStatusImpl.java
new file mode 100644
index 00000000000..305018d18da
--- /dev/null
+++ b/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CEQueueStatusImpl.java
@@ -0,0 +1,91 @@
+/*
+ * 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.monitoring;
+
+import java.util.concurrent.atomic.AtomicLong;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.ce.CeQueueDto;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+public class CEQueueStatusImpl implements CEQueueStatus {
+
+ private final DbClient dbClient;
+ private final AtomicLong inProgress = new AtomicLong(0);
+ private final AtomicLong error = new AtomicLong(0);
+ private final AtomicLong success = new AtomicLong(0);
+ private final AtomicLong processingTime = new AtomicLong(0);
+
+ public CEQueueStatusImpl(DbClient dbClient) {
+ this.dbClient = dbClient;
+ }
+
+ @Override
+ public long addInProgress() {
+ return inProgress.incrementAndGet();
+ }
+
+ @Override
+ public long addError(long processingTimeInMs) {
+ addProcessingTime(processingTimeInMs);
+ inProgress.decrementAndGet();
+ return error.incrementAndGet();
+ }
+
+ @Override
+ public long addSuccess(long processingTimeInMs) {
+ addProcessingTime(processingTimeInMs);
+ inProgress.decrementAndGet();
+ return success.incrementAndGet();
+ }
+
+ private void addProcessingTime(long ms) {
+ checkArgument(ms >= 0, "Processing time can not be < 0");
+ processingTime.addAndGet(ms);
+ }
+
+ @Override
+ public long getPendingCount() {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ return dbClient.ceQueueDao().countByStatus(dbSession, CeQueueDto.Status.PENDING);
+ }
+ }
+
+ @Override
+ public long getInProgressCount() {
+ return inProgress.get();
+ }
+
+ @Override
+ public long getErrorCount() {
+ return error.get();
+ }
+
+ @Override
+ public long getSuccessCount() {
+ return success.get();
+ }
+
+ @Override
+ public long getProcessingTime() {
+ return processingTime.get();
+ }
+}
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeDatabaseMBean.java b/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeDatabaseMBean.java
new file mode 100644
index 00000000000..4000e670c1b
--- /dev/null
+++ b/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeDatabaseMBean.java
@@ -0,0 +1,43 @@
+/*
+ * 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.monitoring;
+
+public interface CeDatabaseMBean {
+
+ String OBJECT_NAME = "SonarQube:name=ComputeEngineDatabaseConnection";
+
+ int getPoolActiveConnections();
+
+ int getPoolMaxActiveConnections();
+
+ int getPoolIdleConnections();
+
+ int getPoolMaxIdleConnections();
+
+ int getPoolMinIdleConnections();
+
+ int getPoolInitialSize();
+
+ long getPoolMaxWaitMillis();
+
+ boolean getPoolRemoveAbandoned();
+
+ int getPoolRemoveAbandonedTimeoutSeconds();
+}
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeDatabaseMBeanImpl.java b/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeDatabaseMBeanImpl.java
new file mode 100644
index 00000000000..52aa2961051
--- /dev/null
+++ b/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeDatabaseMBeanImpl.java
@@ -0,0 +1,113 @@
+/*
+ * 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.monitoring;
+
+import org.apache.commons.dbcp.BasicDataSource;
+import org.picocontainer.Startable;
+import org.sonar.db.DbClient;
+import org.sonar.process.Jmx;
+import org.sonar.process.systeminfo.SystemInfoSection;
+import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
+
+public class CeDatabaseMBeanImpl implements CeDatabaseMBean, Startable, SystemInfoSection {
+ private final DbClient dbClient;
+
+ public CeDatabaseMBeanImpl(DbClient dbClient) {
+ this.dbClient = dbClient;
+ }
+
+ @Override
+ public void start() {
+ Jmx.register(OBJECT_NAME, this);
+ }
+
+ /**
+ * Unregister, if needed
+ */
+ @Override
+ public void stop() {
+ Jmx.unregister(OBJECT_NAME);
+ }
+
+ @Override
+ public int getPoolActiveConnections() {
+ return commonsDbcp().getNumActive();
+ }
+
+ @Override
+ public int getPoolMaxActiveConnections() {
+ return commonsDbcp().getMaxActive();
+ }
+
+ @Override
+ public int getPoolIdleConnections() {
+ return commonsDbcp().getNumIdle();
+ }
+
+ @Override
+ public int getPoolMaxIdleConnections() {
+ return commonsDbcp().getMaxIdle();
+ }
+
+ @Override
+ public int getPoolMinIdleConnections() {
+ return commonsDbcp().getMinIdle();
+ }
+
+ @Override
+ public int getPoolInitialSize() {
+ return commonsDbcp().getInitialSize();
+ }
+
+ @Override
+ public long getPoolMaxWaitMillis() {
+ return commonsDbcp().getMaxWait();
+ }
+
+ @Override
+ public boolean getPoolRemoveAbandoned() {
+ return commonsDbcp().getRemoveAbandoned();
+ }
+
+ @Override
+ public int getPoolRemoveAbandonedTimeoutSeconds() {
+ return commonsDbcp().getRemoveAbandonedTimeout();
+ }
+
+ private BasicDataSource commonsDbcp() {
+ return (BasicDataSource) dbClient.getDatabase().getDataSource();
+ }
+
+ @Override
+ public ProtobufSystemInfo.Section toProtobuf() {
+ ProtobufSystemInfo.Section.Builder builder = ProtobufSystemInfo.Section.newBuilder();
+ builder.setName("Compute Engine Database Connection");
+ builder.addAttributesBuilder().setKey("Pool Initial Size").setLongValue(getPoolInitialSize()).build();
+ builder.addAttributesBuilder().setKey("Pool Active Connections").setLongValue(getPoolActiveConnections()).build();
+ builder.addAttributesBuilder().setKey("Pool Idle Connections").setLongValue(getPoolIdleConnections()).build();
+ builder.addAttributesBuilder().setKey("Pool Max Active Connections").setLongValue(getPoolMaxActiveConnections()).build();
+ builder.addAttributesBuilder().setKey("Pool Max Idle Connections").setLongValue(getPoolMaxIdleConnections()).build();
+ builder.addAttributesBuilder().setKey("Pool Min Idle Connections").setLongValue(getPoolMinIdleConnections()).build();
+ builder.addAttributesBuilder().setKey("Pool Max Wait (ms)").setLongValue(getPoolMaxWaitMillis()).build();
+ builder.addAttributesBuilder().setKey("Pool Remove Abandoned").setBooleanValue(getPoolRemoveAbandoned()).build();
+ builder.addAttributesBuilder().setKey("Pool Remove Abandoned Timeout (sec)").setLongValue(getPoolRemoveAbandonedTimeoutSeconds()).build();
+ return builder.build();
+ }
+}
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeTasksMBean.java b/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeTasksMBean.java
new file mode 100644
index 00000000000..2e85a5d0c02
--- /dev/null
+++ b/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeTasksMBean.java
@@ -0,0 +1,55 @@
+/*
+ * 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.monitoring;
+
+public interface CeTasksMBean {
+
+ String OBJECT_NAME = "SonarQube:name=ComputeEngineTasks";
+
+ /**
+ * Count of batch reports waiting for processing since startup, including reports received before instance startup.
+ */
+ long getPendingCount();
+
+ /**
+ * Count of batch reports under processing.
+ */
+ long getInProgressCount();
+
+ /**
+ * Count of batch reports which processing ended with an error since instance startup.
+ */
+ long getErrorCount();
+
+ /**
+ * Count of batch reports which processing ended successfully since instance startup.
+ */
+ long getSuccessCount();
+
+ /**
+ * Time spent processing reports since startup, in milliseconds.
+ */
+ long getProcessingTime();
+
+ /**
+ * Configured number of Workers.
+ */
+ int getWorkerCount();
+}
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeTasksMBeanImpl.java b/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeTasksMBeanImpl.java
new file mode 100644
index 00000000000..9797b414f26
--- /dev/null
+++ b/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeTasksMBeanImpl.java
@@ -0,0 +1,92 @@
+/*
+ * 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.monitoring;
+
+import org.picocontainer.Startable;
+import org.sonar.process.Jmx;
+import org.sonar.process.systeminfo.SystemInfoSection;
+import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
+import org.sonar.ce.configuration.CeConfiguration;
+
+public class CeTasksMBeanImpl implements CeTasksMBean, Startable, SystemInfoSection {
+ private final CEQueueStatus queueStatus;
+ private final CeConfiguration ceConfiguration;
+
+ public CeTasksMBeanImpl(CEQueueStatus queueStatus, CeConfiguration ceConfiguration) {
+ this.queueStatus = queueStatus;
+ this.ceConfiguration = ceConfiguration;
+ }
+
+ @Override
+ public void start() {
+ Jmx.register(OBJECT_NAME, this);
+ }
+
+ /**
+ * Unregister, if needed
+ */
+ @Override
+ public void stop() {
+ Jmx.unregister(OBJECT_NAME);
+ }
+
+ @Override
+ public long getPendingCount() {
+ return queueStatus.getPendingCount();
+ }
+
+ @Override
+ public long getInProgressCount() {
+ return queueStatus.getInProgressCount();
+ }
+
+ @Override
+ public long getErrorCount() {
+ return queueStatus.getErrorCount();
+ }
+
+ @Override
+ public long getSuccessCount() {
+ return queueStatus.getSuccessCount();
+ }
+
+ @Override
+ public long getProcessingTime() {
+ return queueStatus.getProcessingTime();
+ }
+
+ @Override
+ public int getWorkerCount() {
+ return ceConfiguration.getWorkerCount();
+ }
+
+ @Override
+ public ProtobufSystemInfo.Section toProtobuf() {
+ ProtobufSystemInfo.Section.Builder builder = ProtobufSystemInfo.Section.newBuilder();
+ builder.setName("Compute Engine Tasks");
+ builder.addAttributesBuilder().setKey("Pending").setLongValue(getPendingCount()).build();
+ builder.addAttributesBuilder().setKey("In Progress").setLongValue(getInProgressCount()).build();
+ builder.addAttributesBuilder().setKey("Processed With Error").setLongValue(getErrorCount()).build();
+ builder.addAttributesBuilder().setKey("Processed With Success").setLongValue(getSuccessCount()).build();
+ builder.addAttributesBuilder().setKey("Processing Time (ms)").setLongValue(getProcessingTime()).build();
+ builder.addAttributesBuilder().setKey("Worker Count").setLongValue(getWorkerCount()).build();
+ return builder.build();
+ }
+}
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/package-info.java b/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/package-info.java
new file mode 100644
index 00000000000..029b7eeb436
--- /dev/null
+++ b/server/sonar-ce/src/main/java/org/sonar/ce/monitoring/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.ce.monitoring;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CEQueueStatusImplConcurrentTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CEQueueStatusImplConcurrentTest.java
new file mode 100644
index 00000000000..1c34a059861
--- /dev/null
+++ b/server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CEQueueStatusImplConcurrentTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.monitoring;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import org.junit.After;
+import org.junit.Test;
+import org.sonar.db.DbClient;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class CEQueueStatusImplConcurrentTest {
+ private ExecutorService executorService = Executors.newFixedThreadPool(10, new ThreadFactory() {
+ private int cnt = 0;
+
+ @Override
+ public Thread newThread(Runnable r) {
+ return new Thread(r, CEQueueStatusImplConcurrentTest.class.getSimpleName() + cnt++);
+ }
+ });
+ private CEQueueStatusImpl underTest = new CEQueueStatusImpl(mock(DbClient.class));
+
+ @After
+ public void tearDown() throws Exception {
+ executorService.shutdownNow();
+ }
+
+ @Test
+ public void test_concurrent_modifications_in_any_order() throws InterruptedException {
+ for (Runnable runnable : buildShuffleCallsToUnderTest()) {
+ executorService.submit(runnable);
+ }
+
+ executorService.awaitTermination(1, TimeUnit.SECONDS);
+
+ assertThat(underTest.getInProgressCount()).isEqualTo(1);
+ assertThat(underTest.getErrorCount()).isEqualTo(17);
+ assertThat(underTest.getSuccessCount()).isEqualTo(80);
+ assertThat(underTest.getProcessingTime()).isEqualTo(177);
+ }
+
+ private List<Runnable> buildShuffleCallsToUnderTest() {
+ List<Runnable> res = new ArrayList<>();
+ for (int i = 0; i < 98; i++) {
+ res.add(new AddInProgressRunnable());
+ }
+ for (int i = 0; i < 80; i++) {
+ res.add(new AddSuccessRunnable());
+ }
+ for (int i = 0; i < 17; i++) {
+ res.add(new AddErrorRunnable());
+ }
+ Collections.shuffle(res);
+ return res;
+ }
+
+ private class AddInProgressRunnable implements Runnable {
+ @Override
+ public void run() {
+ underTest.addInProgress();
+ }
+ }
+
+ private class AddErrorRunnable implements Runnable {
+ @Override
+ public void run() {
+ underTest.addError(1);
+ }
+ }
+
+ private class AddSuccessRunnable implements Runnable {
+ @Override
+ public void run() {
+ underTest.addSuccess(2);
+ }
+ }
+}
diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CEQueueStatusImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CEQueueStatusImplTest.java
new file mode 100644
index 00000000000..c62195ab13b
--- /dev/null
+++ b/server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CEQueueStatusImplTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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.monitoring;
+
+import java.util.Random;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mockito;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.ce.CeQueueDto;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class CEQueueStatusImplTest {
+ private static final int SOME_RANDOM_MAX = 96535;
+ private static final int SOME_PROCESSING_TIME = 8723;
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private DbClient dbClient = mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS);
+ private CEQueueStatusImpl underTest = new CEQueueStatusImpl(dbClient);
+
+ @Test
+ public void verify_just_created_instance_metrics() {
+ assertThat(underTest.getInProgressCount()).isEqualTo(0);
+ assertThat(underTest.getErrorCount()).isEqualTo(0);
+ assertThat(underTest.getSuccessCount()).isEqualTo(0);
+ assertThat(underTest.getProcessingTime()).isEqualTo(0);
+ }
+
+ @Test
+ public void addInProgress_increases_InProgress() {
+ underTest.addInProgress();
+
+ assertThat(underTest.getInProgressCount()).isEqualTo(1);
+ assertThat(underTest.getErrorCount()).isEqualTo(0);
+ assertThat(underTest.getSuccessCount()).isEqualTo(0);
+ assertThat(underTest.getProcessingTime()).isEqualTo(0);
+ }
+
+ @Test
+ public void addInProgress_any_number_of_call_change_by_1_per_call() {
+ int calls = new Random().nextInt(SOME_RANDOM_MAX);
+ for (int i = 0; i < calls; i++) {
+ underTest.addInProgress();
+ }
+
+ assertThat(underTest.getInProgressCount()).isEqualTo(calls);
+ assertThat(underTest.getProcessingTime()).isEqualTo(0);
+ }
+
+ @Test
+ public void addError_throws_IAE_if_time_is_less_than_0() {
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Processing time can not be < 0");
+
+ underTest.addError(-1);
+ }
+
+ @Test
+ public void addError_increases_Error_and_decreases_InProgress_by_1_without_check_on_InProgress() {
+ underTest.addError(SOME_PROCESSING_TIME);
+
+ assertThat(underTest.getInProgressCount()).isEqualTo(-1);
+ assertThat(underTest.getErrorCount()).isEqualTo(1);
+ assertThat(underTest.getSuccessCount()).isEqualTo(0);
+ assertThat(underTest.getProcessingTime()).isEqualTo(SOME_PROCESSING_TIME);
+ }
+
+ @Test
+ public void addError_any_number_of_call_change_by_1_per_call() {
+ int calls = new Random().nextInt(SOME_RANDOM_MAX);
+ for (int i = 0; i < calls; i++) {
+ underTest.addError(1);
+ }
+
+ assertThat(underTest.getErrorCount()).isEqualTo(calls);
+ assertThat(underTest.getInProgressCount()).isEqualTo(-calls);
+ assertThat(underTest.getProcessingTime()).isEqualTo(calls);
+ }
+
+ @Test
+ public void addSuccess_throws_IAE_if_time_is_less_than_0() {
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Processing time can not be < 0");
+
+ underTest.addSuccess(-1);
+ }
+
+ @Test
+ public void addSuccess_increases_Error_and_decreases_InProgress_by_1_without_check_on_InProgress() {
+ underTest.addSuccess(SOME_PROCESSING_TIME);
+
+ assertThat(underTest.getInProgressCount()).isEqualTo(-1);
+ assertThat(underTest.getErrorCount()).isEqualTo(0);
+ assertThat(underTest.getSuccessCount()).isEqualTo(1);
+ assertThat(underTest.getProcessingTime()).isEqualTo(SOME_PROCESSING_TIME);
+ }
+
+ @Test
+ public void addSuccess_any_number_of_call_change_by_1_per_call() {
+ int calls = new Random().nextInt(SOME_RANDOM_MAX);
+ for (int i = 0; i < calls; i++) {
+ underTest.addSuccess(1);
+ }
+
+ assertThat(underTest.getSuccessCount()).isEqualTo(calls);
+ assertThat(underTest.getInProgressCount()).isEqualTo(-calls);
+ assertThat(underTest.getProcessingTime()).isEqualTo(calls);
+ }
+
+ @Test
+ public void count_Pending_from_database() {
+ when(dbClient.ceQueueDao().countByStatus(any(DbSession.class), eq(CeQueueDto.Status.PENDING))).thenReturn(42);
+
+ assertThat(underTest.getPendingCount()).isEqualTo(42);
+ }
+}
diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CeDatabaseMBeanImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CeDatabaseMBeanImplTest.java
new file mode 100644
index 00000000000..60156412035
--- /dev/null
+++ b/server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CeDatabaseMBeanImplTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.monitoring;
+
+import java.lang.management.ManagementFactory;
+import javax.annotation.CheckForNull;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CeDatabaseMBeanImplTest {
+
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ CeDatabaseMBeanImpl underTest = new CeDatabaseMBeanImpl(dbTester.getDbClient());
+
+ @Test
+ public void register_and_unregister() throws Exception {
+ assertThat(getMBean()).isNull();
+
+ underTest.start();
+ assertThat(getMBean()).isNotNull();
+
+ underTest.stop();
+ assertThat(getMBean()).isNull();
+ }
+
+ @Test
+ public void export_system_info() {
+ ProtobufSystemInfo.Section section = underTest.toProtobuf();
+ assertThat(section.getName()).isEqualTo("Compute Engine Database Connection");
+ assertThat(section.getAttributesCount()).isEqualTo(9);
+ assertThat(section.getAttributes(0).getKey()).isEqualTo("Pool Initial Size");
+ assertThat(section.getAttributes(0).getLongValue()).isGreaterThanOrEqualTo(0);
+ }
+
+ @CheckForNull
+ private ObjectInstance getMBean() throws Exception {
+ try {
+ return ManagementFactory.getPlatformMBeanServer().getObjectInstance(new ObjectName(CeDatabaseMBean.OBJECT_NAME));
+ } catch (InstanceNotFoundException e) {
+ return null;
+ }
+ }
+}
diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CeTasksMBeanImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CeTasksMBeanImplTest.java
new file mode 100644
index 00000000000..1ec6f932115
--- /dev/null
+++ b/server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CeTasksMBeanImplTest.java
@@ -0,0 +1,156 @@
+/*
+ * 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.monitoring;
+
+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.sonar.ce.configuration.CeConfiguration;
+import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CeTasksMBeanImplTest {
+ private static final long PENDING_COUNT = 2;
+ private static final long IN_PROGRESS_COUNT = 5;
+ private static final long ERROR_COUNT = 10;
+ private static final long SUCCESS_COUNT = 13;
+ private static final long PROCESSING_TIME = 987;
+ private static final int WORKER_COUNT = 56;
+
+ private CeTasksMBeanImpl underTest = new CeTasksMBeanImpl(new DumbCEQueueStatus(), new DumbCeConfiguration());
+
+ @Test
+ public void register_and_unregister() throws Exception {
+ assertThat(getMBean()).isNull();
+
+ underTest.start();
+ assertThat(getMBean()).isNotNull();
+
+ underTest.stop();
+ assertThat(getMBean()).isNull();
+ }
+
+ @Test
+ public void get_methods_delegate_to_the_CEQueueStatus_instance() {
+ assertThat(underTest.getPendingCount()).isEqualTo(PENDING_COUNT);
+ assertThat(underTest.getInProgressCount()).isEqualTo(IN_PROGRESS_COUNT);
+ assertThat(underTest.getErrorCount()).isEqualTo(ERROR_COUNT);
+ assertThat(underTest.getSuccessCount()).isEqualTo(SUCCESS_COUNT);
+ assertThat(underTest.getProcessingTime()).isEqualTo(PROCESSING_TIME);
+ }
+
+ @Test
+ public void getWorkerCount_delegates_to_the_CEConfiguration_instance() {
+ assertThat(underTest.getWorkerCount()).isEqualTo(WORKER_COUNT);
+ }
+
+ @Test
+ public void export_system_info() {
+ ProtobufSystemInfo.Section section = underTest.toProtobuf();
+ assertThat(section.getName()).isEqualTo("Compute Engine Tasks");
+ assertThat(section.getAttributesCount()).isEqualTo(6);
+ }
+
+ /**
+ * 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;
+ }
+
+ @Override
+ public long addInProgress() {
+ return methodNotImplemented();
+ }
+
+ @Override
+ public long getInProgressCount() {
+ return IN_PROGRESS_COUNT;
+ }
+
+ @Override
+ public long addError(long processingTime) {
+ return methodNotImplemented();
+ }
+
+ @Override
+ public long getErrorCount() {
+ return ERROR_COUNT;
+ }
+
+ @Override
+ public long addSuccess(long processingTime) {
+ return methodNotImplemented();
+ }
+
+ @Override
+ public long getSuccessCount() {
+ return SUCCESS_COUNT;
+ }
+
+ @Override
+ public long getProcessingTime() {
+ return PROCESSING_TIME;
+ }
+
+ private long methodNotImplemented() {
+ throw new UnsupportedOperationException("Not Implemented");
+ }
+ }
+
+ private static class DumbCeConfiguration implements CeConfiguration {
+ @Override
+ public int getWorkerCount() {
+ return WORKER_COUNT;
+ }
+
+ @Override
+ public long getQueuePollingDelay() {
+ throw new UnsupportedOperationException("getQueuePollingDelay is not implemented");
+ }
+
+ @Override
+ public long getCancelWornOutsInitialDelay() {
+ throw new UnsupportedOperationException("getCancelWornOutsInitialDelay is not implemented");
+ }
+
+ @Override
+ public long getCancelWornOutsDelay() {
+ throw new UnsupportedOperationException("getCancelWornOutsDelay is not implemented");
+ }
+ }
+
+ @CheckForNull
+ private ObjectInstance getMBean() throws Exception {
+ try {
+ return ManagementFactory.getPlatformMBeanServer().getObjectInstance(new ObjectName(CeTasksMBean.OBJECT_NAME));
+ } catch (InstanceNotFoundException e) {
+ return null;
+ }
+ }
+}
diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/queue/InternalCeQueueImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/queue/InternalCeQueueImplTest.java
index c5a537880b0..2bf444730cb 100644
--- a/server/sonar-ce/src/test/java/org/sonar/ce/queue/InternalCeQueueImplTest.java
+++ b/server/sonar-ce/src/test/java/org/sonar/ce/queue/InternalCeQueueImplTest.java
@@ -33,6 +33,7 @@ import org.junit.rules.ExpectedException;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.internal.TestSystem2;
import org.sonar.ce.monitoring.CEQueueStatus;
+import org.sonar.ce.monitoring.CEQueueStatusImpl;
import org.sonar.core.util.UuidFactory;
import org.sonar.core.util.UuidFactoryImpl;
import org.sonar.db.DbSession;
@@ -43,13 +44,12 @@ import org.sonar.db.ce.CeTaskTypes;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
import org.sonar.db.organization.OrganizationDto;
-import org.sonar.server.computation.monitoring.CEQueueStatusImpl;
import org.sonar.server.organization.DefaultOrganization;
import org.sonar.server.organization.DefaultOrganizationProvider;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.hamcrest.Matchers.*;
+import static org.hamcrest.Matchers.startsWith;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;