aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>2017-08-21 14:37:12 +0200
committerTeryk Bellahsene <teryk@users.noreply.github.com>2017-08-30 16:24:53 +0200
commit6d6359057ee0e992780f51b9e6b42faa76075c6a (patch)
treefa267ba471e22ab53383becbc103e375ac989a13
parent972b352ce1166382b420aef8af3601418071a774 (diff)
downloadsonarqube-6d6359057ee0e992780f51b9e6b42faa76075c6a.tar.gz
sonarqube-6d6359057ee0e992780f51b9e6b42faa76075c6a.zip
SONAR-9721 Send telemetry data once a week
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDaemon.java28
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java53
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/utils/DateUtils.java4
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/utils/DateUtilsTest.java2
-rw-r--r--tests/src/test/java/org/sonarqube/tests/telemetry/TelemetryTest.java1
5 files changed, 79 insertions, 9 deletions
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 7ec293d7e19..d32b773bcd6 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
@@ -21,6 +21,7 @@ package org.sonar.server.telemetry;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.io.StringWriter;
+import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -28,25 +29,33 @@ 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.log.Logger;
-import org.sonar.api.utils.log.Loggers;
+import org.sonar.api.utils.System2;
import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.server.property.InternalProperties;
+
+import static org.sonar.api.utils.DateUtils.formatDate;
+import static org.sonar.api.utils.DateUtils.parseDate;
@ServerSide
public class TelemetryDaemon implements Startable {
private static final String THREAD_NAME_PREFIX = "sq-telemetry-service-";
- private static final Logger LOG = Loggers.get(TelemetryDaemon.class);
+ private static final int SEVEN_DAYS = 7 * 24 * 60 * 60 * 1_000;
+ private static final String I_PROP_LAST_PING = "sonar.telemetry.lastPing";
private final TelemetryClient telemetryClient;
+ private final InternalProperties internalProperties;
private final Server server;
+ private final System2 system2;
private final TelemetryFrequency frequencyInSeconds;
private ScheduledExecutorService executorService;
- public TelemetryDaemon(TelemetryClient telemetryClient, Server server, Configuration config) {
+ public TelemetryDaemon(TelemetryClient telemetryClient, InternalProperties internalProperties, Server server, System2 system2, Configuration config) {
this.telemetryClient = telemetryClient;
+ this.internalProperties = internalProperties;
this.server = server;
this.frequencyInSeconds = new TelemetryFrequency(config);
+ this.system2 = system2;
}
@Override
@@ -58,6 +67,12 @@ public class TelemetryDaemon implements Startable {
.build());
executorService.scheduleWithFixedDelay(() -> {
try {
+ Optional<Long> lastPing = internalProperties.read(I_PROP_LAST_PING).map(Long::valueOf);
+ long now = system2.now();
+ if (lastPing.isPresent() && now - lastPing.get() < SEVEN_DAYS) {
+ return;
+ }
+
StringWriter json = new StringWriter();
try (JsonWriter writer = JsonWriter.of(json)) {
writer.beginObject();
@@ -65,6 +80,7 @@ public class TelemetryDaemon implements Startable {
writer.endObject();
}
telemetryClient.send(json.toString());
+ internalProperties.write(I_PROP_LAST_PING, String.valueOf(startOfDay(now)));
} catch (Exception e) {
// fail silently
}
@@ -81,4 +97,8 @@ public class TelemetryDaemon implements Startable {
Thread.currentThread().interrupt();
}
}
+
+ private static long startOfDay(long now) {
+ return parseDate(formatDate(now)).getTime();
+ }
}
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 1f523fd723f..62011777a39 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
@@ -24,18 +24,28 @@ import org.junit.Before;
import org.junit.Test;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.server.property.InternalProperties;
+import org.sonar.server.property.MapInternalProperties;
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.contains;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
+import static org.sonar.api.utils.DateUtils.parseDate;
public class TelemetryDaemonTest {
+ private static final long ONE_HOUR = 60 * 60 * 1_000L;
+ private static final long ONE_DAY = 24 * ONE_HOUR;
+
private TelemetryClient client = mock(TelemetryClient.class);
+ private InternalProperties internalProperties = new MapInternalProperties();
private FakeServer server = new FakeServer();
+ private TestSystem2 system2 = new TestSystem2();
private MapSettings settings;
private TelemetryDaemon underTest;
@@ -43,8 +53,9 @@ public class TelemetryDaemonTest {
@Before
public void setUp() throws Exception {
settings = new MapSettings(new PropertyDefinitions(TelemetryProperties.class));
+ system2.setNow(System.currentTimeMillis());
- underTest = new TelemetryDaemon(client, server, settings.asConfig());
+ underTest = new TelemetryDaemon(client, internalProperties, server, system2, settings.asConfig());
}
@Test
@@ -56,13 +67,18 @@ public class TelemetryDaemonTest {
}
@Test
- public void send_data_periodically() {
+ public void check_if_should_send_data_periodically() {
+ long now = system2.now();
+ long sixDaysAgo = now - (ONE_DAY * 6L);
+ long sevenDaysAgo = now - (ONE_DAY * 7L);
+ internalProperties.write("sonar.telemetry.lastPing", String.valueOf(sixDaysAgo));
settings.setProperty("sonar.telemetry.frequency", "1");
- underTest = new TelemetryDaemon(client, server, settings.asConfig());
-
+ underTest = new TelemetryDaemon(client, internalProperties, server, system2, settings.asConfig());
underTest.start();
+ verify(client, timeout(1_000).never()).send(anyString());
+ internalProperties.write("sonar.telemetry.lastPing", String.valueOf(sevenDaysAgo));
- verify(client, timeout(3_000).atLeast(2)).send(anyString());
+ verify(client, timeout(1_000).atLeastOnce()).send(anyString());
}
@Test
@@ -74,4 +90,31 @@ public class TelemetryDaemonTest {
verify(client, timeout(2_000).atLeastOnce()).send(contains(id));
}
+
+ @Test
+ public void do_not_send_data_if_last_ping_earlier_than_one_week_ago() {
+ settings.setProperty("sonar.telemetry.frequency", "1");
+ long now = system2.now();
+ long sixDaysAgo = now - (ONE_DAY * 6L);
+
+ internalProperties.write("sonar.telemetry.lastPing", String.valueOf(sixDaysAgo));
+ underTest.start();
+
+ verify(client, timeout(2_000).never()).send(anyString());
+ }
+
+ @Test
+ public void send_data_if_last_ping_is_one_week_ago() {
+ settings.setProperty("sonar.telemetry.frequency", "1");
+ long today = parseDate("2017-08-01").getTime();
+ system2.setNow(today + 15 * ONE_HOUR);
+ long now = system2.now();
+ long sevenDaysAgo = now - (ONE_DAY * 7L);
+ internalProperties.write("sonar.telemetry.lastPing", String.valueOf(sevenDaysAgo));
+
+ underTest.start();
+
+ verify(client, timeout(2_000)).send(anyString());
+ assertThat(internalProperties.read("sonar.telemetry.lastPing").get()).isEqualTo(String.valueOf(today));
+ }
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/DateUtils.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/DateUtils.java
index d226fe6270a..aa326dce1d0 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/DateUtils.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/DateUtils.java
@@ -54,6 +54,10 @@ public final class DateUtils {
return THREAD_SAFE_DATE_FORMAT.format(d);
}
+ public static String formatDate(long ms) {
+ return THREAD_SAFE_DATE_FORMAT.format(new Date(ms));
+ }
+
public static String formatDateTime(Date d) {
return THREAD_SAFE_DATETIME_FORMAT.format(d);
}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/utils/DateUtilsTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/DateUtilsTest.java
index cda37e7996f..0dd1ed07292 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/utils/DateUtilsTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/utils/DateUtilsTest.java
@@ -103,7 +103,9 @@ public class DateUtilsTest {
@Test
public void shouldFormatDate() {
assertThat(DateUtils.formatDate(new Date())).startsWith("20");
+ assertThat(DateUtils.formatDate(new Date().getTime())).startsWith("20");
assertThat(DateUtils.formatDate(new Date()).length()).isEqualTo(10);
+ assertThat(DateUtils.formatDate(new Date().getTime()).length()).isEqualTo(10);
}
@Test
diff --git a/tests/src/test/java/org/sonarqube/tests/telemetry/TelemetryTest.java b/tests/src/test/java/org/sonarqube/tests/telemetry/TelemetryTest.java
index 48797c7a7d5..c6b20b58fb7 100644
--- a/tests/src/test/java/org/sonarqube/tests/telemetry/TelemetryTest.java
+++ b/tests/src/test/java/org/sonarqube/tests/telemetry/TelemetryTest.java
@@ -57,6 +57,7 @@ public class TelemetryTest {
orchestrator = Orchestrator.builderEnv()
.addPlugin(xooPlugin())
.setServerProperty("sonar.telemetry.url", url)
+ .setServerProperty("sonar.telemetry.frequency", "1")
.setServerProperty("sonar.core.id", serverId)
.build();
orchestrator.start();