diff options
author | alain <108417558+alain-kermis-sonarsource@users.noreply.github.com> | 2022-08-30 17:00:34 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-09-05 20:02:56 +0000 |
commit | cd01dd4e2a883177d515b4f71554ee90e449b742 (patch) | |
tree | 1dbcee5083bb35765b17bb9ddd1ce07b349ab401 /server/sonar-webserver-core/src | |
parent | 3aae5514421557500b047eab24d728979fe24f25 (diff) | |
download | sonarqube-cd01dd4e2a883177d515b4f71554ee90e449b742.tar.gz sonarqube-cd01dd4e2a883177d515b4f71554ee90e449b742.zip |
SONAR-17195 Add new telemetry fields
Diffstat (limited to 'server/sonar-webserver-core/src')
4 files changed, 205 insertions, 71 deletions
diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryDaemon.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryDaemon.java index 23544746705..1a5c0296c75 100644 --- a/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryDaemon.java +++ b/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryDaemon.java @@ -22,7 +22,6 @@ package org.sonar.server.telemetry; import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.io.IOException; import java.io.StringWriter; -import java.util.Date; import java.util.Optional; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -38,8 +37,6 @@ import org.sonar.api.utils.text.JsonWriter; import org.sonar.server.property.InternalProperties; import org.sonar.server.util.GlobalLockManager; -import static org.sonar.api.utils.DateUtils.formatDate; -import static org.sonar.api.utils.DateUtils.parseDate; import static org.sonar.process.ProcessProperties.Property.SONAR_TELEMETRY_ENABLE; import static org.sonar.process.ProcessProperties.Property.SONAR_TELEMETRY_FREQUENCY_IN_SECONDS; import static org.sonar.process.ProcessProperties.Property.SONAR_TELEMETRY_URL; diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryDataLoaderImpl.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryDataLoaderImpl.java index 8caa743ca16..75d162fcdc5 100644 --- a/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryDataLoaderImpl.java +++ b/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryDataLoaderImpl.java @@ -21,6 +21,7 @@ package org.sonar.server.telemetry; import java.sql.DatabaseMetaData; import java.sql.SQLException; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -33,7 +34,6 @@ import javax.inject.Inject; import org.sonar.api.config.Configuration; import org.sonar.api.platform.Server; import org.sonar.api.server.ServerSide; -import org.sonar.core.config.CorePropertyDefinitions; import org.sonar.core.platform.PlatformEditionProvider; import org.sonar.core.platform.PluginInfo; import org.sonar.core.platform.PluginRepository; @@ -41,8 +41,10 @@ import org.sonar.core.util.stream.MoreCollectors; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.alm.setting.ALM; -import org.sonar.db.alm.setting.AlmSettingDto; -import org.sonar.db.component.ProjectCountPerAnalysisPropertyValue; +import org.sonar.db.alm.setting.ProjectAlmKeyAndProject; +import org.sonar.db.component.AnalysisPropertyValuePerProject; +import org.sonar.db.component.PrAndBranchCountByProjectDto; +import org.sonar.db.measure.ProjectMeasureDto; import org.sonar.db.measure.SumNclocDbQuery; import org.sonar.server.es.SearchOptions; import org.sonar.server.measure.index.ProjectMeasuresIndex; @@ -55,7 +57,10 @@ import org.sonar.server.user.index.UserQuery; import static java.util.Arrays.asList; import static java.util.Optional.ofNullable; -import static org.apache.commons.lang.StringUtils.startsWith; +import static org.sonar.api.internal.apachecommons.lang.StringUtils.startsWithIgnoreCase; +import static org.sonar.api.measures.CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY; +import static org.sonar.core.config.CorePropertyDefinitions.SONAR_ANALYSIS_DETECTEDCI; +import static org.sonar.core.config.CorePropertyDefinitions.SONAR_ANALYSIS_DETECTEDSCM; import static org.sonar.core.platform.EditionProvider.Edition.COMMUNITY; import static org.sonar.core.platform.EditionProvider.Edition.DATACENTER; import static org.sonar.core.platform.EditionProvider.Edition.ENTERPRISE; @@ -64,6 +69,7 @@ import static org.sonar.server.metric.UnanalyzedLanguageMetrics.UNANALYZED_C_KEY @ServerSide public class TelemetryDataLoaderImpl implements TelemetryDataLoader { + public static final String UNDETECTED = "undetected"; private final Server server; private final DbClient dbClient; private final PluginRepository pluginRepository; @@ -134,11 +140,47 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { data.setHasUnanalyzedCpp(numberOfUnanalyzedCppMeasures > 0); }); - data.setAlmIntegrationCountByAlm(countAlmUsage(dbSession)); data.setExternalAuthenticationProviders(dbClient.userDao().selectExternalIdentityProviders(dbSession)); data.setSonarlintWeeklyUsers(dbClient.userDao().countSonarlintWeeklyUsers(dbSession)); - addScmInformationToTelemetry(dbSession, data); - addCiInformationToTelemetry(dbSession, data); + + Map<String, String> scmByProject = getAnalysisPropertyByProject(dbSession, SONAR_ANALYSIS_DETECTEDSCM); + Map<String, String> ciByProject = getAnalysisPropertyByProject(dbSession, SONAR_ANALYSIS_DETECTEDCI); + Map<String, ProjectAlmKeyAndProject> almAndUrlByProject = getAlmAndUrlByProject(dbSession); + List<String> projectUuids = dbClient.projectDao().selectAllProjectUuids(dbSession); + + Map<String, PrAndBranchCountByProjectDto> prAndBranchCountByProjects = dbClient.branchDao().countPrAndBranchByProjectUuid(dbSession) + .stream().collect(Collectors.toMap(PrAndBranchCountByProjectDto::getProjectUuid, Function.identity())); + + List<TelemetryData.ProjectStatistics> projectStatistics = new ArrayList<>(); + for (String projectUuid : projectUuids) { + Long branchCount = Optional.ofNullable(prAndBranchCountByProjects.get(projectUuid)).map(PrAndBranchCountByProjectDto::getBranch).orElse(0L); + Long pullRequestCount = Optional.ofNullable(prAndBranchCountByProjects.get(projectUuid)).map(PrAndBranchCountByProjectDto::getPullRequest).orElse(0L); + String scm = Optional.ofNullable(scmByProject.get(projectUuid)).orElse(UNDETECTED); + String ci = Optional.ofNullable(ciByProject.get(projectUuid)).orElse(UNDETECTED); + String alm = null; + if (almAndUrlByProject.containsKey(projectUuid)) { + ProjectAlmKeyAndProject projectAlmKeyAndProject = almAndUrlByProject.get(projectUuid); + alm = getAlmName(projectAlmKeyAndProject.getAlmId(), projectAlmKeyAndProject.getUrl()); + } + alm = Optional.ofNullable(alm).orElse(UNDETECTED); + + projectStatistics.add(new TelemetryData.ProjectStatistics(projectUuid, branchCount, pullRequestCount, scm, ci, alm)); + } + data.setProjectStatistics(projectStatistics); + + data.setUsers(dbClient.userDao().selectUsersForTelemetry(dbSession)); + + List<ProjectMeasureDto> measures = dbClient.measureDao().selectLastMeasureForAllProjects(dbSession, NCLOC_LANGUAGE_DISTRIBUTION_KEY); + List<TelemetryData.Project> projects = new ArrayList<>(); + for (ProjectMeasureDto measure : measures) { + for (String measureTextValue : measure.getTextValue().split(";")) { + String[] languageAndLoc = measureTextValue.split("="); + String language = languageAndLoc[0]; + Long loc = Long.parseLong(languageAndLoc[1]); + projects.add(new TelemetryData.Project(measure.getProjectUuid(), measure.getLastAnalysis(), language, loc)); + } + } + data.setProjects(projects); } setSecurityCustomConfigIfPresent(data); @@ -168,40 +210,33 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { }); } - private void addScmInformationToTelemetry(DbSession dbSession, TelemetryData.Builder data) { - Map<String, Long> projectCountPerScmDetected = dbClient.analysisPropertiesDao() - .selectProjectCountPerAnalysisPropertyValueInLastAnalysis(dbSession, CorePropertyDefinitions.SONAR_ANALYSIS_DETECTEDSCM) + private Map<String, String> getAnalysisPropertyByProject(DbSession dbSession, String analysisPropertyKey) { + return dbClient.analysisPropertiesDao() + .selectAnalysisPropertyValueInLastAnalysisPerProject(dbSession, analysisPropertyKey) .stream() - .collect(Collectors.toMap(ProjectCountPerAnalysisPropertyValue::getPropertyValue, ProjectCountPerAnalysisPropertyValue::getCount)); - data.setProjectCountByScm(projectCountPerScmDetected); + .collect(Collectors.toMap(AnalysisPropertyValuePerProject::getProjectUuid, AnalysisPropertyValuePerProject::getPropertyValue)); } - private void addCiInformationToTelemetry(DbSession dbSession, TelemetryData.Builder data) { - Map<String, Long> projectCountPerCiDetected = dbClient.analysisPropertiesDao() - .selectProjectCountPerAnalysisPropertyValueInLastAnalysis(dbSession, CorePropertyDefinitions.SONAR_ANALYSIS_DETECTEDCI) - .stream() - .collect(Collectors.toMap(ProjectCountPerAnalysisPropertyValue::getPropertyValue, ProjectCountPerAnalysisPropertyValue::getCount)); - data.setProjectCountByCi(projectCountPerCiDetected); + private Map<String, ProjectAlmKeyAndProject> getAlmAndUrlByProject(DbSession dbSession) { + List<ProjectAlmKeyAndProject> projectAlmKeyAndProjects = dbClient.projectAlmSettingDao().selectAlmTypeAndUrlByProject(dbSession); + return projectAlmKeyAndProjects.stream().collect(Collectors.toMap(ProjectAlmKeyAndProject::getProjectUuid, Function.identity())); } - private Map<String, Long> countAlmUsage(DbSession dbSession) { - return dbClient.almSettingDao().selectAll(dbSession).stream() - .collect(Collectors.groupingBy(almSettingDto -> { - if (checkIfCloudAlm(almSettingDto, ALM.GITHUB, "https://api.github.com")) { - return "github_cloud"; - } else if (checkIfCloudAlm(almSettingDto, ALM.GITLAB, "https://gitlab.com/api/v4")) { - return "gitlab_cloud"; - } else if (checkIfCloudAlm(almSettingDto, ALM.AZURE_DEVOPS, "https://dev.azure.com")) { - return "azure_devops_cloud"; - } else if (ALM.BITBUCKET_CLOUD.equals(almSettingDto.getAlm())) { - return almSettingDto.getRawAlm(); - } - return almSettingDto.getRawAlm() + "_server"; - }, Collectors.counting())); + private static String getAlmName(String alm, String url) { + if (checkIfCloudAlm(alm, ALM.GITHUB.getId(), url, "https://api.github.com")) { + return "github_cloud"; + } else if (checkIfCloudAlm(alm, ALM.GITLAB.getId(), url, "https://gitlab.com/api/v4")) { + return "gitlab_cloud"; + } else if (checkIfCloudAlm(alm, ALM.AZURE_DEVOPS.getId(), url, "https://dev.azure.com")) { + return "azure_devops_cloud"; + } else if (ALM.BITBUCKET_CLOUD.getId().equals(alm)) { + return alm; + } + return alm + "_server"; } - private static boolean checkIfCloudAlm(AlmSettingDto almSettingDto, ALM alm, String url) { - return alm.equals(almSettingDto.getAlm()) && startsWith(almSettingDto.getUrl(), url); + private static boolean checkIfCloudAlm(String almRaw, String alm, String url, String cloudUrl) { + return alm.equals(almRaw) && startsWithIgnoreCase(url, cloudUrl); } @Override diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java index 1a4f4b48d82..155a3598d0f 100644 --- a/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java +++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java @@ -65,10 +65,7 @@ public class TelemetryDaemonTest { .setServerId("foo") .setVersion("bar") .setPlugins(Collections.emptyMap()) - .setAlmIntegrationCountByAlm(Collections.emptyMap()) .setExternalAuthenticationProviders(singletonList("github")) - .setProjectCountByScm(Collections.emptyMap()) - .setProjectCountByCi(Collections.emptyMap()) .setProjectMeasuresStatistics(ProjectMeasuresStatistics.builder() .setProjectCount(12) .setProjectCountByLanguage(Collections.emptyMap()) diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDataLoaderImplTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDataLoaderImplTest.java index 1d3fac27fe6..590bcef4b18 100644 --- a/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDataLoaderImplTest.java +++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDataLoaderImplTest.java @@ -23,6 +23,7 @@ import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import java.util.stream.IntStream; import org.junit.Rule; import org.junit.Test; @@ -33,8 +34,13 @@ import org.sonar.core.platform.PluginInfo; import org.sonar.core.platform.PluginRepository; import org.sonar.db.DbSession; import org.sonar.db.DbTester; +import org.sonar.db.alm.setting.AlmSettingDto; +import org.sonar.db.component.AnalysisPropertyDto; import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.SnapshotDto; import org.sonar.db.metric.MetricDto; +import org.sonar.db.user.UserDto; +import org.sonar.db.user.UserTelemetryDto; import org.sonar.server.es.EsTester; import org.sonar.server.measure.index.ProjectMeasuresIndex; import org.sonar.server.measure.index.ProjectMeasuresIndexer; @@ -50,6 +56,7 @@ import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; +import static org.assertj.core.groups.Tuple.tuple; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; @@ -57,6 +64,8 @@ import static org.sonar.api.measures.CoreMetrics.COVERAGE_KEY; import static org.sonar.api.measures.CoreMetrics.LINES_KEY; import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; import static org.sonar.api.measures.CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY; +import static org.sonar.core.config.CorePropertyDefinitions.SONAR_ANALYSIS_DETECTEDCI; +import static org.sonar.core.config.CorePropertyDefinitions.SONAR_ANALYSIS_DETECTEDSCM; import static org.sonar.core.platform.EditionProvider.Edition.COMMUNITY; import static org.sonar.core.platform.EditionProvider.Edition.DEVELOPER; import static org.sonar.core.platform.EditionProvider.Edition.ENTERPRISE; @@ -93,15 +102,24 @@ public class TelemetryDataLoaderImplTest { public void send_telemetry_data() { String serverId = "AU-TpxcB-iU5OvuD2FL7"; String version = "7.5.4"; + Long analysisDate = 1L; + Long lastConnectionDate = 5L; + server.setId(serverId); server.setVersion(version); List<PluginInfo> plugins = asList(newPlugin("java", "4.12.0.11033"), newPlugin("scmgit", "1.2"), new PluginInfo("other")); when(pluginRepository.getPluginInfos()).thenReturn(plugins); when(editionProvider.get()).thenReturn(Optional.of(DEVELOPER)); - int userCount = 3; - IntStream.range(0, userCount).forEach(i -> db.users().insertUser(u -> u.setExternalIdentityProvider("provider" + i))); - db.users().insertUser(u -> u.setActive(false).setExternalIdentityProvider("provider0")); + int activeUserCount = 3; + List<UserDto> activeUsers = IntStream.range(0, activeUserCount).mapToObj(i -> db.users().insertUser( + u -> u.setExternalIdentityProvider("provider" + i).setLastSonarlintConnectionDate(i * 2L))) + .collect(Collectors.toList()); + + // update last connection + activeUsers.forEach(u -> db.users().updateLastConnectionDate(u, 5L)); + + UserDto inactiveUser = db.users().insertUser(u -> u.setActive(false).setExternalIdentityProvider("provider0")); userIndexer.indexAll(); MetricDto lines = db.measures().insertMetric(m -> m.setKey(LINES_KEY)); @@ -109,29 +127,37 @@ public class TelemetryDataLoaderImplTest { MetricDto coverage = db.measures().insertMetric(m -> m.setKey(COVERAGE_KEY)); MetricDto nclocDistrib = db.measures().insertMetric(m -> m.setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY)); - ComponentDto project1 = db.components().insertPublicProject(); - ComponentDto project1Branch = db.components().insertProjectBranch(project1); - db.measures().insertLiveMeasure(project1, lines, m -> m.setValue(200d)); - db.measures().insertLiveMeasure(project1, ncloc, m -> m.setValue(100d)); + ComponentDto project1 = db.components().insertPrivateProject(); + db.measures().insertLiveMeasure(project1, lines, m -> m.setValue(110d)); + db.measures().insertLiveMeasure(project1, ncloc, m -> m.setValue(110d)); db.measures().insertLiveMeasure(project1, coverage, m -> m.setValue(80d)); - db.measures().insertLiveMeasure(project1, nclocDistrib, m -> m.setValue(null).setData("java=200;js=50")); + db.measures().insertLiveMeasure(project1, nclocDistrib, m -> m.setValue(null).setData("java=70;js=30;kotlin=10")); - ComponentDto project2 = db.components().insertPublicProject(); - db.measures().insertLiveMeasure(project2, lines, m -> m.setValue(300d)); + ComponentDto project2 = db.components().insertPrivateProject(); + db.measures().insertLiveMeasure(project2, lines, m -> m.setValue(200d)); db.measures().insertLiveMeasure(project2, ncloc, m -> m.setValue(200d)); db.measures().insertLiveMeasure(project2, coverage, m -> m.setValue(80d)); - db.measures().insertLiveMeasure(project2, nclocDistrib, m -> m.setValue(null).setData("java=300;kotlin=2500")); - projectMeasuresIndexer.indexAll(); + db.measures().insertLiveMeasure(project2, nclocDistrib, m -> m.setValue(null).setData("java=180;js=20")); + + SnapshotDto project1Analysis = db.components().insertSnapshot(project1, t -> t.setLast(true).setBuildDate(analysisDate)); + SnapshotDto project2Analysis = db.components().insertSnapshot(project2, t -> t.setLast(true).setBuildDate(analysisDate)); + db.measures().insertMeasure(project1, project1Analysis, nclocDistrib, m -> m.setData("java=70;js=30;kotlin=10")); + db.measures().insertMeasure(project2, project2Analysis, nclocDistrib, m -> m.setData("java=180;js=20")); + + insertAnalysisProperty(project1Analysis, "prop-uuid-1", SONAR_ANALYSIS_DETECTEDCI, "ci-1"); + insertAnalysisProperty(project2Analysis, "prop-uuid-2", SONAR_ANALYSIS_DETECTEDCI, "ci-2"); + insertAnalysisProperty(project1Analysis, "prop-uuid-3", SONAR_ANALYSIS_DETECTEDSCM, "scm-1"); + insertAnalysisProperty(project2Analysis, "prop-uuid-4", SONAR_ANALYSIS_DETECTEDSCM, "scm-2"); // alm db.almSettings().insertAzureAlmSetting(); - db.almSettings().insertAzureAlmSetting(a -> a.setUrl("https://dev.azure.com")); - db.almSettings().insertBitbucketAlmSetting(); - db.almSettings().insertBitbucketCloudAlmSetting(); db.almSettings().insertGitHubAlmSetting(); - db.almSettings().insertGitHubAlmSetting(a -> a.setUrl("https://api.github.com")); - db.almSettings().insertGitlabAlmSetting(); - db.almSettings().insertGitlabAlmSetting(a -> a.setUrl("https://gitlab.com/api/v4")); + AlmSettingDto almSettingDto = db.almSettings().insertAzureAlmSetting(a -> a.setUrl("https://dev.azure.com")); + AlmSettingDto gitHubAlmSetting = db.almSettings().insertGitHubAlmSetting(a -> a.setUrl("https://api.github.com")); + db.almSettings().insertAzureProjectAlmSetting(almSettingDto, db.components().getProjectDto(project1)); + db.almSettings().insertGitlabProjectAlmSetting(gitHubAlmSetting, db.components().getProjectDto(project2)); + + projectMeasuresIndexer.indexAll(); TelemetryData data = communityUnderTest.load(); assertThat(data.getServerId()).isEqualTo(serverId); @@ -140,24 +166,39 @@ public class TelemetryDataLoaderImplTest { assertDatabaseMetadata(data.getDatabase()); assertThat(data.getPlugins()).containsOnly( entry("java", "4.12.0.11033"), entry("scmgit", "1.2"), entry("other", "undefined")); - assertThat(data.getUserCount()).isEqualTo(userCount); + assertThat(data.getUserCount()).isEqualTo(activeUserCount); assertThat(data.getProjectCount()).isEqualTo(2L); - assertThat(data.getNcloc()).isEqualTo(300L); + assertThat(data.getNcloc()).isEqualTo(310L); assertThat(data.getProjectCountByLanguage()).containsOnly( - entry("java", 2L), entry("kotlin", 1L), entry("js", 1L)); + entry("java", 2L), entry("kotlin", 1L), entry("js", 2L)); assertThat(data.getNclocByLanguage()).containsOnly( - entry("java", 500L), entry("kotlin", 2500L), entry("js", 50L)); + entry("java", 250L), entry("kotlin", 10L), entry("js", 50L)); assertThat(data.isInDocker()).isFalse(); - assertThat(data.getAlmIntegrationCountByAlm()) - .containsEntry("azure_devops_server", 1L) - .containsEntry("azure_devops_cloud", 1L) - .containsEntry("bitbucket_server", 1L) - .containsEntry("bitbucket_cloud", 1L) - .containsEntry("gitlab_server", 1L) - .containsEntry("gitlab_cloud", 1L) - .containsEntry("github_cloud", 1L) - .containsEntry("github_server", 1L); assertThat(data.getExternalAuthenticationProviders()).containsExactlyInAnyOrder("provider0", "provider1", "provider2"); + + assertThat(data.getUserTelemetries()) + .extracting(UserTelemetryDto::getUuid, UserTelemetryDto::getLastConnectionDate, UserTelemetryDto::getLastSonarlintConnectionDate, UserTelemetryDto::isActive) + .containsExactlyInAnyOrder( + tuple(activeUsers.get(0).getUuid(), lastConnectionDate, activeUsers.get(0).getLastSonarlintConnectionDate(), true), + tuple(activeUsers.get(1).getUuid(), lastConnectionDate, activeUsers.get(1).getLastSonarlintConnectionDate(), true), + tuple(activeUsers.get(2).getUuid(), lastConnectionDate, activeUsers.get(2).getLastSonarlintConnectionDate(), true), + tuple(inactiveUser.getUuid(), null, inactiveUser.getLastSonarlintConnectionDate(), false)); + assertThat(data.getProjects()) + .extracting(TelemetryData.Project::getProjectUuid, TelemetryData.Project::getLanguage, TelemetryData.Project::getLoc, TelemetryData.Project::getLastAnalysis) + .containsExactlyInAnyOrder( + tuple(project1.uuid(), "java", 70L, analysisDate), + tuple(project1.uuid(), "js", 30L, analysisDate), + tuple(project1.uuid(), "kotlin", 10L, analysisDate), + tuple(project2.uuid(), "java", 180L, analysisDate), + tuple(project2.uuid(), "js", 20L, analysisDate) + ); + assertThat(data.getProjectStatistics()) + .extracting(TelemetryData.ProjectStatistics::getBranchCount, TelemetryData.ProjectStatistics::getPullRequestCount, + TelemetryData.ProjectStatistics::getScm, TelemetryData.ProjectStatistics::getCi, TelemetryData.ProjectStatistics::getAlm) + .containsExactlyInAnyOrder( + tuple(1L, 0L, "scm-1", "ci-1", "azure_devops_cloud"), + tuple(1L, 0L, "scm-2", "ci-2", "github_cloud") + ); } private void assertDatabaseMetadata(TelemetryData.Database database) { @@ -205,6 +246,50 @@ public class TelemetryDataLoaderImplTest { } @Test + public void take_largest_branch_snapshot_project_data() { + server.setId("AU-TpxcB-iU5OvuD2FL7").setVersion("7.5.4"); + + MetricDto lines = db.measures().insertMetric(m -> m.setKey(LINES_KEY)); + MetricDto ncloc = db.measures().insertMetric(m -> m.setKey(NCLOC_KEY)); + MetricDto coverage = db.measures().insertMetric(m -> m.setKey(COVERAGE_KEY)); + MetricDto nclocDistrib = db.measures().insertMetric(m -> m.setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY)); + + ComponentDto project = db.components().insertPublicProject(); + db.measures().insertLiveMeasure(project, lines, m -> m.setValue(110d)); + db.measures().insertLiveMeasure(project, ncloc, m -> m.setValue(110d)); + db.measures().insertLiveMeasure(project, coverage, m -> m.setValue(80d)); + db.measures().insertLiveMeasure(project, nclocDistrib, m -> m.setValue(null).setData("java=70;js=30;kotlin=10")); + + ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BRANCH)); + db.measures().insertLiveMeasure(branch, lines, m -> m.setValue(180d)); + db.measures().insertLiveMeasure(branch, ncloc, m -> m.setValue(180d)); + db.measures().insertLiveMeasure(branch, coverage, m -> m.setValue(80d)); + db.measures().insertLiveMeasure(branch, nclocDistrib, m -> m.setValue(null).setData("java=100;js=50;kotlin=30")); + + SnapshotDto project1Analysis = db.components().insertSnapshot(project, t -> t.setLast(true)); + SnapshotDto project2Analysis = db.components().insertSnapshot(branch, t -> t.setLast(true)); + db.measures().insertMeasure(project, project1Analysis, nclocDistrib, m -> m.setData("java=70;js=30;kotlin=10")); + db.measures().insertMeasure(branch, project2Analysis, nclocDistrib, m -> m.setData("java=100;js=50;kotlin=30")); + + projectMeasuresIndexer.indexAll(); + + TelemetryData data = communityUnderTest.load(); + + assertThat(data.getProjects()).extracting(TelemetryData.Project::getProjectUuid, TelemetryData.Project::getLanguage, TelemetryData.Project::getLoc) + .containsExactlyInAnyOrder( + tuple(project.uuid(), "java", 100L), + tuple(project.uuid(), "js", 50L), + tuple(project.uuid(), "kotlin", 30L) + ); + assertThat(data.getProjectStatistics()) + .extracting(TelemetryData.ProjectStatistics::getBranchCount, TelemetryData.ProjectStatistics::getPullRequestCount, + TelemetryData.ProjectStatistics::getScm, TelemetryData.ProjectStatistics::getCi) + .containsExactlyInAnyOrder( + tuple(2L, 0L, "undetected", "undetected") + ); + } + + @Test public void data_contains_no_license_type_on_community_edition() { TelemetryData data = communityUnderTest.load(); @@ -351,9 +436,29 @@ public class TelemetryDataLoaderImplTest { assertThat(data.getCustomSecurityConfigs()).isEmpty(); } + @Test + public void undetected_alm_ci_slm_data() { + server.setId("AU-TpxcB-iU5OvuD2FL7").setVersion("7.5.4"); + db.components().insertPublicProject(); + projectMeasuresIndexer.indexAll(); + TelemetryData data = communityUnderTest.load(); + assertThat(data.getProjectStatistics()) + .extracting(TelemetryData.ProjectStatistics::getAlm, TelemetryData.ProjectStatistics::getScm, TelemetryData.ProjectStatistics::getCi) + .containsExactlyInAnyOrder(tuple("undetected", "undetected", "undetected")); + } + private PluginInfo newPlugin(String key, String version) { return new PluginInfo(key) .setVersion(Version.create(version)); } + private void insertAnalysisProperty(SnapshotDto snapshotDto, String uuid, String key, String value) { + db.getDbClient().analysisPropertiesDao().insert(db.getSession(), new AnalysisPropertyDto() + .setUuid(uuid) + .setAnalysisUuid(snapshotDto.getUuid()) + .setKey(key) + .setValue(value) + .setCreatedAt(1L)); + } + } |