--- /dev/null
+description = 'Module providing the core classes and interfaces for telemetry metrics in SonarQube.'
+
+sonar {
+ properties {
+ property 'sonar.projectName', "${projectTitle} :: Server :: Telemetry Core"
+ }
+}
+
+dependencies {
+ compileOnlyApi 'com.github.spotbugs:spotbugs-annotations'
+
+ implementation 'com.fasterxml.jackson.core:jackson-databind'
+
+ testImplementation(platform("org.junit:junit-bom:5.9.1"))
+ testImplementation 'org.assertj:assertj-core'
+ testImplementation 'org.junit.jupiter:junit-jupiter-api'
+ testImplementation 'org.junit.jupiter:junit-jupiter-params'
+
+ testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
+}
+
+tasks.test {
+ useJUnitPlatform()
+}
\ No newline at end of file
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.telemetry.core;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * Represents the dimension of the data provided by a {@link TelemetryDataProvider}.
+ * {@link Dimension#PROJECT}, {@link Dimension#LANGUAGE} and {@link Dimension#USER} should not provide aggregated data.
+ * For aggregated data (i.e. average number of lines of code per project), use #INSTALLATION.
+ */
+public enum Dimension {
+ INSTALLATION("installation"),
+ USER("user"),
+ PROJECT("project"),
+ LANGUAGE("language");
+
+ private final String value;
+
+ Dimension(String value) {
+ this.value = value;
+ }
+
+ @JsonValue
+ public String getValue() {
+ return value;
+ }
+
+ public static Dimension fromValue(String value) {
+ for (Dimension dimension : Dimension.values()) {
+ if (dimension.value.equalsIgnoreCase(value)) {
+ return dimension;
+ }
+ }
+ throw new IllegalArgumentException("Unknown dimension value: " + value);
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.telemetry.core;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * Represent the granularity of the data provided by a {@link TelemetryDataProvider}. This both defines the time period between to pushes to
+ * telemetry server for a given metric and the time period that the data represents.
+ * Modifying this enum needs to be discussed beforehand with Data Platform team.
+ */
+public enum Granularity {
+ DAILY("daily"),
+ WEEKLY("weekly"),
+ MONTHLY("monthly");
+
+ private final String value;
+
+ Granularity(String value) {
+ this.value = value;
+ }
+
+ @JsonValue
+ public String getValue() {
+ return value;
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.telemetry.core;
+
+import java.util.Map;
+
+/**
+ * This interface is used to provide data to the telemetry system. The telemetry system will call the methods of this interface to get the
+ * data that will be sent to the telemetry server.
+ * If you want to add new metric to the telemetry system, you need to create a new implementation of this interface and register it in the
+ * Spring context as a bean.
+ *
+ * @param <T> type of the value provided by this instance. Should be either {@link Boolean}, {@link String},
+ * {@link Integer} or {@link Float}.
+ */
+public interface TelemetryDataProvider<T> {
+
+ /**
+ * @return the key of the metric that will be used to store the value of the data provided by this instance. The combination of
+ * metric key and dimension needs to be universally unique. The metric key needs to be written in snake_case.
+ */
+ String getMetricKey();
+
+ /**
+ * @return the dimension ("category") of the data provided by this instance. The combination of metric key and dimension needs to be
+ * universally unique.
+ */
+ Dimension getDimension();
+
+ /**
+ * @return returns the granularity of this telemetry metric.
+ * @see Granularity
+ */
+ Granularity getGranularity();
+
+ /**
+ * @return the type of the data provided by this instance.
+ */
+ TelemetryDataType getType();
+
+ /**
+ * The implementation of this method might often need to make a call to a database.
+ * For each metric either this method or {@link TelemetryDataProvider#getUuidValues()} should be implemented and used. Not both at once.
+ *
+ * @return the value of the data provided by this instance.
+ */
+ default T getValue() {
+ throw new IllegalStateException("Not implemented");
+ }
+
+ /**
+ * The implementation of this method might often need to make a call to a database.
+ * Similiar as {@link TelemetryDataProvider#getValue()} this method returns values of the metric. Some of the metrics
+ * associate a UUID with a value. This method is used to return all the values associated with the UUIDs.
+ *
+ * @return map of UUIDs and their values.
+ */
+ default Map<String, T> getUuidValues() {
+ throw new IllegalStateException("Not implemented");
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.telemetry.core;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * Represents the type of the data provided by a {@link TelemetryDataProvider}.
+ * Modifying this enum needs to be discussed beforehand with Data Platform team.
+ */
+public enum TelemetryDataType {
+ BOOLEAN("boolean"),
+ STRING("string"),
+ INTEGER("integer"),
+ FLOAT("float");
+
+ private final String value;
+
+ TelemetryDataType(String value) {
+ this.value = value;
+ }
+
+ @JsonValue
+ public String getValue() {
+ return value;
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.telemetry.core;
+
+import javax.annotation.ParametersAreNonnullByDefault;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.telemetry.core;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class DimensionTest {
+ @Test
+ void getValue() {
+ assertEquals("installation", Dimension.INSTALLATION.getValue());
+ assertEquals("user", Dimension.USER.getValue());
+ assertEquals("project", Dimension.PROJECT.getValue());
+ assertEquals("language", Dimension.LANGUAGE.getValue());
+ }
+
+ @Test
+ void fromValue() {
+ assertEquals(Dimension.INSTALLATION, Dimension.fromValue("installation"));
+ assertEquals(Dimension.USER, Dimension.fromValue("user"));
+ assertEquals(Dimension.PROJECT, Dimension.fromValue("project"));
+ assertEquals(Dimension.LANGUAGE, Dimension.fromValue("language"));
+
+ assertEquals(Dimension.INSTALLATION, Dimension.fromValue("INSTALLATION"));
+ assertEquals(Dimension.USER, Dimension.fromValue("USER"));
+ assertEquals(Dimension.PROJECT, Dimension.fromValue("PROJECT"));
+ assertEquals(Dimension.LANGUAGE, Dimension.fromValue("LANGUAGE"));
+ }
+
+ @Test
+ void fromValue_whenInvalid() {
+ Exception exception = assertThrows(IllegalArgumentException.class, () -> {
+ Dimension.fromValue("invalid");
+ });
+ assertEquals("Unknown dimension value: invalid", exception.getMessage());
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.telemetry.core;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class GranularityTest {
+
+ @Test
+ void getValue() {
+ assertEquals("daily", Granularity.DAILY.getValue());
+ assertEquals("weekly", Granularity.WEEKLY.getValue());
+ assertEquals("monthly", Granularity.MONTHLY.getValue());
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.telemetry.core;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class TelemetryDataTypeTest {
+ @Test
+ void getValue() {
+ assertEquals("integer", TelemetryDataType.INTEGER.getValue());
+ assertEquals("string", TelemetryDataType.STRING.getValue());
+ assertEquals("boolean", TelemetryDataType.BOOLEAN.getValue());
+ assertEquals("float", TelemetryDataType.FLOAT.getValue());
+ }
+
+}
}
dependencies {
+ api project(':server:sonar-telemetry-core')
+
+ implementation project(':server:sonar-process')
+ implementation project(':server:sonar-server-common')
+ implementation project(':server:sonar-webserver-core')
+ implementation project(':server:sonar-webserver-webapi')
+ implementation project(':sonar-core')
+
testImplementation(platform("org.junit:junit-bom:5.9.1"))
testImplementation 'com.squareup.okhttp3:mockwebserver'
testImplementation 'com.tngtech.java:junit-dataprovider'
testImplementation project(':sonar-testing-harness')
testImplementation testFixtures(project(':server:sonar-server-common'))
- api project(':server:sonar-process')
- api project(':server:sonar-server-common')
- api project(':server:sonar-webserver-core')
- api project(':server:sonar-webserver-webapi')
- api project(':sonar-core')
-
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
}
import org.sonar.api.impl.utils.TestSystem2;
import org.sonar.core.util.UuidFactory;
import org.sonar.db.DbTester;
-import org.sonar.telemetry.Dimension;
-import org.sonar.telemetry.TelemetryDataProvider;
import org.sonar.telemetry.FakeServer;
+import org.sonar.telemetry.core.Dimension;
+import org.sonar.telemetry.core.TelemetryDataProvider;
import org.sonar.telemetry.metrics.schema.BaseMessage;
import static org.assertj.core.api.Assertions.assertThat;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 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.telemetry.project;
-
-import java.util.Map;
-import java.util.function.Consumer;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.RegisterExtension;
-import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ProjectData;
-import org.sonar.db.measure.LiveMeasureDto;
-import org.sonar.db.metric.MetricDto;
-import org.sonar.db.project.ProjectDto;
-import org.sonar.telemetry.project.ProjectCppAutoconfigTelemetryProvider;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.api.measures.CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY;
-import static org.sonar.api.measures.Metric.ValueType.STRING;
-
-class ProjectCppAutoconfigTelemetryProviderIT {
-
- private final System2 system2 = new AlwaysIncreasingSystem2(1000L);
-
- @RegisterExtension
- public final DbTester db = DbTester.create(system2);
-
- ProjectCppAutoconfigTelemetryProvider underTest = new ProjectCppAutoconfigTelemetryProvider(db.getDbClient());
-
- @Test
- void getUuidValues_whenNoProjects_returnEmptyList() {
- assertThat(underTest.getUuidValues()).isEmpty();
- }
-
- @Test
- void getUuidValues_whenNoCppAndCProjects_returnEmptyMap() {
- Consumer<MetricDto> configureMetric = metric -> metric
- .setValueType(STRING.name())
- .setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY);
-
- MetricDto metric = db.measures().insertMetric(configureMetric);
-
- ProjectData project1 = db.components().insertPrivateProject();
- ProjectData project2 = db.components().insertPrivateProject();
-
- insertLiveMeasure("java", metric).accept(project1);
- insertLiveMeasure("cobol", metric).accept(project2);
-
-
- assertThat(underTest.getUuidValues()).isEmpty();
- }
-
- @Test
- void getUuidValues_when1CppAnd1CProject_returnMapWithSize2AndAutoconfigByDefault() {
- Consumer<MetricDto> configureMetric = metric -> metric
- .setValueType(STRING.name())
- .setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY);
-
- MetricDto metric = db.measures().insertMetric(configureMetric);
-
- ProjectData project1 = db.components().insertPrivateProject();
- ProjectData project2 = db.components().insertPrivateProject();
- ProjectData project3 = db.components().insertPrivateProject();
- ProjectData project4 = db.components().insertPrivateProject();
-
- insertLiveMeasure("c", metric).accept(project1);
- insertLiveMeasure("cpp", metric).accept(project2);
- insertLiveMeasure("java", metric).accept(project3);
- insertLiveMeasure("cobol", metric).accept(project4);
-
- Map<String, String> actualResult = underTest.getUuidValues();
-
- assertThat(actualResult).hasSize(2);
- assertThat(actualResult).containsExactlyInAnyOrderEntriesOf(Map.of(project1.getProjectDto().getUuid(), "AUTOCONFIG",
- project2.getProjectDto().getUuid(), "AUTOCONFIG"));
- }
-
- @Test
- void getUuidValues_whenCAndCppProjectsWithDifferentConfig_returnMapWithSize2AndNotAutoconfig() {
- Consumer<MetricDto> configureMetric = metric -> metric
- .setValueType(STRING.name())
- .setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY);
-
- MetricDto metric = db.measures().insertMetric(configureMetric);
-
- ProjectData project1 = db.components().insertPrivateProject();
- ProjectData project2 = db.components().insertPrivateProject();
- ProjectData project3 = db.components().insertPrivateProject();
- ProjectData project4 = db.components().insertPrivateProject();
-
- insertLiveMeasure("c", metric).accept(project1);
- insertLiveMeasure("cpp", metric).accept(project2);
- insertLiveMeasure("java", metric).accept(project3);
- insertLiveMeasure("cobol", metric).accept(project4);
-
- db.properties().insertProperty("sonar.cfamily.build-wrapper-output", "anyvalue", project1.getProjectDto().getUuid());
- db.properties().insertProperty("sonar.cfamily.compile-commands", "anyvalue", project2.getProjectDto().getUuid());
-
- Map<String, String> actualResult = underTest.getUuidValues();
-
- assertThat(actualResult).hasSize(2);
- assertThat(actualResult).containsExactlyInAnyOrderEntriesOf(Map.of(project1.getProjectDto().getUuid(), "BW_DEPRECATED",
- project2.getProjectDto().getUuid(), "COMPDB"));
- }
-
- private Consumer<LiveMeasureDto> configureLiveMeasure(String language, MetricDto metric, ProjectDto project, ComponentDto componentDto) {
- return liveMeasure -> liveMeasure
- .setMetricUuid(metric.getUuid())
- .setComponentUuid(componentDto.uuid())
- .setProjectUuid(project.getUuid())
- .setData(language + "=" + 100);
- }
-
- private Consumer<ProjectData> insertLiveMeasure(String language, MetricDto metric) {
- return projectData -> db.measures().insertLiveMeasure(projectData.getMainBranchComponent(), metric,
- configureLiveMeasure(language, metric, projectData.getProjectDto(), projectData.getMainBranchComponent()));
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 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.telemetry.user;
-
-import java.util.Map;
-import org.junit.Rule;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbTester;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.util.DigestUtil;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class TelemetryUserEnabledProviderIT {
-
- private final System2 system2 = new AlwaysIncreasingSystem2();
-
- @Rule
- public final DbTester db = DbTester.create(system2);
-
-
- private final TelemetryUserEnabledProvider underTest = new TelemetryUserEnabledProvider(db.getDbClient());
-
- @BeforeEach
- public void beforeEach() {
- db.executeUpdateSql("delete from users");
- }
-
- @Test
- void getUuidValues_whenNoUsersInDatabase_shouldReturnEmptyMap() {
- Map<String, Boolean> uuidValues = underTest.getUuidValues();
-
- assertThat(uuidValues).isEmpty();
- }
-
- @Test
- void getUuidValues_whenSomeUsersActive_shouldReturnBothBooleanValues() {
- db.users().insertUser(user -> user.setUuid("uuid1").setActive(true));
- db.users().insertUser(user -> user.setUuid("uuid1").setActive(false));
- db.getSession().commit();
-
- Map<String, Boolean> uuidValues = underTest.getUuidValues();
-
- assertThat(uuidValues).hasSize(2);
- assertThat(uuidValues.values().stream().filter(Boolean::booleanValue)).hasSize(1);
- assertThat(uuidValues.values().stream().filter(b -> !b)).hasSize(1);
- }
-
- @Test
- void getUuidValues_when10ActiveUsers_shouldReturn10BooleanValues() {
- for (int i = 0; i < 10; i++) {
- db.users().insertUser(user -> user.setActive(true));
- }
- db.getSession().commit();
-
- Map<String, Boolean> uuidValues = underTest.getUuidValues();
-
- assertThat(uuidValues).hasSize(10);
- assertThat(uuidValues.values().stream().filter(Boolean::booleanValue)).hasSize(10);
- }
-
- @Test
- void getUuidValues_shouldAnonymizeUserUuids() {
- UserDto userDto1 = db.users().insertUser();
- UserDto userDto2 = db.users().insertUser();
- db.getSession().commit();
-
- Map<String, Boolean> uuidValues = underTest.getUuidValues();
-
- String anonymizedUser1 = DigestUtil.sha3_224Hex(userDto1.getUuid());
- String anonymizedUser2 = DigestUtil.sha3_224Hex(userDto2.getUuid());
- assertThat(uuidValues.keySet()).containsExactlyInAnyOrder(anonymizedUser1, anonymizedUser2);
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 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.telemetry;
-
-import com.fasterxml.jackson.annotation.JsonValue;
-
-/**
- * Represents the dimension of the data provided by a {@link TelemetryDataProvider}.
- * {@link Dimension#PROJECT}, {@link Dimension#LANGUAGE} and {@link Dimension#USER} should not provide aggregated data.
- * For aggregated data (i.e. average number of lines of code per project), use #INSTALLATION.
- */
-public enum Dimension {
- INSTALLATION("installation"),
- USER("user"),
- PROJECT("project"),
- LANGUAGE("language");
-
- private final String value;
-
- Dimension(String value) {
- this.value = value;
- }
-
- @JsonValue
- public String getValue() {
- return value;
- }
-
- public static Dimension fromValue(String value) {
- for (Dimension dimension : Dimension.values()) {
- if (dimension.value.equalsIgnoreCase(value)) {
- return dimension;
- }
- }
- throw new IllegalArgumentException("Unknown dimension value: " + value);
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 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.telemetry;
-
-import com.fasterxml.jackson.annotation.JsonValue;
-
-/**
- * Represent the granularity of the data provided by a {@link TelemetryDataProvider}. This both defines the time period between to pushes to
- * telemetry server for a given metric and the time period that the data represents.
- * Modifying this enum needs to be discussed beforehand with Data Platform team.
- */
-public enum Granularity {
- DAILY("daily"),
- WEEKLY("weekly"),
- MONTHLY("monthly");
-
- private final String value;
-
- Granularity(String value) {
- this.value = value;
- }
-
- @JsonValue
- public String getValue() {
- return value;
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 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.telemetry;
-
-import java.util.Map;
-
-/**
- * This interface is used to provide data to the telemetry system. The telemetry system will call the methods of this interface to get the
- * data that will be sent to the telemetry server.
- * If you want to add new metric to the telemetry system, you need to create a new implementation of this interface and register it in the
- * Spring context as a bean.
- *
- * @param <T> type of the value provided by this instance. Should be either {@link Boolean}, {@link String},
- * {@link Integer} or {@link Float}.
- */
-public interface TelemetryDataProvider<T> {
-
- /**
- * @return the key of the metric that will be used to store the value of the data provided by this instance. The combination of
- * metric key and dimension needs to be universally unique. The metric key needs to be written in snake_case.
- */
- String getMetricKey();
-
- /**
- * @return the dimension ("category") of the data provided by this instance. The combination of metric key and dimension needs to be
- * universally unique.
- */
- Dimension getDimension();
-
- /**
- * @return returns the granularity of this telemetry metric.
- * @see Granularity
- */
- Granularity getGranularity();
-
- /**
- * @return the type of the data provided by this instance.
- */
- TelemetryDataType getType();
-
- /**
- * The implementation of this method might often need to make a call to a database.
- * For each metric either this method or {@link TelemetryDataProvider#getUuidValues()} should be implemented and used. Not both at once.
- *
- * @return the value of the data provided by this instance.
- */
- default T getValue() {
- throw new IllegalStateException("Not implemented");
- }
-
- /**
- * The implementation of this method might often need to make a call to a database.
- * Similiar as {@link TelemetryDataProvider#getValue()} this method returns values of the metric. Some of the metrics
- * associate a UUID with a value. This method is used to return all the values associated with the UUIDs.
- *
- * @return map of UUIDs and their values.
- */
- default Map<String, T> getUuidValues() {
- throw new IllegalStateException("Not implemented");
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 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.telemetry;
-
-import com.fasterxml.jackson.annotation.JsonValue;
-
-/**
- * Represents the type of the data provided by a {@link TelemetryDataProvider}.
- * Modifying this enum needs to be discussed beforehand with Data Platform team.
- */
-public enum TelemetryDataType {
- BOOLEAN("boolean"),
- STRING("string"),
- INTEGER("integer"),
- FLOAT("float");
-
- private final String value;
-
- TelemetryDataType(String value) {
- this.value = value;
- }
-
- @JsonValue
- public String getValue() {
- return value;
- }
-}
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.telemetry.TelemetryMetricsSentDto;
-import org.sonar.telemetry.Dimension;
-import org.sonar.telemetry.TelemetryDataProvider;
+import org.sonar.telemetry.core.Dimension;
+import org.sonar.telemetry.core.TelemetryDataProvider;
import org.sonar.telemetry.metrics.schema.BaseMessage;
import org.sonar.telemetry.metrics.schema.Metric;
import org.sonar.telemetry.metrics.util.SentMetricsStorage;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
-import org.sonar.telemetry.TelemetryDataProvider;
+import org.sonar.telemetry.core.TelemetryDataProvider;
import org.sonar.telemetry.metrics.schema.InstallationMetric;
import org.sonar.telemetry.metrics.schema.LanguageMetric;
import org.sonar.telemetry.metrics.schema.Metric;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Objects;
import java.util.Set;
-import org.sonar.telemetry.Dimension;
+import org.sonar.telemetry.core.Dimension;
public class BaseMessage {
@JsonProperty("message_uuid")
*/
package org.sonar.telemetry.metrics.schema;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataType;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataType;
public class InstallationMetric extends Metric {
package org.sonar.telemetry.metrics.schema;
import com.fasterxml.jackson.annotation.JsonProperty;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataType;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataType;
public class LanguageMetric extends Metric {
package org.sonar.telemetry.metrics.schema;
import com.fasterxml.jackson.annotation.JsonProperty;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataType;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataType;
public abstract class Metric {
@JsonProperty("key")
package org.sonar.telemetry.metrics.schema;
import com.fasterxml.jackson.annotation.JsonProperty;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataType;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataType;
public class ProjectMetric extends Metric {
package org.sonar.telemetry.metrics.schema;
import com.fasterxml.jackson.annotation.JsonProperty;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataType;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataType;
public class UserMetric extends Metric {
import java.util.Map;
import java.util.Optional;
import org.sonar.db.telemetry.TelemetryMetricsSentDto;
-import org.sonar.telemetry.Dimension;
-import org.sonar.telemetry.Granularity;
+import org.sonar.telemetry.core.Dimension;
+import org.sonar.telemetry.core.Granularity;
public class SentMetricsStorage {
private final Map<Dimension, Map<String, TelemetryMetricsSentDto>> dimensionMetricKeyMap = new EnumMap<>(Dimension.class);
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 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.telemetry.project;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.project.ProjectDto;
-import org.sonar.db.property.PropertyDto;
-import org.sonar.db.property.PropertyQuery;
-import org.sonar.telemetry.Dimension;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataType;
-import org.sonar.telemetry.TelemetryDataProvider;
-
-public class ProjectCppAutoconfigTelemetryProvider implements TelemetryDataProvider<String> {
-
- private final DbClient dbClient;
-
- public ProjectCppAutoconfigTelemetryProvider(DbClient dbClient) {
- this.dbClient = dbClient;
- }
-
- @Override
- public String getMetricKey() {
- return "project_cpp_config_type";
- }
-
- @Override
- public Dimension getDimension() {
- return Dimension.PROJECT;
- }
-
- @Override
- public Granularity getGranularity() {
- return Granularity.WEEKLY;
- }
-
- @Override
- public TelemetryDataType getType() {
- return TelemetryDataType.STRING;
- }
-
- @Override
- public Map<String, String> getUuidValues() {
- Map<String, String> cppConfigTypePerProjectUuid = new HashMap<>();
- try (DbSession dbSession = dbClient.openSession(true)) {
- //TODO in the feature ideally languages should be defined in the codebase as enums, using strings is error-prone
- List<ProjectDto> cppProjects = dbClient.projectDao().selectProjectsByLanguage(dbSession, Set.of("cpp", "c"));
- for (ProjectDto cppProject : cppProjects) {
- CppConfigType cppConfigType = getCppConfigType(cppProject, dbSession);
- cppConfigTypePerProjectUuid.put(cppProject.getUuid(), cppConfigType.name());
- }
- }
- return cppConfigTypePerProjectUuid;
- }
-
- private CppConfigType getCppConfigType(ProjectDto project, DbSession dbSession) {
- List<PropertyDto> propertyDtos = dbClient.propertiesDao().selectByQuery(PropertyQuery
- .builder()
- .setEntityUuid(project.getUuid())
- .build(), dbSession);
- for (PropertyDto propertyDto : propertyDtos) {
- if (propertyDto.getKey().equals("sonar.cfamily.build-wrapper-output")) {
- return CppConfigType.BW_DEPRECATED;
- }
- if (propertyDto.getKey().equals("sonar.cfamily.compile-commands")) {
- return CppConfigType.COMPDB;
- }
- }
- return CppConfigType.AUTOCONFIG;
- }
-
- enum CppConfigType {
- BW_DEPRECATED, COMPDB, AUTOCONFIG
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 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.telemetry.project;
-
-import javax.annotation.ParametersAreNonnullByDefault;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 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.telemetry.user;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserQuery;
-import org.sonar.server.util.DigestUtil;
-import org.sonar.telemetry.Dimension;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataProvider;
-import org.sonar.telemetry.TelemetryDataType;
-
-public class TelemetryUserEnabledProvider implements TelemetryDataProvider<Boolean> {
-
- private final DbClient dbClient;
-
- public TelemetryUserEnabledProvider(DbClient dbClient) {
- this.dbClient = dbClient;
- }
-
- @Override
- public String getMetricKey() {
- return "user_enabled";
- }
-
- @Override
- public Dimension getDimension() {
- return Dimension.USER;
- }
-
- @Override
- public Granularity getGranularity() {
- return Granularity.DAILY;
- }
-
- @Override
- public TelemetryDataType getType() {
- return TelemetryDataType.BOOLEAN;
- }
-
- @Override
- public Map<String, Boolean> getUuidValues() {
- Map<String, Boolean> result = new HashMap<>();
- int pageSize = 1000;
- int page = 1;
- try (DbSession dbSession = dbClient.openSession(false)) {
- List<UserDto> userDtos;
- do {
- userDtos = dbClient.userDao().selectUsers(dbSession, UserQuery.builder().build(), page, pageSize);
- for (UserDto userDto : userDtos) {
- String anonymizedUuid = DigestUtil.sha3_224Hex(userDto.getUuid());
- result.put(anonymizedUuid, userDto.isActive());
- }
- page++;
- } while (!userDtos.isEmpty());
- }
- return result;
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 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.telemetry.user;
-
-import javax.annotation.ParametersAreNonnullByDefault;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 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.telemetry;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-class DimensionTest {
- @Test
- void getValue() {
- assertEquals("installation", Dimension.INSTALLATION.getValue());
- assertEquals("user", Dimension.USER.getValue());
- assertEquals("project", Dimension.PROJECT.getValue());
- assertEquals("language", Dimension.LANGUAGE.getValue());
- }
-
- @Test
- void fromValue() {
- assertEquals(Dimension.INSTALLATION, Dimension.fromValue("installation"));
- assertEquals(Dimension.USER, Dimension.fromValue("user"));
- assertEquals(Dimension.PROJECT, Dimension.fromValue("project"));
- assertEquals(Dimension.LANGUAGE, Dimension.fromValue("language"));
-
- assertEquals(Dimension.INSTALLATION, Dimension.fromValue("INSTALLATION"));
- assertEquals(Dimension.USER, Dimension.fromValue("USER"));
- assertEquals(Dimension.PROJECT, Dimension.fromValue("PROJECT"));
- assertEquals(Dimension.LANGUAGE, Dimension.fromValue("LANGUAGE"));
- }
-
- @Test
- void fromValue_whenInvalid() {
- Exception exception = assertThrows(IllegalArgumentException.class, () -> {
- Dimension.fromValue("invalid");
- });
- assertEquals("Unknown dimension value: invalid", exception.getMessage());
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 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.telemetry;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-class GranularityTest {
-
- @Test
- void getValue() {
- assertEquals("daily", Granularity.DAILY.getValue());
- assertEquals("weekly", Granularity.WEEKLY.getValue());
- assertEquals("monthly", Granularity.MONTHLY.getValue());
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 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.telemetry;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-class TelemetryDataTypeTest {
- @Test
- void getValue() {
- assertEquals("integer", TelemetryDataType.INTEGER.getValue());
- assertEquals("string", TelemetryDataType.STRING.getValue());
- assertEquals("boolean", TelemetryDataType.BOOLEAN.getValue());
- assertEquals("float", TelemetryDataType.FLOAT.getValue());
- }
-
-}
import java.util.Set;
import org.assertj.core.groups.Tuple;
import org.junit.jupiter.api.Test;
-import org.sonar.telemetry.Dimension;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataProvider;
-import org.sonar.telemetry.TelemetryDataType;
+import org.sonar.telemetry.core.Dimension;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataProvider;
+import org.sonar.telemetry.core.TelemetryDataType;
import org.sonar.telemetry.metrics.schema.InstallationMetric;
import org.sonar.telemetry.metrics.schema.LanguageMetric;
import org.sonar.telemetry.metrics.schema.Metric;
package org.sonar.telemetry.metrics;
import java.util.Map;
-import org.sonar.telemetry.Dimension;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataProvider;
-import org.sonar.telemetry.TelemetryDataType;
+import org.sonar.telemetry.core.Dimension;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataProvider;
+import org.sonar.telemetry.core.TelemetryDataType;
public class TestTelemetryBean implements TelemetryDataProvider<String> {
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
-import org.sonar.telemetry.Dimension;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataType;
+import org.sonar.telemetry.core.Dimension;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataType;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
package org.sonar.telemetry.metrics.schema;
import org.junit.jupiter.api.Test;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataType;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataType;
import static org.assertj.core.api.Assertions.assertThat;
package org.sonar.telemetry.metrics.schema;
import org.junit.jupiter.api.Test;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataType;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataType;
import static org.assertj.core.api.Assertions.assertThat;
package org.sonar.telemetry.metrics.schema;
import org.junit.jupiter.api.Test;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataType;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataType;
import static org.assertj.core.api.Assertions.assertThat;
package org.sonar.telemetry.metrics.schema;
import org.junit.jupiter.api.Test;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataType;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataType;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.stream.IntStream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
-import org.sonar.telemetry.Dimension;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataType;
+import org.sonar.telemetry.core.Dimension;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataType;
import org.sonar.telemetry.metrics.schema.BaseMessage;
import org.sonar.telemetry.metrics.schema.InstallationMetric;
import org.sonar.telemetry.metrics.schema.LanguageMetric;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.sonar.db.telemetry.TelemetryMetricsSentDto;
-import org.sonar.telemetry.Dimension;
-import org.sonar.telemetry.Granularity;
+import org.sonar.telemetry.core.Dimension;
+import org.sonar.telemetry.core.Granularity;
public class SentMetricsStorageTest {
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 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.telemetry.project;
-
-import org.junit.jupiter.api.Test;
-import org.sonar.db.DbClient;
-import org.sonar.telemetry.Dimension;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataType;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.Mockito.mock;
-
-class ProjectCppAutoconfigTelemetryProviderTest {
-
- @Test
- void testGetters() {
- ProjectCppAutoconfigTelemetryProvider provider = new ProjectCppAutoconfigTelemetryProvider(mock(DbClient.class));
-
- assertEquals("project_cpp_config_type", provider.getMetricKey());
- assertEquals(Dimension.PROJECT, provider.getDimension());
- assertEquals(Granularity.WEEKLY, provider.getGranularity());
- assertEquals(TelemetryDataType.STRING, provider.getType());
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 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.telemetry.user;
-
-import org.junit.jupiter.api.Test;
-import org.sonar.db.DbClient;
-import org.sonar.telemetry.Dimension;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataType;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-class TelemetryUserEnabledProviderTest {
-
- private final DbClient dbClient = mock(DbClient.class);
-
- private final TelemetryUserEnabledProvider underTest = new TelemetryUserEnabledProvider(dbClient);
-
- @Test
- void testGetters() {
- assertThat(underTest.getDimension()).isEqualTo(Dimension.USER);
- assertThat(underTest.getGranularity()).isEqualTo(Granularity.DAILY);
- assertThat(underTest.getMetricKey()).isEqualTo("user_enabled");
- assertThat(underTest.getType()).isEqualTo(TelemetryDataType.BOOLEAN);
- }
-}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.platform.telemetry;
+
+import java.util.Map;
+import java.util.function.Consumer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ProjectData;
+import org.sonar.db.measure.LiveMeasureDto;
+import org.sonar.db.metric.MetricDto;
+import org.sonar.db.project.ProjectDto;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.measures.CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY;
+import static org.sonar.api.measures.Metric.ValueType.STRING;
+
+class ProjectCppAutoconfigTelemetryProviderIT {
+
+ private final System2 system2 = new AlwaysIncreasingSystem2(1000L);
+
+ @RegisterExtension
+ public final DbTester db = DbTester.create(system2);
+
+ ProjectCppAutoconfigTelemetryProvider underTest = new ProjectCppAutoconfigTelemetryProvider(db.getDbClient());
+
+ @Test
+ void getUuidValues_whenNoProjects_returnEmptyList() {
+ assertThat(underTest.getUuidValues()).isEmpty();
+ }
+
+ @Test
+ void getUuidValues_whenNoCppAndCProjects_returnEmptyMap() {
+ Consumer<MetricDto> configureMetric = metric -> metric
+ .setValueType(STRING.name())
+ .setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY);
+
+ MetricDto metric = db.measures().insertMetric(configureMetric);
+
+ ProjectData project1 = db.components().insertPrivateProject();
+ ProjectData project2 = db.components().insertPrivateProject();
+
+ insertLiveMeasure("java", metric).accept(project1);
+ insertLiveMeasure("cobol", metric).accept(project2);
+
+
+ assertThat(underTest.getUuidValues()).isEmpty();
+ }
+
+ @Test
+ void getUuidValues_when1CppAnd1CProject_returnMapWithSize2AndAutoconfigByDefault() {
+ Consumer<MetricDto> configureMetric = metric -> metric
+ .setValueType(STRING.name())
+ .setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY);
+
+ MetricDto metric = db.measures().insertMetric(configureMetric);
+
+ ProjectData project1 = db.components().insertPrivateProject();
+ ProjectData project2 = db.components().insertPrivateProject();
+ ProjectData project3 = db.components().insertPrivateProject();
+ ProjectData project4 = db.components().insertPrivateProject();
+
+ insertLiveMeasure("c", metric).accept(project1);
+ insertLiveMeasure("cpp", metric).accept(project2);
+ insertLiveMeasure("java", metric).accept(project3);
+ insertLiveMeasure("cobol", metric).accept(project4);
+
+ Map<String, String> actualResult = underTest.getUuidValues();
+
+ assertThat(actualResult).hasSize(2);
+ assertThat(actualResult).containsExactlyInAnyOrderEntriesOf(Map.of(project1.getProjectDto().getUuid(), "AUTOCONFIG",
+ project2.getProjectDto().getUuid(), "AUTOCONFIG"));
+ }
+
+ @Test
+ void getUuidValues_whenCAndCppProjectsWithDifferentConfig_returnMapWithSize2AndNotAutoconfig() {
+ Consumer<MetricDto> configureMetric = metric -> metric
+ .setValueType(STRING.name())
+ .setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY);
+
+ MetricDto metric = db.measures().insertMetric(configureMetric);
+
+ ProjectData project1 = db.components().insertPrivateProject();
+ ProjectData project2 = db.components().insertPrivateProject();
+ ProjectData project3 = db.components().insertPrivateProject();
+ ProjectData project4 = db.components().insertPrivateProject();
+
+ insertLiveMeasure("c", metric).accept(project1);
+ insertLiveMeasure("cpp", metric).accept(project2);
+ insertLiveMeasure("java", metric).accept(project3);
+ insertLiveMeasure("cobol", metric).accept(project4);
+
+ db.properties().insertProperty("sonar.cfamily.build-wrapper-output", "anyvalue", project1.getProjectDto().getUuid());
+ db.properties().insertProperty("sonar.cfamily.compile-commands", "anyvalue", project2.getProjectDto().getUuid());
+
+ Map<String, String> actualResult = underTest.getUuidValues();
+
+ assertThat(actualResult).hasSize(2);
+ assertThat(actualResult).containsExactlyInAnyOrderEntriesOf(Map.of(project1.getProjectDto().getUuid(), "BW_DEPRECATED",
+ project2.getProjectDto().getUuid(), "COMPDB"));
+ }
+
+ private Consumer<LiveMeasureDto> configureLiveMeasure(String language, MetricDto metric, ProjectDto project, ComponentDto componentDto) {
+ return liveMeasure -> liveMeasure
+ .setMetricUuid(metric.getUuid())
+ .setComponentUuid(componentDto.uuid())
+ .setProjectUuid(project.getUuid())
+ .setData(language + "=" + 100);
+ }
+
+ private Consumer<ProjectData> insertLiveMeasure(String language, MetricDto metric) {
+ return projectData -> db.measures().insertLiveMeasure(projectData.getMainBranchComponent(), metric,
+ configureLiveMeasure(language, metric, projectData.getProjectDto(), projectData.getMainBranchComponent()));
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.platform.telemetry;
+
+import java.util.Map;
+import org.junit.Rule;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.util.DigestUtil;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class TelemetryUserEnabledProviderIT {
+
+ private final System2 system2 = new AlwaysIncreasingSystem2();
+
+ @Rule
+ public final DbTester db = DbTester.create(system2);
+
+
+ private final TelemetryUserEnabledProvider underTest = new TelemetryUserEnabledProvider(db.getDbClient());
+
+ @BeforeEach
+ public void beforeEach() {
+ db.executeUpdateSql("delete from users");
+ }
+
+ @Test
+ void getUuidValues_whenNoUsersInDatabase_shouldReturnEmptyMap() {
+ Map<String, Boolean> uuidValues = underTest.getUuidValues();
+
+ assertThat(uuidValues).isEmpty();
+ }
+
+ @Test
+ void getUuidValues_whenSomeUsersActive_shouldReturnBothBooleanValues() {
+ db.users().insertUser(user -> user.setUuid("uuid1").setActive(true));
+ db.users().insertUser(user -> user.setUuid("uuid1").setActive(false));
+ db.getSession().commit();
+
+ Map<String, Boolean> uuidValues = underTest.getUuidValues();
+
+ assertThat(uuidValues).hasSize(2);
+ assertThat(uuidValues.values().stream().filter(Boolean::booleanValue)).hasSize(1);
+ assertThat(uuidValues.values().stream().filter(b -> !b)).hasSize(1);
+ }
+
+ @Test
+ void getUuidValues_when10ActiveUsers_shouldReturn10BooleanValues() {
+ for (int i = 0; i < 10; i++) {
+ db.users().insertUser(user -> user.setActive(true));
+ }
+ db.getSession().commit();
+
+ Map<String, Boolean> uuidValues = underTest.getUuidValues();
+
+ assertThat(uuidValues).hasSize(10);
+ assertThat(uuidValues.values().stream().filter(Boolean::booleanValue)).hasSize(10);
+ }
+
+ @Test
+ void getUuidValues_shouldAnonymizeUserUuids() {
+ UserDto userDto1 = db.users().insertUser();
+ UserDto userDto2 = db.users().insertUser();
+ db.getSession().commit();
+
+ Map<String, Boolean> uuidValues = underTest.getUuidValues();
+
+ String anonymizedUser1 = DigestUtil.sha3_224Hex(userDto1.getUuid());
+ String anonymizedUser2 = DigestUtil.sha3_224Hex(userDto2.getUuid());
+ assertThat(uuidValues.keySet()).containsExactlyInAnyOrder(anonymizedUser1, anonymizedUser2);
+ }
+
+}
import org.sonar.server.platform.SystemInfoWriterModule;
import org.sonar.server.platform.WebCoreExtensionsInstaller;
import org.sonar.server.platform.db.CheckAnyonePermissionsAtStartup;
+import org.sonar.server.platform.telemetry.ProjectCppAutoconfigTelemetryProvider;
import org.sonar.server.platform.telemetry.TelemetryNclocProvider;
+import org.sonar.server.platform.telemetry.TelemetryUserEnabledProvider;
import org.sonar.server.platform.telemetry.TelemetryVersionProvider;
import org.sonar.server.platform.web.ActionDeprecationLoggerInterceptor;
import org.sonar.server.platform.web.SonarLintConnectionFilter;
import org.sonar.telemetry.legacy.TelemetryDataJsonWriter;
import org.sonar.telemetry.legacy.TelemetryDataLoaderImpl;
import org.sonar.telemetry.metrics.TelemetryMetricsLoader;
-import org.sonar.telemetry.project.ProjectCppAutoconfigTelemetryProvider;
-import org.sonar.telemetry.user.TelemetryUserEnabledProvider;
import static org.sonar.core.extension.CoreExtensionsInstaller.noAdditionalSideFilter;
import static org.sonar.core.extension.PlatformLevelPredicates.hasPlatformLevel4OrNone;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.platform.telemetry;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.project.ProjectDto;
+import org.sonar.db.property.PropertyDto;
+import org.sonar.db.property.PropertyQuery;
+import org.sonar.telemetry.core.Dimension;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataProvider;
+import org.sonar.telemetry.core.TelemetryDataType;
+
+public class ProjectCppAutoconfigTelemetryProvider implements TelemetryDataProvider<String> {
+
+ private final DbClient dbClient;
+
+ public ProjectCppAutoconfigTelemetryProvider(DbClient dbClient) {
+ this.dbClient = dbClient;
+ }
+
+ @Override
+ public String getMetricKey() {
+ return "project_cpp_config_type";
+ }
+
+ @Override
+ public Dimension getDimension() {
+ return Dimension.PROJECT;
+ }
+
+ @Override
+ public Granularity getGranularity() {
+ return Granularity.WEEKLY;
+ }
+
+ @Override
+ public TelemetryDataType getType() {
+ return TelemetryDataType.STRING;
+ }
+
+ @Override
+ public Map<String, String> getUuidValues() {
+ Map<String, String> cppConfigTypePerProjectUuid = new HashMap<>();
+ try (DbSession dbSession = dbClient.openSession(true)) {
+ //TODO in the feature ideally languages should be defined in the codebase as enums, using strings is error-prone
+ List<ProjectDto> cppProjects = dbClient.projectDao().selectProjectsByLanguage(dbSession, Set.of("cpp", "c"));
+ for (ProjectDto cppProject : cppProjects) {
+ CppConfigType cppConfigType = getCppConfigType(cppProject, dbSession);
+ cppConfigTypePerProjectUuid.put(cppProject.getUuid(), cppConfigType.name());
+ }
+ }
+ return cppConfigTypePerProjectUuid;
+ }
+
+ private CppConfigType getCppConfigType(ProjectDto project, DbSession dbSession) {
+ List<PropertyDto> propertyDtos = dbClient.propertiesDao().selectByQuery(PropertyQuery
+ .builder()
+ .setEntityUuid(project.getUuid())
+ .build(), dbSession);
+ for (PropertyDto propertyDto : propertyDtos) {
+ if (propertyDto.getKey().equals("sonar.cfamily.build-wrapper-output")) {
+ return CppConfigType.BW_DEPRECATED;
+ }
+ if (propertyDto.getKey().equals("sonar.cfamily.compile-commands")) {
+ return CppConfigType.COMPDB;
+ }
+ }
+ return CppConfigType.AUTOCONFIG;
+ }
+
+ enum CppConfigType {
+ BW_DEPRECATED, COMPDB, AUTOCONFIG
+ }
+}
import org.sonar.db.DbSession;
import org.sonar.db.measure.ProjectLocDistributionDto;
import org.sonar.db.metric.MetricDto;
-import org.sonar.telemetry.Dimension;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataProvider;
-import org.sonar.telemetry.TelemetryDataType;
+import org.sonar.telemetry.core.Dimension;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataProvider;
+import org.sonar.telemetry.core.TelemetryDataType;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toMap;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.platform.telemetry;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.user.UserDto;
+import org.sonar.db.user.UserQuery;
+import org.sonar.server.util.DigestUtil;
+import org.sonar.telemetry.core.Dimension;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataProvider;
+import org.sonar.telemetry.core.TelemetryDataType;
+
+public class TelemetryUserEnabledProvider implements TelemetryDataProvider<Boolean> {
+
+ private final DbClient dbClient;
+
+ public TelemetryUserEnabledProvider(DbClient dbClient) {
+ this.dbClient = dbClient;
+ }
+
+ @Override
+ public String getMetricKey() {
+ return "user_enabled";
+ }
+
+ @Override
+ public Dimension getDimension() {
+ return Dimension.USER;
+ }
+
+ @Override
+ public Granularity getGranularity() {
+ return Granularity.DAILY;
+ }
+
+ @Override
+ public TelemetryDataType getType() {
+ return TelemetryDataType.BOOLEAN;
+ }
+
+ @Override
+ public Map<String, Boolean> getUuidValues() {
+ Map<String, Boolean> result = new HashMap<>();
+ int pageSize = 1000;
+ int page = 1;
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ List<UserDto> userDtos;
+ do {
+ userDtos = dbClient.userDao().selectUsers(dbSession, UserQuery.builder().build(), page, pageSize);
+ for (UserDto userDto : userDtos) {
+ String anonymizedUuid = DigestUtil.sha3_224Hex(userDto.getUuid());
+ result.put(anonymizedUuid, userDto.isActive());
+ }
+ page++;
+ } while (!userDtos.isEmpty());
+ }
+ return result;
+ }
+}
package org.sonar.server.platform.telemetry;
import org.sonar.api.platform.Server;
-import org.sonar.telemetry.Dimension;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataProvider;
-import org.sonar.telemetry.TelemetryDataType;
+import org.sonar.telemetry.core.Dimension;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataProvider;
+import org.sonar.telemetry.core.TelemetryDataType;
public class TelemetryVersionProvider implements TelemetryDataProvider<String> {
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.platform.telemetry;
+
+import org.junit.jupiter.api.Test;
+import org.sonar.db.DbClient;
+import org.sonar.telemetry.core.Dimension;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataType;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+
+class ProjectCppAutoconfigTelemetryProviderTest {
+
+ @Test
+ void testGetters() {
+ ProjectCppAutoconfigTelemetryProvider provider = new ProjectCppAutoconfigTelemetryProvider(mock(DbClient.class));
+
+ assertEquals("project_cpp_config_type", provider.getMetricKey());
+ assertEquals(Dimension.PROJECT, provider.getDimension());
+ assertEquals(Granularity.WEEKLY, provider.getGranularity());
+ assertEquals(TelemetryDataType.STRING, provider.getType());
+ }
+}
import org.sonar.db.DbSession;
import org.sonar.db.measure.ProjectLocDistributionDto;
import org.sonar.db.metric.MetricDto;
-import org.sonar.telemetry.Dimension;
-import org.sonar.telemetry.Granularity;
+import org.sonar.telemetry.core.Dimension;
+import org.sonar.telemetry.core.Granularity;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.platform.telemetry;
+
+import org.junit.jupiter.api.Test;
+import org.sonar.db.DbClient;
+import org.sonar.telemetry.core.Dimension;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataType;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+class TelemetryUserEnabledProviderTest {
+
+ private final DbClient dbClient = mock(DbClient.class);
+
+ private final TelemetryUserEnabledProvider underTest = new TelemetryUserEnabledProvider(dbClient);
+
+ @Test
+ void testGetters() {
+ assertThat(underTest.getDimension()).isEqualTo(Dimension.USER);
+ assertThat(underTest.getGranularity()).isEqualTo(Granularity.DAILY);
+ assertThat(underTest.getMetricKey()).isEqualTo("user_enabled");
+ assertThat(underTest.getType()).isEqualTo(TelemetryDataType.BOOLEAN);
+ }
+}
import org.junit.jupiter.api.Test;
import org.sonar.api.platform.Server;
-import org.sonar.telemetry.Dimension;
-import org.sonar.telemetry.Granularity;
-import org.sonar.telemetry.TelemetryDataType;
+import org.sonar.telemetry.core.Dimension;
+import org.sonar.telemetry.core.Granularity;
+import org.sonar.telemetry.core.TelemetryDataType;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
include 'server:sonar-process'
include 'server:sonar-server-common'
include 'server:sonar-telemetry'
+include 'server:sonar-telemetry-core'
include 'server:sonar-web'
include 'server:sonar-web:design-system'
include 'server:sonar-webserver'