Skip to content

Commit 4e47e76

Browse files
Allow GsonBuilder to be passed in and used through Analytics and AnalyticsClient (#446)
Co-authored-by: Louis Lepper <llepper2@atlassian.com>
1 parent de66ffc commit 4e47e76

File tree

4 files changed

+77
-32
lines changed

4 files changed

+77
-32
lines changed

analytics/src/main/java/com/segment/analytics/Analytics.java

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ public static class Builder {
149149
private List<Callback> callbacks;
150150
private int queueCapacity;
151151
private boolean forceTlsV1 = false;
152+
private GsonBuilder gsonBuilder;
152153

153154
Builder(String writeKey) {
154155
if (writeKey == null || writeKey.trim().length() == 0) {
@@ -248,6 +249,20 @@ public Builder queueCapacity(int capacity) {
248249
this.queueCapacity = capacity;
249250
return this;
250251
}
252+
253+
public Builder gsonBuilder(GsonBuilder gsonBuilder) {
254+
if (gsonBuilder == null) {
255+
throw new NullPointerException("Null gsonBuilder");
256+
}
257+
258+
if (this.gsonBuilder != null) {
259+
throw new IllegalStateException("gsonBuilder is already registered.");
260+
}
261+
262+
this.gsonBuilder = gsonBuilder;
263+
return this;
264+
}
265+
251266
/** Set the queueSize at which flushes should be triggered. */
252267
@Beta
253268
public Builder flushQueueSize(int flushQueueSize) {
@@ -341,11 +356,15 @@ public Builder forceTlsVersion1() {
341356

342357
/** Create a {@link Analytics} client. */
343358
public Analytics build() {
344-
Gson gson =
345-
new GsonBuilder() //
346-
.registerTypeAdapterFactory(new AutoValueAdapterFactory()) //
347-
.registerTypeAdapter(Date.class, new ISO8601DateAdapter()) //
348-
.create();
359+
if (gsonBuilder == null) {
360+
gsonBuilder = new GsonBuilder();
361+
}
362+
363+
gsonBuilder
364+
.registerTypeAdapterFactory(new AutoValueAdapterFactory())
365+
.registerTypeAdapter(Date.class, new ISO8601DateAdapter());
366+
367+
Gson gson = gsonBuilder.create();
349368

350369
if (endpoint == null) {
351370
if (uploadURL != null) {
@@ -450,7 +469,8 @@ public void log(String message) {
450469
threadFactory,
451470
networkExecutor,
452471
callbacks,
453-
writeKey);
472+
writeKey,
473+
gson);
454474

455475
return new Analytics(analyticsClient, messageTransformers, messageInterceptors, log);
456476
}

analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public class AnalyticsClient {
4040
private static final int BATCH_MAX_SIZE = 1024 * 500;
4141
private static final int MSG_MAX_SIZE = 1024 * 32;
4242
private static final Charset ENCODING = StandardCharsets.UTF_8;
43-
private static Gson gsonInstance;
43+
private Gson gsonInstance;
4444
private static final String instanceId = UUID.randomUUID().toString();
4545

4646
static {
@@ -80,7 +80,8 @@ public static AnalyticsClient create(
8080
ThreadFactory threadFactory,
8181
ExecutorService networkExecutor,
8282
List<Callback> callbacks,
83-
String writeKey) {
83+
String writeKey,
84+
Gson gsonInstance) {
8485
return new AnalyticsClient(
8586
new LinkedBlockingQueue<Message>(queueCapacity),
8687
uploadUrl,
@@ -94,7 +95,8 @@ public static AnalyticsClient create(
9495
networkExecutor,
9596
callbacks,
9697
new AtomicBoolean(false),
97-
writeKey);
98+
writeKey,
99+
gsonInstance);
98100
}
99101

100102
public AnalyticsClient(
@@ -110,7 +112,8 @@ public AnalyticsClient(
110112
ExecutorService networkExecutor,
111113
List<Callback> callbacks,
112114
AtomicBoolean isShutDown,
113-
String writeKey) {
115+
String writeKey,
116+
Gson gsonInstance) {
114117
this.messageQueue = messageQueue;
115118
this.uploadUrl = uploadUrl;
116119
this.service = service;
@@ -123,6 +126,7 @@ public AnalyticsClient(
123126
this.networkExecutor = networkExecutor;
124127
this.isShutDown = isShutDown;
125128
this.writeKey = writeKey;
129+
this.gsonInstance = gsonInstance;
126130

127131
this.currentQueueSizeInBytes = 0;
128132

@@ -141,24 +145,10 @@ public void run() {
141145
TimeUnit.MILLISECONDS);
142146
}
143147

144-
/**
145-
* Creating GSON object everytime we check the size seems costly
146-
*
147-
* @return gson instance
148-
*/
149-
public Gson getGsonInstance() {
150-
if (gsonInstance == null) {
151-
gsonInstance = new Gson();
152-
}
153-
return gsonInstance;
154-
}
155-
156148
public int messageSizeInBytes(Message message) {
157-
Gson gson = getGsonInstance();
158-
String stringifiedMessage = gson.toJson(message);
149+
String stringifiedMessage = gsonInstance.toJson(message);
159150

160-
int sizeInBytes = stringifiedMessage.getBytes(ENCODING).length;
161-
return sizeInBytes;
151+
return stringifiedMessage.getBytes(ENCODING).length;
162152
}
163153

164154
private Boolean isBackPressuredAfterSize(int incomingSize) {
@@ -269,7 +259,7 @@ public void run() {
269259
LinkedList<Message> messages = new LinkedList<>();
270260
AtomicInteger currentBatchSize = new AtomicInteger();
271261
boolean batchSizeLimitReached = false;
272-
int contextSize = getGsonInstance().toJson(CONTEXT).getBytes(ENCODING).length;
262+
int contextSize = gsonInstance.toJson(CONTEXT).getBytes(ENCODING).length;
273263
try {
274264
while (!stop) {
275265
Message message = messageQueue.take();

analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import static org.mockito.Mockito.mock;
88
import static org.mockito.Mockito.verify;
99

10+
import com.google.gson.GsonBuilder;
1011
import java.util.concurrent.ExecutorService;
1112
import java.util.concurrent.ThreadFactory;
1213
import java.util.concurrent.TimeUnit;
@@ -167,6 +168,34 @@ public void buildsWithValidInterceptor() {
167168
assertThat(analytics).isNotNull();
168169
}
169170

171+
@Test
172+
public void nullGsonBuilder() {
173+
try {
174+
builder.gsonBuilder(null);
175+
fail("Should fail for null gsonBuilder");
176+
} catch (NullPointerException e) {
177+
assertThat(e).hasMessage("Null gsonBuilder");
178+
}
179+
}
180+
181+
@Test
182+
public void duplicateGsonBuilder() {
183+
GsonBuilder gsonBuilder = new GsonBuilder();
184+
try {
185+
builder.gsonBuilder(gsonBuilder).gsonBuilder(gsonBuilder);
186+
fail("Should fail for duplicate gsonBuilder");
187+
} catch (IllegalStateException e) {
188+
assertThat(e).hasMessage("gsonBuilder is already registered.");
189+
}
190+
}
191+
192+
@Test
193+
public void buildsWithValidGsonBuilder() {
194+
GsonBuilder gsonBuilder = new GsonBuilder();
195+
Analytics analytics = builder.gsonBuilder(gsonBuilder).build();
196+
assertThat(analytics).isNotNull();
197+
}
198+
170199
@Test
171200
public void invalidFlushQueueSize() {
172201
try {

analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import static org.mockito.Mockito.when;
1717
import static org.mockito.MockitoAnnotations.openMocks;
1818

19+
import com.google.gson.Gson;
1920
import com.segment.analytics.Callback;
2021
import com.segment.analytics.Log;
2122
import com.segment.analytics.TestUtils.MessageBuilderTest;
@@ -105,7 +106,8 @@ AnalyticsClient newClient() {
105106
networkExecutor,
106107
Collections.singletonList(callback),
107108
isShutDown,
108-
writeKey);
109+
writeKey,
110+
new Gson());
109111
}
110112

111113
@Test
@@ -293,7 +295,8 @@ public void flushHowManyTimesNecessaryToStayWithinLimit() throws InterruptedExce
293295
networkExecutor,
294296
Collections.singletonList(callback),
295297
isShutDown,
296-
writeKey);
298+
writeKey,
299+
new Gson());
297300

298301
Map<String, String> properties = new HashMap<String, String>();
299302

@@ -868,7 +871,8 @@ public void submitBatchBelowThreshold() throws InterruptedException, IllegalArgu
868871
networkExecutor,
869872
Collections.singletonList(callback),
870873
isShutDown,
871-
writeKey);
874+
writeKey,
875+
new Gson());
872876

873877
Map<String, String> properties = new HashMap<String, String>();
874878
properties.put("property3", generateDataOfSizeSpecialChars(MAX_MSG_SIZE, true));
@@ -909,7 +913,8 @@ public void submitBatchAboveThreshold() throws InterruptedException, IllegalArgu
909913
networkExecutor,
910914
Collections.singletonList(callback),
911915
isShutDown,
912-
writeKey);
916+
writeKey,
917+
new Gson());
913918

914919
Map<String, String> properties = new HashMap<String, String>();
915920
properties.put("property3", generateDataOfSizeSpecialChars(MAX_MSG_SIZE, true));
@@ -949,7 +954,8 @@ public void submitManySmallMessagesBatchAboveThreshold() throws InterruptedExcep
949954
networkExecutor,
950955
Collections.singletonList(callback),
951956
isShutDown,
952-
writeKey);
957+
writeKey,
958+
new Gson());
953959

954960
Map<String, String> properties = new HashMap<String, String>();
955961
properties.put("property3", generateDataOfSizeSpecialChars(1024 * 8, true));

0 commit comments

Comments
 (0)