1. A small-scale (individual or small team) instance of the SonarQube server requires at least 2GB of RAM to run efficiently and 1GB of free RAM for the OS. If you are installing an instance for a large teams or Enterprise, please consider the additional recommendations below.
2. The amount of disk space you need will depend on how much code you analyze with SonarQube.
3. SonarQube must be installed on hard drives that have excellent read & write performance. Most importantly, the "data" folder houses the Elasticsearch indices on which a huge amount of I/O will be done when the server is up and running. Great read & write hard drive performance will therefore have a great impact on the overall SonarQube server performance.
-4. SonarQube does not support 32-bit systems on the server side. SonarQube does, however, support 32-bit systems on the scanner side.
### Enterprise Hardware Recommendations
For large teams or Enterprise-scale installations of SonarQube, additional hardware is required. At the Enterprise level, [monitoring your SonarQube instance](/instance-administration/monitoring/) is essential and should guide further hardware upgrades as your instance grows. A starting configuration should include at least:
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.scanner.report;
+
+import com.sun.jna.Platform;
+
+public class JavaArchitectureInformationProvider {
+
+ public boolean is64bitJavaVersion() {
+ return Platform.is64Bit();
+ }
+
+}
*/
package org.sonar.scanner.report;
+import com.google.common.annotations.VisibleForTesting;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import okhttp3.HttpUrl;
import org.apache.commons.io.FileUtils;
import org.sonar.api.Startable;
+import org.sonar.api.notifications.AnalysisWarnings;
import org.sonar.api.platform.Server;
import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.TempFolder;
private static final String BRANCH = "branch";
private static final String ID = "id";
+ @VisibleForTesting
+ static final String SUPPORT_OF_32_BIT_JRE_IS_DEPRECATED_MESSAGE = "You are using a 32 bits JRE. "
+ + "The support of 32 bits JRE is deprecated and a future version of the scanner will remove it completely.";
+
private final DefaultScannerWsClient wsClient;
private final AnalysisContextReportPublisher contextPublisher;
private final InputModuleHierarchy moduleHierarchy;
private final Path reportDir;
private final ScannerReportWriter writer;
private final ScannerReportReader reader;
+ private final AnalysisWarnings analysisWarnings;
+ private final JavaArchitectureInformationProvider javaArchitectureInformationProvider;
public ReportPublisher(ScanProperties properties, DefaultScannerWsClient wsClient, Server server, AnalysisContextReportPublisher contextPublisher,
InputModuleHierarchy moduleHierarchy, GlobalAnalysisMode analysisMode, TempFolder temp, ReportPublisherStep[] publishers, BranchConfiguration branchConfiguration,
- CeTaskReportDataHolder ceTaskReportDataHolder) {
+ CeTaskReportDataHolder ceTaskReportDataHolder, AnalysisWarnings analysisWarnings,
+ JavaArchitectureInformationProvider javaArchitectureInformationProvider) {
this.wsClient = wsClient;
this.server = server;
this.contextPublisher = contextPublisher;
this.properties = properties;
this.ceTaskReportDataHolder = ceTaskReportDataHolder;
this.reportDir = moduleHierarchy.root().getWorkDir().resolve("scanner-report");
+ this.analysisWarnings = analysisWarnings;
+ this.javaArchitectureInformationProvider = javaArchitectureInformationProvider;
this.writer = new ScannerReportWriter(reportDir.toFile());
this.reader = new ScannerReportReader(reportDir.toFile());
}
}
public void execute() {
+ logDeprecationWarningIf32bitJava();
File report = generateReportFile();
if (properties.shouldKeepReport()) {
LOG.info("Analysis report generated in " + reportDir);
logSuccess();
}
- private void logSuccess() {
- if (analysisMode.isMediumTest()) {
- LOG.info("ANALYSIS SUCCESSFUL");
- } else if (!properties.shouldWaitForQualityGate()) {
- LOG.info("ANALYSIS SUCCESSFUL, you can find the results at: {}", ceTaskReportDataHolder.getDashboardUrl());
- LOG.info("Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report");
- LOG.info("More about the report processing at {}", ceTaskReportDataHolder.getCeTaskUrl());
+ private void logDeprecationWarningIf32bitJava() {
+ if (!javaArchitectureInformationProvider.is64bitJavaVersion()) {
+ analysisWarnings.addUnique(SUPPORT_OF_32_BIT_JRE_IS_DEPRECATED_MESSAGE);
+ LOG.warn(SUPPORT_OF_32_BIT_JRE_IS_DEPRECATED_MESSAGE);
}
}
}
}
+ private void logSuccess() {
+ if (analysisMode.isMediumTest()) {
+ LOG.info("ANALYSIS SUCCESSFUL");
+ } else if (!properties.shouldWaitForQualityGate()) {
+ LOG.info("ANALYSIS SUCCESSFUL, you can find the results at: {}", ceTaskReportDataHolder.getDashboardUrl());
+ LOG.info("Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report");
+ LOG.info("More about the report processing at {}", ceTaskReportDataHolder.getCeTaskUrl());
+ }
+ }
+
/**
* Uploads the report file to server and returns the generated task id
*/
import org.sonar.scanner.report.ChangedLinesPublisher;
import org.sonar.scanner.report.ComponentsPublisher;
import org.sonar.scanner.report.ContextPropertiesPublisher;
+import org.sonar.scanner.report.JavaArchitectureInformationProvider;
import org.sonar.scanner.report.MetadataPublisher;
import org.sonar.scanner.report.ReportPublisher;
import org.sonar.scanner.report.SourcePublisher;
// Report
ReferenceBranchSupplier.class,
ScannerMetrics.class,
+ JavaArchitectureInformationProvider.class,
ReportPublisher.class,
AnalysisContextReportPublisher.class,
MetadataPublisher.class,
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.scanner.report;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class JavaArchitectureInformationProviderTest {
+
+ private JavaArchitectureInformationProvider javaArchitectureInformationProvider = new JavaArchitectureInformationProvider();
+
+ @Test
+ public void is64bitJavaVersion_returnsTrue_whenRunningWith64bitJava() {
+ assertThat(javaArchitectureInformationProvider.is64bitJavaVersion()).isTrue();
+ }
+
+}
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.impl.utils.JUnitTempFolder;
+import org.sonar.api.notifications.AnalysisWarnings;
import org.sonar.api.platform.Server;
import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.TempFolder;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
+import static org.sonar.scanner.report.ReportPublisher.SUPPORT_OF_32_BIT_JRE_IS_DEPRECATED_MESSAGE;
import static org.sonar.scanner.scan.branch.BranchType.BRANCH;
import static org.sonar.scanner.scan.branch.BranchType.PULL_REQUEST;
private BranchConfiguration branchConfiguration = mock(BranchConfiguration.class);
private CeTaskReportDataHolder reportMetadataHolder = mock(CeTaskReportDataHolder.class);
private ReportPublisher underTest;
+ private AnalysisWarnings analysisWarnings = mock(AnalysisWarnings.class);
+ private JavaArchitectureInformationProvider javaArchitectureInformationProvider = mock(JavaArchitectureInformationProvider.class);
@Before
public void setUp() {
.resolve("folder")
.resolve("report-task.txt"));
underTest = new ReportPublisher(properties, wsClient, server, contextPublisher, moduleHierarchy, mode, reportTempFolder,
- new ReportPublisherStep[0], branchConfiguration, reportMetadataHolder);
+ new ReportPublisherStep[0], branchConfiguration, reportMetadataHolder, analysisWarnings, javaArchitectureInformationProvider);
}
@Test
verify(wsClient).call(argThat(req -> (req).getWriteTimeOutInMs().orElse(0) == 60_000));
}
+ @Test
+ public void should_not_log_success_when_should_wait_for_QG() {
+ when(properties.shouldWaitForQualityGate()).thenReturn(true);
+
+ MockWsResponse submitMockResponse = new MockWsResponse();
+ submitMockResponse.setContent(Ce.SubmitResponse.newBuilder().setTaskId("task-1234").build().toByteArray());
+ when(wsClient.call(any())).thenReturn(submitMockResponse);
+
+ underTest.start();
+ underTest.execute();
+
+ assertThat(logTester.logs()).noneMatch(s -> s.contains("ANALYSIS SUCCESSFUL"));
+ }
+
@Test
public void dump_information_about_report_uploading() throws IOException {
underTest.prepareAndDumpMetadata("TASK-123");
when(branchConfiguration.branchType()).thenReturn(BRANCH);
when(branchConfiguration.branchName()).thenReturn("branch-6.7");
ReportPublisher underTest = new ReportPublisher(properties, wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
- new ReportPublisherStep[0], branchConfiguration, reportMetadataHolder);
+ new ReportPublisherStep[0], branchConfiguration, reportMetadataHolder, analysisWarnings, javaArchitectureInformationProvider);
underTest.prepareAndDumpMetadata("TASK-123");
when(branchConfiguration.pullRequestKey()).thenReturn("105");
ReportPublisher underTest = new ReportPublisher(properties, wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
- new ReportPublisherStep[0], branchConfiguration, reportMetadataHolder);
+ new ReportPublisherStep[0], branchConfiguration, reportMetadataHolder, analysisWarnings, javaArchitectureInformationProvider);
underTest.prepareAndDumpMetadata("TASK-123");
.containsExactlyInAnyOrder("pullRequest=" + pullRequestId);
}
+ @Test
+ public void test_do_not_log_or_add_warning_if_using_64bit_jre() {
+ when(javaArchitectureInformationProvider.is64bitJavaVersion()).thenReturn(true);
+ when(mode.isMediumTest()).thenReturn(true);
+ underTest.start();
+ underTest.execute();
+
+ assertThat(logTester.logs(LoggerLevel.WARN)).isEmpty();
+
+ verifyNoInteractions(analysisWarnings);
+ }
+
+ @Test
+ public void test_log_and_add_warning_if_using_non64bit_jre() {
+ when(javaArchitectureInformationProvider.is64bitJavaVersion()).thenReturn(false);
+ when(mode.isMediumTest()).thenReturn(true);
+ underTest.start();
+ underTest.execute();
+
+ assertThat(logTester.logs(LoggerLevel.WARN)).containsOnly(SUPPORT_OF_32_BIT_JRE_IS_DEPRECATED_MESSAGE);
+ verify(analysisWarnings).addUnique(SUPPORT_OF_32_BIT_JRE_IS_DEPRECATED_MESSAGE);
+ }
+
}