aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorAlain Kermis <alain.kermis@sonarsource.com>2025-01-10 10:24:15 +0100
committersonartech <sonartech@sonarsource.com>2025-01-10 20:03:28 +0000
commit8b2ac2905ad630975d72af0a27ccdb45b4513bf0 (patch)
treee324f455b4cb730e57bc3cb618105c21bd9f3118 /server
parentee7071668930a5cd5eab81035c74419f02d9526b (diff)
downloadsonarqube-8b2ac2905ad630975d72af0a27ccdb45b4513bf0.tar.gz
sonarqube-8b2ac2905ad630975d72af0a27ccdb45b4513bf0.zip
SONAR-23224 Reduce risk of telemetry daemon from endlessly sending messages
Diffstat (limited to 'server')
-rw-r--r--server/sonar-telemetry/src/main/java/org/sonar/telemetry/TelemetryDaemon.java28
-rw-r--r--server/sonar-telemetry/src/test/java/org/sonar/telemetry/TelemetryDaemonTest.java51
2 files changed, 49 insertions, 30 deletions
diff --git a/server/sonar-telemetry/src/main/java/org/sonar/telemetry/TelemetryDaemon.java b/server/sonar-telemetry/src/main/java/org/sonar/telemetry/TelemetryDaemon.java
index a7c60adffa0..8d6ac35d955 100644
--- a/server/sonar-telemetry/src/main/java/org/sonar/telemetry/TelemetryDaemon.java
+++ b/server/sonar-telemetry/src/main/java/org/sonar/telemetry/TelemetryDaemon.java
@@ -38,13 +38,13 @@ import org.sonar.db.DbSession;
import org.sonar.server.property.InternalProperties;
import org.sonar.server.util.AbstractStoppableScheduledExecutorServiceImpl;
import org.sonar.server.util.GlobalLockManager;
+import org.sonar.telemetry.core.MessageSerializer;
import org.sonar.telemetry.core.TelemetryClient;
+import org.sonar.telemetry.core.schema.BaseMessage;
import org.sonar.telemetry.legacy.TelemetryData;
import org.sonar.telemetry.legacy.TelemetryDataJsonWriter;
import org.sonar.telemetry.legacy.TelemetryDataLoader;
import org.sonar.telemetry.metrics.TelemetryMetricsLoader;
-import org.sonar.telemetry.core.schema.BaseMessage;
-import org.sonar.telemetry.core.MessageSerializer;
import static org.sonar.process.ProcessProperties.Property.SONAR_TELEMETRY_ENABLE;
import static org.sonar.process.ProcessProperties.Property.SONAR_TELEMETRY_FREQUENCY_IN_SECONDS;
@@ -116,29 +116,27 @@ public class TelemetryDaemon extends AbstractStoppableScheduledExecutorServiceIm
private Runnable telemetryCommand() {
return () -> {
- try {
-
- if (!lockManager.tryLock(LOCK_NAME, lockDuration())) {
- return;
- }
+ if (!lockManager.tryLock(LOCK_NAME, lockDuration())) {
+ return;
+ }
- long now = system2.now();
+ long now = system2.now();
+ try {
if (shouldUploadStatistics(now)) {
uploadLegacyTelemetry();
uploadMetrics();
-
- updateTelemetryProps(now);
+ writeTelemetrySequence();
}
} catch (Exception e) {
LOG.debug("Error while checking SonarQube statistics: {}", e.getMessage(), e);
+ } finally {
+ writeLastPing(now);
}
// do not check at start up to exclude test instance which are not up for a long time
};
}
- private void updateTelemetryProps(long now) {
- internalProperties.write(I_PROP_LAST_PING, String.valueOf(now));
-
+ private void writeTelemetrySequence() {
Optional<String> currentSequence = internalProperties.read(I_PROP_MESSAGE_SEQUENCE);
if (currentSequence.isEmpty()) {
internalProperties.write(I_PROP_MESSAGE_SEQUENCE, String.valueOf(1));
@@ -149,6 +147,10 @@ public class TelemetryDaemon extends AbstractStoppableScheduledExecutorServiceIm
internalProperties.write(I_PROP_MESSAGE_SEQUENCE, String.valueOf(current + 1));
}
+ private void writeLastPing(long now) {
+ internalProperties.write(I_PROP_LAST_PING, String.valueOf(now));
+ }
+
private void optOut() {
StringWriter json = new StringWriter();
try (JsonWriter writer = JsonWriter.of(json)) {
diff --git a/server/sonar-telemetry/src/test/java/org/sonar/telemetry/TelemetryDaemonTest.java b/server/sonar-telemetry/src/test/java/org/sonar/telemetry/TelemetryDaemonTest.java
index 4d3aac41a58..c5b4044877f 100644
--- a/server/sonar-telemetry/src/test/java/org/sonar/telemetry/TelemetryDaemonTest.java
+++ b/server/sonar-telemetry/src/test/java/org/sonar/telemetry/TelemetryDaemonTest.java
@@ -99,7 +99,7 @@ class TelemetryDaemonTest {
}
@Test
- void send_data_via_client_at_startup_after_initial_delay() throws IOException {
+ void start_sendsDataAtStartupAfterInitialDelay() throws IOException {
initTelemetrySettingsToDefaultValues();
when(lockManager.tryLock(any(), anyInt())).thenReturn(true);
settings.setProperty("sonar.telemetry.frequencyInSeconds", "1");
@@ -112,18 +112,8 @@ class TelemetryDaemonTest {
verify(dataJsonWriter).writeTelemetryData(any(JsonWriter.class), same(SOME_TELEMETRY_DATA));
}
- private void mockDataJsonWriterDoingSomething() {
- doAnswer(t -> {
- JsonWriter json = t.getArgument(0);
- json.beginObject().prop("foo", "bar").endObject();
- return null;
- })
- .when(dataJsonWriter)
- .writeTelemetryData(any(), any());
- }
-
@Test
- void check_if_should_send_data_periodically() throws IOException {
+ void start_shouldCheckIfDataSentPeriodically() throws IOException {
initTelemetrySettingsToDefaultValues();
when(lockManager.tryLock(any(), anyInt())).thenReturn(true);
long now = system2.now();
@@ -146,7 +136,7 @@ class TelemetryDaemonTest {
}
@Test
- void do_not_send_data_if_last_ping_earlier_than_one_day_ago() throws IOException {
+ void start_whenLastPingEarlierThanOneDayAgo_shouldNotSendData() throws IOException {
initTelemetrySettingsToDefaultValues();
when(lockManager.tryLock(any(), anyInt())).thenReturn(true);
settings.setProperty("sonar.telemetry.frequencyInSeconds", "1");
@@ -161,7 +151,24 @@ class TelemetryDaemonTest {
}
@Test
- void send_data_if_last_ping_is_over_one_day_ago() throws IOException {
+ void start_whenExceptionThrown_shouldNotRepeatedlySendDataAndLastPingPropIsStillSet() throws IOException {
+ initTelemetrySettingsToDefaultValues();
+ when(lockManager.tryLock(any(), anyInt())).thenReturn(true);
+ settings.setProperty("sonar.telemetry.frequencyInSeconds", "1");
+ long today = parseDate("2017-08-01").getTime();
+ system2.setNow(today);
+ settings.removeProperty("telemetry.lastPing");
+ mockDataJsonWriterDoingSomething();
+ when(dataLoader.load()).thenThrow(new IllegalStateException("Some error was thrown."));
+
+ underTest.start();
+
+ verify(client, after(2_000).never()).upload(anyString());
+ verify(internalProperties, timeout(4_000)).write("telemetry.lastPing", String.valueOf(today));
+ }
+
+ @Test
+ void start_whenLastPingOverOneDayAgo_shouldSendData() throws IOException {
initTelemetrySettingsToDefaultValues();
when(lockManager.tryLock(any(), anyInt())).thenReturn(true);
settings.setProperty("sonar.telemetry.frequencyInSeconds", "1");
@@ -180,7 +187,7 @@ class TelemetryDaemonTest {
}
@Test
- void opt_out_sent_once() throws IOException {
+ void start_whenOptOut_shouldSendOnceAndLogsPresent() throws IOException {
initTelemetrySettingsToDefaultValues();
when(lockManager.tryLock(any(), anyInt())).thenReturn(true);
settings.setProperty("sonar.telemetry.frequencyInSeconds", "1");
@@ -196,7 +203,7 @@ class TelemetryDaemonTest {
}
@Test
- void write_sequence_as_one_if_not_previously_present() {
+ void start_whenSequenceNotPresent_shouldBeSetToOne() {
initTelemetrySettingsToDefaultValues();
when(lockManager.tryLock(any(), anyInt())).thenReturn(true);
settings.setProperty("sonar.telemetry.frequencyInSeconds", "1");
@@ -208,7 +215,7 @@ class TelemetryDaemonTest {
}
@Test
- void write_sequence_correctly_incremented() {
+ void start_whenSequencePresent_shouldIncrementCorrectly() {
initTelemetrySettingsToDefaultValues();
when(lockManager.tryLock(any(), anyInt())).thenReturn(true);
settings.setProperty("sonar.telemetry.frequencyInSeconds", "1");
@@ -225,6 +232,16 @@ class TelemetryDaemonTest {
verify(internalProperties, timeout(4_000)).write("telemetry.messageSeq", "11");
}
+ private void mockDataJsonWriterDoingSomething() {
+ doAnswer(t -> {
+ JsonWriter json = t.getArgument(0);
+ json.beginObject().prop("foo", "bar").endObject();
+ return null;
+ })
+ .when(dataJsonWriter)
+ .writeTelemetryData(any(), any());
+ }
+
private void initTelemetrySettingsToDefaultValues() {
settings.setProperty(SONAR_TELEMETRY_ENABLE.getKey(), SONAR_TELEMETRY_ENABLE.getDefaultValue());
settings.setProperty(SONAR_TELEMETRY_URL.getKey(), SONAR_TELEMETRY_URL.getDefaultValue());