Browse Source

SONAR-10834 Send the edition to telemetry

tags/7.5
Simon Brandhof 6 years ago
parent
commit
7779a568c2

+ 15
- 0
server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryData.java View File

package org.sonar.server.telemetry; package org.sonar.server.telemetry;


import java.util.Map; import java.util.Map;
import java.util.Optional;
import org.sonar.core.platform.EditionProvider;
import org.sonar.server.measure.index.ProjectMeasuresStatistics; import org.sonar.server.measure.index.ProjectMeasuresStatistics;


import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNull;
private final Database database; private final Database database;
private final Map<String, Long> projectCountByLanguage; private final Map<String, Long> projectCountByLanguage;
private final Map<String, Long> nclocByLanguage; private final Map<String, Long> nclocByLanguage;
private final Optional<EditionProvider.Edition> edition;


private TelemetryData(Builder builder) { private TelemetryData(Builder builder) {
serverId = builder.serverId; serverId = builder.serverId;
database = builder.database; database = builder.database;
projectCountByLanguage = builder.projectMeasuresStatistics.getProjectCountByLanguage(); projectCountByLanguage = builder.projectMeasuresStatistics.getProjectCountByLanguage();
nclocByLanguage = builder.projectMeasuresStatistics.getNclocByLanguage(); nclocByLanguage = builder.projectMeasuresStatistics.getNclocByLanguage();
edition = builder.edition;
} }


public String getServerId() { public String getServerId() {
return nclocByLanguage; return nclocByLanguage;
} }


public Optional<EditionProvider.Edition> getEdition() {
return edition;
}

static Builder builder() { static Builder builder() {
return new Builder(); return new Builder();
} }
private ProjectMeasuresStatistics projectMeasuresStatistics; private ProjectMeasuresStatistics projectMeasuresStatistics;
private Long ncloc; private Long ncloc;
private Boolean usingBranches; private Boolean usingBranches;
private Optional<EditionProvider.Edition> edition;


private Builder() { private Builder() {
// enforce static factory method // enforce static factory method
return this; return this;
} }


public Builder setEdition(Optional<EditionProvider.Edition> edition) {
this.edition = edition;
return this;
}

TelemetryData build() { TelemetryData build() {
requireNonNull(serverId); requireNonNull(serverId);
requireNonNull(version); requireNonNull(version);
requireNonNull(ncloc); requireNonNull(ncloc);
requireNonNull(database); requireNonNull(database);
requireNonNull(usingBranches); requireNonNull(usingBranches);
requireNonNull(edition);


return new TelemetryData(this); return new TelemetryData(this);
} }

+ 2
- 0
server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDataJsonWriter.java View File

*/ */
package org.sonar.server.telemetry; package org.sonar.server.telemetry;


import java.util.Locale;
import org.sonar.api.utils.text.JsonWriter; import org.sonar.api.utils.text.JsonWriter;


import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY;
json.beginObject(); json.beginObject();
json.prop("id", statistics.getServerId()); json.prop("id", statistics.getServerId());
json.prop("version", statistics.getVersion()); json.prop("version", statistics.getVersion());
statistics.getEdition().ifPresent(e -> json.prop("edition", e.name().toLowerCase(Locale.ENGLISH)));
json.name("database"); json.name("database");
json.beginObject(); json.beginObject();
json.prop("name", statistics.getDatabase().getName()); json.prop("name", statistics.getDatabase().getName());

+ 6
- 1
server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDataLoader.java View File

import org.sonar.api.ce.ComputeEngineSide; import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.platform.Server; import org.sonar.api.platform.Server;
import org.sonar.api.server.ServerSide; import org.sonar.api.server.ServerSide;
import org.sonar.core.platform.PlatformEditionProvider;
import org.sonar.core.platform.PluginInfo; import org.sonar.core.platform.PluginInfo;
import org.sonar.core.platform.PluginRepository; import org.sonar.core.platform.PluginRepository;
import org.sonar.core.util.stream.MoreCollectors; import org.sonar.core.util.stream.MoreCollectors;
private final PluginRepository pluginRepository; private final PluginRepository pluginRepository;
private final UserIndex userIndex; private final UserIndex userIndex;
private final ProjectMeasuresIndex projectMeasuresIndex; private final ProjectMeasuresIndex projectMeasuresIndex;
private final PlatformEditionProvider editionProvider;


