diff options
author | Teryk Bellahsene <teryk.bellahsene@sonarsource.com> | 2017-08-25 17:27:19 +0200 |
---|---|---|
committer | Teryk Bellahsene <teryk@users.noreply.github.com> | 2017-08-30 16:24:53 +0200 |
commit | 518a2a6b1ab13528353fd2c12f8870fb63a05823 (patch) | |
tree | 688139b5d3f23b336c4cf068039bec374a90d6ca /server | |
parent | 1c6140eb0fcf46beeb5e9785689e19c45ff135a8 (diff) | |
download | sonarqube-518a2a6b1ab13528353fd2c12f8870fb63a05823.tar.gz sonarqube-518a2a6b1ab13528353fd2c12f8870fb63a05823.zip |
SONAR-9721 Extract TelemetryDataLoader from TelemetryDataDaemon
Diffstat (limited to 'server')
8 files changed, 229 insertions, 33 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryClient.java b/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryClient.java index 1bc8a656b67..51f5e86f461 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryClient.java +++ b/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryClient.java @@ -59,7 +59,7 @@ public class TelemetryClient { try { okHttpClient.newCall(request.build()).execute(); } catch (IOException e) { - LOG.debug("Error when sending opt-out usage statistics: %s", e.getMessage()); + LOG.debug("Error when sending opt-out usage statistics: {}", e.getMessage()); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDaemon.java b/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDaemon.java index 24ae7cc22cb..a32c66e04c6 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDaemon.java +++ b/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDaemon.java @@ -29,19 +29,12 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import org.picocontainer.Startable; import org.sonar.api.config.Configuration; -import org.sonar.api.platform.Server; import org.sonar.api.server.ServerSide; import org.sonar.api.utils.System2; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.api.utils.text.JsonWriter; -import org.sonar.core.platform.PluginRepository; -import org.sonar.server.es.SearchOptions; -import org.sonar.server.measure.index.ProjectMeasuresIndex; -import org.sonar.server.measure.index.ProjectMeasuresStatistics; import org.sonar.server.property.InternalProperties; -import org.sonar.server.user.index.UserIndex; -import org.sonar.server.user.index.UserQuery; import static org.sonar.api.measures.CoreMetrics.LINES_KEY; import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; @@ -59,27 +52,20 @@ public class TelemetryDaemon implements Startable { static final String I_PROP_OPT_OUT = "telemetry.optOut"; private static final Logger LOG = Loggers.get(TelemetryDaemon.class); + private final TelemetryDataLoader dataLoader; private final TelemetryClient telemetryClient; private final Configuration config; private final InternalProperties internalProperties; - private final Server server; - private final PluginRepository pluginRepository; private final System2 system2; - private final UserIndex userIndex; - private final ProjectMeasuresIndex projectMeasuresIndex; private ScheduledExecutorService executorService; - public TelemetryDaemon(TelemetryClient telemetryClient, Configuration config, InternalProperties internalProperties, Server server, PluginRepository pluginRepository, - System2 system2, UserIndex userIndex, ProjectMeasuresIndex projectMeasuresIndex) { + public TelemetryDaemon(TelemetryDataLoader dataLoader, TelemetryClient telemetryClient, Configuration config, InternalProperties internalProperties, System2 system2) { + this.dataLoader = dataLoader; this.telemetryClient = telemetryClient; this.config = config; this.internalProperties = internalProperties; - this.server = server; - this.pluginRepository = pluginRepository; this.system2 = system2; - this.userIndex = userIndex; - this.projectMeasuresIndex = projectMeasuresIndex; } @Override @@ -139,28 +125,22 @@ public class TelemetryDaemon implements Startable { StringWriter json = new StringWriter(); try (JsonWriter writer = JsonWriter.of(json)) { writer.beginObject(); - writer.prop("id", server.getId()); + writer.prop("id", dataLoader.loadServerId()); writer.endObject(); } telemetryClient.optOut(json.toString()); } private void uploadStatistics() throws IOException { + TelemetryData statistics = dataLoader.load(); StringWriter json = new StringWriter(); try (JsonWriter writer = JsonWriter.of(json)) { writer.beginObject(); - writer.prop("id", server.getId()); - writer.prop("version", server.getVersion()); + writer.prop("id", statistics.getServerId()); + writer.prop("version", statistics.getVersion()); writer.name("plugins"); - writer.beginObject(); - pluginRepository.getPluginInfos().forEach(plugin -> { - String version = plugin.getVersion() == null ? "undefined" : plugin.getVersion().getName(); - writer.prop(plugin.getKey(), version); - }); - writer.endObject(); - long userCount = userIndex.search(UserQuery.builder().build(), new SearchOptions().setLimit(1)).getTotal(); - writer.prop("userCount", userCount); - ProjectMeasuresStatistics statistics = projectMeasuresIndex.searchTelemetryStatistics(); + writer.valueObject(statistics.getPlugins()); + writer.prop("userCount", statistics.getUserCount()); writer.prop("projectCount", statistics.getProjectCount()); writer.prop(LINES_KEY, statistics.getLines()); writer.prop(NCLOC_KEY, statistics.getNcloc()); diff --git a/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryData.java b/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryData.java new file mode 100644 index 00000000000..1d9cb633bb8 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryData.java @@ -0,0 +1,133 @@ +/* + * 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.telemetry; + +import java.util.Map; +import org.sonar.server.measure.index.ProjectMeasuresStatistics; + +import static java.util.Objects.requireNonNull; + +public class TelemetryData { + private final String serverId; + private final String version; + private final Map<String, String> plugins; + private final long lines; + private final long ncloc; + private final long userCount; + private final long projectCount; + private final Map<String, Long> projectCountByLanguage; + private final Map<String, Long> nclocByLanguage; + + public TelemetryData(Builder builder) { + serverId = builder.serverId; + version = builder.version; + plugins = builder.plugins; + lines = builder.projectMeasuresStatistics.getLines(); + ncloc = builder.projectMeasuresStatistics.getNcloc(); + userCount = builder.userCount; + projectCount = builder.projectMeasuresStatistics.getProjectCount(); + projectCountByLanguage = builder.projectMeasuresStatistics.getProjectCountByLanguage(); + nclocByLanguage = builder.projectMeasuresStatistics.getNclocByLanguage(); + } + + public String getServerId() { + return serverId; + } + + public String getVersion() { + return version; + } + + public Map<String, String> getPlugins() { + return plugins; + } + + public long getLines() { + return lines; + } + + public long getNcloc() { + return ncloc; + } + + public long getUserCount() { + return userCount; + } + + public long getProjectCount() { + return projectCount; + } + + public Map<String, Long> getProjectCountByLanguage() { + return projectCountByLanguage; + } + + public Map<String, Long> getNclocByLanguage() { + return nclocByLanguage; + } + + static Builder builder() { + return new Builder(); + } + + static class Builder { + private String serverId; + private String version; + private long userCount; + private Map<String, String> plugins; + private ProjectMeasuresStatistics projectMeasuresStatistics; + + private Builder() { + // enforce static factory method + } + + Builder setServerId(String serverId) { + this.serverId = serverId; + return this; + } + + Builder setVersion(String version) { + this.version = version; + return this; + } + + void setUserCount(long userCount) { + this.userCount = userCount; + } + + void setPlugins(Map<String, String> plugins) { + this.plugins = plugins; + } + + void setProjectMeasuresStatistics(ProjectMeasuresStatistics projectMeasuresStatistics) { + this.projectMeasuresStatistics = projectMeasuresStatistics; + } + + TelemetryData build() { + requireNonNull(serverId); + requireNonNull(version); + requireNonNull(plugins); + requireNonNull(projectMeasuresStatistics); + + return new TelemetryData(this); + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDataLoader.java b/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDataLoader.java new file mode 100644 index 00000000000..82749856e50 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDataLoader.java @@ -0,0 +1,69 @@ +/* + * 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.telemetry; + +import java.util.Map; +import java.util.function.Function; +import org.sonar.api.platform.Server; +import org.sonar.api.server.ServerSide; +import org.sonar.core.platform.PluginInfo; +import org.sonar.core.platform.PluginRepository; +import org.sonar.core.util.stream.MoreCollectors; +import org.sonar.server.es.SearchOptions; +import org.sonar.server.measure.index.ProjectMeasuresIndex; +import org.sonar.server.measure.index.ProjectMeasuresStatistics; +import org.sonar.server.user.index.UserIndex; +import org.sonar.server.user.index.UserQuery; + +@ServerSide +public class TelemetryDataLoader { + private final Server server; + private final PluginRepository pluginRepository; + private final UserIndex userIndex; + private final ProjectMeasuresIndex projectMeasuresIndex; + + public TelemetryDataLoader(Server server, PluginRepository pluginRepository, UserIndex userIndex, ProjectMeasuresIndex projectMeasuresIndex) { + this.server = server; + this.pluginRepository = pluginRepository; + this.userIndex = userIndex; + this.projectMeasuresIndex = projectMeasuresIndex; + } + + public TelemetryData load() { + TelemetryData.Builder data = TelemetryData.builder(); + + data.setServerId(server.getId()); + data.setVersion(server.getVersion()); + Function<PluginInfo, String> getVersion = plugin -> plugin.getVersion() == null ? "undefined" : plugin.getVersion().getName(); + Map<String, String> plugins = pluginRepository.getPluginInfos().stream().collect(MoreCollectors.uniqueIndex(PluginInfo::getKey, getVersion)); + data.setPlugins(plugins); + long userCount = userIndex.search(UserQuery.builder().build(), new SearchOptions().setLimit(1)).getTotal(); + data.setUserCount(userCount); + ProjectMeasuresStatistics projectMeasuresStatistics = projectMeasuresIndex.searchTelemetryStatistics(); + data.setProjectMeasuresStatistics(projectMeasuresStatistics); + + return data.build(); + } + + String loadServerId() { + return server.getId(); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryModule.java b/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryModule.java index d9a576458dc..bb2e4a9b298 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryModule.java @@ -25,6 +25,7 @@ public class TelemetryModule extends Module { @Override protected void configureModule() { add( + TelemetryDataLoader.class, TelemetryDaemon.class, TelemetryClient.class); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/telemetry/FakeServer.java b/server/sonar-server/src/test/java/org/sonar/server/telemetry/FakeServer.java index a793b0cc0bb..85237c7c3d6 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/telemetry/FakeServer.java +++ b/server/sonar-server/src/test/java/org/sonar/server/telemetry/FakeServer.java @@ -25,10 +25,17 @@ import java.util.Date; import javax.annotation.CheckForNull; import org.sonar.api.platform.Server; +import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; + class FakeServer extends Server { private String id; private String version; + public FakeServer() { + this.id = randomAlphanumeric(20); + this.version = randomAlphanumeric(10); + } + @Override public String getId() { return id; diff --git a/server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java b/server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java index 0c5f6c179b3..16dc742383d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java @@ -33,6 +33,8 @@ import org.sonar.api.config.Configuration; import org.sonar.api.config.PropertyDefinitions; import org.sonar.api.config.internal.MapSettings; import org.sonar.api.utils.internal.TestSystem2; +import org.sonar.api.utils.log.LogTester; +import org.sonar.api.utils.log.LoggerLevel; import org.sonar.core.config.TelemetryProperties; import org.sonar.core.platform.PluginInfo; import org.sonar.core.platform.PluginRepository; @@ -71,6 +73,8 @@ public class TelemetryDaemonTest { public UserSessionRule userSession = UserSessionRule.standalone(); @Rule public EsTester es = new EsTester(new UserIndexDefinition(emptyConfig), new ProjectMeasuresIndexDefinition(emptyConfig)); + @Rule + public LogTester logger = new LogTester().setLevel(LoggerLevel.DEBUG); private TelemetryClient client = mock(TelemetryClient.class); private InternalProperties internalProperties = new MapInternalProperties(); @@ -86,8 +90,8 @@ public class TelemetryDaemonTest { settings = new MapSettings(new PropertyDefinitions(TelemetryProperties.all())); system2.setNow(System.currentTimeMillis()); - underTest = new TelemetryDaemon(client, settings.asConfig(), internalProperties, server, pluginRepository, system2, new UserIndex(es.client()), - new ProjectMeasuresIndex(es.client(), null)); + underTest = new TelemetryDaemon(new TelemetryDataLoader(server, pluginRepository, new UserIndex(es.client()), new ProjectMeasuresIndex(es.client(), null)), client, + settings.asConfig(), internalProperties, system2); } @Test @@ -121,6 +125,7 @@ public class TelemetryDaemonTest { String json = jsonCaptor.getValue(); assertJson(json).isSimilarTo(getClass().getResource("telemetry-example.json")); assertJson(getClass().getResource("telemetry-example.json")).isSimilarTo(json); + assertThat(logger.logs(LoggerLevel.INFO)).contains("Sharing of SonarQube statistics is enabled."); } @Test @@ -194,6 +199,7 @@ public class TelemetryDaemonTest { verify(client, timeout(1_000).never()).upload(anyString()); verify(client, timeout(1_000).times(1)).optOut(anyString()); + assertThat(logger.logs(LoggerLevel.INFO)).contains("Sharing of SonarQube statistics is disabled."); } private PluginInfo newPlugin(String key, String version) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryModuleTest.java index 7a3e7df1006..57c07eb666f 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryModuleTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryModuleTest.java @@ -29,6 +29,6 @@ public class TelemetryModuleTest { public void verify_count_of_added_components() { ComponentContainer container = new ComponentContainer(); new TelemetryModule().configure(container); - assertThat(container.size()).isEqualTo(2 + 2); + assertThat(container.size()).isEqualTo(3 + 2); } } |