aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre <pierre.guillot@sonarsource.com>2022-09-28 16:28:42 +0200
committerPhilippe Perrin <philippe.perrin@sonarsource.com>2022-10-07 12:13:56 +0200
commit3ee9a7c22dcb895d21b3b4226c811a05740a3726 (patch)
tree603a133e59d91b0652efc3612056be5351852fe6
parentd3f6b8bef5066a586f939e7d8b017321fd00dde4 (diff)
downloadsonarqube-3ee9a7c22dcb895d21b3b4226c811a05740a3726.tar.gz
sonarqube-3ee9a7c22dcb895d21b3b4226c811a05740a3726.zip
SONAR-17413 Compress telemetry payload
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java1
-rw-r--r--server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryClient.java41
-rw-r--r--server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryClientCompressionTest.java62
-rw-r--r--server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryClientTest.java2
4 files changed, 103 insertions, 3 deletions
diff --git a/server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java b/server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java
index b51061ebc3b..fa5b7a898c4 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java
@@ -168,6 +168,7 @@ public class ProcessProperties {
SONAR_TELEMETRY_ENABLE("sonar.telemetry.enable", "true"),
SONAR_TELEMETRY_URL("sonar.telemetry.url", "https://telemetry.sonarsource.com/sonarqube"),
SONAR_TELEMETRY_FREQUENCY_IN_SECONDS("sonar.telemetry.frequencyInSeconds", "10800"),
+ SONAR_TELEMETRY_COMPRESSION("sonar.telemetry.compression", "true"),
SONAR_UPDATECENTER_ACTIVATE("sonar.updatecenter.activate", "true"),
diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryClient.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryClient.java
index 69167d65841..c203a4cf5ab 100644
--- a/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryClient.java
+++ b/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryClient.java
@@ -26,12 +26,16 @@ import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
+import okio.BufferedSink;
+import okio.GzipSink;
+import okio.Okio;
import org.sonar.api.Startable;
import org.sonar.api.config.Configuration;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import static org.sonar.process.ProcessProperties.Property.SONAR_TELEMETRY_COMPRESSION;
import static org.sonar.process.ProcessProperties.Property.SONAR_TELEMETRY_URL;
@ServerSide
@@ -42,10 +46,11 @@ public class TelemetryClient implements Startable {
private final OkHttpClient okHttpClient;
private final Configuration config;
private String serverUrl;
+ private boolean compression;
public TelemetryClient(OkHttpClient okHttpClient, Configuration config) {
- this.okHttpClient = okHttpClient;
this.config = config;
+ this.okHttpClient = okHttpClient;
}
void upload(String json) throws IOException {
@@ -68,12 +73,40 @@ public class TelemetryClient implements Startable {
private Request buildHttpRequest(String json) {
Request.Builder request = new Request.Builder();
+ request.addHeader("Content-Encoding", "gzip");
+ request.addHeader("Content-Type", "application/json");
request.url(serverUrl);
RequestBody body = RequestBody.create(JSON, json);
- request.post(body);
+ if (compression) {
+ request.post(gzip(body));
+ } else {
+ request.post(body);
+ }
return request.build();
}
+ private static RequestBody gzip(final RequestBody body) {
+ return new RequestBody() {
+ @Override
+ public MediaType contentType() {
+ return body.contentType();
+ }
+
+ @Override
+ public long contentLength() {
+ // We don't know the compressed length in advance!
+ return -1;
+ }
+
+ @Override
+ public void writeTo(BufferedSink sink) throws IOException {
+ BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
+ body.writeTo(gzipSink);
+ gzipSink.close();
+ }
+ };
+ }
+
private static void execute(Call call) throws IOException {
try (Response ignored = call.execute()) {
// auto close connection to avoid leaked connection
@@ -82,7 +115,9 @@ public class TelemetryClient implements Startable {
@Override
public void start() {
- this.serverUrl = config.get(SONAR_TELEMETRY_URL.getKey()).orElseThrow(() -> new IllegalStateException(String.format("Setting '%s' must be provided.", SONAR_TELEMETRY_URL)));
+ this.serverUrl = config.get(SONAR_TELEMETRY_URL.getKey())
+ .orElseThrow(() -> new IllegalStateException(String.format("Setting '%s' must be provided.", SONAR_TELEMETRY_URL)));
+ this.compression = config.getBoolean(SONAR_TELEMETRY_COMPRESSION.getKey()).orElse(true);
}
@Override
diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryClientCompressionTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryClientCompressionTest.java
new file mode 100644
index 00000000000..b463b00c91c
--- /dev/null
+++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryClientCompressionTest.java
@@ -0,0 +1,62 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.telemetry;
+
+import java.io.IOException;
+import java.util.Objects;
+import okhttp3.MediaType;
+import okhttp3.OkHttpClient;
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.mockwebserver.MockWebServer;
+import okhttp3.mockwebserver.RecordedRequest;
+import okio.GzipSource;
+import okio.Okio;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.sonar.api.config.internal.MapSettings;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.process.ProcessProperties.Property.SONAR_TELEMETRY_URL;
+
+public class TelemetryClientCompressionTest {
+
+ private final OkHttpClient okHttpClient = new OkHttpClient();
+ private final MockWebServer telemetryServer = new MockWebServer();
+
+ @Test
+ public void payload_is_gzip_encoded() throws IOException, InterruptedException {
+ telemetryServer.enqueue(new MockResponse().setResponseCode(200));
+ MapSettings settings = new MapSettings();
+ settings.setProperty(SONAR_TELEMETRY_URL.getKey(), telemetryServer.url("/").toString());
+ TelemetryClient underTest = new TelemetryClient(okHttpClient, settings.asConfig());
+ underTest.start();
+ underTest.upload("payload compressed with gzip");
+
+ RecordedRequest request = telemetryServer.takeRequest();
+
+ String contentType = Objects.requireNonNull(request.getHeader("content-type"));
+ assertThat(MediaType.parse(contentType)).isEqualTo(MediaType.parse("application/json; charset=utf-8"));
+ assertThat(request.getHeader("content-encoding")).isEqualTo("gzip");
+
+ GzipSource source = new GzipSource(request.getBody());
+ String body = Okio.buffer(source).readUtf8();
+ Assertions.assertThat(body).isEqualTo("payload compressed with gzip");
+ }
+}
diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryClientTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryClientTest.java
index d24e3c1b396..b39727bae36 100644
--- a/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryClientTest.java
+++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryClientTest.java
@@ -32,6 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static org.sonar.process.ProcessProperties.Property.SONAR_TELEMETRY_COMPRESSION;
import static org.sonar.process.ProcessProperties.Property.SONAR_TELEMETRY_URL;
public class TelemetryClientTest {
@@ -48,6 +49,7 @@ public class TelemetryClientTest {
public void upload() throws IOException {
ArgumentCaptor<Request> requestCaptor = ArgumentCaptor.forClass(Request.class);
settings.setProperty(SONAR_TELEMETRY_URL.getKey(), TELEMETRY_URL);
+ settings.setProperty(SONAR_TELEMETRY_COMPRESSION.getKey(), false);
underTest.start();
underTest.upload(JSON);