]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9721 Send telemetry data once a week
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Mon, 21 Aug 2017 12:37:12 +0000 (14:37 +0200)
committerTeryk Bellahsene <teryk@users.noreply.github.com>
Wed, 30 Aug 2017 14:24:53 +0000 (16:24 +0200)
server/sonar-server/src/main/java/org/sonar/server/telemetry/TelemetryDaemon.java
server/sonar-server/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java
sonar-plugin-api/src/main/java/org/sonar/api/utils/DateUtils.java
sonar-plugin-api/src/test/java/org/sonar/api/utils/DateUtilsTest.java
tests/src/test/java/org/sonarqube/tests/telemetry/TelemetryTest.java

index 7ec293d7e19f52ef5cbb0141c579341614557aa6..d32b773bcd6fe1bcf3de721236020b8daa40992b 100644 (file)
@@ -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();
+  }
 }
index 1f523fd723f84c421661f026d47185f9142dc0b3..62011777a395c33e32daeee0945d3796ade2c599 100644 (file)
@@ -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));
+  }
 }
index d226fe6270a2845ae2665843c5cdda6fb2c179d6..aa326dce1d027122f845a89c17d140c3af8ffda5 100644 (file)
@@ -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);
   }
index cda37e7996f8b725db24c9fbfccf6c9268803aac..0dd1ed07292efdc9696e3b39ef19d347015a2cef 100644 (file)
@@ -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
index 48797c7a7d5f6bed12ba86e7fe3dc37ec5e47752..c6b20b58fb7bebcdbd4ee34e23c551ec37413002 100644 (file)
@@ -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();