public TelemetryDataLoader(Server server, DbClient dbClient, PluginRepository pluginRepository, UserIndex userIndex, ProjectMeasuresIndex projectMeasuresIndex) {
public TelemetryDataLoader(Server server, DbClient dbClient, PluginRepository pluginRepository, UserIndex userIndex, ProjectMeasuresIndex projectMeasuresIndex,
PlatformEditionProvider editionProvider) {
this.server = server; this.server = server;
this.dbClient = dbClient; this.dbClient = dbClient;
this.pluginRepository = pluginRepository; this.pluginRepository = pluginRepository;
this.userIndex = userIndex; this.userIndex = userIndex;
this.projectMeasuresIndex = projectMeasuresIndex; this.projectMeasuresIndex = projectMeasuresIndex;
this.editionProvider = editionProvider;
} }


public TelemetryData load() { public TelemetryData load() {


data.setServerId(server.getId()); data.setServerId(server.getId());
data.setVersion(server.getVersion()); data.setVersion(server.getVersion());
data.setEdition(editionProvider.get());
Function<PluginInfo, String> getVersion = plugin -> plugin.getVersion() == null ? "undefined" : plugin.getVersion().getName(); 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)); Map<String, String> plugins = pluginRepository.getPluginInfos().stream().collect(MoreCollectors.uniqueIndex(PluginInfo::getKey, getVersion));
data.setPlugins(plugins); data.setPlugins(plugins);

+ 17
- 8
server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java View File

import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.stream.IntStream; import java.util.stream.IntStream;
import org.junit.After; import org.junit.After;
import org.junit.Rule; import org.junit.Rule;
import org.sonar.api.utils.internal.TestSystem2; import org.sonar.api.utils.internal.TestSystem2;
import org.sonar.api.utils.log.LogTester; import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel; import org.sonar.api.utils.log.LoggerLevel;
import org.sonar.core.platform.EditionProvider;
import org.sonar.core.platform.PlatformEditionProvider;
import org.sonar.core.platform.PluginInfo; import org.sonar.core.platform.PluginInfo;
import org.sonar.core.platform.PluginRepository; import org.sonar.core.platform.PluginRepository;
import org.sonar.db.DbSession; import org.sonar.db.DbSession;
private MapSettings settings = new MapSettings(); private MapSettings settings = new MapSettings();
private ProjectMeasuresIndexer projectMeasuresIndexer = new ProjectMeasuresIndexer(db.getDbClient(), es.client()); private ProjectMeasuresIndexer projectMeasuresIndexer = new ProjectMeasuresIndexer(db.getDbClient(), es.client());
private UserIndexer userIndexer = new UserIndexer(db.getDbClient(), es.client()); private UserIndexer userIndexer = new UserIndexer(db.getDbClient(), es.client());
private PlatformEditionProvider editionProvider = mock(PlatformEditionProvider.class);


private TelemetryDaemon underTest = new TelemetryDaemon(new TelemetryDataLoader(server, db.getDbClient(), pluginRepository, new UserIndex(es.client(), system2),
new ProjectMeasuresIndex(es.client(), null, system2)), client, settings.asConfig(), internalProperties, system2);
private final TelemetryDataLoader dataLoader = new TelemetryDataLoader(server, db.getDbClient(), pluginRepository, new UserIndex(es.client(), system2),
new ProjectMeasuresIndex(es.client(), null, system2), editionProvider);
private TelemetryDaemon underTest = new TelemetryDaemon(dataLoader, client, settings.asConfig(), internalProperties, system2);


@After @After
public void tearDown() { public void tearDown() {
server.setVersion("7.5.4"); server.setVersion("7.5.4");
List<PluginInfo> plugins = asList(newPlugin("java", "4.12.0.11033"), newPlugin("scmgit", "1.2"), new PluginInfo("other")); List<PluginInfo> plugins = asList(newPlugin("java", "4.12.0.11033"), newPlugin("scmgit", "1.2"), new PluginInfo("other"));
when(pluginRepository.getPluginInfos()).thenReturn(plugins); when(pluginRepository.getPluginInfos()).thenReturn(plugins);
when(editionProvider.get()).thenReturn(Optional.of(EditionProvider.Edition.DEVELOPER));


IntStream.range(0, 3).forEach(i -> db.users().insertUser()); IntStream.range(0, 3).forEach(i -> db.users().insertUser());
db.users().insertUser(u -> u.setActive(false)); db.users().insertUser(u -> u.setActive(false));


underTest.start(); underTest.start();


ArgumentCaptor<String> jsonCaptor = ArgumentCaptor.forClass(String.class);
verify(client, timeout(2_000).atLeastOnce()).upload(jsonCaptor.capture());
ArgumentCaptor<String> jsonCaptor = captureJson();
String json = jsonCaptor.getValue(); String json = jsonCaptor.getValue();
assertJson(json).ignoreFields("database").isSimilarTo(getClass().getResource("telemetry-example.json")); assertJson(json).ignoreFields("database").isSimilarTo(getClass().getResource("telemetry-example.json"));
assertJson(getClass().getResource("telemetry-example.json")).ignoreFields("database").isSimilarTo(json); assertJson(getClass().getResource("telemetry-example.json")).ignoreFields("database").isSimilarTo(json);


underTest.start(); underTest.start();


ArgumentCaptor<String> jsonCaptor = ArgumentCaptor.forClass(String.class);
verify(client, timeout(2_000).atLeastOnce()).upload(jsonCaptor.capture());
ArgumentCaptor<String> jsonCaptor = captureJson();
assertJson(jsonCaptor.getValue()).isSimilarTo("{\n" + assertJson(jsonCaptor.getValue()).isSimilarTo("{\n" +
" \"ncloc\": 20\n" + " \"ncloc\": 20\n" +
"}\n"); "}\n");
server.setVersion(version); server.setVersion(version);
underTest.start(); underTest.start();


ArgumentCaptor<String> json = ArgumentCaptor.forClass(String.class);
verify(client, timeout(2_000).atLeastOnce()).upload(json.capture());
ArgumentCaptor<String> json = captureJson();
assertThat(json.getValue()).contains(id, version); assertThat(json.getValue()).contains(id, version);
} }


settings.setProperty(SONAR_TELEMETRY_URL.getKey(), SONAR_TELEMETRY_URL.getDefaultValue()); settings.setProperty(SONAR_TELEMETRY_URL.getKey(), SONAR_TELEMETRY_URL.getDefaultValue());
settings.setProperty(SONAR_TELEMETRY_FREQUENCY_IN_SECONDS.getKey(), SONAR_TELEMETRY_FREQUENCY_IN_SECONDS.getDefaultValue()); settings.setProperty(SONAR_TELEMETRY_FREQUENCY_IN_SECONDS.getKey(), SONAR_TELEMETRY_FREQUENCY_IN_SECONDS.getDefaultValue());
} }

private ArgumentCaptor<String> captureJson() throws IOException {
ArgumentCaptor<String> jsonCaptor = ArgumentCaptor.forClass(String.class);
verify(client, timeout(2_000).atLeastOnce()).upload(jsonCaptor.capture());
return jsonCaptor;
}
} }

+ 1
- 0
server/sonar-server/src/test/resources/org/sonar/server/telemetry/telemetry-example.json View File

{ {
"id": "AU-TpxcB-iU5OvuD2FL7", "id": "AU-TpxcB-iU5OvuD2FL7",
"version": "7.5.4", "version": "7.5.4",
"edition": "developer",
"database": { "database": {
"name": "PostgreSQL", "name": "PostgreSQL",
"version": "9.6.5" "version": "9.6.5"

Loading…
Cancel
Save