From be37e43a5e40588755344b6f05c12948e96f9dbd Mon Sep 17 00:00:00 2001 From: James Kiser Date: Tue, 30 Oct 2018 13:38:07 -0700 Subject: [PATCH 001/272] ISSUE-135: use JsonElement.getAsString() when deserializing dates / adding tests --- .../analytics/gson/ISO8601DateAdapter.java | 2 +- .../java/com/segment/analytics/TestUtils.java | 7 +++ .../gson/ISO8601DateAdapterTest.java | 43 +++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 analytics-core/src/test/java/com/segment/analytics/gson/ISO8601DateAdapterTest.java diff --git a/analytics-core/src/main/java/com/segment/analytics/gson/ISO8601DateAdapter.java b/analytics-core/src/main/java/com/segment/analytics/gson/ISO8601DateAdapter.java index 39b50a4f..2ab9f527 100644 --- a/analytics-core/src/main/java/com/segment/analytics/gson/ISO8601DateAdapter.java +++ b/analytics-core/src/main/java/com/segment/analytics/gson/ISO8601DateAdapter.java @@ -23,6 +23,6 @@ public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext @Override public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - return Iso8601Utils.parse(json.toString()); + return Iso8601Utils.parse(json.getAsString()); } } diff --git a/analytics-core/src/test/java/com/segment/analytics/TestUtils.java b/analytics-core/src/test/java/com/segment/analytics/TestUtils.java index e31dcac8..512fcb6b 100644 --- a/analytics-core/src/test/java/com/segment/analytics/TestUtils.java +++ b/analytics-core/src/test/java/com/segment/analytics/TestUtils.java @@ -1,5 +1,8 @@ package com.segment.analytics; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.segment.analytics.gson.ISO8601DateAdapter; import com.segment.analytics.messages.*; import java.util.Calendar; import java.util.Date; @@ -12,6 +15,10 @@ private TestUtils() { throw new AssertionError("No instances."); } + public static final Gson GSON = new GsonBuilder() + .registerTypeAdapter(Date.class, new ISO8601DateAdapter()) + .create(); + @SuppressWarnings("UnusedDeclaration") public enum MessageBuilderFactory { ALIAS { diff --git a/analytics-core/src/test/java/com/segment/analytics/gson/ISO8601DateAdapterTest.java b/analytics-core/src/test/java/com/segment/analytics/gson/ISO8601DateAdapterTest.java new file mode 100644 index 00000000..5d331eaf --- /dev/null +++ b/analytics-core/src/test/java/com/segment/analytics/gson/ISO8601DateAdapterTest.java @@ -0,0 +1,43 @@ +package com.segment.analytics.gson; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.segment.analytics.TestUtils; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Date; + +import static com.segment.analytics.TestUtils.newDate; +import static org.assertj.core.api.Assertions.assertThat; + +public class ISO8601DateAdapterTest { + + private static class TestModel { + final Date timestamp; + public TestModel(Date timestamp) { + this.timestamp = timestamp; + } + } + + @Test + public void testSerializeDate() { + TestModel testModel = new TestModel(newDate(1996, 12, 19, 16, 39, 57, 0, -8 * 60)); + + JsonElement e = TestUtils.GSON.toJsonTree(testModel); + Assert.assertTrue(e.isJsonObject()); + + JsonObject o = e.getAsJsonObject(); + Assert.assertTrue(o.has("timestamp")); + + assertThat(o.get("timestamp").getAsString()).isEqualTo("1996-12-20T00:39:57.000Z"); + } + + @Test + public void testDeserializeDate() { + String serializedTestModel = "{\"timestamp\":\"1996-06-01T16:39:57.000Z\"}"; + Date expected = newDate(1996, 06, 01, 16, 39, 57, 0, 0); + TestModel actual = TestUtils.GSON.fromJson(serializedTestModel, TestModel.class); + assertThat(actual.timestamp).isEqualTo(expected); + } +} From 3c358113e4ddbce0a065a01ab2dc255efcedc7ec Mon Sep 17 00:00:00 2001 From: James Kiser Date: Tue, 30 Oct 2018 16:34:26 -0700 Subject: [PATCH 002/272] ISSUE-135: moving gson constant --- .../src/test/java/com/segment/analytics/TestUtils.java | 4 ---- .../segment/analytics/gson/ISO8601DateAdapterTest.java | 10 ++++++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/analytics-core/src/test/java/com/segment/analytics/TestUtils.java b/analytics-core/src/test/java/com/segment/analytics/TestUtils.java index 512fcb6b..fe1f6f03 100644 --- a/analytics-core/src/test/java/com/segment/analytics/TestUtils.java +++ b/analytics-core/src/test/java/com/segment/analytics/TestUtils.java @@ -15,10 +15,6 @@ private TestUtils() { throw new AssertionError("No instances."); } - public static final Gson GSON = new GsonBuilder() - .registerTypeAdapter(Date.class, new ISO8601DateAdapter()) - .create(); - @SuppressWarnings("UnusedDeclaration") public enum MessageBuilderFactory { ALIAS { diff --git a/analytics-core/src/test/java/com/segment/analytics/gson/ISO8601DateAdapterTest.java b/analytics-core/src/test/java/com/segment/analytics/gson/ISO8601DateAdapterTest.java index 5d331eaf..5570b6e2 100644 --- a/analytics-core/src/test/java/com/segment/analytics/gson/ISO8601DateAdapterTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/gson/ISO8601DateAdapterTest.java @@ -1,5 +1,7 @@ package com.segment.analytics.gson; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.segment.analytics.TestUtils; @@ -13,6 +15,10 @@ public class ISO8601DateAdapterTest { + public static final Gson GSON = new GsonBuilder() + .registerTypeAdapter(Date.class, new ISO8601DateAdapter()) + .create(); + private static class TestModel { final Date timestamp; public TestModel(Date timestamp) { @@ -24,7 +30,7 @@ public TestModel(Date timestamp) { public void testSerializeDate() { TestModel testModel = new TestModel(newDate(1996, 12, 19, 16, 39, 57, 0, -8 * 60)); - JsonElement e = TestUtils.GSON.toJsonTree(testModel); + JsonElement e = GSON.toJsonTree(testModel); Assert.assertTrue(e.isJsonObject()); JsonObject o = e.getAsJsonObject(); @@ -37,7 +43,7 @@ public void testSerializeDate() { public void testDeserializeDate() { String serializedTestModel = "{\"timestamp\":\"1996-06-01T16:39:57.000Z\"}"; Date expected = newDate(1996, 06, 01, 16, 39, 57, 0, 0); - TestModel actual = TestUtils.GSON.fromJson(serializedTestModel, TestModel.class); + TestModel actual = GSON.fromJson(serializedTestModel, TestModel.class); assertThat(actual.timestamp).isEqualTo(expected); } } From cf8cb637a426cb78dd5a73caccb22b51b01b6836 Mon Sep 17 00:00:00 2001 From: nhi-nguyen Date: Thu, 28 Feb 2019 17:26:10 -0800 Subject: [PATCH 003/272] Fix scheduled e2e test jobs (#142) Run e2e tests instead of multi-tests for the scheduled tests --- .circleci/config.yml | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a349f37f..08237626 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -98,12 +98,6 @@ workflows: - test-jdk10 - test-jdk9 - test-jdk8 - e2e: - jobs: - - test - - e2e: - requires: - - test static_analysis: jobs: - test @@ -136,7 +130,7 @@ workflows: - master - scheduled_e2e_testing jobs: - - test-jdklatest - - test-jdk10 - - test-jdk9 - - test-jdk8 + - test + - e2e: + requires: + - test From 203c1dfc75efec1c97d9f1dd6246be5be0f196c4 Mon Sep 17 00:00:00 2001 From: William Grosset Date: Thu, 28 Feb 2019 20:34:56 -0800 Subject: [PATCH 004/272] Update README --- README.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/README.md b/README.md index 2470f5c9..2475e25e 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,48 @@ analytics-java analytics-java is a Java client for [Segment](https://segment.com) +
+ +

You can't fix what you can't measure

+
+ +Analytics helps you measure your users, product, and business. It unlocks insights into your app's funnel, core business metrics, and whether you have product-market fit. + +## How to get started +1. **Collect analytics data** from your app(s). + - The top 200 Segment companies collect data from 5+ source types (web, mobile, server, CRM, etc.). +2. **Send the data to analytics tools** (for example, Google Analytics, Amplitude, Mixpanel). + - Over 250+ Segment companies send data to eight categories of destinations such as analytics tools, warehouses, email marketing and remarketing systems, session recording, and more. +3. **Explore your data** by creating metrics (for example, new signups, retention cohorts, and revenue generation). + - The best Segment companies use retention cohorts to measure product market fit. Netflix has 70% paid retention after 12 months, 30% after 7 years. + +[Segment](https://segment.com) collects analytics data and allows you to send it to more than 250 apps (such as Google Analytics, Mixpanel, Optimizely, Facebook Ads, Slack, Sentry) just by flipping a switch. You only need one Segment code snippet, and you can turn integrations on and off at will, with no additional code. [Sign up with Segment today](https://app.segment.com/signup). + +### Why? +1. **Power all your analytics apps with the same data**. Instead of writing code to integrate all of your tools individually, send data to Segment, once. + +2. **Install tracking for the last time**. We're the last integration you'll ever need to write. You only need to instrument Segment once. Reduce all of your tracking code and advertising tags into a single set of API calls. + +3. **Send data from anywhere**. Send Segment data from any device, and we'll transform and send it on to any tool. + +4. **Query your data in SQL**. Slice, dice, and analyze your data in detail with Segment SQL. We'll transform and load your customer behavioral data directly from your apps into Amazon Redshift, Google BigQuery, or Postgres. Save weeks of engineering time by not having to invent your own data warehouse and ETL pipeline. + + For example, you can capture data on any app: + ```js + analytics.track('Order Completed', { price: 99.84 }) + ``` + Then, query the resulting data in SQL: + ```sql + select * from app.order_completed + order by price desc + ``` + +### 🚀 Startup Program +
+ +
+If you are part of a new startup (<$5M raised, <2 years since founding), we just launched a new startup program for you. You can get a Segment Team plan (up to $25,000 value in Segment credits) for free up to 2 years — apply here! + ## Documentation Documentation is available at [https://segment.com/libraries/java](https://segment.com/libraries/java). From 22960eb2684000f19e7bcf049d8678124850e973 Mon Sep 17 00:00:00 2001 From: Satish Subhashrao Saley Date: Sun, 10 Mar 2019 21:39:14 -0700 Subject: [PATCH 005/272] ISSUE-146 Configurable message queue size --- .../java/com/segment/analytics/Analytics.java | 70 +++++++++++++++---- .../analytics/internal/AnalyticsClient.java | 7 +- .../analytics/AnalyticsBuilderTest.java | 23 ++++++ .../com/segment/analytics/AnalyticsTest.java | 15 ++++ 4 files changed, 101 insertions(+), 14 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index ffc19c8d..cfdf9ce1 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -65,11 +65,50 @@ public static Builder builder(String writeKey) { /** Enqueue the given message to be uploaded to Segment's servers. */ public void enqueue(MessageBuilder builder) { + Message message = buildMessage(builder); + if(message == null){ + return; + } + client.enqueue(message); + } + + /** + * Inserts the message into queue if it is possible to do + * so immediately without violating capacity restrictions, returning + * {@code true} upon success and {@code false} if no space is currently + * available. + * @param builder + */ + public boolean offer(MessageBuilder builder) { + Message message = buildMessage(builder); + if(message == null){ + return false; + } + return client.offer(message); + } + + /** Flush events in the message queue. */ + public void flush() { + client.flush(); + } + + /** Stops this instance from processing further requests. */ + public void shutdown() { + client.shutdown(); + } + + /** + * Helper method to build message + * @param builder + * @return Instance of Message if valid message can be build + * null if skipping this message + */ + private Message buildMessage(MessageBuilder builder){ for (MessageTransformer messageTransformer : messageTransformers) { boolean shouldContinue = messageTransformer.transform(builder); if (!shouldContinue) { log.print(Log.Level.VERBOSE, "Skipping message %s.", builder); - return; + return null; } } Message message = builder.build(); @@ -77,20 +116,10 @@ public void enqueue(MessageBuilder builder) { message = messageInterceptor.intercept(message); if (message == null) { log.print(Log.Level.VERBOSE, "Skipping message %s.", builder); - return; + return null; } } - client.enqueue(message); - } - - /** Flush events in the message queue. */ - public void flush() { - client.flush(); - } - - /** Stops this instance from processing further requests. */ - public void shutdown() { - client.shutdown(); + return message; } /** Fluent API for creating {@link Analytics} instances. */ @@ -111,6 +140,7 @@ public static class Builder { private int flushQueueSize; private long flushIntervalInMillis; private List callbacks; + private int queueCapacity; Builder(String writeKey) { if (writeKey == null || writeKey.trim().length() == 0) { @@ -190,6 +220,16 @@ public Builder messageInterceptor(MessageInterceptor interceptor) { return this; } + /** + * Set queue capacity + */ + public Builder queueCapacity(int capacity) { + if (capacity <= 0) { + throw new IllegalArgumentException("capacity should be positive."); + } + this.queueCapacity = capacity; + return this; + } /** Set the queueSize at which flushes should be triggered. */ @Beta public Builder flushQueueSize(int flushQueueSize) { @@ -275,6 +315,9 @@ public Analytics build() { if (flushIntervalInMillis == 0) { flushIntervalInMillis = Platform.get().defaultFlushIntervalInMillis(); } + if(queueCapacity == 0) { + queueCapacity = Integer.MAX_VALUE; + } if (flushQueueSize == 0) { flushQueueSize = Platform.get().defaultFlushQueueSize(); } @@ -321,6 +364,7 @@ public void log(String message) { AnalyticsClient analyticsClient = AnalyticsClient.create( segmentService, + queueCapacity, flushQueueSize, flushIntervalInMillis, log, diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 80df17ac..a61d0659 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -48,6 +48,7 @@ public class AnalyticsClient { public static AnalyticsClient create( SegmentService segmentService, + int queueCapacity, int flushQueueSize, long flushIntervalInMillis, Log log, @@ -55,7 +56,7 @@ public static AnalyticsClient create( ExecutorService networkExecutor, List callbacks) { return new AnalyticsClient( - new LinkedBlockingQueue(), + new LinkedBlockingQueue(queueCapacity), segmentService, flushQueueSize, flushIntervalInMillis, @@ -105,6 +106,10 @@ public void enqueue(Message message) { } } + public boolean offer(Message message) { + return messageQueue.offer(message); + } + public void flush() { enqueue(FlushMessage.POISON); } diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java index e9f99bc1..ccec1ba0 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java @@ -317,4 +317,27 @@ public void pluginCanConfigure() { builder.plugin(plugin); verify(plugin).configure(builder); } + + @Test + public void invalidQueueCapacity() { + try { + builder.queueCapacity(0); + fail("Should fail when queue capacity is 0"); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage("capacity should be positive."); + } + + try { + builder.queueCapacity(-1); + fail("Should fail when queue capacity is -1"); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage("capacity should be positive."); + } + } + + @Test + public void buildWithQueueCapacity() { + Analytics analytics = builder.queueCapacity(10).build(); + assertThat(analytics).isNotNull(); + } } diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsTest.java index e0dbfdbf..9f4faf48 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsTest.java @@ -88,4 +88,19 @@ public void flushIsDispatched() { verify(client).flush(); } + + @Test + public void offerIsDispatched(MessageBuilderTest builder) { + MessageBuilder messageBuilder = builder.get().userId("dummy"); + Message message = messageBuilder.build(); + when(messageTransformer.transform(messageBuilder)).thenReturn(true); + when(messageInterceptor.intercept(any(Message.class))).thenReturn(message); + + analytics.offer(messageBuilder); + + verify(messageTransformer).transform(messageBuilder); + verify(messageInterceptor).intercept(any(Message.class)); + verify(client).offer(message); + } + } From cc0470d157bdfcb6ae498b0a8bc7f8c16af787c5 Mon Sep 17 00:00:00 2001 From: kkaushik90 Date: Wed, 22 Jan 2020 11:34:36 +1100 Subject: [PATCH 006/272] Fix integration options map The `Map` takes values that are of `Object` class only. This should actually be `Map`, which can be written in short as `Map`. --- .../java/com/segment/analytics/messages/MessageBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java b/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java index 968dfa95..96f27005 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java @@ -172,7 +172,7 @@ public V enableIntegration(String key, boolean enable) { * * @see Integrations */ - public V integrationOptions(String key, Map options) { + public V integrationOptions(String key, Map options) { if (isNullOrEmpty(key)) { throw new IllegalArgumentException("Key cannot be null or empty."); } From d8590043b8b24d6df6d08e5198f5c83a052d9134 Mon Sep 17 00:00:00 2001 From: Leif Dreizler Date: Wed, 8 Apr 2020 00:10:18 -0700 Subject: [PATCH 007/272] update snyk --- .circleci/config.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 08237626..c68788d5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -88,7 +88,12 @@ jobs: steps: - checkout - attach_workspace: { at: . } - - run: curl -sL https://raw.githubusercontent.com/segmentio/snyk_helpers/master/initialization/snyk.sh | sh + - run: + name: Snyk + command: curl -sL https://raw.githubusercontent.com/segmentio/snyk_helpers/master/initialization/snyk.sh | sh + environment: + SNYK_FAIL_ON: upgradable + SNYK_SEVERITY_THRESHOLD: high workflows: version: 2 From 54d7dfa63157d1b1012de65b4a992a89f6bbde1e Mon Sep 17 00:00:00 2001 From: Ben Turney Date: Mon, 10 Aug 2020 17:03:06 -0400 Subject: [PATCH 008/272] Fix sample in javadoc --- analytics-sample/src/main/java/sample/BlockingFlush.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analytics-sample/src/main/java/sample/BlockingFlush.java b/analytics-sample/src/main/java/sample/BlockingFlush.java index c9154b41..fee534ca 100644 --- a/analytics-sample/src/main/java/sample/BlockingFlush.java +++ b/analytics-sample/src/main/java/sample/BlockingFlush.java @@ -16,7 +16,7 @@ *

  * BlockingFlush blockingFlush = BlockingFlush.create();
  * Analytics analytics = Analytics.builder(writeKey)
- *      .plugin(blockingFlush)
+ *      .plugin(blockingFlush.plugin())
  *      .build();
  *
  * // Do some work.

From 8b7b1ee33b59215e43ce3ef57e6f9d8105b6f19b Mon Sep 17 00:00:00 2001
From: Samuel Le Berrigaud 
Date: Mon, 21 Sep 2020 16:07:12 +0200
Subject: [PATCH 009/272] ISSUE-164 Allow processing of already buffered
 messages on shutdown

- send a STOP signal to the looper on shutdown for
  - graceful shutdown
  - flushing the last messages that were buffered
- give a chance to the looper & network executors to gracefully
  shutdown, and timeout if necessary.
- do not accept more messages after shutdown but log at error level
---
 .../analytics/internal/AnalyticsClient.java   | 184 ++++++++++-------
 .../analytics/internal/StopMessage.java       |  61 ++++++
 .../internal/AnalyticsClientTest.java         | 189 +++++++++++++-----
 3 files changed, 320 insertions(+), 114 deletions(-)
 create mode 100644 analytics/src/main/java/com/segment/analytics/internal/StopMessage.java

diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java
index 80df17ac..2c3b8506 100644
--- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java
+++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java
@@ -23,6 +23,7 @@
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 import retrofit.RetrofitError;
 
 public class AnalyticsClient {
@@ -45,35 +46,38 @@ public class AnalyticsClient {
   private final ExecutorService networkExecutor;
   private final ExecutorService looperExecutor;
   private final ScheduledExecutorService flushScheduler;
+  private final AtomicBoolean isShutDown;
 
   public static AnalyticsClient create(
-      SegmentService segmentService,
-      int flushQueueSize,
-      long flushIntervalInMillis,
-      Log log,
-      ThreadFactory threadFactory,
-      ExecutorService networkExecutor,
-      List callbacks) {
+          SegmentService segmentService,
+          int flushQueueSize,
+          long flushIntervalInMillis,
+          Log log,
+          ThreadFactory threadFactory,
+          ExecutorService networkExecutor,
+          List callbacks) {
     return new AnalyticsClient(
-        new LinkedBlockingQueue(),
-        segmentService,
-        flushQueueSize,
-        flushIntervalInMillis,
-        log,
-        threadFactory,
-        networkExecutor,
-        callbacks);
+            new LinkedBlockingQueue(),
+            segmentService,
+            flushQueueSize,
+            flushIntervalInMillis,
+            log,
+            threadFactory,
+            networkExecutor,
+            callbacks,
+            new AtomicBoolean(false));
   }
 
   AnalyticsClient(
-      BlockingQueue messageQueue,
-      SegmentService service,
-      int maxQueueSize,
-      long flushIntervalInMillis,
-      Log log,
-      ThreadFactory threadFactory,
-      ExecutorService networkExecutor,
-      List callbacks) {
+          BlockingQueue messageQueue,
+          SegmentService service,
+          int maxQueueSize,
+          long flushIntervalInMillis,
+          Log log,
+          ThreadFactory threadFactory,
+          ExecutorService networkExecutor,
+          List callbacks,
+          AtomicBoolean isShutDown) {
     this.messageQueue = messageQueue;
     this.service = service;
     this.size = maxQueueSize;
@@ -81,39 +85,72 @@ public static AnalyticsClient create(
     this.callbacks = callbacks;
     this.looperExecutor = Executors.newSingleThreadExecutor(threadFactory);
     this.networkExecutor = networkExecutor;
+    this.isShutDown = isShutDown;
 
     looperExecutor.submit(new Looper());
 
     flushScheduler = Executors.newScheduledThreadPool(1, threadFactory);
     flushScheduler.scheduleAtFixedRate(
-        new Runnable() {
-          @Override
-          public void run() {
-            flush();
-          }
-        },
-        flushIntervalInMillis,
-        flushIntervalInMillis,
-        TimeUnit.MILLISECONDS);
+            new Runnable() {
+              @Override
+              public void run() {
+                flush();
+              }
+            },
+            flushIntervalInMillis,
+            flushIntervalInMillis,
+            TimeUnit.MILLISECONDS);
   }
 
   public void enqueue(Message message) {
+    if (message != StopMessage.STOP && isShutDown.get()) {
+      log.print(ERROR, "Attempt to enqueue a message when shutdown has been called %s.", message);
+      return;
+    }
+
     try {
       messageQueue.put(message);
     } catch (InterruptedException e) {
       log.print(ERROR, e, "Interrupted while adding message %s.", message);
+      Thread.currentThread().interrupt();
     }
   }
 
   public void flush() {
-    enqueue(FlushMessage.POISON);
+    if (!isShutDown.get()) {
+      enqueue(FlushMessage.POISON);
+    }
   }
 
   public void shutdown() {
-    messageQueue.clear();
-    looperExecutor.shutdownNow();
-    flushScheduler.shutdownNow();
-    networkExecutor.shutdown(); // Let in-flight requests complete.
+    if (isShutDown.compareAndSet(false, true)) {
+      final long start = System.currentTimeMillis();
+
+      // first let's tell the system to stop
+      enqueue(StopMessage.STOP);
+
+      // we can shutdown the flush scheduler without worrying
+      flushScheduler.shutdownNow();
+
+      shutdownAndWait(looperExecutor, "looper");
+      shutdownAndWait(networkExecutor, "network");
+
+      log.print(VERBOSE, "Analytics client shut down in %s ms", (System.currentTimeMillis() - start));
+    }
+  }
+
+  public void shutdownAndWait(ExecutorService executor, String name) {
+    try {
+      executor.shutdown();
+      final boolean executorTerminated = executor.awaitTermination(1, TimeUnit.SECONDS);
+
+      log.print(VERBOSE, "%s executor %s.",
+              name,
+              executorTerminated ? "terminated normally" : "timed out");
+    } catch (InterruptedException e) {
+      log.print(ERROR, e, "Interrupted while stopping %s executor.", name);
+      Thread.currentThread().interrupt();
+    }
   }
 
   /**
@@ -121,45 +158,56 @@ public void shutdown() {
    * messages, it triggers a flush.
    */
   class Looper implements Runnable {
+    private boolean stop;
+
+    public Looper() {
+      this.stop = false;
+    }
+
     @Override
     public void run() {
       List messages = new ArrayList<>();
       try {
-        //noinspection InfiniteLoopStatement
-        while (true) {
+        while (!stop) {
           Message message = messageQueue.take();
 
-          if (message != FlushMessage.POISON) {
+          if (message == StopMessage.STOP) {
+            log.print(VERBOSE, "Stopping the Looper");
+            stop = true;
+          } else if (message == FlushMessage.POISON) {
+            if (!messages.isEmpty()) {
+              log.print(VERBOSE, "Flushing messages.");
+            }
+          } else {
             messages.add(message);
-          } else if (messages.size() < 1) {
-            log.print(VERBOSE, "No messages to flush.");
-            continue;
           }
 
-          if (messages.size() >= size || message == FlushMessage.POISON) {
+          if (!messages.isEmpty() && (messages.size() >= size || message == FlushMessage.POISON || message == StopMessage.STOP)) {
             Batch batch = Batch.create(CONTEXT, messages);
             log.print(
-                VERBOSE,
-                "Batching %s message(s) into batch %s.",
-                messages.size(),
-                batch.sequence());
+                    VERBOSE,
+                    "Batching %s message(s) into batch %s.",
+                    messages.size(),
+                    batch.sequence());
             networkExecutor.submit(BatchUploadTask.create(AnalyticsClient.this, batch));
             messages = new ArrayList<>();
           }
         }
       } catch (InterruptedException e) {
         log.print(DEBUG, "Looper interrupted while polling for messages.");
+        Thread.currentThread().interrupt();
       }
+      log.print(VERBOSE, "Looper stopped");
     }
   }
 
   static class BatchUploadTask implements Runnable {
     private static final Backo BACKO =
-        Backo.builder() //
-            .base(TimeUnit.SECONDS, 15) //
-            .cap(TimeUnit.HOURS, 1) //
-            .jitter(1) //
-            .build();
+            Backo.builder() //
+                    .base(TimeUnit.SECONDS, 15) //
+                    .cap(TimeUnit.HOURS, 1) //
+                    .jitter(1) //
+                    .build();
     private static final int MAX_ATTEMPTS = 50; // Max 50 hours ~ 2 days
 
     private final AnalyticsClient client;
@@ -195,32 +243,32 @@ boolean upload() {
         switch (error.getKind()) {
           case NETWORK:
             client.log.print(
-                DEBUG, error, "Could not upload batch %s. Retrying.", batch.sequence());
+                    DEBUG, error, "Could not upload batch %s. Retrying.", batch.sequence());
             return true;
           case HTTP:
             // Retry 5xx and 429 responses.
             int status = error.getResponse().getStatus();
             if (is5xx(status)) {
               client.log.print(
-                  DEBUG,
-                  error,
-                  "Could not upload batch %s due to server error. Retrying.",
-                  batch.sequence());
+                      DEBUG,
+                      error,
+                      "Could not upload batch %s due to server error. Retrying.",
+                      batch.sequence());
               return true;
             }
             if (status == 429) {
               client.log.print(
-                  DEBUG,
-                  error,
-                  "Could not upload batch %s due to rate limiting. Retrying.",
-                  batch.sequence());
+                      DEBUG,
+                      error,
+                      "Could not upload batch %s due to rate limiting. Retrying.",
+                      batch.sequence());
               return true;
             }
             client.log.print(
-                ERROR,
-                error,
-                "Could not upload batch %s due to HTTP error. Giving up.",
-                batch.sequence());
+                    ERROR,
+                    error,
+                    "Could not upload batch %s due to HTTP error. Giving up.",
+                    batch.sequence());
             for (Message message : batch.batch()) {
               for (Callback callback : client.callbacks) {
                 callback.failure(message, error);
@@ -229,7 +277,7 @@ boolean upload() {
             return false; // Don't retry
           default:
             client.log.print(
-                ERROR, error, "Could not upload batch %s. Giving up.", batch.sequence());
+                    ERROR, error, "Could not upload batch %s. Giving up.", batch.sequence());
             for (Message message : batch.batch()) {
               for (Callback callback : client.callbacks) {
                 callback.failure(message, error);
@@ -249,7 +297,7 @@ public void run() {
           backo.sleep(attempt);
         } catch (InterruptedException e) {
           client.log.print(
-              DEBUG, "Thread interrupted while backing off for batch %s.", batch.sequence());
+                  DEBUG, "Thread interrupted while backing off for batch %s.", batch.sequence());
           return;
         }
       }
diff --git a/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java b/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java
new file mode 100644
index 00000000..5907416a
--- /dev/null
+++ b/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java
@@ -0,0 +1,61 @@
+package com.segment.analytics.internal;
+
+import com.segment.analytics.messages.Message;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.Date;
+import java.util.Map;
+
+class StopMessage implements Message {
+  static final StopMessage STOP = new StopMessage();
+
+  private StopMessage() {}
+
+  @Nonnull
+  @Override
+  public Type type() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Nonnull
+  @Override
+  public String messageId() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Nonnull
+  @Override
+  public Date timestamp() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Nullable
+  @Override
+  public Map context() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Nullable
+  @Override
+  public String anonymousId() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Nullable
+  @Override
+  public String userId() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Nullable
+  @Override
+  public Map integrations() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public String toString() {
+    return "FlushMessage{}";
+  }
+}
diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java
index 6a5b5b88..d4b89311 100644
--- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java
+++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java
@@ -1,14 +1,19 @@
 package com.segment.analytics.internal;
 
+import static com.segment.analytics.internal.FlushMessage.POISON;
+import static com.segment.analytics.internal.StopMessage.STOP;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.argThat;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 import static org.mockito.MockitoAnnotations.initMocks;
 
@@ -31,6 +36,8 @@
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
 import org.hamcrest.Description;
 import org.hamcrest.TypeSafeMatcher;
 import org.junit.Before;
@@ -47,32 +54,36 @@
 public class AnalyticsClientTest {
   // Backo instance for testing which trims down the wait times.
   private static final Backo BACKO =
-      Backo.builder().base(TimeUnit.NANOSECONDS, 1).factor(1).build();
+          Backo.builder().base(TimeUnit.NANOSECONDS, 1).factor(1).build();
 
   Log log = Log.NONE;
   ThreadFactory threadFactory;
-  @Mock BlockingQueue messageQueue;
+  BlockingQueue messageQueue;
   @Mock SegmentService segmentService;
   @Mock ExecutorService networkExecutor;
   @Mock Callback callback;
+  AtomicBoolean isShutDown;
 
   @Before
   public void setUp() {
     initMocks(this);
+    isShutDown = new AtomicBoolean(false);
+    messageQueue = spy(new LinkedBlockingQueue());
     threadFactory = Executors.defaultThreadFactory();
   }
 
   // Defers loading the client until tests can initialize all required dependencies.
   AnalyticsClient newClient() {
     return new AnalyticsClient(
-        messageQueue,
-        segmentService,
-        50,
-        TimeUnit.HOURS.toMillis(1),
-        log,
-        threadFactory,
-        networkExecutor,
-        Collections.singletonList(callback));
+            messageQueue,
+            segmentService,
+            50,
+            TimeUnit.HOURS.toMillis(1),
+            log,
+            threadFactory,
+            networkExecutor,
+            Collections.singletonList(callback),
+            isShutDown);
   }
 
   @Test
@@ -86,13 +97,14 @@ public void enqueueAddsToQueue(MessageBuilderTest builder) throws InterruptedExc
   }
 
   @Test
-  public void shutdown() {
+  public void shutdown() throws InterruptedException {
+    messageQueue = new LinkedBlockingQueue<>();
     AnalyticsClient client = newClient();
 
     client.shutdown();
 
-    verify(messageQueue).clear();
     verify(networkExecutor).shutdown();
+    verify(networkExecutor).awaitTermination(1, TimeUnit.SECONDS);
   }
 
   @Test
@@ -179,10 +191,10 @@ public void batchRetriesForNetworkErrors() {
     // Throw a network error 3 times.
     RetrofitError retrofitError = RetrofitError.networkError(null, new IOException());
     when(segmentService.upload(batch))
-        .thenThrow(retrofitError)
-        .thenThrow(retrofitError)
-        .thenThrow(retrofitError)
-        .thenReturn(null);
+            .thenThrow(retrofitError)
+            .thenThrow(retrofitError)
+            .thenThrow(retrofitError)
+            .thenReturn(null);
 
     BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch);
     batchUploadTask.run();
@@ -200,14 +212,14 @@ public void batchRetriesForHTTP5xxErrors() {
 
     // Throw a HTTP error 3 times.
     Response response =
-        new Response(
-            "https://api.segment.io", 500, "Server Error", Collections.
emptyList(), null); + new Response( + "https://api.segment.io", 500, "Server Error", Collections.
emptyList(), null); RetrofitError retrofitError = RetrofitError.httpError(null, response, null, null); when(segmentService.upload(batch)) - .thenThrow(retrofitError) - .thenThrow(retrofitError) - .thenThrow(retrofitError) - .thenReturn(null); + .thenThrow(retrofitError) + .thenThrow(retrofitError) + .thenThrow(retrofitError) + .thenReturn(null); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); batchUploadTask.run(); @@ -225,14 +237,14 @@ public void batchRetriesForHTTP429Errors() { // Throw a HTTP error 3 times. Response response = - new Response( - "https://api.segment.io", 429, "Rate Limited", Collections.
emptyList(), null); + new Response( + "https://api.segment.io", 429, "Rate Limited", Collections.
emptyList(), null); RetrofitError retrofitError = RetrofitError.httpError(null, response, null, null); when(segmentService.upload(batch)) - .thenThrow(retrofitError) - .thenThrow(retrofitError) - .thenThrow(retrofitError) - .thenReturn(null); + .thenThrow(retrofitError) + .thenThrow(retrofitError) + .thenThrow(retrofitError) + .thenReturn(null); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); batchUploadTask.run(); @@ -250,8 +262,8 @@ public void batchDoesNotRetryForNon5xxAndNon429HTTPErrors() { // Throw a HTTP error that should not be retried. Response response = - new Response( - "https://api.segment.io", 404, "Not Found", Collections.
emptyList(), null); + new Response( + "https://api.segment.io", 404, "Not Found", Collections.
emptyList(), null); RetrofitError retrofitError = RetrofitError.httpError(null, response, null, null); doThrow(retrofitError).when(segmentService).upload(batch); @@ -269,7 +281,7 @@ public void batchDoesNotRetryForNonNetworkErrors() { TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); Batch batch = batchFor(trackMessage); RetrofitError retrofitError = - RetrofitError.conversionError(null, null, null, null, new ConversionException("fake")); + RetrofitError.conversionError(null, null, null, null, new ConversionException("fake")); doThrow(retrofitError).when(segmentService).upload(batch); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); @@ -294,20 +306,105 @@ public void givesUpAfterMaxRetries() { // 50 == MAX_ATTEMPTS in AnalyticsClient.java verify(segmentService, times(50)).upload(batch); verify(callback) - .failure( - eq(trackMessage), - argThat( - new TypeSafeMatcher() { - @Override - public void describeTo(Description description) { - description.appendText("expected IOException"); - } - - @Override - protected boolean matchesSafely(Throwable item) { - IOException exception = (IOException) item; - return exception.getMessage().equals("50 retries exhausted"); - } - })); + .failure( + eq(trackMessage), + argThat( + new TypeSafeMatcher() { + @Override + public void describeTo(Description description) { + description.appendText("expected IOException"); + } + + @Override + protected boolean matchesSafely(Throwable item) { + IOException exception = (IOException) item; + return exception.getMessage().equals("50 retries exhausted"); + } + })); + } + + @Test + public void flushWhenNotShutDown() throws InterruptedException { + AnalyticsClient client = newClient(); + + client.flush(); + verify(messageQueue).put(POISON); + } + + @Test + public void flushWhenShutDown() throws InterruptedException { + AnalyticsClient client = newClient(); + isShutDown.set(true); + + client.flush(); + + verify(messageQueue, times(0)).put(any(Message.class)); + } + + @Test + public void enqueueWithRegularMessageWhenNotShutdown(MessageBuilderTest builder) + throws InterruptedException { + AnalyticsClient client = newClient(); + + + final Message message = builder.get().userId("foo").build(); + client.enqueue(message); + + verify(messageQueue).put(message); + } + + @Test + public void enqueueWithRegularMessageWhenShutdown(MessageBuilderTest builder) throws InterruptedException { + AnalyticsClient client = newClient(); + isShutDown.set(true); + + client.enqueue(builder.get().userId("foo").build()); + + verify(messageQueue, times(0)).put(any(Message.class)); + } + + @Test + public void enqueueWithStopMessageWhenShutdown() throws InterruptedException { + AnalyticsClient client = newClient(); + isShutDown.set(true); + + client.enqueue(STOP); + + verify(messageQueue).put(STOP); + } + + @Test + public void shutdownWhenAlreadyShutDown() throws InterruptedException { + AnalyticsClient client = newClient(); + isShutDown.set(true); + + client.shutdown(); + + verify(messageQueue, times(0)).put(any(Message.class)); + verifyZeroInteractions(networkExecutor, callback, segmentService); + } + + @Test + public void shutdownWithNoMessageInTheQueue() throws InterruptedException { + AnalyticsClient client = newClient(); + client.shutdown(); + + verify(messageQueue).put(STOP); + verify(networkExecutor).shutdown(); + verify(networkExecutor).awaitTermination(1, TimeUnit.SECONDS); + verifyNoMoreInteractions(networkExecutor); + } + + @Test + public void shutdownWithMessagesInTheQueue(MessageBuilderTest builder) throws InterruptedException { + AnalyticsClient client = newClient(); + + client.enqueue(builder.get().userId("foo").build()); + client.shutdown(); + + verify(messageQueue).put(STOP); + verify(networkExecutor).shutdown(); + verify(networkExecutor).awaitTermination(1, TimeUnit.SECONDS); + verify(networkExecutor).submit(any(AnalyticsClient.BatchUploadTask.class)); } } From 52d184e621601118231536553490dd9e747ef553 Mon Sep 17 00:00:00 2001 From: "Sean C. Sullivan" Date: Sat, 10 Oct 2020 16:20:29 -0700 Subject: [PATCH 010/272] maven-compiler-plugin 3.8.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 74d54b11..7316532e 100644 --- a/pom.xml +++ b/pom.xml @@ -159,7 +159,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.0 + 3.8.1 true ${java.version} From 89464350d8c03edb5f0f5b63808b5dd1abbf4df7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2020 20:52:48 +0000 Subject: [PATCH 011/272] Bump junit from 4.11 to 4.13.1 Bumps [junit](https://github.com/junit-team/junit4) from 4.11 to 4.13.1. - [Release notes](https://github.com/junit-team/junit4/releases) - [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.11.md) - [Commits](https://github.com/junit-team/junit4/compare/r4.11...r4.13.1) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 74d54b11..58abd202 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ 0.6.0.20150202 - 4.11 + 4.13.1 1.0.2 2.0.0 1.9.5 From f9c1c16090f59bcdc167a88ad0736ff86d382b88 Mon Sep 17 00:00:00 2001 From: Kelly Lu Date: Mon, 19 Oct 2020 14:54:29 -0700 Subject: [PATCH 012/272] Blank commit To test CI --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2475e25e..7e0bdfcb 100644 --- a/README.md +++ b/README.md @@ -130,3 +130,4 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` + From 92f14a4446f42955b6130463ea91ca4e1ad21ba6 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Tue, 20 Oct 2020 13:15:53 -0300 Subject: [PATCH 013/272] upgrading lib to java 11 --- .../com/segment/analytics/messages/GroupMessage.java | 1 - .../src/test/java/com/segment/analytics/TestUtils.java | 9 ++++++++- pom.xml | 9 ++++----- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java index 8edce2a1..96190e21 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java @@ -20,7 +20,6 @@ @AutoValue @AutoGson // public abstract class GroupMessage implements Message { - /** * Start building an {@link GroupMessage} instance. * diff --git a/analytics-core/src/test/java/com/segment/analytics/TestUtils.java b/analytics-core/src/test/java/com/segment/analytics/TestUtils.java index e31dcac8..826aa193 100644 --- a/analytics-core/src/test/java/com/segment/analytics/TestUtils.java +++ b/analytics-core/src/test/java/com/segment/analytics/TestUtils.java @@ -1,6 +1,13 @@ package com.segment.analytics; -import com.segment.analytics.messages.*; +import com.segment.analytics.messages.MessageBuilder; +import com.segment.analytics.messages.GroupMessage; +import com.segment.analytics.messages.AliasMessage; +import com.segment.analytics.messages.IdentifyMessage; +import com.segment.analytics.messages.ScreenMessage; +import com.segment.analytics.messages.PageMessage; +import com.segment.analytics.messages.TrackMessage; +import com.segment.analytics.messages.Message; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; diff --git a/pom.xml b/pom.xml index 74d54b11..aec2f7f9 100644 --- a/pom.xml +++ b/pom.xml @@ -27,11 +27,11 @@ UTF-8 - 1.7 + 11 1.2.60 1.14.0 1.9.0 - 1.6 + 1.7 3.0.1 2.3.1 3.9.0 @@ -159,11 +159,10 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.0 + 3.8.1 true - ${java.version} - ${java.version} + ${java.version} true From c7d956ce7a78e3c2f037d66522ac844af30a5f08 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Tue, 20 Oct 2020 13:18:00 -0300 Subject: [PATCH 014/272] removing jdk tests from 8 to 10 --- .circleci/config.yml | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c68788d5..8da42537 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -31,20 +31,10 @@ jobs: docker: - image: circleci/openjdk - test-jdk10: + test-jdk11: <<: *java-base-test docker: - - image: circleci/openjdk:10-jdk-browsers - - test-jdk9: - <<: *java-base-test - docker: - - image: circleci/openjdk:9-jdk-browsers - - test-jdk8: - <<: *java-base-test - docker: - - image: circleci/openjdk:8-jdk-browsers + - image: circleci/openjdk:11-jdk-browsers test: <<: *java-base-test @@ -100,9 +90,7 @@ workflows: multi-test: jobs: - test-jdklatest - - test-jdk10 - - test-jdk9 - - test-jdk8 + - test-jdk11 static_analysis: jobs: - test From a6264356156eb8e8f7e5d68a0e7b2977a198b6e3 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Tue, 20 Oct 2020 13:25:31 -0300 Subject: [PATCH 015/272] import messages as * --- .../src/test/java/com/segment/analytics/TestUtils.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/analytics/src/test/java/com/segment/analytics/TestUtils.java b/analytics/src/test/java/com/segment/analytics/TestUtils.java index d79b354a..1fa27ad4 100644 --- a/analytics/src/test/java/com/segment/analytics/TestUtils.java +++ b/analytics/src/test/java/com/segment/analytics/TestUtils.java @@ -1,12 +1,6 @@ package com.segment.analytics; -import com.segment.analytics.messages.AliasMessage; -import com.segment.analytics.messages.GroupMessage; -import com.segment.analytics.messages.IdentifyMessage; -import com.segment.analytics.messages.Message; -import com.segment.analytics.messages.MessageBuilder; -import com.segment.analytics.messages.ScreenMessage; -import com.segment.analytics.messages.TrackMessage; +import com.segment.analytics.messages.*; public final class TestUtils { private TestUtils() { From 5fa72ce60565d2915731ba82edd0c2a61558ddc9 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Tue, 20 Oct 2020 13:30:26 -0300 Subject: [PATCH 016/272] reverting --- .../src/test/java/com/segment/analytics/TestUtils.java | 9 +-------- .../src/test/java/com/segment/analytics/TestUtils.java | 8 +++++++- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/analytics-core/src/test/java/com/segment/analytics/TestUtils.java b/analytics-core/src/test/java/com/segment/analytics/TestUtils.java index 826aa193..e31dcac8 100644 --- a/analytics-core/src/test/java/com/segment/analytics/TestUtils.java +++ b/analytics-core/src/test/java/com/segment/analytics/TestUtils.java @@ -1,13 +1,6 @@ package com.segment.analytics; -import com.segment.analytics.messages.MessageBuilder; -import com.segment.analytics.messages.GroupMessage; -import com.segment.analytics.messages.AliasMessage; -import com.segment.analytics.messages.IdentifyMessage; -import com.segment.analytics.messages.ScreenMessage; -import com.segment.analytics.messages.PageMessage; -import com.segment.analytics.messages.TrackMessage; -import com.segment.analytics.messages.Message; +import com.segment.analytics.messages.*; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; diff --git a/analytics/src/test/java/com/segment/analytics/TestUtils.java b/analytics/src/test/java/com/segment/analytics/TestUtils.java index 1fa27ad4..d79b354a 100644 --- a/analytics/src/test/java/com/segment/analytics/TestUtils.java +++ b/analytics/src/test/java/com/segment/analytics/TestUtils.java @@ -1,6 +1,12 @@ package com.segment.analytics; -import com.segment.analytics.messages.*; +import com.segment.analytics.messages.AliasMessage; +import com.segment.analytics.messages.GroupMessage; +import com.segment.analytics.messages.IdentifyMessage; +import com.segment.analytics.messages.Message; +import com.segment.analytics.messages.MessageBuilder; +import com.segment.analytics.messages.ScreenMessage; +import com.segment.analytics.messages.TrackMessage; public final class TestUtils { private TestUtils() { From 2dd21716d1c9d7c5e41c0aa2cf59ef23f029aa3e Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Fri, 23 Oct 2020 01:48:08 -0300 Subject: [PATCH 017/272] no need to do signature checking --- pom.xml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/pom.xml b/pom.xml index aec2f7f9..004f7116 100644 --- a/pom.xml +++ b/pom.xml @@ -263,18 +263,6 @@ - - org.codehaus.mojo - animal-sniffer-maven-plugin - 1.16 - - - org.codehaus.mojo.signature - java17 - 1.0 - - - org.apache.maven.plugins maven-surefire-plugin From d6b399cb86fb5b930c3b03e61185f68603b19415 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Fri, 23 Oct 2020 01:50:18 -0300 Subject: [PATCH 018/272] removing test on jdk8 --- .circleci/config.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8da42537..b3639b7f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -36,11 +36,6 @@ jobs: docker: - image: circleci/openjdk:11-jdk-browsers - test: - <<: *java-base-test - docker: - - image: circleci/openjdk:8-jdk-browsers - publish: <<: *java-base-test docker: From 8d9cd74dee906319f342fa596b13f7e399bc78e9 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Wed, 28 Oct 2020 23:46:23 -0300 Subject: [PATCH 019/272] using new classes and interfaces of retrofit2 --- analytics-core/pom.xml | 6 +-- .../analytics/http/SegmentService.java | 7 +-- .../src/main/java/sample/Main.java | 16 +++---- analytics/pom.xml | 4 ++ .../java/com/segment/analytics/Analytics.java | 43 ++++++++----------- .../AnalyticsRequestInterceptor.java | 20 ++++++--- .../java/com/segment/analytics/Platform.java | 6 +-- .../analytics/internal/AnalyticsClient.java | 11 +++-- pom.xml | 15 +++---- 9 files changed, 62 insertions(+), 66 deletions(-) diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index 6f436e8e..b241d58c 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -14,13 +14,9 @@ - com.squareup.retrofit + com.squareup.retrofit2 retrofit - - com.jakewharton.retrofit - retrofit1-okhttp3-client - com.google.code.gson gson diff --git a/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java b/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java index 808fac51..d90ab026 100644 --- a/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java +++ b/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java @@ -1,11 +1,12 @@ package com.segment.analytics.http; import com.segment.analytics.messages.Batch; -import retrofit.http.Body; -import retrofit.http.POST; +import retrofit2.http.Body; +import retrofit2.http.POST; +import retrofit2.Call; /** REST interface for the Segment API. */ public interface SegmentService { @POST("/v1/import") - UploadResponse upload(@Body Batch batch); + Call upload(@Body Batch batch); } diff --git a/analytics-sample/src/main/java/sample/Main.java b/analytics-sample/src/main/java/sample/Main.java index cfad1468..84f55984 100644 --- a/analytics-sample/src/main/java/sample/Main.java +++ b/analytics-sample/src/main/java/sample/Main.java @@ -1,6 +1,5 @@ package sample; -import com.jakewharton.retrofit.Ok3Client; import com.segment.analytics.Analytics; import com.segment.analytics.messages.TrackMessage; import java.util.LinkedHashMap; @@ -9,7 +8,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import okhttp3.OkHttpClient; -import retrofit.client.Client; public class Main { public static void main(String... args) throws Exception { @@ -49,13 +47,11 @@ public static void main(String... args) throws Exception { * customize the client to your needs. For instance, this client is configured to automatically * gzip outgoing requests. */ - private static Client createClient() { - return new Ok3Client( - new OkHttpClient.Builder() - .connectTimeout(15, TimeUnit.SECONDS) - .readTimeout(15, TimeUnit.SECONDS) - .writeTimeout(15, TimeUnit.SECONDS) - .addInterceptor(new GzipRequestInterceptor()) - .build()); + private static OkHttpClient createClient() { + return new OkHttpClient.Builder() + .connectTimeout(15, TimeUnit.SECONDS) + .readTimeout(15, TimeUnit.SECONDS) + .writeTimeout(15, TimeUnit.SECONDS) + .addInterceptor(new GzipRequestInterceptor()).build(); } } diff --git a/analytics/pom.xml b/analytics/pom.xml index 7a67a3aa..fa438b1f 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -22,6 +22,10 @@ com.squareup.okhttp3 okhttp + + com.squareup.retrofit2 + converter-gson + com.google.code.findbugs findbugs diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index ffc19c8d..91d22d16 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -9,6 +9,10 @@ import com.segment.analytics.internal.AnalyticsVersion; import com.segment.analytics.messages.Message; import com.segment.analytics.messages.MessageBuilder; + +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; + import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -16,11 +20,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; -import retrofit.Endpoint; -import retrofit.Endpoints; -import retrofit.RestAdapter; -import retrofit.client.Client; -import retrofit.converter.GsonConverter; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; /** * The entry point into the Segment for Java library. @@ -95,14 +96,13 @@ public void shutdown() { /** Fluent API for creating {@link Analytics} instances. */ public static class Builder { - private static final Endpoint DEFAULT_ENDPOINT = - Endpoints.newFixedEndpoint("https://api.segment.io"); + private static final HttpUrl DEFAULT_ENDPOINT = HttpUrl.parse("https://api.segment.io"); private static final String DEFAULT_USER_AGENT = "analytics-java/" + AnalyticsVersion.get(); private final String writeKey; - private Client client; + private OkHttpClient client; private Log log; - private Endpoint endpoint; + private HttpUrl endpoint; private String userAgent = DEFAULT_USER_AGENT; private List messageTransformers; private List messageInterceptors; @@ -120,7 +120,7 @@ public static class Builder { } /** Set a custom networking client. */ - public Builder client(Client client) { + public Builder client(OkHttpClient client) { if (client == null) { throw new NullPointerException("Null client"); } @@ -145,7 +145,7 @@ public Builder endpoint(String endpoint) { if (endpoint == null || endpoint.trim().length() == 0) { throw new NullPointerException("endpoint cannot be null or empty."); } - this.endpoint = Endpoints.newFixedEndpoint(endpoint); + this.endpoint = HttpUrl.parse(endpoint); return this; } @@ -268,6 +268,7 @@ public Analytics build() { } if (client == null) { client = Platform.get().defaultClient(); + client = client.newBuilder().addInterceptor(new AnalyticsRequestInterceptor(writeKey, userAgent)).build(); } if (log == null) { log = Log.NONE; @@ -300,20 +301,12 @@ public Analytics build() { callbacks = Collections.unmodifiableList(callbacks); } - RestAdapter restAdapter = - new RestAdapter.Builder() - .setConverter(new GsonConverter(gson)) - .setEndpoint(endpoint) - .setClient(client) - .setRequestInterceptor(new AnalyticsRequestInterceptor(writeKey, userAgent)) - .setLogLevel(RestAdapter.LogLevel.FULL) - .setLog( - new RestAdapter.Log() { - @Override - public void log(String message) { - log.print(Log.Level.VERBOSE, "%s", message); - } - }) + Retrofit restAdapter = + new Retrofit.Builder() + .addConverterFactory(GsonConverterFactory.create(gson)) + .baseUrl(endpoint) + .client(client) + // .setLogLevel(RestAdapter.LogLevel.FULL) .build(); SegmentService segmentService = restAdapter.create(SegmentService.class); diff --git a/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java b/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java index 8148fba5..65672e3f 100644 --- a/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java +++ b/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java @@ -1,10 +1,14 @@ package com.segment.analytics; +import java.io.IOException; + import javax.annotation.Nonnull; import okhttp3.Credentials; -import retrofit.RequestInterceptor; +import okhttp3.Headers; +import okhttp3.Interceptor; +import okhttp3.Request; -class AnalyticsRequestInterceptor implements RequestInterceptor { +class AnalyticsRequestInterceptor implements Interceptor { private static final String AUTHORIZATION_HEADER = "Authorization"; private static final String USER_AGENT_HEADER = "User-Agent"; @@ -17,8 +21,14 @@ class AnalyticsRequestInterceptor implements RequestInterceptor { } @Override - public void intercept(RequestFacade request) { - request.addHeader(AUTHORIZATION_HEADER, Credentials.basic(writeKey, "")); - request.addHeader(USER_AGENT_HEADER, userAgent); + public okhttp3.Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + Headers headers = request.headers().newBuilder() + .add(AUTHORIZATION_HEADER, Credentials.basic(writeKey, "")) + .add(USER_AGENT_HEADER, userAgent) + .build(); + + request = request.newBuilder().headers(headers).build(); + return chain.proceed(request); } } diff --git a/analytics/src/main/java/com/segment/analytics/Platform.java b/analytics/src/main/java/com/segment/analytics/Platform.java index 2da0e9da..a5de5cb5 100644 --- a/analytics/src/main/java/com/segment/analytics/Platform.java +++ b/analytics/src/main/java/com/segment/analytics/Platform.java @@ -2,13 +2,11 @@ import static java.lang.Thread.MIN_PRIORITY; -import com.jakewharton.retrofit.Ok3Client; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import okhttp3.OkHttpClient; -import retrofit.client.Client; class Platform { static final String THREAD_NAME = "Analytics"; @@ -23,14 +21,14 @@ private static Platform findPlatform() { return new Platform(); } - Client defaultClient() { + OkHttpClient defaultClient() { OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(15, TimeUnit.SECONDS) .readTimeout(15, TimeUnit.SECONDS) .writeTimeout(15, TimeUnit.SECONDS) .build(); - return new Ok3Client(client); + return client; } ExecutorService defaultNetworkExecutor() { diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 80df17ac..608ea0c6 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -23,7 +23,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; -import retrofit.RetrofitError; public class AnalyticsClient { private static final Map CONTEXT; @@ -191,15 +190,15 @@ boolean upload() { } } return false; - } catch (RetrofitError error) { - switch (error.getKind()) { - case NETWORK: + } catch (Throwable error) { + switch ("NETWORK") { // wrong change + case "NETWORK": // wrong change client.log.print( DEBUG, error, "Could not upload batch %s. Retrying.", batch.sequence()); return true; - case HTTP: + case "HTTP": // wrong change // Retry 5xx and 429 responses. - int status = error.getResponse().getStatus(); + int status = 400; // wrong change if (is5xx(status)) { client.log.print( DEBUG, diff --git a/pom.xml b/pom.xml index 74d54b11..45f11fd8 100644 --- a/pom.xml +++ b/pom.xml @@ -30,12 +30,11 @@ 1.7 1.2.60 1.14.0 - 1.9.0 + 2.9.0 1.6 3.0.1 2.3.1 3.9.0 - 1.1.0 26.0-jre 1.0.0 1.2.5.RELEASE @@ -70,10 +69,15 @@ - com.squareup.retrofit + com.squareup.retrofit2 retrofit ${retrofit.version} + + com.squareup.retrofit2 + converter-gson + 2.0.0 + com.google.auto.value auto-value @@ -100,11 +104,6 @@ okhttp ${okhttp.version} - - com.jakewharton.retrofit - retrofit1-okhttp3-client - ${retrofit1-okhttp3-client.version} - com.google.guava guava From bffb50d23f5c5b624d9e7708b334555ff95faf54 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Mon, 2 Nov 2020 02:03:10 -0300 Subject: [PATCH 020/272] upgrading tests to mockito 2 --- analytics/pom.xml | 4 + .../AnalyticsRequestInterceptor.java | 9 +- .../java/com/segment/analytics/Callback.java | 3 + .../analytics/internal/AnalyticsClient.java | 111 ++++++++--------- .../AnalyticsRequestInterceptorTest.java | 36 ++++-- .../com/segment/analytics/ChainAdapter.java | 69 +++++++++++ .../internal/AnalyticsClientTest.java | 116 ++++++++++-------- pom.xml | 9 +- 8 files changed, 226 insertions(+), 131 deletions(-) create mode 100644 analytics/src/test/java/com/segment/analytics/ChainAdapter.java diff --git a/analytics/pom.xml b/analytics/pom.xml index fa438b1f..05225d19 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -26,6 +26,10 @@ com.squareup.retrofit2 converter-gson + + com.squareup.retrofit2 + retrofit-mock + com.google.code.findbugs findbugs diff --git a/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java b/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java index 65672e3f..de61e453 100644 --- a/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java +++ b/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java @@ -23,12 +23,11 @@ class AnalyticsRequestInterceptor implements Interceptor { @Override public okhttp3.Response intercept(Chain chain) throws IOException { Request request = chain.request(); - Headers headers = request.headers().newBuilder() - .add(AUTHORIZATION_HEADER, Credentials.basic(writeKey, "")) - .add(USER_AGENT_HEADER, userAgent) + Request newRequest = request.newBuilder() + .addHeader(AUTHORIZATION_HEADER, Credentials.basic(writeKey, "")) + .addHeader(USER_AGENT_HEADER, userAgent) .build(); - request = request.newBuilder().headers(headers).build(); - return chain.proceed(request); + return chain.proceed(newRequest); } } diff --git a/analytics/src/main/java/com/segment/analytics/Callback.java b/analytics/src/main/java/com/segment/analytics/Callback.java index 7fa136f2..b61bfd08 100644 --- a/analytics/src/main/java/com/segment/analytics/Callback.java +++ b/analytics/src/main/java/com/segment/analytics/Callback.java @@ -1,7 +1,10 @@ package com.segment.analytics; +import com.segment.analytics.http.UploadResponse; import com.segment.analytics.messages.Message; +import retrofit2.Response; + /** * Callback invoked when the client library is done processing a message. * diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 608ea0c6..e4786f24 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -7,9 +7,14 @@ import com.segment.analytics.Callback; import com.segment.analytics.Log; import com.segment.analytics.http.SegmentService; +import com.segment.analytics.http.UploadResponse; import com.segment.analytics.messages.Batch; import com.segment.analytics.messages.Message; import com.segment.backo.Backo; + +import retrofit2.Call; +import retrofit2.Response; + import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -175,67 +180,60 @@ static BatchUploadTask create(AnalyticsClient client, Batch batch) { this.backo = backo; } + private void notifyCallbacksWithException(Batch batch, Exception exception) { + for (Message message : batch.batch()) { + for (Callback callback : client.callbacks) { + callback.failure(message, exception); + } + } + } + /** Returns {@code true} to indicate a batch should be retried. {@code false} otherwise. */ boolean upload() { + client.log.print(VERBOSE, "Uploading batch %s.", batch.sequence()); + try { - client.log.print(VERBOSE, "Uploading batch %s.", batch.sequence()); + Call call = client.service.upload(batch); + Response response = call.execute(); - // Ignore return value, UploadResponse#onSuccess will never return false for 200 OK - client.service.upload(batch); + if (response.isSuccessful()) { + client.log.print(VERBOSE, "Uploaded batch %s.", batch.sequence()); - client.log.print(VERBOSE, "Uploaded batch %s.", batch.sequence()); - for (Message message : batch.batch()) { - for (Callback callback : client.callbacks) { - callback.success(message); + for (Message message : batch.batch()) { + for (Callback callback : client.callbacks) { + callback.success(message); + } } + + return false; } - return false; - } catch (Throwable error) { - switch ("NETWORK") { // wrong change - case "NETWORK": // wrong change - client.log.print( - DEBUG, error, "Could not upload batch %s. Retrying.", batch.sequence()); - return true; - case "HTTP": // wrong change - // Retry 5xx and 429 responses. - int status = 400; // wrong change - if (is5xx(status)) { - client.log.print( - DEBUG, - error, - "Could not upload batch %s due to server error. Retrying.", - batch.sequence()); - return true; - } - if (status == 429) { - client.log.print( - DEBUG, - error, - "Could not upload batch %s due to rate limiting. Retrying.", - batch.sequence()); - return true; - } - client.log.print( - ERROR, - error, - "Could not upload batch %s due to HTTP error. Giving up.", - batch.sequence()); - for (Message message : batch.batch()) { - for (Callback callback : client.callbacks) { - callback.failure(message, error); - } - } - return false; // Don't retry - default: - client.log.print( - ERROR, error, "Could not upload batch %s. Giving up.", batch.sequence()); - for (Message message : batch.batch()) { - for (Callback callback : client.callbacks) { - callback.failure(message, error); - } - } - return false; // Don't retry + + int status = response.code(); + if (is5xx(status)) { + client.log.print(DEBUG, "Could not upload batch %s due to server error. Retrying.", + batch.sequence()); + return true; + } else if (status == 429) { + client.log.print(DEBUG, "Could not upload batch %s due to rate limiting. Retrying.", + batch.sequence()); + return true; } + + client.log.print(DEBUG, "Could not upload batch %s. Giving up.", batch.sequence()); + + notifyCallbacksWithException(batch, new IOException("HTTP Error")); + + return false; + } catch(IOException error) { + client.log.print(DEBUG, error, "Could not upload batch %s. Retrying.", batch.sequence()); + + return true; + } catch (Exception exception) { + client.log.print(DEBUG, "Could not upload batch %s. Giving up.", batch.sequence()); + + notifyCallbacksWithException(batch, exception); + + return false; } } @@ -254,12 +252,7 @@ public void run() { } client.log.print(ERROR, "Could not upload batch %s. Retries exhausted.", batch.sequence()); - IOException exception = new IOException(MAX_ATTEMPTS + " retries exhausted"); - for (Message message : batch.batch()) { - for (Callback callback : client.callbacks) { - callback.failure(message, exception); - } - } + notifyCallbacksWithException(batch, new IOException(MAX_ATTEMPTS + " retries exhausted")); } private static boolean is5xx(int status) { diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsRequestInterceptorTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsRequestInterceptorTest.java index 2864541d..9c7fad28 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsRequestInterceptorTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsRequestInterceptorTest.java @@ -1,22 +1,36 @@ package com.segment.analytics; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; +import static org.junit.Assert.assertThat; -import com.segment.analytics.messages.*; +import java.io.IOException; + +import org.hamcrest.core.Is; import org.junit.Test; -import retrofit.RequestInterceptor.RequestFacade; +import org.mockito.Mock; + +import okhttp3.Connection; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.Interceptor.Chain; public class AnalyticsRequestInterceptorTest { + @Mock private Connection mockConnection; + @Test - public void interceptor() { - RequestFacade requestFacade = mock(RequestFacade.class); - AnalyticsRequestInterceptor interceptor = - new AnalyticsRequestInterceptor("writeKey", "userAgent"); + public void testInterceptor() throws IOException { + AnalyticsRequestInterceptor interceptor = new AnalyticsRequestInterceptor("writeKey", "userAgent"); + + final Request request = new Request.Builder().url("https://api.segment.io").get().build(); - interceptor.intercept(requestFacade); + Chain chain = new ChainAdapter(request, mockConnection) { + @Override + public Response proceed(Request request) throws IOException { + assertThat(request.header("Authorization"), Is.is("Basic d3JpdGVLZXk6")); + assertThat(request.header("User-Agent"), Is.is("userAgent")); + return null; + } + }; - verify(requestFacade).addHeader("Authorization", "Basic d3JpdGVLZXk6"); - verify(requestFacade).addHeader("User-Agent", "userAgent"); + interceptor.intercept(chain); } } diff --git a/analytics/src/test/java/com/segment/analytics/ChainAdapter.java b/analytics/src/test/java/com/segment/analytics/ChainAdapter.java new file mode 100644 index 00000000..c4a9a673 --- /dev/null +++ b/analytics/src/test/java/com/segment/analytics/ChainAdapter.java @@ -0,0 +1,69 @@ +package com.segment.analytics; + +import java.util.concurrent.TimeUnit; + +import okhttp3.Call; +import okhttp3.Connection; +import okhttp3.Interceptor; +import okhttp3.Request; + +/** + * Base class for mock interceptors. + * + * @author Patrick Bassut + */ +abstract class ChainAdapter implements Interceptor.Chain { + + private final Connection mockConnection; + private final Request request; + + protected ChainAdapter(Request request, Connection mockConnection) { + this.mockConnection = mockConnection; + this.request = request; + } + + @Override + public Request request() { + return request; + } + + @Override + public Connection connection() { + return mockConnection; + } + + @Override + public Call call() { + return null; + } + + @Override + public int connectTimeoutMillis() { + return 0; + } + + @Override + public Interceptor.Chain withConnectTimeout(int timeout, TimeUnit unit) { + return null; + } + + @Override + public int readTimeoutMillis() { + return 0; + } + + @Override + public Interceptor.Chain withReadTimeout(int timeout, TimeUnit unit) { + return null; + } + + @Override + public int writeTimeoutMillis() { + return 0; + } + + @Override + public Interceptor.Chain withWriteTimeout(int timeout, TimeUnit unit) { + return null; + } +} diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 6a5b5b88..45b7d6a9 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -5,6 +5,7 @@ import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; @@ -20,8 +21,10 @@ import com.segment.analytics.messages.Batch; import com.segment.analytics.messages.Message; import com.segment.analytics.messages.TrackMessage; +import com.segment.analytics.http.UploadResponse; import com.segment.backo.Backo; import com.squareup.burst.BurstJUnit4; + import java.io.IOException; import java.util.Collections; import java.util.Queue; @@ -31,17 +34,21 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; -import org.hamcrest.Description; -import org.hamcrest.TypeSafeMatcher; + import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatcher; import org.mockito.Mock; -import retrofit.RetrofitError; -import retrofit.client.Header; -import retrofit.client.Response; -import retrofit.converter.ConversionException; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import okhttp3.ResponseBody; +import retrofit2.Call; +import retrofit2.Response; +import retrofit2.mock.Calls; @RunWith(BurstJUnit4.class) // public class AnalyticsClientTest { @@ -55,6 +62,7 @@ public class AnalyticsClientTest { @Mock SegmentService segmentService; @Mock ExecutorService networkExecutor; @Mock Callback callback; + @Mock UploadResponse response; @Before public void setUp() { @@ -176,13 +184,15 @@ public void batchRetriesForNetworkErrors() { TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); Batch batch = batchFor(trackMessage); + Response successResponse = Response.success(200, response); + Response failureResponse = Response.error(429, ResponseBody.create(null, "")); + // Throw a network error 3 times. - RetrofitError retrofitError = RetrofitError.networkError(null, new IOException()); when(segmentService.upload(batch)) - .thenThrow(retrofitError) - .thenThrow(retrofitError) - .thenThrow(retrofitError) - .thenReturn(null); + .thenReturn(Calls.response(failureResponse)) + .thenReturn(Calls.response(failureResponse)) + .thenReturn(Calls.response(failureResponse)) + .thenReturn(Calls.response(successResponse)); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); batchUploadTask.run(); @@ -199,15 +209,14 @@ public void batchRetriesForHTTP5xxErrors() { Batch batch = batchFor(trackMessage); // Throw a HTTP error 3 times. - Response response = - new Response( - "https://api.segment.io", 500, "Server Error", Collections.
emptyList(), null); - RetrofitError retrofitError = RetrofitError.httpError(null, response, null, null); + + Response successResponse = Response.success(200, response); + Response failResponse = Response.error(500, ResponseBody.create(null, "Server Error")); when(segmentService.upload(batch)) - .thenThrow(retrofitError) - .thenThrow(retrofitError) - .thenThrow(retrofitError) - .thenReturn(null); + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(successResponse)); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); batchUploadTask.run(); @@ -224,15 +233,13 @@ public void batchRetriesForHTTP429Errors() { Batch batch = batchFor(trackMessage); // Throw a HTTP error 3 times. - Response response = - new Response( - "https://api.segment.io", 429, "Rate Limited", Collections.
emptyList(), null); - RetrofitError retrofitError = RetrofitError.httpError(null, response, null, null); + Response successResponse = Response.success(200, response); + Response failResponse = Response.error(429, ResponseBody.create(null, "Rate Limited")); when(segmentService.upload(batch)) - .thenThrow(retrofitError) - .thenThrow(retrofitError) - .thenThrow(retrofitError) - .thenReturn(null); + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(successResponse)); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); batchUploadTask.run(); @@ -249,18 +256,16 @@ public void batchDoesNotRetryForNon5xxAndNon429HTTPErrors() { Batch batch = batchFor(trackMessage); // Throw a HTTP error that should not be retried. - Response response = - new Response( - "https://api.segment.io", 404, "Not Found", Collections.
emptyList(), null); - RetrofitError retrofitError = RetrofitError.httpError(null, response, null, null); - doThrow(retrofitError).when(segmentService).upload(batch); + Response failResponse = Response.error(404, ResponseBody.create(null, "Not Found")); + when(segmentService.upload(batch)) + .thenReturn(Calls.response(failResponse)); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); batchUploadTask.run(); // Verify we only tried to upload once. verify(segmentService).upload(batch); - verify(callback).failure(trackMessage, retrofitError); + verify(callback).failure(eq(trackMessage), any(IOException.class)); } @Test @@ -268,16 +273,17 @@ public void batchDoesNotRetryForNonNetworkErrors() { AnalyticsClient client = newClient(); TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); Batch batch = batchFor(trackMessage); - RetrofitError retrofitError = - RetrofitError.conversionError(null, null, null, null, new ConversionException("fake")); - doThrow(retrofitError).when(segmentService).upload(batch); + + Call networkFailure = Calls.failure(new RuntimeException()); + when(segmentService.upload(batch)) + .thenReturn(networkFailure); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); batchUploadTask.run(); // Verify we only tried to upload once. verify(segmentService).upload(batch); - verify(callback).failure(trackMessage, retrofitError); + verify(callback).failure(eq(trackMessage), any(RuntimeException.class)); } @Test @@ -285,8 +291,14 @@ public void givesUpAfterMaxRetries() { AnalyticsClient client = newClient(); TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); Batch batch = batchFor(trackMessage); - RetrofitError retrofitError = RetrofitError.networkError(null, new IOException()); - when(segmentService.upload(batch)).thenThrow(retrofitError); + + when(segmentService.upload(batch)) + .thenAnswer(new Answer>(){ + public Call answer(InvocationOnMock invocation) { + Response failResponse = Response.error(429, ResponseBody.create(null, "Not Found")); + return Calls.response(failResponse); + } + }); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); batchUploadTask.run(); @@ -294,20 +306,16 @@ public void givesUpAfterMaxRetries() { // 50 == MAX_ATTEMPTS in AnalyticsClient.java verify(segmentService, times(50)).upload(batch); verify(callback) - .failure( - eq(trackMessage), - argThat( - new TypeSafeMatcher() { - @Override - public void describeTo(Description description) { - description.appendText("expected IOException"); - } - - @Override - protected boolean matchesSafely(Throwable item) { - IOException exception = (IOException) item; - return exception.getMessage().equals("50 retries exhausted"); - } - })); + .failure( + eq(trackMessage), + argThat( + new ArgumentMatcher(){ + @Override + public boolean matches(IOException exception) { + return exception.getMessage().equals("50 retries exhausted"); + } + } + ) + ); } } diff --git a/pom.xml b/pom.xml index 45f11fd8..e735e412 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 1.2.60 1.14.0 2.9.0 - 1.6 + 1.7.4 3.0.1 2.3.1 3.9.0 @@ -44,7 +44,7 @@ 4.11 1.0.2 2.0.0 - 1.9.5 + 2.21.0 @@ -78,6 +78,11 @@ converter-gson 2.0.0 + + com.squareup.retrofit2 + retrofit-mock + ${retrofit.version} + com.google.auto.value auto-value From 196e6bd8959a0930022a226f37bda0817530a794 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Mon, 2 Nov 2020 12:12:54 -0300 Subject: [PATCH 021/272] fixing spotless violations --- .../analytics/http/SegmentService.java | 2 +- .../src/main/java/sample/Main.java | 3 +- .../java/com/segment/analytics/Analytics.java | 12 +-- .../AnalyticsRequestInterceptor.java | 12 +-- .../java/com/segment/analytics/Callback.java | 3 - .../analytics/internal/AnalyticsClient.java | 17 ++-- .../AnalyticsRequestInterceptorTest.java | 30 +++---- .../com/segment/analytics/ChainAdapter.java | 85 +++++++++---------- .../internal/AnalyticsClientTest.java | 83 +++++++++--------- 9 files changed, 120 insertions(+), 127 deletions(-) diff --git a/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java b/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java index d90ab026..48636a00 100644 --- a/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java +++ b/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java @@ -1,9 +1,9 @@ package com.segment.analytics.http; import com.segment.analytics.messages.Batch; +import retrofit2.Call; import retrofit2.http.Body; import retrofit2.http.POST; -import retrofit2.Call; /** REST interface for the Segment API. */ public interface SegmentService { diff --git a/analytics-sample/src/main/java/sample/Main.java b/analytics-sample/src/main/java/sample/Main.java index 84f55984..77204369 100644 --- a/analytics-sample/src/main/java/sample/Main.java +++ b/analytics-sample/src/main/java/sample/Main.java @@ -52,6 +52,7 @@ private static OkHttpClient createClient() { .connectTimeout(15, TimeUnit.SECONDS) .readTimeout(15, TimeUnit.SECONDS) .writeTimeout(15, TimeUnit.SECONDS) - .addInterceptor(new GzipRequestInterceptor()).build(); + .addInterceptor(new GzipRequestInterceptor()) + .build(); } } diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index 91d22d16..f2eb8b7c 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -9,10 +9,6 @@ import com.segment.analytics.internal.AnalyticsVersion; import com.segment.analytics.messages.Message; import com.segment.analytics.messages.MessageBuilder; - -import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; - import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -20,6 +16,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; @@ -268,7 +266,11 @@ public Analytics build() { } if (client == null) { client = Platform.get().defaultClient(); - client = client.newBuilder().addInterceptor(new AnalyticsRequestInterceptor(writeKey, userAgent)).build(); + client = + client + .newBuilder() + .addInterceptor(new AnalyticsRequestInterceptor(writeKey, userAgent)) + .build(); } if (log == null) { log = Log.NONE; diff --git a/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java b/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java index de61e453..d4c2e895 100644 --- a/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java +++ b/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java @@ -1,10 +1,8 @@ package com.segment.analytics; import java.io.IOException; - import javax.annotation.Nonnull; import okhttp3.Credentials; -import okhttp3.Headers; import okhttp3.Interceptor; import okhttp3.Request; @@ -23,10 +21,12 @@ class AnalyticsRequestInterceptor implements Interceptor { @Override public okhttp3.Response intercept(Chain chain) throws IOException { Request request = chain.request(); - Request newRequest = request.newBuilder() - .addHeader(AUTHORIZATION_HEADER, Credentials.basic(writeKey, "")) - .addHeader(USER_AGENT_HEADER, userAgent) - .build(); + Request newRequest = + request + .newBuilder() + .addHeader(AUTHORIZATION_HEADER, Credentials.basic(writeKey, "")) + .addHeader(USER_AGENT_HEADER, userAgent) + .build(); return chain.proceed(newRequest); } diff --git a/analytics/src/main/java/com/segment/analytics/Callback.java b/analytics/src/main/java/com/segment/analytics/Callback.java index b61bfd08..7fa136f2 100644 --- a/analytics/src/main/java/com/segment/analytics/Callback.java +++ b/analytics/src/main/java/com/segment/analytics/Callback.java @@ -1,10 +1,7 @@ package com.segment.analytics; -import com.segment.analytics.http.UploadResponse; import com.segment.analytics.messages.Message; -import retrofit2.Response; - /** * Callback invoked when the client library is done processing a message. * diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index e4786f24..0315e0a1 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -11,10 +11,6 @@ import com.segment.analytics.messages.Batch; import com.segment.analytics.messages.Message; import com.segment.backo.Backo; - -import retrofit2.Call; -import retrofit2.Response; - import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -28,6 +24,8 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; +import retrofit2.Call; +import retrofit2.Response; public class AnalyticsClient { private static final Map CONTEXT; @@ -210,12 +208,12 @@ boolean upload() { int status = response.code(); if (is5xx(status)) { - client.log.print(DEBUG, "Could not upload batch %s due to server error. Retrying.", - batch.sequence()); + client.log.print( + DEBUG, "Could not upload batch %s due to server error. Retrying.", batch.sequence()); return true; } else if (status == 429) { - client.log.print(DEBUG, "Could not upload batch %s due to rate limiting. Retrying.", - batch.sequence()); + client.log.print( + DEBUG, "Could not upload batch %s due to rate limiting. Retrying.", batch.sequence()); return true; } @@ -224,7 +222,7 @@ boolean upload() { notifyCallbacksWithException(batch, new IOException("HTTP Error")); return false; - } catch(IOException error) { + } catch (IOException error) { client.log.print(DEBUG, error, "Could not upload batch %s. Retrying.", batch.sequence()); return true; @@ -241,6 +239,7 @@ boolean upload() { public void run() { for (int attempt = 0; attempt < MAX_ATTEMPTS; attempt++) { boolean retry = upload(); + client.log.print(VERBOSE, String.format("Retrying %d", attempt)); if (!retry) return; try { backo.sleep(attempt); diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsRequestInterceptorTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsRequestInterceptorTest.java index 9c7fad28..cd884bb3 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsRequestInterceptorTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsRequestInterceptorTest.java @@ -3,33 +3,33 @@ import static org.junit.Assert.assertThat; import java.io.IOException; - -import org.hamcrest.core.Is; -import org.junit.Test; -import org.mockito.Mock; - import okhttp3.Connection; +import okhttp3.Interceptor.Chain; import okhttp3.Request; import okhttp3.Response; -import okhttp3.Interceptor.Chain; +import org.hamcrest.core.Is; +import org.junit.Test; +import org.mockito.Mock; public class AnalyticsRequestInterceptorTest { @Mock private Connection mockConnection; @Test public void testInterceptor() throws IOException { - AnalyticsRequestInterceptor interceptor = new AnalyticsRequestInterceptor("writeKey", "userAgent"); + AnalyticsRequestInterceptor interceptor = + new AnalyticsRequestInterceptor("writeKey", "userAgent"); final Request request = new Request.Builder().url("https://api.segment.io").get().build(); - Chain chain = new ChainAdapter(request, mockConnection) { - @Override - public Response proceed(Request request) throws IOException { - assertThat(request.header("Authorization"), Is.is("Basic d3JpdGVLZXk6")); - assertThat(request.header("User-Agent"), Is.is("userAgent")); - return null; - } - }; + Chain chain = + new ChainAdapter(request, mockConnection) { + @Override + public Response proceed(Request request) throws IOException { + assertThat(request.header("Authorization"), Is.is("Basic d3JpdGVLZXk6")); + assertThat(request.header("User-Agent"), Is.is("userAgent")); + return null; + } + }; interceptor.intercept(chain); } diff --git a/analytics/src/test/java/com/segment/analytics/ChainAdapter.java b/analytics/src/test/java/com/segment/analytics/ChainAdapter.java index c4a9a673..ba0a62c7 100644 --- a/analytics/src/test/java/com/segment/analytics/ChainAdapter.java +++ b/analytics/src/test/java/com/segment/analytics/ChainAdapter.java @@ -1,7 +1,6 @@ package com.segment.analytics; import java.util.concurrent.TimeUnit; - import okhttp3.Call; import okhttp3.Connection; import okhttp3.Interceptor; @@ -14,56 +13,56 @@ */ abstract class ChainAdapter implements Interceptor.Chain { - private final Connection mockConnection; - private final Request request; + private final Connection mockConnection; + private final Request request; - protected ChainAdapter(Request request, Connection mockConnection) { - this.mockConnection = mockConnection; - this.request = request; - } + protected ChainAdapter(Request request, Connection mockConnection) { + this.mockConnection = mockConnection; + this.request = request; + } - @Override - public Request request() { - return request; - } + @Override + public Request request() { + return request; + } - @Override - public Connection connection() { - return mockConnection; - } + @Override + public Connection connection() { + return mockConnection; + } - @Override - public Call call() { - return null; - } + @Override + public Call call() { + return null; + } - @Override - public int connectTimeoutMillis() { - return 0; - } + @Override + public int connectTimeoutMillis() { + return 0; + } - @Override - public Interceptor.Chain withConnectTimeout(int timeout, TimeUnit unit) { - return null; - } + @Override + public Interceptor.Chain withConnectTimeout(int timeout, TimeUnit unit) { + return null; + } - @Override - public int readTimeoutMillis() { - return 0; - } + @Override + public int readTimeoutMillis() { + return 0; + } - @Override - public Interceptor.Chain withReadTimeout(int timeout, TimeUnit unit) { - return null; - } + @Override + public Interceptor.Chain withReadTimeout(int timeout, TimeUnit unit) { + return null; + } - @Override - public int writeTimeoutMillis() { - return 0; - } + @Override + public int writeTimeoutMillis() { + return 0; + } - @Override - public Interceptor.Chain withWriteTimeout(int timeout, TimeUnit unit) { - return null; - } + @Override + public Interceptor.Chain withWriteTimeout(int timeout, TimeUnit unit) { + return null; + } } diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 45b7d6a9..ef942391 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -4,8 +4,6 @@ import static org.mockito.Matchers.any; import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; @@ -17,14 +15,13 @@ import com.segment.analytics.Log; import com.segment.analytics.TestUtils.MessageBuilderTest; import com.segment.analytics.http.SegmentService; +import com.segment.analytics.http.UploadResponse; import com.segment.analytics.internal.AnalyticsClient.BatchUploadTask; import com.segment.analytics.messages.Batch; import com.segment.analytics.messages.Message; import com.segment.analytics.messages.TrackMessage; -import com.segment.analytics.http.UploadResponse; import com.segment.backo.Backo; import com.squareup.burst.BurstJUnit4; - import java.io.IOException; import java.util.Collections; import java.util.Queue; @@ -34,9 +31,8 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; - +import okhttp3.ResponseBody; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -44,8 +40,6 @@ import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; - -import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.Response; import retrofit2.mock.Calls; @@ -189,10 +183,10 @@ public void batchRetriesForNetworkErrors() { // Throw a network error 3 times. when(segmentService.upload(batch)) - .thenReturn(Calls.response(failureResponse)) - .thenReturn(Calls.response(failureResponse)) - .thenReturn(Calls.response(failureResponse)) - .thenReturn(Calls.response(successResponse)); + .thenReturn(Calls.response(failureResponse)) + .thenReturn(Calls.response(failureResponse)) + .thenReturn(Calls.response(failureResponse)) + .thenReturn(Calls.response(successResponse)); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); batchUploadTask.run(); @@ -211,12 +205,13 @@ public void batchRetriesForHTTP5xxErrors() { // Throw a HTTP error 3 times. Response successResponse = Response.success(200, response); - Response failResponse = Response.error(500, ResponseBody.create(null, "Server Error")); + Response failResponse = + Response.error(500, ResponseBody.create(null, "Server Error")); when(segmentService.upload(batch)) - .thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(successResponse)); + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(successResponse)); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); batchUploadTask.run(); @@ -234,12 +229,13 @@ public void batchRetriesForHTTP429Errors() { // Throw a HTTP error 3 times. Response successResponse = Response.success(200, response); - Response failResponse = Response.error(429, ResponseBody.create(null, "Rate Limited")); + Response failResponse = + Response.error(429, ResponseBody.create(null, "Rate Limited")); when(segmentService.upload(batch)) - .thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(successResponse)); + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(successResponse)); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); batchUploadTask.run(); @@ -256,9 +252,9 @@ public void batchDoesNotRetryForNon5xxAndNon429HTTPErrors() { Batch batch = batchFor(trackMessage); // Throw a HTTP error that should not be retried. - Response failResponse = Response.error(404, ResponseBody.create(null, "Not Found")); - when(segmentService.upload(batch)) - .thenReturn(Calls.response(failResponse)); + Response failResponse = + Response.error(404, ResponseBody.create(null, "Not Found")); + when(segmentService.upload(batch)).thenReturn(Calls.response(failResponse)); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); batchUploadTask.run(); @@ -275,8 +271,7 @@ public void batchDoesNotRetryForNonNetworkErrors() { Batch batch = batchFor(trackMessage); Call networkFailure = Calls.failure(new RuntimeException()); - when(segmentService.upload(batch)) - .thenReturn(networkFailure); + when(segmentService.upload(batch)).thenReturn(networkFailure); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); batchUploadTask.run(); @@ -293,12 +288,14 @@ public void givesUpAfterMaxRetries() { Batch batch = batchFor(trackMessage); when(segmentService.upload(batch)) - .thenAnswer(new Answer>(){ - public Call answer(InvocationOnMock invocation) { - Response failResponse = Response.error(429, ResponseBody.create(null, "Not Found")); - return Calls.response(failResponse); - } - }); + .thenAnswer( + new Answer>() { + public Call answer(InvocationOnMock invocation) { + Response failResponse = + Response.error(429, ResponseBody.create(null, "Not Found")); + return Calls.response(failResponse); + } + }); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); batchUploadTask.run(); @@ -306,16 +303,14 @@ public Call answer(InvocationOnMock invocation) { // 50 == MAX_ATTEMPTS in AnalyticsClient.java verify(segmentService, times(50)).upload(batch); verify(callback) - .failure( - eq(trackMessage), - argThat( - new ArgumentMatcher(){ - @Override - public boolean matches(IOException exception) { - return exception.getMessage().equals("50 retries exhausted"); - } - } - ) - ); + .failure( + eq(trackMessage), + argThat( + new ArgumentMatcher() { + @Override + public boolean matches(IOException exception) { + return exception.getMessage().equals("50 retries exhausted"); + } + })); } } From 2faeef3a7b870eff7a347487b6f9c02d33870238 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Mon, 2 Nov 2020 15:52:25 -0300 Subject: [PATCH 022/272] bumping up dependency versions --- analytics/pom.xml | 4 ++++ pom.xml | 12 +++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/analytics/pom.xml b/analytics/pom.xml index 05225d19..9713d8b1 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -22,6 +22,10 @@ com.squareup.okhttp3 okhttp + + com.squareup.okhttp3 + logging-interceptor + com.squareup.retrofit2 converter-gson diff --git a/pom.xml b/pom.xml index e735e412..e3a53493 100644 --- a/pom.xml +++ b/pom.xml @@ -33,8 +33,9 @@ 2.9.0 1.7.4 3.0.1 - 2.3.1 - 3.9.0 + 2.8.6 + 4.0.1 + 4.0.1 26.0-jre 1.0.0 1.2.5.RELEASE @@ -76,7 +77,7 @@ com.squareup.retrofit2 converter-gson - 2.0.0 + 2.9.0 com.squareup.retrofit2 @@ -109,6 +110,11 @@ okhttp ${okhttp.version} + + com.squareup.okhttp3 + logging-interceptor + ${logging.version} + com.google.guava guava From a9280917a648af4af19674c0de6d11e208500d87 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Mon, 2 Nov 2020 15:52:35 -0300 Subject: [PATCH 023/272] setting up logging interceptor --- .../java/com/segment/analytics/Analytics.java | 21 +++++++++++++------ .../analytics/internal/AnalyticsClient.java | 1 - 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index f2eb8b7c..7178bbd4 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -18,6 +18,7 @@ import java.util.concurrent.TimeUnit; import okhttp3.HttpUrl; import okhttp3.OkHttpClient; +import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; @@ -266,11 +267,6 @@ public Analytics build() { } if (client == null) { client = Platform.get().defaultClient(); - client = - client - .newBuilder() - .addInterceptor(new AnalyticsRequestInterceptor(writeKey, userAgent)) - .build(); } if (log == null) { log = Log.NONE; @@ -303,12 +299,25 @@ public Analytics build() { callbacks = Collections.unmodifiableList(callbacks); } + HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger(){ + @Override + public void log(String message) { + log.print(Log.Level.VERBOSE, "%s", message); + } + }); + + interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC); + + client = client.newBuilder() + .addInterceptor(new AnalyticsRequestInterceptor(writeKey, userAgent)) + .addInterceptor(interceptor) + .build(); + Retrofit restAdapter = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create(gson)) .baseUrl(endpoint) .client(client) - // .setLogLevel(RestAdapter.LogLevel.FULL) .build(); SegmentService segmentService = restAdapter.create(SegmentService.class); diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 0315e0a1..3d32748c 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -239,7 +239,6 @@ boolean upload() { public void run() { for (int attempt = 0; attempt < MAX_ATTEMPTS; attempt++) { boolean retry = upload(); - client.log.print(VERBOSE, String.format("Retrying %d", attempt)); if (!retry) return; try { backo.sleep(attempt); From 3beaf876d27635d53709343188b6c240bf08ded4 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Mon, 2 Nov 2020 15:53:48 -0300 Subject: [PATCH 024/272] spotless apply --- .../java/com/segment/analytics/Analytics.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index 7178bbd4..2dc0bd76 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -299,19 +299,23 @@ public Analytics build() { callbacks = Collections.unmodifiableList(callbacks); } - HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger(){ - @Override - public void log(String message) { - log.print(Log.Level.VERBOSE, "%s", message); - } - }); + HttpLoggingInterceptor interceptor = + new HttpLoggingInterceptor( + new HttpLoggingInterceptor.Logger() { + @Override + public void log(String message) { + log.print(Log.Level.VERBOSE, "%s", message); + } + }); interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC); - client = client.newBuilder() - .addInterceptor(new AnalyticsRequestInterceptor(writeKey, userAgent)) - .addInterceptor(interceptor) - .build(); + client = + client + .newBuilder() + .addInterceptor(new AnalyticsRequestInterceptor(writeKey, userAgent)) + .addInterceptor(interceptor) + .build(); Retrofit restAdapter = new Retrofit.Builder() From 6966c80d348e78e9095d04203e7898081fa04e8b Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Mon, 2 Nov 2020 16:47:46 -0300 Subject: [PATCH 025/272] downgrading failsafe --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e3a53493..7e8fc1f1 100644 --- a/pom.xml +++ b/pom.xml @@ -289,7 +289,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.22.1 + 2.18.1 false From f520f1e6382b7ce6aba1c9ee6540097bfcb95bde Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Tue, 17 Nov 2020 12:06:10 -0300 Subject: [PATCH 026/272] bringing back default test job --- .circleci/config.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index b3639b7f..b1f317cd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -36,6 +36,11 @@ jobs: docker: - image: circleci/openjdk:11-jdk-browsers + test: + <<: *java-base-test + docker: + - image: circleci/openjdk:11-jdk-browsers + publish: <<: *java-base-test docker: From c01dbf94690128afd7dec7a22b8dd8ef00659a7e Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Thu, 19 Nov 2020 18:38:12 -0300 Subject: [PATCH 027/272] placing java8 testing back --- .circleci/config.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index b1f317cd..f08406b6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -36,6 +36,11 @@ jobs: docker: - image: circleci/openjdk:11-jdk-browsers + test-jdk8: + <<: *java-base-test + docker: + - image: circleci/openjdk:8-jdk-browsers + test: <<: *java-base-test docker: From b18d0638332e254fbc8cdfbe00a1047d5d61e1df Mon Sep 17 00:00:00 2001 From: "Shane L. Duvall" Date: Thu, 19 Nov 2020 16:43:16 -0600 Subject: [PATCH 028/272] Update config.yml Remove tab in file --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f08406b6..a605256e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -36,7 +36,7 @@ jobs: docker: - image: circleci/openjdk:11-jdk-browsers - test-jdk8: + test-jdk8: <<: *java-base-test docker: - image: circleci/openjdk:8-jdk-browsers From 07891a3a3cb6f70a1a89024d2f2d02d5ea38557e Mon Sep 17 00:00:00 2001 From: "Shane L. Duvall" Date: Thu, 19 Nov 2020 16:45:07 -0600 Subject: [PATCH 029/272] Update config.yml found another tab that is now removed --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a605256e..ed2ec43c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -37,8 +37,8 @@ jobs: - image: circleci/openjdk:11-jdk-browsers test-jdk8: - <<: *java-base-test - docker: + <<: *java-base-test + docker: - image: circleci/openjdk:8-jdk-browsers test: From 6feff2935162214b218685810144e45b89765d78 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Thu, 19 Nov 2020 19:54:32 -0300 Subject: [PATCH 030/272] fixing violations --- .../java/com/segment/analytics/TestUtils.java | 3 - .../gson/ISO8601DateAdapterTest.java | 58 +++++++++---------- 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/analytics-core/src/test/java/com/segment/analytics/TestUtils.java b/analytics-core/src/test/java/com/segment/analytics/TestUtils.java index fe1f6f03..e31dcac8 100644 --- a/analytics-core/src/test/java/com/segment/analytics/TestUtils.java +++ b/analytics-core/src/test/java/com/segment/analytics/TestUtils.java @@ -1,8 +1,5 @@ package com.segment.analytics; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.segment.analytics.gson.ISO8601DateAdapter; import com.segment.analytics.messages.*; import java.util.Calendar; import java.util.Date; diff --git a/analytics-core/src/test/java/com/segment/analytics/gson/ISO8601DateAdapterTest.java b/analytics-core/src/test/java/com/segment/analytics/gson/ISO8601DateAdapterTest.java index 5570b6e2..7e02791e 100644 --- a/analytics-core/src/test/java/com/segment/analytics/gson/ISO8601DateAdapterTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/gson/ISO8601DateAdapterTest.java @@ -1,49 +1,47 @@ package com.segment.analytics.gson; +import static com.segment.analytics.TestUtils.newDate; +import static org.assertj.core.api.Assertions.assertThat; + import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import com.segment.analytics.TestUtils; +import java.util.Date; import org.junit.Assert; import org.junit.Test; -import java.util.Date; - -import static com.segment.analytics.TestUtils.newDate; -import static org.assertj.core.api.Assertions.assertThat; - public class ISO8601DateAdapterTest { - public static final Gson GSON = new GsonBuilder() - .registerTypeAdapter(Date.class, new ISO8601DateAdapter()) - .create(); + public static final Gson GSON = + new GsonBuilder().registerTypeAdapter(Date.class, new ISO8601DateAdapter()).create(); - private static class TestModel { - final Date timestamp; - public TestModel(Date timestamp) { - this.timestamp = timestamp; - } + private static class TestModel { + final Date timestamp; + + public TestModel(Date timestamp) { + this.timestamp = timestamp; } + } - @Test - public void testSerializeDate() { - TestModel testModel = new TestModel(newDate(1996, 12, 19, 16, 39, 57, 0, -8 * 60)); + @Test + public void testSerializeDate() { + TestModel testModel = new TestModel(newDate(1996, 12, 19, 16, 39, 57, 0, -8 * 60)); - JsonElement e = GSON.toJsonTree(testModel); - Assert.assertTrue(e.isJsonObject()); + JsonElement e = GSON.toJsonTree(testModel); + Assert.assertTrue(e.isJsonObject()); - JsonObject o = e.getAsJsonObject(); - Assert.assertTrue(o.has("timestamp")); + JsonObject o = e.getAsJsonObject(); + Assert.assertTrue(o.has("timestamp")); - assertThat(o.get("timestamp").getAsString()).isEqualTo("1996-12-20T00:39:57.000Z"); - } + assertThat(o.get("timestamp").getAsString()).isEqualTo("1996-12-20T00:39:57.000Z"); + } - @Test - public void testDeserializeDate() { - String serializedTestModel = "{\"timestamp\":\"1996-06-01T16:39:57.000Z\"}"; - Date expected = newDate(1996, 06, 01, 16, 39, 57, 0, 0); - TestModel actual = GSON.fromJson(serializedTestModel, TestModel.class); - assertThat(actual.timestamp).isEqualTo(expected); - } + @Test + public void testDeserializeDate() { + String serializedTestModel = "{\"timestamp\":\"1996-06-01T16:39:57.000Z\"}"; + Date expected = newDate(1996, 06, 01, 16, 39, 57, 0, 0); + TestModel actual = GSON.fromJson(serializedTestModel, TestModel.class); + assertThat(actual.timestamp).isEqualTo(expected); + } } From fc080383d19a1bedda0afeea8ca48251a9a72cf8 Mon Sep 17 00:00:00 2001 From: "Shane L. Duvall" Date: Thu, 19 Nov 2020 17:04:24 -0600 Subject: [PATCH 031/272] trigger new build Using correct branch this time --- .circleci/config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ed2ec43c..172863b6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,5 +1,4 @@ version: 2 - jobs: java-base-test: &java-base-test working_directory: ~/analytics-java From 8efbbf4ef29af4e6c35ee13e79987b12e4a18e0d Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Fri, 20 Nov 2020 02:34:29 -0300 Subject: [PATCH 032/272] source/target config --- pom.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 25d06b2f..3cbae2e8 100644 --- a/pom.xml +++ b/pom.xml @@ -27,11 +27,11 @@ UTF-8 - 11 + 8 1.2.60 1.14.0 2.9.0 - 1.7.4 + 1.7.1 3.0.1 2.8.6 @@ -173,7 +173,8 @@ 3.8.1 true - ${java.version} + ${java.version} + ${java.version} true From 1e300eafad8b3a09ad14e697694f3854bc6156b1 Mon Sep 17 00:00:00 2001 From: "Shane L. Duvall" Date: Fri, 20 Nov 2020 14:33:20 -0600 Subject: [PATCH 033/272] Add test-jdk8 job updated config.yaml to test jdk8 job --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 172863b6..ad2d29ce 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -95,6 +95,7 @@ workflows: jobs: - test-jdklatest - test-jdk11 + - test-jdk8 static_analysis: jobs: - test From 0ba2df57c75405d9e1ad1cff1e52f33f16af1e6a Mon Sep 17 00:00:00 2001 From: "Sean C. Sullivan" Date: Wed, 25 Nov 2020 14:47:39 -0800 Subject: [PATCH 034/272] upgrade from Mockito 2.x to Mockito 3.x --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3cbae2e8..e2e8fe5d 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ 4.13.1 1.0.2 2.0.0 - 2.21.0 + 3.6.28 From 216fce12fd0d504c570b1b4a33fdc1a882f44964 Mon Sep 17 00:00:00 2001 From: "Sean C. Sullivan" Date: Wed, 25 Nov 2020 14:44:45 -0800 Subject: [PATCH 035/272] enable Dependabot v2 add Dependabot version 2 yaml file https://github.blog/2020-06-01-keep-all-your-packages-up-to-date-with-dependabot/ --- .github/dependabot.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..e1d1cc74 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "maven" + directory: "/" + schedule: + interval: "weekly" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" From 2c9c075002dff737a36ff0fcb4fc58c788006776 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Sun, 29 Nov 2020 23:03:38 -0300 Subject: [PATCH 036/272] limiting by message size --- .../analytics/internal/AnalyticsClient.java | 25 +++++++++++++++++++ .../internal/AnalyticsClientTest.java | 3 +++ 2 files changed, 28 insertions(+) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 3d32748c..cba72329 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -4,12 +4,14 @@ import static com.segment.analytics.Log.Level.ERROR; import static com.segment.analytics.Log.Level.VERBOSE; +import com.google.gson.Gson; import com.segment.analytics.Callback; import com.segment.analytics.Log; import com.segment.analytics.http.SegmentService; import com.segment.analytics.http.UploadResponse; import com.segment.analytics.messages.Batch; import com.segment.analytics.messages.Message; +import com.segment.analytics.messages.TrackMessage; import com.segment.backo.Backo; import java.io.IOException; import java.util.ArrayList; @@ -24,11 +26,14 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; +import java.lang.instrument.Instrumentation; + import retrofit2.Call; import retrofit2.Response; public class AnalyticsClient { private static final Map CONTEXT; + private static final int MESSAGE_QUEUE_MAX_BYTE_SIZE = 1024 * 32; static { Map library = new LinkedHashMap<>(); @@ -39,6 +44,7 @@ public class AnalyticsClient { CONTEXT = Collections.unmodifiableMap(context); } + private final BlockingQueue messageQueue; private final SegmentService service; private final int size; @@ -101,12 +107,31 @@ public void run() { public void enqueue(Message message) { try { + if (isBackPressured()) { + log.print(VERBOSE, "Maximum storage size have been hit. Dropping messages"); + return; + } + messageQueue.put(message); } catch (InterruptedException e) { log.print(ERROR, e, "Interrupted while adding message %s.", message); } } + public int messageSizeInBytes(TrackMessage message) { + Gson gson = new Gson(); + String stringifiedMessage = gson.toJson(message); + return stringifiedMessage.length(); + } + + private Boolean isBackPressured() { + int messageQueueSize = messageQueue.stream() + .map(message -> messageSizeInBytes((TrackMessage) message)) + .reduce(0, (messageASize, messageBSize) -> messageASize + messageBSize); + + return messageQueueSize >= MESSAGE_QUEUE_MAX_BYTE_SIZE; + } + public void flush() { enqueue(FlushMessage.POISON); } diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index ef942391..17e79b4d 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -23,7 +23,10 @@ import com.segment.backo.Backo; import com.squareup.burst.BurstJUnit4; import java.io.IOException; +import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.Queue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; From 154df108ef446a218daea0135e3aac653ac4011c Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Sun, 29 Nov 2020 23:18:14 -0300 Subject: [PATCH 037/272] tests --- .../internal/AnalyticsClientTest.java | 557 +++++++++--------- 1 file changed, 290 insertions(+), 267 deletions(-) diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 17e79b4d..9540fc9a 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -49,271 +49,294 @@ @RunWith(BurstJUnit4.class) // public class AnalyticsClientTest { - // Backo instance for testing which trims down the wait times. - private static final Backo BACKO = - Backo.builder().base(TimeUnit.NANOSECONDS, 1).factor(1).build(); - - Log log = Log.NONE; - ThreadFactory threadFactory; - @Mock BlockingQueue messageQueue; - @Mock SegmentService segmentService; - @Mock ExecutorService networkExecutor; - @Mock Callback callback; - @Mock UploadResponse response; - - @Before - public void setUp() { - initMocks(this); - threadFactory = Executors.defaultThreadFactory(); - } - - // Defers loading the client until tests can initialize all required dependencies. - AnalyticsClient newClient() { - return new AnalyticsClient( - messageQueue, - segmentService, - 50, - TimeUnit.HOURS.toMillis(1), - log, - threadFactory, - networkExecutor, - Collections.singletonList(callback)); - } - - @Test - public void enqueueAddsToQueue(MessageBuilderTest builder) throws InterruptedException { - AnalyticsClient client = newClient(); - - Message message = builder.get().userId("prateek").build(); - client.enqueue(message); - - verify(messageQueue).put(message); - } - - @Test - public void shutdown() { - AnalyticsClient client = newClient(); - - client.shutdown(); - - verify(messageQueue).clear(); - verify(networkExecutor).shutdown(); - } - - @Test - public void flushInsertsPoison() throws InterruptedException { - AnalyticsClient client = newClient(); - - client.flush(); - - verify(messageQueue).put(FlushMessage.POISON); - } - - /** Wait until the queue is drained. */ - static void wait(Queue queue) { - //noinspection StatementWithEmptyBody - while (queue.size() > 0) {} - } - - /** - * Verify that a {@link BatchUploadTask} was submitted to the executor, and return the {@link - * BatchUploadTask#batch} it was uploading.. - */ - static Batch captureBatch(ExecutorService executor) { - final ArgumentCaptor runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class); - verify(executor, timeout(1000)).submit(runnableArgumentCaptor.capture()); - final BatchUploadTask task = (BatchUploadTask) runnableArgumentCaptor.getValue(); - return task.batch; - } - - @Test - public void flushSubmitsToExecutor() { - messageQueue = new LinkedBlockingQueue<>(); - AnalyticsClient client = newClient(); - - TrackMessage first = TrackMessage.builder("foo").userId("bar").build(); - TrackMessage second = TrackMessage.builder("qaz").userId("qux").build(); - client.enqueue(first); - client.enqueue(second); - client.flush(); - wait(messageQueue); - - assertThat(captureBatch(networkExecutor).batch()).containsExactly(first, second); - } - - @Test - public void enqueueMaxTriggersFlush() { - messageQueue = new LinkedBlockingQueue<>(); - AnalyticsClient client = newClient(); - - // Enqueuing 51 messages (> 50) should trigger flush. - for (int i = 0; i < 51; i++) { - client.enqueue(TrackMessage.builder("Event " + i).userId("bar").build()); - } - wait(messageQueue); - - // Verify that the executor saw the batch. - assertThat(captureBatch(networkExecutor).batch()).hasSize(50); - } - - @Test - public void enqueueBeforeMaxDoesNotTriggerFlush() { - messageQueue = new LinkedBlockingQueue<>(); - AnalyticsClient client = newClient(); - - // Enqueuing 5 messages (< 50) should not trigger flush. - for (int i = 0; i < 5; i++) { - client.enqueue(TrackMessage.builder("Event " + i).userId("bar").build()); - } - wait(messageQueue); - - // Verify that the executor didn't see anything. - verify(networkExecutor, never()).submit(any(Runnable.class)); - } - - static Batch batchFor(Message message) { - return Batch.create(Collections.emptyMap(), Collections.singletonList(message)); - } - - @Test - public void batchRetriesForNetworkErrors() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - Response successResponse = Response.success(200, response); - Response failureResponse = Response.error(429, ResponseBody.create(null, "")); - - // Throw a network error 3 times. - when(segmentService.upload(batch)) - .thenReturn(Calls.response(failureResponse)) - .thenReturn(Calls.response(failureResponse)) - .thenReturn(Calls.response(failureResponse)) - .thenReturn(Calls.response(successResponse)); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); - batchUploadTask.run(); - - // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. - verify(segmentService, times(4)).upload(batch); - verify(callback).success(trackMessage); - } - - @Test - public void batchRetriesForHTTP5xxErrors() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - // Throw a HTTP error 3 times. - - Response successResponse = Response.success(200, response); - Response failResponse = - Response.error(500, ResponseBody.create(null, "Server Error")); - when(segmentService.upload(batch)) - .thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(successResponse)); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); - batchUploadTask.run(); - - // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. - verify(segmentService, times(4)).upload(batch); - verify(callback).success(trackMessage); - } - - @Test - public void batchRetriesForHTTP429Errors() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - // Throw a HTTP error 3 times. - Response successResponse = Response.success(200, response); - Response failResponse = - Response.error(429, ResponseBody.create(null, "Rate Limited")); - when(segmentService.upload(batch)) - .thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(successResponse)); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); - batchUploadTask.run(); - - // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. - verify(segmentService, times(4)).upload(batch); - verify(callback).success(trackMessage); - } - - @Test - public void batchDoesNotRetryForNon5xxAndNon429HTTPErrors() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - // Throw a HTTP error that should not be retried. - Response failResponse = - Response.error(404, ResponseBody.create(null, "Not Found")); - when(segmentService.upload(batch)).thenReturn(Calls.response(failResponse)); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); - batchUploadTask.run(); - - // Verify we only tried to upload once. - verify(segmentService).upload(batch); - verify(callback).failure(eq(trackMessage), any(IOException.class)); - } - - @Test - public void batchDoesNotRetryForNonNetworkErrors() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - Call networkFailure = Calls.failure(new RuntimeException()); - when(segmentService.upload(batch)).thenReturn(networkFailure); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); - batchUploadTask.run(); - - // Verify we only tried to upload once. - verify(segmentService).upload(batch); - verify(callback).failure(eq(trackMessage), any(RuntimeException.class)); - } - - @Test - public void givesUpAfterMaxRetries() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - when(segmentService.upload(batch)) - .thenAnswer( - new Answer>() { - public Call answer(InvocationOnMock invocation) { - Response failResponse = - Response.error(429, ResponseBody.create(null, "Not Found")); - return Calls.response(failResponse); - } - }); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); - batchUploadTask.run(); - - // 50 == MAX_ATTEMPTS in AnalyticsClient.java - verify(segmentService, times(50)).upload(batch); - verify(callback) - .failure( - eq(trackMessage), - argThat( - new ArgumentMatcher() { - @Override - public boolean matches(IOException exception) { - return exception.getMessage().equals("50 retries exhausted"); - } - })); - } + // Backo instance for testing which trims down the wait times. + private static final Backo BACKO = Backo.builder().base(TimeUnit.NANOSECONDS, 1).factor(1).build(); + + Log log = Log.NONE; + ThreadFactory threadFactory; + @Mock + BlockingQueue messageQueue; + @Mock + SegmentService segmentService; + @Mock + ExecutorService networkExecutor; + @Mock + Callback callback; + @Mock + UploadResponse response; + + @Before + public void setUp() { + initMocks(this); + threadFactory = Executors.defaultThreadFactory(); + } + + // Defers loading the client until tests can initialize all required + // dependencies. + AnalyticsClient newClient() { + return new AnalyticsClient(messageQueue, segmentService, 50, TimeUnit.HOURS.toMillis(1), log, threadFactory, + networkExecutor, Collections.singletonList(callback)); + } + + @Test + public void enqueueAddsToQueue(MessageBuilderTest builder) throws InterruptedException { + AnalyticsClient client = newClient(); + + Message message = builder.get().userId("prateek").build(); + client.enqueue(message); + + verify(messageQueue).put(message); + } + + @Test + public void shutdown() { + AnalyticsClient client = newClient(); + + client.shutdown(); + + verify(messageQueue).clear(); + verify(networkExecutor).shutdown(); + } + + @Test + public void flushInsertsPoison() throws InterruptedException { + AnalyticsClient client = newClient(); + + client.flush(); + + verify(messageQueue).put(FlushMessage.POISON); + } + + /** Wait until the queue is drained. */ + static void wait(Queue queue) { + // noinspection StatementWithEmptyBody + while (queue.size() > 0) { + } + } + + /** + * Verify that a {@link BatchUploadTask} was submitted to the executor, and + * return the {@link BatchUploadTask#batch} it was uploading.. + */ + static Batch captureBatch(ExecutorService executor) { + final ArgumentCaptor runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class); + verify(executor, timeout(1000)).submit(runnableArgumentCaptor.capture()); + final BatchUploadTask task = (BatchUploadTask) runnableArgumentCaptor.getValue(); + return task.batch; + } + + @Test + public void flushSubmitsToExecutor() { + messageQueue = new LinkedBlockingQueue<>(); + AnalyticsClient client = newClient(); + + TrackMessage first = TrackMessage.builder("foo").userId("bar").build(); + TrackMessage second = TrackMessage.builder("qaz").userId("qux").build(); + client.enqueue(first); + client.enqueue(second); + client.flush(); + wait(messageQueue); + + assertThat(captureBatch(networkExecutor).batch()).containsExactly(first, second); + } + + @Test + public void enqueueMaxTriggersFlush() { + messageQueue = new LinkedBlockingQueue<>(); + AnalyticsClient client = newClient(); + + // Enqueuing 51 messages (> 50) should trigger flush. + for (int i = 0; i < 51; i++) { + client.enqueue(TrackMessage.builder("Event " + i).userId("bar").build()); + } + wait(messageQueue); + + // Verify that the executor saw the batch. + assertThat(captureBatch(networkExecutor).batch()).hasSize(50); + } + + private static String createDataSize(int msgSize) { + char[] chars = new char[msgSize]; + Arrays.fill(chars, 'a'); + + return new String(chars); + } + + @Test + public void calculatesMessageByteSize() { + AnalyticsClient client = newClient(); + Map properties = new HashMap(); + + properties.put("dummy-property", createDataSize(1024 * 33)); + + TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); + client.enqueue(bigMessage); + + // can't test for exact size cause other attributes come in play + assertThat(client.messageSizeInBytes(bigMessage)).isGreaterThan(1024 * 33); + } + + @Test + public void dontEnqueueWhenReachesMaxSize() throws InterruptedException { + AnalyticsClient client = newClient(); + Map properties = new HashMap(); + + properties.put("dummy-property", createDataSize(1024 * 33)); + + TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); + client.enqueue(bigMessage); + + // assertThat(client.messageSizeInBytes(bigMessage)).isEqualTo(30); + + Message tinyMessage = TrackMessage.builder("Tinny Event").userId("bar").build(); + client.enqueue(tinyMessage); + wait(messageQueue); + + verify(messageQueue, times(2)).put(any(Message.class)); + } + + @Test + public void enqueueBeforeMaxDoesNotTriggerFlush() { + messageQueue = new LinkedBlockingQueue<>(); + AnalyticsClient client = newClient(); + + // Enqueuing 5 messages (< 50) should not trigger flush. + for (int i = 0; i < 5; i++) { + client.enqueue(TrackMessage.builder("Event " + i).userId("bar").build()); + } + wait(messageQueue); + + // Verify that the executor didn't see anything. + verify(networkExecutor, never()).submit(any(Runnable.class)); + } + + static Batch batchFor(Message message) { + return Batch.create(Collections.emptyMap(), Collections.singletonList(message)); + } + + @Test + public void batchRetriesForNetworkErrors() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + Response successResponse = Response.success(200, response); + Response failureResponse = Response.error(429, ResponseBody.create(null, "")); + + // Throw a network error 3 times. + when(segmentService.upload(batch)).thenReturn(Calls.response(failureResponse)) + .thenReturn(Calls.response(failureResponse)).thenReturn(Calls.response(failureResponse)) + .thenReturn(Calls.response(successResponse)); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + batchUploadTask.run(); + + // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. + verify(segmentService, times(4)).upload(batch); + verify(callback).success(trackMessage); + } + + @Test + public void batchRetriesForHTTP5xxErrors() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + // Throw a HTTP error 3 times. + + Response successResponse = Response.success(200, response); + Response failResponse = Response.error(500, ResponseBody.create(null, "Server Error")); + when(segmentService.upload(batch)).thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)).thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(successResponse)); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + batchUploadTask.run(); + + // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. + verify(segmentService, times(4)).upload(batch); + verify(callback).success(trackMessage); + } + + @Test + public void batchRetriesForHTTP429Errors() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + // Throw a HTTP error 3 times. + Response successResponse = Response.success(200, response); + Response failResponse = Response.error(429, ResponseBody.create(null, "Rate Limited")); + when(segmentService.upload(batch)).thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)).thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(successResponse)); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + batchUploadTask.run(); + + // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. + verify(segmentService, times(4)).upload(batch); + verify(callback).success(trackMessage); + } + + @Test + public void batchDoesNotRetryForNon5xxAndNon429HTTPErrors() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + // Throw a HTTP error that should not be retried. + Response failResponse = Response.error(404, ResponseBody.create(null, "Not Found")); + when(segmentService.upload(batch)).thenReturn(Calls.response(failResponse)); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + batchUploadTask.run(); + + // Verify we only tried to upload once. + verify(segmentService).upload(batch); + verify(callback).failure(eq(trackMessage), any(IOException.class)); + } + + @Test + public void batchDoesNotRetryForNonNetworkErrors() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + Call networkFailure = Calls.failure(new RuntimeException()); + when(segmentService.upload(batch)).thenReturn(networkFailure); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + batchUploadTask.run(); + + // Verify we only tried to upload once. + verify(segmentService).upload(batch); + verify(callback).failure(eq(trackMessage), any(RuntimeException.class)); + } + + @Test + public void givesUpAfterMaxRetries() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + when(segmentService.upload(batch)).thenAnswer(new Answer>() { + public Call answer(InvocationOnMock invocation) { + Response failResponse = Response.error(429, ResponseBody.create(null, "Not Found")); + return Calls.response(failResponse); + } + }); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + batchUploadTask.run(); + + // 50 == MAX_ATTEMPTS in AnalyticsClient.java + verify(segmentService, times(50)).upload(batch); + verify(callback).failure(eq(trackMessage), argThat(new ArgumentMatcher() { + @Override + public boolean matches(IOException exception) { + return exception.getMessage().equals("50 retries exhausted"); + } + })); + } } From 06631c5a2832d5d036335a599da4a188a48dc7e0 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Mon, 14 Dec 2020 02:49:19 -0300 Subject: [PATCH 038/272] adding new parameters to kotlin tester that the lib supports --- analytics-cli/src/main/kotlin/cli/Main.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/analytics-cli/src/main/kotlin/cli/Main.kt b/analytics-cli/src/main/kotlin/cli/Main.kt index 01b06180..8a2b2ff6 100644 --- a/analytics-cli/src/main/kotlin/cli/Main.kt +++ b/analytics-cli/src/main/kotlin/cli/Main.kt @@ -13,7 +13,8 @@ val usage = """ Analytics Java CLI Usage: - analytics --writeKey= --type= --userId= [--event=] [--properties=] [--name=] [--traits=] [--groupId=] [--previousId=] + analytics --writeKey= --type= --userId= [--event=] [--properties=] [--name=] [--traits=] [--groupId=] [--previousId=] [--anonymousId=] [--integrations=] [--traits=] [--context=] + analytics -h | --help analytics --version From e195b63b27182ea7339e48c183637fafdac9298e Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Sun, 20 Dec 2020 15:10:12 -0300 Subject: [PATCH 039/272] Add functionality to set custom endpoint with host and prefix --- .../analytics/http/SegmentService.java | 2 +- .../java/com/segment/analytics/Analytics.java | 28 +++++++++-- .../analytics/AnalyticsBuilderTest.java | 48 +++++++++++++++++++ 3 files changed, 72 insertions(+), 6 deletions(-) diff --git a/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java b/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java index 48636a00..5b66e330 100644 --- a/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java +++ b/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java @@ -7,6 +7,6 @@ /** REST interface for the Segment API. */ public interface SegmentService { - @POST("/v1/import") + @POST("") Call upload(@Body Batch batch); } diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index 2dc0bd76..51863377 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -101,7 +101,8 @@ public static class Builder { private final String writeKey; private OkHttpClient client; private Log log; - private HttpUrl endpoint; + public HttpUrl endpoint; + public HttpUrl uploadURL; private String userAgent = DEFAULT_USER_AGENT; private List messageTransformers; private List messageInterceptors; @@ -137,14 +138,26 @@ public Builder log(Log log) { } /** - * Set an endpoint that this client should upload events to. Uses {@code https://api.segment.io} - * by default. + * Set an endpoint (host only) that this client should upload events to. Uses {@code + * https://api.segment.io} by default. */ public Builder endpoint(String endpoint) { if (endpoint == null || endpoint.trim().length() == 0) { throw new NullPointerException("endpoint cannot be null or empty."); } - this.endpoint = HttpUrl.parse(endpoint); + this.endpoint = HttpUrl.parse(endpoint + "/v1/import/"); + return this; + } + + /** + * Set an endpoint (host and prefix) that this client should upload events to. Uses {@code + * https://api.segment.io/v1} by default. + */ + public Builder setUploadURL(String uploadURL) { + if (uploadURL == null || uploadURL.trim().length() == 0) { + throw new NullPointerException("endpoint cannot be null or empty."); + } + this.uploadURL = HttpUrl.parse(uploadURL); return this; } @@ -262,9 +275,14 @@ public Analytics build() { .registerTypeAdapter(Date.class, new ISO8601DateAdapter()) // .create(); - if (endpoint == null) { + if (endpoint == null && uploadURL == null) { endpoint = DEFAULT_ENDPOINT; } + + if (endpoint == null && uploadURL != null) { + endpoint = uploadURL; + } + if (client == null) { client = Platform.get().defaultClient(); } diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java index e9f99bc1..b8c6890c 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java @@ -2,6 +2,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; +import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -251,6 +252,53 @@ public void buildsWithValidEndpoint() { assertThat(analytics).isNotNull(); } + @Test + public void buildsCorrectEndpoint() { + builder.endpoint("https://api.segment.io"); + String expectedURL = "https://api.segment.io/v1/import/"; + assertEquals(expectedURL, builder.endpoint.toString()); + } + + @Test + public void buildsWithValidUploadURL() { + Analytics analytics = builder.setUploadURL("https://example.com/v2/batch/").build(); + assertThat(analytics).isNotNull(); + } + + @Test + public void buildsCorrectURLWithUploadURL() { + builder.setUploadURL("https://example.com/v2/batch/").build(); + String expectedURL = "https://example.com/v2/batch/"; + assertEquals(expectedURL, builder.uploadURL.toString()); + } + + @Test + public void nullHostAndPrefixEndpoint() { + try { + builder.setUploadURL(null); + fail("Should fail for null endpoint"); + } catch (NullPointerException e) { + assertThat(e).hasMessage("endpoint cannot be null or empty."); + } + } + + @Test + public void emptyHostAndPrefixEndpoint() { + try { + builder.setUploadURL(""); + fail("Should fail for empty endpoint"); + } catch (NullPointerException e) { + assertThat(e).hasMessage("endpoint cannot be null or empty."); + } + + try { + builder.setUploadURL(" "); + fail("Should fail for empty endpoint"); + } catch (NullPointerException e) { + assertThat(e).hasMessage("endpoint cannot be null or empty."); + } + } + @Test public void nullThreadFactory() { try { From 1d7758a184dd86b3c27ebe6f1850e4c7fd30c437 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Thu, 7 Jan 2021 01:43:25 -0300 Subject: [PATCH 040/272] configurable retry count on analyticsClient --- .../java/com/segment/analytics/Analytics.java | 11 +++++++++ .../analytics/internal/AnalyticsClient.java | 19 ++++++++++----- .../internal/AnalyticsClientTest.java | 23 +++++++++++-------- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index 51863377..8628f42d 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -109,6 +109,7 @@ public static class Builder { private ExecutorService networkExecutor; private ThreadFactory threadFactory; private int flushQueueSize; + private int maximumFlushAttempts; private long flushIntervalInMillis; private List callbacks; @@ -223,6 +224,15 @@ public Builder flushInterval(long flushInterval, TimeUnit unit) { return this; } + /** Set the interval at which the queue should be flushed. */ + public Builder retries(int maximumRetries) { + if (maximumFlushAttempts < 0) { + throw new IllegalArgumentException("retries must be greater than 0"); + } + this.maximumFlushAttempts = maximumRetries; + return this; + } + /** Set the {@link ExecutorService} on which all HTTP requests will be made. */ public Builder networkExecutor(ExecutorService networkExecutor) { if (networkExecutor == null) { @@ -349,6 +359,7 @@ public void log(String message) { segmentService, flushQueueSize, flushIntervalInMillis, + maximumFlushAttempts, log, threadFactory, networkExecutor, diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index cba72329..f65c1361 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -48,6 +48,7 @@ public class AnalyticsClient { private final BlockingQueue messageQueue; private final SegmentService service; private final int size; + private final int maximumRetries; private final Log log; private final List callbacks; private final ExecutorService networkExecutor; @@ -58,6 +59,7 @@ public static AnalyticsClient create( SegmentService segmentService, int flushQueueSize, long flushIntervalInMillis, + int maximumRetries, Log log, ThreadFactory threadFactory, ExecutorService networkExecutor, @@ -67,6 +69,7 @@ public static AnalyticsClient create( segmentService, flushQueueSize, flushIntervalInMillis, + maximumRetries, log, threadFactory, networkExecutor, @@ -78,6 +81,7 @@ public static AnalyticsClient create( SegmentService service, int maxQueueSize, long flushIntervalInMillis, + int maximumRetries, Log log, ThreadFactory threadFactory, ExecutorService networkExecutor, @@ -85,6 +89,7 @@ public static AnalyticsClient create( this.messageQueue = messageQueue; this.service = service; this.size = maxQueueSize; + this.maximumRetries = maximumRetries; this.log = log; this.callbacks = callbacks; this.looperExecutor = Executors.newSingleThreadExecutor(threadFactory); @@ -170,7 +175,7 @@ public void run() { "Batching %s message(s) into batch %s.", messages.size(), batch.sequence()); - networkExecutor.submit(BatchUploadTask.create(AnalyticsClient.this, batch)); + networkExecutor.submit(BatchUploadTask.create(AnalyticsClient.this, batch, maximumRetries)); messages = new ArrayList<>(); } } @@ -192,15 +197,17 @@ static class BatchUploadTask implements Runnable { private final AnalyticsClient client; private final Backo backo; final Batch batch; + private final int maximumFlushAttempts; - static BatchUploadTask create(AnalyticsClient client, Batch batch) { - return new BatchUploadTask(client, BACKO, batch); + static BatchUploadTask create(AnalyticsClient client, Batch batch, int maximumFlushAttempts) { + return new BatchUploadTask(client, BACKO, batch, maximumFlushAttempts); } - BatchUploadTask(AnalyticsClient client, Backo backo, Batch batch) { + BatchUploadTask(AnalyticsClient client, Backo backo, Batch batch, int maximumRetries) { this.client = client; this.batch = batch; this.backo = backo; + this.maximumFlushAttempts = maximumRetries; } private void notifyCallbacksWithException(Batch batch, Exception exception) { @@ -262,7 +269,7 @@ boolean upload() { @Override public void run() { - for (int attempt = 0; attempt < MAX_ATTEMPTS; attempt++) { + for (int attempt = 0; attempt < maximumFlushAttempts; attempt++) { boolean retry = upload(); if (!retry) return; try { @@ -275,7 +282,7 @@ public void run() { } client.log.print(ERROR, "Could not upload batch %s. Retries exhausted.", batch.sequence()); - notifyCallbacksWithException(batch, new IOException(MAX_ATTEMPTS + " retries exhausted")); + notifyCallbacksWithException(batch, new IOException(maximumFlushAttempts + " retries exhausted")); } private static boolean is5xx(int status) { diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 9540fc9a..017e86df 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -52,6 +52,8 @@ public class AnalyticsClientTest { // Backo instance for testing which trims down the wait times. private static final Backo BACKO = Backo.builder().base(TimeUnit.NANOSECONDS, 1).factor(1).build(); + private int DEFAULT_RETRIES = 10; + Log log = Log.NONE; ThreadFactory threadFactory; @Mock @@ -74,7 +76,7 @@ public void setUp() { // Defers loading the client until tests can initialize all required // dependencies. AnalyticsClient newClient() { - return new AnalyticsClient(messageQueue, segmentService, 50, TimeUnit.HOURS.toMillis(1), log, threadFactory, + return new AnalyticsClient(messageQueue, segmentService, 50, TimeUnit.HOURS.toMillis(1), DEFAULT_RETRIES, log, threadFactory, networkExecutor, Collections.singletonList(callback)); } @@ -228,7 +230,7 @@ public void batchRetriesForNetworkErrors() { .thenReturn(Calls.response(failureResponse)).thenReturn(Calls.response(failureResponse)) .thenReturn(Calls.response(successResponse)); - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); batchUploadTask.run(); // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. @@ -250,7 +252,7 @@ public void batchRetriesForHTTP5xxErrors() { .thenReturn(Calls.response(failResponse)).thenReturn(Calls.response(failResponse)) .thenReturn(Calls.response(successResponse)); - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); batchUploadTask.run(); // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. @@ -271,7 +273,7 @@ public void batchRetriesForHTTP429Errors() { .thenReturn(Calls.response(failResponse)).thenReturn(Calls.response(failResponse)) .thenReturn(Calls.response(successResponse)); - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); batchUploadTask.run(); // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. @@ -289,7 +291,7 @@ public void batchDoesNotRetryForNon5xxAndNon429HTTPErrors() { Response failResponse = Response.error(404, ResponseBody.create(null, "Not Found")); when(segmentService.upload(batch)).thenReturn(Calls.response(failResponse)); - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); batchUploadTask.run(); // Verify we only tried to upload once. @@ -306,7 +308,7 @@ public void batchDoesNotRetryForNonNetworkErrors() { Call networkFailure = Calls.failure(new RuntimeException()); when(segmentService.upload(batch)).thenReturn(networkFailure); - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); batchUploadTask.run(); // Verify we only tried to upload once. @@ -327,15 +329,16 @@ public Call answer(InvocationOnMock invocation) { } }); - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, 10); batchUploadTask.run(); - // 50 == MAX_ATTEMPTS in AnalyticsClient.java - verify(segmentService, times(50)).upload(batch); + // 10 == maximumFlushAttempts + // tries only 10 even though default is 50 in AnalyticsClient.java + verify(segmentService, times(10)).upload(batch); verify(callback).failure(eq(trackMessage), argThat(new ArgumentMatcher() { @Override public boolean matches(IOException exception) { - return exception.getMessage().equals("50 retries exhausted"); + return exception.getMessage().equals("10 retries exhausted"); } })); } From 6d996cc9a5347484245949a05ccd17b862e9b4ae Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Thu, 7 Jan 2021 01:43:38 -0300 Subject: [PATCH 041/272] simpler logic --- .../src/main/java/com/segment/analytics/Analytics.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index 8628f42d..c87e0948 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -285,12 +285,12 @@ public Analytics build() { .registerTypeAdapter(Date.class, new ISO8601DateAdapter()) // .create(); - if (endpoint == null && uploadURL == null) { + if(endpoint == null) { endpoint = DEFAULT_ENDPOINT; - } - if (endpoint == null && uploadURL != null) { - endpoint = uploadURL; + if (uploadURL != null) { + endpoint = uploadURL; + } } if (client == null) { From 1f000df892f2b00c1f12da21ae9620d24d948af7 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Thu, 7 Jan 2021 02:46:24 -0300 Subject: [PATCH 042/272] tests --- .../java/com/segment/analytics/Analytics.java | 8 +- .../analytics/internal/AnalyticsClient.java | 20 +- .../analytics/AnalyticsBuilderTest.java | 17 + .../internal/AnalyticsClientTest.java | 640 ++++++++++-------- 4 files changed, 379 insertions(+), 306 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index c87e0948..13106d88 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -224,10 +224,10 @@ public Builder flushInterval(long flushInterval, TimeUnit unit) { return this; } - /** Set the interval at which the queue should be flushed. */ + /** Set how many retries should happen before getting exhausted */ public Builder retries(int maximumRetries) { - if (maximumFlushAttempts < 0) { - throw new IllegalArgumentException("retries must be greater than 0"); + if (maximumRetries < 1) { + throw new IllegalArgumentException("retries must be at least 1"); } this.maximumFlushAttempts = maximumRetries; return this; @@ -285,7 +285,7 @@ public Analytics build() { .registerTypeAdapter(Date.class, new ISO8601DateAdapter()) // .create(); - if(endpoint == null) { + if (endpoint == null) { endpoint = DEFAULT_ENDPOINT; if (uploadURL != null) { diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index f65c1361..0fa748fa 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -26,8 +26,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; -import java.lang.instrument.Instrumentation; - import retrofit2.Call; import retrofit2.Response; @@ -44,7 +42,6 @@ public class AnalyticsClient { CONTEXT = Collections.unmodifiableMap(context); } - private final BlockingQueue messageQueue; private final SegmentService service; private final int size; @@ -130,9 +127,11 @@ public int messageSizeInBytes(TrackMessage message) { } private Boolean isBackPressured() { - int messageQueueSize = messageQueue.stream() - .map(message -> messageSizeInBytes((TrackMessage) message)) - .reduce(0, (messageASize, messageBSize) -> messageASize + messageBSize); + int messageQueueSize = + messageQueue + .stream() + .map(message -> messageSizeInBytes((TrackMessage) message)) + .reduce(0, (messageASize, messageBSize) -> messageASize + messageBSize); return messageQueueSize >= MESSAGE_QUEUE_MAX_BYTE_SIZE; } @@ -175,7 +174,8 @@ public void run() { "Batching %s message(s) into batch %s.", messages.size(), batch.sequence()); - networkExecutor.submit(BatchUploadTask.create(AnalyticsClient.this, batch, maximumRetries)); + networkExecutor.submit( + BatchUploadTask.create(AnalyticsClient.this, batch, maximumRetries)); messages = new ArrayList<>(); } } @@ -269,7 +269,8 @@ boolean upload() { @Override public void run() { - for (int attempt = 0; attempt < maximumFlushAttempts; attempt++) { + int attempt = 0; + for (; attempt <= maximumFlushAttempts; attempt++) { boolean retry = upload(); if (!retry) return; try { @@ -282,7 +283,8 @@ public void run() { } client.log.print(ERROR, "Could not upload batch %s. Retries exhausted.", batch.sequence()); - notifyCallbacksWithException(batch, new IOException(maximumFlushAttempts + " retries exhausted")); + notifyCallbacksWithException( + batch, new IOException(Integer.toString(attempt) + " retries exhausted")); } private static boolean is5xx(int status) { diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java index b8c6890c..23182d08 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java @@ -95,6 +95,23 @@ public void nullLog() { } } + @Test + public void negativeRetryCount() { + try { + builder.retries(0); + fail("Should fail for retries less than 1"); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage("retries must be at least 1"); + } + + try { + builder.retries(-1); + fail("Should fail for retries less than 1"); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage("retries must be at least 1"); + } + } + @Test public void nullTransformer() { try { diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 017e86df..2f0afe7e 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -49,297 +49,351 @@ @RunWith(BurstJUnit4.class) // public class AnalyticsClientTest { - // Backo instance for testing which trims down the wait times. - private static final Backo BACKO = Backo.builder().base(TimeUnit.NANOSECONDS, 1).factor(1).build(); - - private int DEFAULT_RETRIES = 10; - - Log log = Log.NONE; - ThreadFactory threadFactory; - @Mock - BlockingQueue messageQueue; - @Mock - SegmentService segmentService; - @Mock - ExecutorService networkExecutor; - @Mock - Callback callback; - @Mock - UploadResponse response; - - @Before - public void setUp() { - initMocks(this); - threadFactory = Executors.defaultThreadFactory(); - } - - // Defers loading the client until tests can initialize all required - // dependencies. - AnalyticsClient newClient() { - return new AnalyticsClient(messageQueue, segmentService, 50, TimeUnit.HOURS.toMillis(1), DEFAULT_RETRIES, log, threadFactory, - networkExecutor, Collections.singletonList(callback)); - } - - @Test - public void enqueueAddsToQueue(MessageBuilderTest builder) throws InterruptedException { - AnalyticsClient client = newClient(); - - Message message = builder.get().userId("prateek").build(); - client.enqueue(message); - - verify(messageQueue).put(message); - } - - @Test - public void shutdown() { - AnalyticsClient client = newClient(); - - client.shutdown(); - - verify(messageQueue).clear(); - verify(networkExecutor).shutdown(); - } - - @Test - public void flushInsertsPoison() throws InterruptedException { - AnalyticsClient client = newClient(); - - client.flush(); - - verify(messageQueue).put(FlushMessage.POISON); - } - - /** Wait until the queue is drained. */ - static void wait(Queue queue) { - // noinspection StatementWithEmptyBody - while (queue.size() > 0) { - } - } - - /** - * Verify that a {@link BatchUploadTask} was submitted to the executor, and - * return the {@link BatchUploadTask#batch} it was uploading.. - */ - static Batch captureBatch(ExecutorService executor) { - final ArgumentCaptor runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class); - verify(executor, timeout(1000)).submit(runnableArgumentCaptor.capture()); - final BatchUploadTask task = (BatchUploadTask) runnableArgumentCaptor.getValue(); - return task.batch; - } - - @Test - public void flushSubmitsToExecutor() { - messageQueue = new LinkedBlockingQueue<>(); - AnalyticsClient client = newClient(); - - TrackMessage first = TrackMessage.builder("foo").userId("bar").build(); - TrackMessage second = TrackMessage.builder("qaz").userId("qux").build(); - client.enqueue(first); - client.enqueue(second); - client.flush(); - wait(messageQueue); - - assertThat(captureBatch(networkExecutor).batch()).containsExactly(first, second); - } - - @Test - public void enqueueMaxTriggersFlush() { - messageQueue = new LinkedBlockingQueue<>(); - AnalyticsClient client = newClient(); - - // Enqueuing 51 messages (> 50) should trigger flush. - for (int i = 0; i < 51; i++) { - client.enqueue(TrackMessage.builder("Event " + i).userId("bar").build()); - } - wait(messageQueue); - - // Verify that the executor saw the batch. - assertThat(captureBatch(networkExecutor).batch()).hasSize(50); - } - - private static String createDataSize(int msgSize) { - char[] chars = new char[msgSize]; - Arrays.fill(chars, 'a'); - - return new String(chars); - } - - @Test - public void calculatesMessageByteSize() { - AnalyticsClient client = newClient(); - Map properties = new HashMap(); - - properties.put("dummy-property", createDataSize(1024 * 33)); - - TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); - client.enqueue(bigMessage); - - // can't test for exact size cause other attributes come in play - assertThat(client.messageSizeInBytes(bigMessage)).isGreaterThan(1024 * 33); - } - - @Test - public void dontEnqueueWhenReachesMaxSize() throws InterruptedException { - AnalyticsClient client = newClient(); - Map properties = new HashMap(); - - properties.put("dummy-property", createDataSize(1024 * 33)); - - TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); - client.enqueue(bigMessage); - - // assertThat(client.messageSizeInBytes(bigMessage)).isEqualTo(30); - - Message tinyMessage = TrackMessage.builder("Tinny Event").userId("bar").build(); - client.enqueue(tinyMessage); - wait(messageQueue); - - verify(messageQueue, times(2)).put(any(Message.class)); - } - - @Test - public void enqueueBeforeMaxDoesNotTriggerFlush() { - messageQueue = new LinkedBlockingQueue<>(); - AnalyticsClient client = newClient(); - - // Enqueuing 5 messages (< 50) should not trigger flush. - for (int i = 0; i < 5; i++) { - client.enqueue(TrackMessage.builder("Event " + i).userId("bar").build()); - } - wait(messageQueue); - - // Verify that the executor didn't see anything. - verify(networkExecutor, never()).submit(any(Runnable.class)); - } - - static Batch batchFor(Message message) { - return Batch.create(Collections.emptyMap(), Collections.singletonList(message)); - } - - @Test - public void batchRetriesForNetworkErrors() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - Response successResponse = Response.success(200, response); - Response failureResponse = Response.error(429, ResponseBody.create(null, "")); - - // Throw a network error 3 times. - when(segmentService.upload(batch)).thenReturn(Calls.response(failureResponse)) - .thenReturn(Calls.response(failureResponse)).thenReturn(Calls.response(failureResponse)) - .thenReturn(Calls.response(successResponse)); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); - batchUploadTask.run(); - - // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. - verify(segmentService, times(4)).upload(batch); - verify(callback).success(trackMessage); - } - - @Test - public void batchRetriesForHTTP5xxErrors() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - // Throw a HTTP error 3 times. - - Response successResponse = Response.success(200, response); - Response failResponse = Response.error(500, ResponseBody.create(null, "Server Error")); - when(segmentService.upload(batch)).thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(failResponse)).thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(successResponse)); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); - batchUploadTask.run(); - - // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. - verify(segmentService, times(4)).upload(batch); - verify(callback).success(trackMessage); - } - - @Test - public void batchRetriesForHTTP429Errors() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - // Throw a HTTP error 3 times. - Response successResponse = Response.success(200, response); - Response failResponse = Response.error(429, ResponseBody.create(null, "Rate Limited")); - when(segmentService.upload(batch)).thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(failResponse)).thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(successResponse)); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); - batchUploadTask.run(); - - // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. - verify(segmentService, times(4)).upload(batch); - verify(callback).success(trackMessage); - } - - @Test - public void batchDoesNotRetryForNon5xxAndNon429HTTPErrors() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - // Throw a HTTP error that should not be retried. - Response failResponse = Response.error(404, ResponseBody.create(null, "Not Found")); - when(segmentService.upload(batch)).thenReturn(Calls.response(failResponse)); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); - batchUploadTask.run(); - - // Verify we only tried to upload once. - verify(segmentService).upload(batch); - verify(callback).failure(eq(trackMessage), any(IOException.class)); - } - - @Test - public void batchDoesNotRetryForNonNetworkErrors() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - Call networkFailure = Calls.failure(new RuntimeException()); - when(segmentService.upload(batch)).thenReturn(networkFailure); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); - batchUploadTask.run(); - - // Verify we only tried to upload once. - verify(segmentService).upload(batch); - verify(callback).failure(eq(trackMessage), any(RuntimeException.class)); - } - - @Test - public void givesUpAfterMaxRetries() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - when(segmentService.upload(batch)).thenAnswer(new Answer>() { - public Call answer(InvocationOnMock invocation) { - Response failResponse = Response.error(429, ResponseBody.create(null, "Not Found")); - return Calls.response(failResponse); - } - }); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, 10); - batchUploadTask.run(); - - // 10 == maximumFlushAttempts - // tries only 10 even though default is 50 in AnalyticsClient.java - verify(segmentService, times(10)).upload(batch); - verify(callback).failure(eq(trackMessage), argThat(new ArgumentMatcher() { - @Override - public boolean matches(IOException exception) { - return exception.getMessage().equals("10 retries exhausted"); - } - })); - } + // Backo instance for testing which trims down the wait times. + private static final Backo BACKO = + Backo.builder().base(TimeUnit.NANOSECONDS, 1).factor(1).build(); + + private int DEFAULT_RETRIES = 10; + + Log log = Log.NONE; + ThreadFactory threadFactory; + @Mock BlockingQueue messageQueue; + @Mock SegmentService segmentService; + @Mock ExecutorService networkExecutor; + @Mock Callback callback; + @Mock UploadResponse response; + + @Before + public void setUp() { + initMocks(this); + threadFactory = Executors.defaultThreadFactory(); + } + + // Defers loading the client until tests can initialize all required + // dependencies. + AnalyticsClient newClient() { + return new AnalyticsClient( + messageQueue, + segmentService, + 50, + TimeUnit.HOURS.toMillis(1), + DEFAULT_RETRIES, + log, + threadFactory, + networkExecutor, + Collections.singletonList(callback)); + } + + @Test + public void enqueueAddsToQueue(MessageBuilderTest builder) throws InterruptedException { + AnalyticsClient client = newClient(); + + Message message = builder.get().userId("prateek").build(); + client.enqueue(message); + + verify(messageQueue).put(message); + } + + @Test + public void shutdown() { + AnalyticsClient client = newClient(); + + client.shutdown(); + + verify(messageQueue).clear(); + verify(networkExecutor).shutdown(); + } + + @Test + public void flushInsertsPoison() throws InterruptedException { + AnalyticsClient client = newClient(); + + client.flush(); + + verify(messageQueue).put(FlushMessage.POISON); + } + + /** Wait until the queue is drained. */ + static void wait(Queue queue) { + // noinspection StatementWithEmptyBody + while (queue.size() > 0) {} + } + + /** + * Verify that a {@link BatchUploadTask} was submitted to the executor, and return the {@link + * BatchUploadTask#batch} it was uploading.. + */ + static Batch captureBatch(ExecutorService executor) { + final ArgumentCaptor runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class); + verify(executor, timeout(1000)).submit(runnableArgumentCaptor.capture()); + final BatchUploadTask task = (BatchUploadTask) runnableArgumentCaptor.getValue(); + return task.batch; + } + + @Test + public void flushSubmitsToExecutor() { + messageQueue = new LinkedBlockingQueue<>(); + AnalyticsClient client = newClient(); + + TrackMessage first = TrackMessage.builder("foo").userId("bar").build(); + TrackMessage second = TrackMessage.builder("qaz").userId("qux").build(); + client.enqueue(first); + client.enqueue(second); + client.flush(); + wait(messageQueue); + + assertThat(captureBatch(networkExecutor).batch()).containsExactly(first, second); + } + + @Test + public void enqueueMaxTriggersFlush() { + messageQueue = new LinkedBlockingQueue<>(); + AnalyticsClient client = newClient(); + + // Enqueuing 51 messages (> 50) should trigger flush. + for (int i = 0; i < 51; i++) { + client.enqueue(TrackMessage.builder("Event " + i).userId("bar").build()); + } + wait(messageQueue); + + // Verify that the executor saw the batch. + assertThat(captureBatch(networkExecutor).batch()).hasSize(50); + } + + private static String createDataSize(int msgSize) { + char[] chars = new char[msgSize]; + Arrays.fill(chars, 'a'); + + return new String(chars); + } + + @Test + public void calculatesMessageByteSize() { + AnalyticsClient client = newClient(); + Map properties = new HashMap(); + + properties.put("dummy-property", createDataSize(1024 * 33)); + + TrackMessage bigMessage = + TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); + client.enqueue(bigMessage); + + // can't test for exact size cause other attributes come in play + assertThat(client.messageSizeInBytes(bigMessage)).isGreaterThan(1024 * 33); + } + + @Test + public void dontEnqueueWhenReachesMaxSize() throws InterruptedException { + AnalyticsClient client = newClient(); + Map properties = new HashMap(); + + properties.put("dummy-property", createDataSize(1024 * 33)); + + TrackMessage bigMessage = + TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); + client.enqueue(bigMessage); + + // assertThat(client.messageSizeInBytes(bigMessage)).isEqualTo(30); + + Message tinyMessage = TrackMessage.builder("Tinny Event").userId("bar").build(); + client.enqueue(tinyMessage); + wait(messageQueue); + + verify(messageQueue, times(2)).put(any(Message.class)); + } + + @Test + public void enqueueBeforeMaxDoesNotTriggerFlush() { + messageQueue = new LinkedBlockingQueue<>(); + AnalyticsClient client = newClient(); + + // Enqueuing 5 messages (< 50) should not trigger flush. + for (int i = 0; i < 5; i++) { + client.enqueue(TrackMessage.builder("Event " + i).userId("bar").build()); + } + wait(messageQueue); + + // Verify that the executor didn't see anything. + verify(networkExecutor, never()).submit(any(Runnable.class)); + } + + static Batch batchFor(Message message) { + return Batch.create(Collections.emptyMap(), Collections.singletonList(message)); + } + + @Test + public void batchRetriesForNetworkErrors() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + Response successResponse = Response.success(200, response); + Response failureResponse = Response.error(429, ResponseBody.create(null, "")); + + // Throw a network error 3 times. + when(segmentService.upload(batch)) + .thenReturn(Calls.response(failureResponse)) + .thenReturn(Calls.response(failureResponse)) + .thenReturn(Calls.response(failureResponse)) + .thenReturn(Calls.response(successResponse)); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); + batchUploadTask.run(); + + // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. + verify(segmentService, times(4)).upload(batch); + verify(callback).success(trackMessage); + } + + @Test + public void batchRetriesForHTTP5xxErrors() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + // Throw a HTTP error 3 times. + + Response successResponse = Response.success(200, response); + Response failResponse = + Response.error(500, ResponseBody.create(null, "Server Error")); + when(segmentService.upload(batch)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(successResponse)); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); + batchUploadTask.run(); + + // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. + verify(segmentService, times(4)).upload(batch); + verify(callback).success(trackMessage); + } + + @Test + public void batchRetriesForHTTP429Errors() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + // Throw a HTTP error 3 times. + Response successResponse = Response.success(200, response); + Response failResponse = + Response.error(429, ResponseBody.create(null, "Rate Limited")); + when(segmentService.upload(batch)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(successResponse)); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); + batchUploadTask.run(); + + // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. + verify(segmentService, times(4)).upload(batch); + verify(callback).success(trackMessage); + } + + @Test + public void batchDoesNotRetryForNon5xxAndNon429HTTPErrors() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + // Throw a HTTP error that should not be retried. + Response failResponse = + Response.error(404, ResponseBody.create(null, "Not Found")); + when(segmentService.upload(batch)).thenReturn(Calls.response(failResponse)); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); + batchUploadTask.run(); + + // Verify we only tried to upload once. + verify(segmentService).upload(batch); + verify(callback).failure(eq(trackMessage), any(IOException.class)); + } + + @Test + public void batchDoesNotRetryForNonNetworkErrors() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + Call networkFailure = Calls.failure(new RuntimeException()); + when(segmentService.upload(batch)).thenReturn(networkFailure); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); + batchUploadTask.run(); + + // Verify we only tried to upload once. + verify(segmentService).upload(batch); + verify(callback).failure(eq(trackMessage), any(RuntimeException.class)); + } + + @Test + public void givesUpAfterMaxRetries() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + when(segmentService.upload(batch)) + .thenAnswer( + new Answer>() { + public Call answer(InvocationOnMock invocation) { + Response failResponse = + Response.error(429, ResponseBody.create(null, "Not Found")); + return Calls.response(failResponse); + } + }); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, 10); + batchUploadTask.run(); + + // 10 == maximumFlushAttempts + // tries 11(one normal run + 10 retries) even though default is 50 in AnalyticsClient.java + verify(segmentService, times(11)).upload(batch); + verify(callback) + .failure( + eq(trackMessage), + argThat( + new ArgumentMatcher() { + @Override + public boolean matches(IOException exception) { + return exception.getMessage().equals("11 retries exhausted"); + } + })); + } + + @Test + public void neverRetries() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + when(segmentService.upload(batch)) + .thenAnswer( + new Answer>() { + public Call answer(InvocationOnMock invocation) { + Response failResponse = + Response.error(429, ResponseBody.create(null, "Not Found")); + return Calls.response(failResponse); + } + }); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, 0); + batchUploadTask.run(); + + // runs once but never retries + verify(segmentService, times(1)).upload(batch); + verify(callback) + .failure( + eq(trackMessage), + argThat( + new ArgumentMatcher() { + @Override + public boolean matches(IOException exception) { + return exception.getMessage().equals("1 retries exhausted"); + } + })); + } } From 33010f36cdb75263829ff7f1c9227b209343a59f Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Fri, 15 Jan 2021 22:32:06 -0300 Subject: [PATCH 043/272] defragmenting long if into local variables --- .../java/com/segment/analytics/internal/AnalyticsClient.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 588d1e91..4fadc23c 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -209,7 +209,10 @@ public void run() { messages.add(message); } - if (!messages.isEmpty() && (messages.size() >= size || message == FlushMessage.POISON || message == StopMessage.STOP)) { + Boolean isBlockingSignal = message == FlushMessage.POISON || message == StopMessage.STOP + Boolean isOverflow = messages.size() >= size + + if (!messages.isEmpty() && (isOverflow || isBlockingSignal)) { Batch batch = Batch.create(CONTEXT, messages); log.print( VERBOSE, From 5765296bce504afcbdd169f191a390933f7f2b1d Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Fri, 15 Jan 2021 22:41:54 -0300 Subject: [PATCH 044/272] spotless fixes --- .../analytics/internal/AnalyticsClient.java | 116 ++-- .../internal/AnalyticsClientTest.java | 628 +++++++++--------- 2 files changed, 383 insertions(+), 361 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 4fadc23c..9c4b021a 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -26,11 +26,9 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; -import java.lang.instrument.Instrumentation; - +import java.util.concurrent.atomic.AtomicBoolean; import retrofit2.Call; import retrofit2.Response; -import java.util.concurrent.atomic.AtomicBoolean; public class AnalyticsClient { private static final Map CONTEXT; @@ -45,7 +43,6 @@ public class AnalyticsClient { CONTEXT = Collections.unmodifiableMap(context); } - private final BlockingQueue messageQueue; private final SegmentService service; private final int size; @@ -57,35 +54,35 @@ public class AnalyticsClient { private final AtomicBoolean isShutDown; public static AnalyticsClient create( - SegmentService segmentService, - int flushQueueSize, - long flushIntervalInMillis, - Log log, - ThreadFactory threadFactory, - ExecutorService networkExecutor, - List callbacks) { + SegmentService segmentService, + int flushQueueSize, + long flushIntervalInMillis, + Log log, + ThreadFactory threadFactory, + ExecutorService networkExecutor, + List callbacks) { return new AnalyticsClient( - new LinkedBlockingQueue(), - segmentService, - flushQueueSize, - flushIntervalInMillis, - log, - threadFactory, - networkExecutor, - callbacks, - new AtomicBoolean(false)); + new LinkedBlockingQueue(), + segmentService, + flushQueueSize, + flushIntervalInMillis, + log, + threadFactory, + networkExecutor, + callbacks, + new AtomicBoolean(false)); } AnalyticsClient( - BlockingQueue messageQueue, - SegmentService service, - int maxQueueSize, - long flushIntervalInMillis, - Log log, - ThreadFactory threadFactory, - ExecutorService networkExecutor, - List callbacks, - AtomicBoolean isShutDown) { + BlockingQueue messageQueue, + SegmentService service, + int maxQueueSize, + long flushIntervalInMillis, + Log log, + ThreadFactory threadFactory, + ExecutorService networkExecutor, + List callbacks, + AtomicBoolean isShutDown) { this.messageQueue = messageQueue; this.service = service; this.size = maxQueueSize; @@ -99,15 +96,15 @@ public static AnalyticsClient create( flushScheduler = Executors.newScheduledThreadPool(1, threadFactory); flushScheduler.scheduleAtFixedRate( - new Runnable() { - @Override - public void run() { - flush(); - } - }, - flushIntervalInMillis, - flushIntervalInMillis, - TimeUnit.MILLISECONDS); + new Runnable() { + @Override + public void run() { + flush(); + } + }, + flushIntervalInMillis, + flushIntervalInMillis, + TimeUnit.MILLISECONDS); } public void enqueue(Message message) { @@ -136,9 +133,11 @@ public int messageSizeInBytes(TrackMessage message) { } private Boolean isBackPressured() { - int messageQueueSize = messageQueue.stream() - .map(message -> messageSizeInBytes((TrackMessage) message)) - .reduce(0, (messageASize, messageBSize) -> messageASize + messageBSize); + int messageQueueSize = + messageQueue + .stream() + .map(message -> messageSizeInBytes((TrackMessage) message)) + .reduce(0, (messageASize, messageBSize) -> messageASize + messageBSize); return messageQueueSize >= MESSAGE_QUEUE_MAX_BYTE_SIZE; } @@ -162,7 +161,8 @@ public void shutdown() { shutdownAndWait(looperExecutor, "looper"); shutdownAndWait(networkExecutor, "network"); - log.print(VERBOSE, "Analytics client shut down in %s ms", (System.currentTimeMillis() - start)); + log.print( + VERBOSE, "Analytics client shut down in %s ms", (System.currentTimeMillis() - start)); } } @@ -171,9 +171,11 @@ public void shutdownAndWait(ExecutorService executor, String name) { executor.shutdown(); final boolean executorTerminated = executor.awaitTermination(1, TimeUnit.SECONDS); - log.print(VERBOSE, "%s executor %s.", - name, - executorTerminated ? "terminated normally" : "timed out"); + log.print( + VERBOSE, + "%s executor %s.", + name, + executorTerminated ? "terminated normally" : "timed out"); } catch (InterruptedException e) { log.print(ERROR, e, "Interrupted while stopping %s executor.", name); Thread.currentThread().interrupt(); @@ -209,16 +211,16 @@ public void run() { messages.add(message); } - Boolean isBlockingSignal = message == FlushMessage.POISON || message == StopMessage.STOP - Boolean isOverflow = messages.size() >= size + Boolean isBlockingSignal = message == FlushMessage.POISON || message == StopMessage.STOP; + Boolean isOverflow = messages.size() >= size; if (!messages.isEmpty() && (isOverflow || isBlockingSignal)) { Batch batch = Batch.create(CONTEXT, messages); log.print( - VERBOSE, - "Batching %s message(s) into batch %s.", - messages.size(), - batch.sequence()); + VERBOSE, + "Batching %s message(s) into batch %s.", + messages.size(), + batch.sequence()); networkExecutor.submit(BatchUploadTask.create(AnalyticsClient.this, batch)); messages = new ArrayList<>(); } @@ -233,11 +235,11 @@ public void run() { static class BatchUploadTask implements Runnable { private static final Backo BACKO = - Backo.builder() // - .base(TimeUnit.SECONDS, 15) // - .cap(TimeUnit.HOURS, 1) // - .jitter(1) // - .build(); + Backo.builder() // + .base(TimeUnit.SECONDS, 15) // + .cap(TimeUnit.HOURS, 1) // + .jitter(1) // + .build(); private static final int MAX_ATTEMPTS = 50; // Max 50 hours ~ 2 days private final AnalyticsClient client; @@ -320,7 +322,7 @@ public void run() { backo.sleep(attempt); } catch (InterruptedException e) { client.log.print( - DEBUG, "Thread interrupted while backing off for batch %s.", batch.sequence()); + DEBUG, "Thread interrupted while backing off for batch %s.", batch.sequence()); return; } } diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 4cd430fc..b84bb9c7 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -39,11 +39,8 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; -import okhttp3.ResponseBody; import java.util.concurrent.atomic.AtomicBoolean; - -import org.hamcrest.Description; -import org.hamcrest.TypeSafeMatcher; +import okhttp3.ResponseBody; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -58,303 +55,325 @@ @RunWith(BurstJUnit4.class) // public class AnalyticsClientTest { - // Backo instance for testing which trims down the wait times. - private static final Backo BACKO = Backo.builder().base(TimeUnit.NANOSECONDS, 1).factor(1).build(); - - Log log = Log.NONE; - ThreadFactory threadFactory; - BlockingQueue messageQueue; - @Mock - SegmentService segmentService; - @Mock - ExecutorService networkExecutor; - @Mock - Callback callback; - @Mock - UploadResponse response; - - AtomicBoolean isShutDown; - - @Before - public void setUp() { - initMocks(this); - - isShutDown = new AtomicBoolean(false); + // Backo instance for testing which trims down the wait times. + private static final Backo BACKO = + Backo.builder().base(TimeUnit.NANOSECONDS, 1).factor(1).build(); + + Log log = Log.NONE; + ThreadFactory threadFactory; + BlockingQueue messageQueue; + @Mock SegmentService segmentService; + @Mock ExecutorService networkExecutor; + @Mock Callback callback; + @Mock UploadResponse response; + + AtomicBoolean isShutDown; + + @Before + public void setUp() { + initMocks(this); + + isShutDown = new AtomicBoolean(false); messageQueue = spy(new LinkedBlockingQueue()); - threadFactory = Executors.defaultThreadFactory(); - } - - // Defers loading the client until tests can initialize all required - // dependencies. - AnalyticsClient newClient() { - return new AnalyticsClient(messageQueue, segmentService, 50, TimeUnit.HOURS.toMillis(1), log, threadFactory, - networkExecutor, Collections.singletonList(callback), isShutDown); - } - - @Test - public void enqueueAddsToQueue(MessageBuilderTest builder) throws InterruptedException { - AnalyticsClient client = newClient(); - - Message message = builder.get().userId("prateek").build(); - client.enqueue(message); - - verify(messageQueue).put(message); - } - - @Test - public void shutdown() throws InterruptedException { - messageQueue = new LinkedBlockingQueue<>(); - AnalyticsClient client = newClient(); - - client.shutdown(); - - verify(networkExecutor).shutdown(); - verify(networkExecutor).awaitTermination(1, TimeUnit.SECONDS); - } - - @Test - public void flushInsertsPoison() throws InterruptedException { - AnalyticsClient client = newClient(); - - client.flush(); - - verify(messageQueue).put(FlushMessage.POISON); - } - - /** Wait until the queue is drained. */ - static void wait(Queue queue) { - // noinspection StatementWithEmptyBody - while (queue.size() > 0) { - } - } - - /** - * Verify that a {@link BatchUploadTask} was submitted to the executor, and - * return the {@link BatchUploadTask#batch} it was uploading.. - */ - static Batch captureBatch(ExecutorService executor) { - final ArgumentCaptor runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class); - verify(executor, timeout(1000)).submit(runnableArgumentCaptor.capture()); - final BatchUploadTask task = (BatchUploadTask) runnableArgumentCaptor.getValue(); - return task.batch; - } - - @Test - public void flushSubmitsToExecutor() { - messageQueue = new LinkedBlockingQueue<>(); - AnalyticsClient client = newClient(); - - TrackMessage first = TrackMessage.builder("foo").userId("bar").build(); - TrackMessage second = TrackMessage.builder("qaz").userId("qux").build(); - client.enqueue(first); - client.enqueue(second); - client.flush(); - wait(messageQueue); - - assertThat(captureBatch(networkExecutor).batch()).containsExactly(first, second); - } - - @Test - public void enqueueMaxTriggersFlush() { - messageQueue = new LinkedBlockingQueue<>(); - AnalyticsClient client = newClient(); - - // Enqueuing 51 messages (> 50) should trigger flush. - for (int i = 0; i < 51; i++) { - client.enqueue(TrackMessage.builder("Event " + i).userId("bar").build()); - } - wait(messageQueue); - - // Verify that the executor saw the batch. - assertThat(captureBatch(networkExecutor).batch()).hasSize(50); - } - - private static String createDataSize(int msgSize) { - char[] chars = new char[msgSize]; - Arrays.fill(chars, 'a'); - - return new String(chars); - } - - @Test - public void calculatesMessageByteSize() { - AnalyticsClient client = newClient(); - Map properties = new HashMap(); - - properties.put("dummy-property", createDataSize(1024 * 33)); - - TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); - client.enqueue(bigMessage); - - // can't test for exact size cause other attributes come in play - assertThat(client.messageSizeInBytes(bigMessage)).isGreaterThan(1024 * 33); - } - - @Test - public void dontEnqueueWhenReachesMaxSize() throws InterruptedException { - AnalyticsClient client = newClient(); - Map properties = new HashMap(); - - properties.put("dummy-property", createDataSize(1024 * 33)); - - TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); - client.enqueue(bigMessage); - - // assertThat(client.messageSizeInBytes(bigMessage)).isEqualTo(30); - - Message tinyMessage = TrackMessage.builder("Tinny Event").userId("bar").build(); - client.enqueue(tinyMessage); - wait(messageQueue); - - verify(messageQueue, times(2)).put(any(Message.class)); - } - - @Test - public void enqueueBeforeMaxDoesNotTriggerFlush() { - messageQueue = new LinkedBlockingQueue<>(); - AnalyticsClient client = newClient(); - - // Enqueuing 5 messages (< 50) should not trigger flush. - for (int i = 0; i < 5; i++) { - client.enqueue(TrackMessage.builder("Event " + i).userId("bar").build()); - } - wait(messageQueue); - - // Verify that the executor didn't see anything. - verify(networkExecutor, never()).submit(any(Runnable.class)); - } - - static Batch batchFor(Message message) { - return Batch.create(Collections.emptyMap(), Collections.singletonList(message)); - } - - @Test - public void batchRetriesForNetworkErrors() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - Response successResponse = Response.success(200, response); - Response failureResponse = Response.error(429, ResponseBody.create(null, "")); - - // Throw a network error 3 times. - when(segmentService.upload(batch)).thenReturn(Calls.response(failureResponse)) - .thenReturn(Calls.response(failureResponse)).thenReturn(Calls.response(failureResponse)) - .thenReturn(Calls.response(successResponse)); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); - batchUploadTask.run(); - - // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. - verify(segmentService, times(4)).upload(batch); - verify(callback).success(trackMessage); - } - - @Test - public void batchRetriesForHTTP5xxErrors() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - // Throw a HTTP error 3 times. - - Response successResponse = Response.success(200, response); - Response failResponse = Response.error(500, ResponseBody.create(null, "Server Error")); - when(segmentService.upload(batch)).thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(failResponse)).thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(successResponse)); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); - batchUploadTask.run(); - - // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. - verify(segmentService, times(4)).upload(batch); - verify(callback).success(trackMessage); - } - - @Test - public void batchRetriesForHTTP429Errors() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - // Throw a HTTP error 3 times. - Response successResponse = Response.success(200, response); - Response failResponse = Response.error(429, ResponseBody.create(null, "Rate Limited")); - when(segmentService.upload(batch)).thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(failResponse)).thenReturn(Calls.response(failResponse)) - .thenReturn(Calls.response(successResponse)); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); - batchUploadTask.run(); - - // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. - verify(segmentService, times(4)).upload(batch); - verify(callback).success(trackMessage); - } - - @Test - public void batchDoesNotRetryForNon5xxAndNon429HTTPErrors() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - // Throw a HTTP error that should not be retried. - Response failResponse = Response.error(404, ResponseBody.create(null, "Not Found")); - when(segmentService.upload(batch)).thenReturn(Calls.response(failResponse)); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); - batchUploadTask.run(); - - // Verify we only tried to upload once. - verify(segmentService).upload(batch); - verify(callback).failure(eq(trackMessage), any(IOException.class)); - } - - @Test - public void batchDoesNotRetryForNonNetworkErrors() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - Call networkFailure = Calls.failure(new RuntimeException()); - when(segmentService.upload(batch)).thenReturn(networkFailure); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); - batchUploadTask.run(); - - // Verify we only tried to upload once. - verify(segmentService).upload(batch); - verify(callback).failure(eq(trackMessage), any(RuntimeException.class)); - } - - @Test - public void givesUpAfterMaxRetries() { - AnalyticsClient client = newClient(); - TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); - Batch batch = batchFor(trackMessage); - - when(segmentService.upload(batch)).thenAnswer(new Answer>() { - public Call answer(InvocationOnMock invocation) { - Response failResponse = Response.error(429, ResponseBody.create(null, "Not Found")); - return Calls.response(failResponse); - } - }); - - BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); - batchUploadTask.run(); - - // 50 == MAX_ATTEMPTS in AnalyticsClient.java - verify(segmentService, times(50)).upload(batch); - verify(callback).failure(eq(trackMessage), argThat(new ArgumentMatcher() { - @Override - public boolean matches(IOException exception) { - return exception.getMessage().equals("50 retries exhausted"); - } - })); - } - - @Test + threadFactory = Executors.defaultThreadFactory(); + } + + // Defers loading the client until tests can initialize all required + // dependencies. + AnalyticsClient newClient() { + return new AnalyticsClient( + messageQueue, + segmentService, + 50, + TimeUnit.HOURS.toMillis(1), + log, + threadFactory, + networkExecutor, + Collections.singletonList(callback), + isShutDown); + } + + @Test + public void enqueueAddsToQueue(MessageBuilderTest builder) throws InterruptedException { + AnalyticsClient client = newClient(); + + Message message = builder.get().userId("prateek").build(); + client.enqueue(message); + + verify(messageQueue).put(message); + } + + @Test + public void shutdown() throws InterruptedException { + messageQueue = new LinkedBlockingQueue<>(); + AnalyticsClient client = newClient(); + + client.shutdown(); + + verify(networkExecutor).shutdown(); + verify(networkExecutor).awaitTermination(1, TimeUnit.SECONDS); + } + + @Test + public void flushInsertsPoison() throws InterruptedException { + AnalyticsClient client = newClient(); + + client.flush(); + + verify(messageQueue).put(FlushMessage.POISON); + } + + /** Wait until the queue is drained. */ + static void wait(Queue queue) { + // noinspection StatementWithEmptyBody + while (queue.size() > 0) {} + } + + /** + * Verify that a {@link BatchUploadTask} was submitted to the executor, and return the {@link + * BatchUploadTask#batch} it was uploading.. + */ + static Batch captureBatch(ExecutorService executor) { + final ArgumentCaptor runnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class); + verify(executor, timeout(1000)).submit(runnableArgumentCaptor.capture()); + final BatchUploadTask task = (BatchUploadTask) runnableArgumentCaptor.getValue(); + return task.batch; + } + + @Test + public void flushSubmitsToExecutor() { + messageQueue = new LinkedBlockingQueue<>(); + AnalyticsClient client = newClient(); + + TrackMessage first = TrackMessage.builder("foo").userId("bar").build(); + TrackMessage second = TrackMessage.builder("qaz").userId("qux").build(); + client.enqueue(first); + client.enqueue(second); + client.flush(); + wait(messageQueue); + + assertThat(captureBatch(networkExecutor).batch()).containsExactly(first, second); + } + + @Test + public void enqueueMaxTriggersFlush() { + messageQueue = new LinkedBlockingQueue<>(); + AnalyticsClient client = newClient(); + + // Enqueuing 51 messages (> 50) should trigger flush. + for (int i = 0; i < 51; i++) { + client.enqueue(TrackMessage.builder("Event " + i).userId("bar").build()); + } + wait(messageQueue); + + // Verify that the executor saw the batch. + assertThat(captureBatch(networkExecutor).batch()).hasSize(50); + } + + private static String createDataSize(int msgSize) { + char[] chars = new char[msgSize]; + Arrays.fill(chars, 'a'); + + return new String(chars); + } + + @Test + public void calculatesMessageByteSize() { + AnalyticsClient client = newClient(); + Map properties = new HashMap(); + + properties.put("dummy-property", createDataSize(1024 * 33)); + + TrackMessage bigMessage = + TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); + client.enqueue(bigMessage); + + // can't test for exact size cause other attributes come in play + assertThat(client.messageSizeInBytes(bigMessage)).isGreaterThan(1024 * 33); + } + + @Test + public void dontEnqueueWhenReachesMaxSize() throws InterruptedException { + AnalyticsClient client = newClient(); + Map properties = new HashMap(); + + properties.put("dummy-property", createDataSize(1024 * 33)); + + TrackMessage bigMessage = + TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); + client.enqueue(bigMessage); + + // assertThat(client.messageSizeInBytes(bigMessage)).isEqualTo(30); + + Message tinyMessage = TrackMessage.builder("Tinny Event").userId("bar").build(); + client.enqueue(tinyMessage); + wait(messageQueue); + + verify(messageQueue, times(2)).put(any(Message.class)); + } + + @Test + public void enqueueBeforeMaxDoesNotTriggerFlush() { + messageQueue = new LinkedBlockingQueue<>(); + AnalyticsClient client = newClient(); + + // Enqueuing 5 messages (< 50) should not trigger flush. + for (int i = 0; i < 5; i++) { + client.enqueue(TrackMessage.builder("Event " + i).userId("bar").build()); + } + wait(messageQueue); + + // Verify that the executor didn't see anything. + verify(networkExecutor, never()).submit(any(Runnable.class)); + } + + static Batch batchFor(Message message) { + return Batch.create(Collections.emptyMap(), Collections.singletonList(message)); + } + + @Test + public void batchRetriesForNetworkErrors() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + Response successResponse = Response.success(200, response); + Response failureResponse = Response.error(429, ResponseBody.create(null, "")); + + // Throw a network error 3 times. + when(segmentService.upload(batch)) + .thenReturn(Calls.response(failureResponse)) + .thenReturn(Calls.response(failureResponse)) + .thenReturn(Calls.response(failureResponse)) + .thenReturn(Calls.response(successResponse)); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + batchUploadTask.run(); + + // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. + verify(segmentService, times(4)).upload(batch); + verify(callback).success(trackMessage); + } + + @Test + public void batchRetriesForHTTP5xxErrors() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + // Throw a HTTP error 3 times. + + Response successResponse = Response.success(200, response); + Response failResponse = + Response.error(500, ResponseBody.create(null, "Server Error")); + when(segmentService.upload(batch)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(successResponse)); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + batchUploadTask.run(); + + // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. + verify(segmentService, times(4)).upload(batch); + verify(callback).success(trackMessage); + } + + @Test + public void batchRetriesForHTTP429Errors() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + // Throw a HTTP error 3 times. + Response successResponse = Response.success(200, response); + Response failResponse = + Response.error(429, ResponseBody.create(null, "Rate Limited")); + when(segmentService.upload(batch)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(failResponse)) + .thenReturn(Calls.response(successResponse)); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + batchUploadTask.run(); + + // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. + verify(segmentService, times(4)).upload(batch); + verify(callback).success(trackMessage); + } + + @Test + public void batchDoesNotRetryForNon5xxAndNon429HTTPErrors() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + // Throw a HTTP error that should not be retried. + Response failResponse = + Response.error(404, ResponseBody.create(null, "Not Found")); + when(segmentService.upload(batch)).thenReturn(Calls.response(failResponse)); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + batchUploadTask.run(); + + // Verify we only tried to upload once. + verify(segmentService).upload(batch); + verify(callback).failure(eq(trackMessage), any(IOException.class)); + } + + @Test + public void batchDoesNotRetryForNonNetworkErrors() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + Call networkFailure = Calls.failure(new RuntimeException()); + when(segmentService.upload(batch)).thenReturn(networkFailure); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + batchUploadTask.run(); + + // Verify we only tried to upload once. + verify(segmentService).upload(batch); + verify(callback).failure(eq(trackMessage), any(RuntimeException.class)); + } + + @Test + public void givesUpAfterMaxRetries() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + when(segmentService.upload(batch)) + .thenAnswer( + new Answer>() { + public Call answer(InvocationOnMock invocation) { + Response failResponse = + Response.error(429, ResponseBody.create(null, "Not Found")); + return Calls.response(failResponse); + } + }); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch); + batchUploadTask.run(); + + // 50 == MAX_ATTEMPTS in AnalyticsClient.java + verify(segmentService, times(50)).upload(batch); + verify(callback) + .failure( + eq(trackMessage), + argThat( + new ArgumentMatcher() { + @Override + public boolean matches(IOException exception) { + return exception.getMessage().equals("50 retries exhausted"); + } + })); + } + + @Test public void flushWhenNotShutDown() throws InterruptedException { AnalyticsClient client = newClient(); @@ -374,10 +393,9 @@ public void flushWhenShutDown() throws InterruptedException { @Test public void enqueueWithRegularMessageWhenNotShutdown(MessageBuilderTest builder) - throws InterruptedException { + throws InterruptedException { AnalyticsClient client = newClient(); - final Message message = builder.get().userId("foo").build(); client.enqueue(message); @@ -385,7 +403,8 @@ public void enqueueWithRegularMessageWhenNotShutdown(MessageBuilderTest builder) } @Test - public void enqueueWithRegularMessageWhenShutdown(MessageBuilderTest builder) throws InterruptedException { + public void enqueueWithRegularMessageWhenShutdown(MessageBuilderTest builder) + throws InterruptedException { AnalyticsClient client = newClient(); isShutDown.set(true); @@ -427,7 +446,8 @@ public void shutdownWithNoMessageInTheQueue() throws InterruptedException { } @Test - public void shutdownWithMessagesInTheQueue(MessageBuilderTest builder) throws InterruptedException { + public void shutdownWithMessagesInTheQueue(MessageBuilderTest builder) + throws InterruptedException { AnalyticsClient client = newClient(); client.enqueue(builder.get().userId("foo").build()); From 8965c26f3478f31e952f8320f9129ceb4ed0f81e Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Fri, 15 Jan 2021 23:31:58 -0300 Subject: [PATCH 045/272] fixing toString of stopMessage --- .../java/com/segment/analytics/internal/StopMessage.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java b/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java index 5907416a..39dea83b 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java +++ b/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java @@ -1,11 +1,10 @@ package com.segment.analytics.internal; import com.segment.analytics.messages.Message; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.Date; import java.util.Map; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; class StopMessage implements Message { static final StopMessage STOP = new StopMessage(); @@ -56,6 +55,6 @@ public Map integrations() { @Override public String toString() { - return "FlushMessage{}"; + return "StopMessage{}"; } } From 70581541bfa0b6d541bc4a2118079c5364ec2080 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Fri, 15 Jan 2021 23:48:22 -0300 Subject: [PATCH 046/272] fixing tests --- .../analytics/internal/AnalyticsClientTest.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index b84bb9c7..fd0640a9 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -170,7 +170,7 @@ public void enqueueMaxTriggersFlush() { assertThat(captureBatch(networkExecutor).batch()).hasSize(50); } - private static String createDataSize(int msgSize) { + private static String generateMassDataOfSize(int msgSize) { char[] chars = new char[msgSize]; Arrays.fill(chars, 'a'); @@ -182,7 +182,7 @@ public void calculatesMessageByteSize() { AnalyticsClient client = newClient(); Map properties = new HashMap(); - properties.put("dummy-property", createDataSize(1024 * 33)); + properties.put("dummy-property", generateMassDataOfSize(1024 * 33)); TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); @@ -197,19 +197,17 @@ public void dontEnqueueWhenReachesMaxSize() throws InterruptedException { AnalyticsClient client = newClient(); Map properties = new HashMap(); - properties.put("dummy-property", createDataSize(1024 * 33)); + properties.put("dummy-property", generateMassDataOfSize(1024 * 33)); TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); client.enqueue(bigMessage); - // assertThat(client.messageSizeInBytes(bigMessage)).isEqualTo(30); - Message tinyMessage = TrackMessage.builder("Tinny Event").userId("bar").build(); client.enqueue(tinyMessage); wait(messageQueue); - verify(messageQueue, times(2)).put(any(Message.class)); + verify(messageQueue, times(1)).put(any(Message.class)); } @Test From b5792dcef0e16fd651be4b7ff9dc62dfa6b8f974 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Tue, 19 Jan 2021 01:43:24 -0300 Subject: [PATCH 047/272] tweaking code to calculate queue size in bytes --- .../analytics/internal/AnalyticsClient.java | 43 +++++++++---------- .../internal/AnalyticsClientTest.java | 7 ++- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 9c4b021a..4a069918 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -11,7 +11,6 @@ import com.segment.analytics.http.UploadResponse; import com.segment.analytics.messages.Batch; import com.segment.analytics.messages.Message; -import com.segment.analytics.messages.TrackMessage; import com.segment.backo.Backo; import java.io.IOException; import java.util.ArrayList; @@ -107,6 +106,22 @@ public void run() { TimeUnit.MILLISECONDS); } + public int messageSizeInBytes(Message message) { + Gson gson = new Gson(); + String stringifiedMessage = gson.toJson(message); + return stringifiedMessage.length(); + } + + private Boolean isBackPressured(List messages) { + int messageQueueSize = 0; + + for (Message message : messages) { + messageQueueSize += messageSizeInBytes(message); + } + + return messageQueueSize >= MESSAGE_QUEUE_MAX_BYTE_SIZE; + } + public void enqueue(Message message) { if (message != StopMessage.STOP && isShutDown.get()) { log.print(ERROR, "Attempt to enqueue a message when shutdown has been called %s.", message); @@ -114,11 +129,6 @@ public void enqueue(Message message) { } try { - if (isBackPressured()) { - log.print(VERBOSE, "Maximum storage size have been hit. Dropping messages"); - return; - } - messageQueue.put(message); } catch (InterruptedException e) { log.print(ERROR, e, "Interrupted while adding message %s.", message); @@ -126,22 +136,6 @@ public void enqueue(Message message) { } } - public int messageSizeInBytes(TrackMessage message) { - Gson gson = new Gson(); - String stringifiedMessage = gson.toJson(message); - return stringifiedMessage.length(); - } - - private Boolean isBackPressured() { - int messageQueueSize = - messageQueue - .stream() - .map(message -> messageSizeInBytes((TrackMessage) message)) - .reduce(0, (messageASize, messageBSize) -> messageASize + messageBSize); - - return messageQueueSize >= MESSAGE_QUEUE_MAX_BYTE_SIZE; - } - public void flush() { if (!isShutDown.get()) { enqueue(FlushMessage.POISON); @@ -214,6 +208,11 @@ public void run() { Boolean isBlockingSignal = message == FlushMessage.POISON || message == StopMessage.STOP; Boolean isOverflow = messages.size() >= size; + if (isBackPressured(messages)) { + log.print(VERBOSE, "Maximum storage size has been hit. Flushing"); + isOverflow = true; + } + if (!messages.isEmpty() && (isOverflow || isBlockingSignal)) { Batch batch = Batch.create(CONTEXT, messages); log.print( diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index fd0640a9..a363a0e0 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -60,6 +60,7 @@ public class AnalyticsClientTest { Backo.builder().base(TimeUnit.NANOSECONDS, 1).factor(1).build(); Log log = Log.NONE; + ThreadFactory threadFactory; BlockingQueue messageQueue; @Mock SegmentService segmentService; @@ -178,7 +179,7 @@ private static String generateMassDataOfSize(int msgSize) { } @Test - public void calculatesMessageByteSize() { + public void shouldBeAbleToCalculateMessageSize() { AnalyticsClient client = newClient(); Map properties = new HashMap(); @@ -203,11 +204,9 @@ public void dontEnqueueWhenReachesMaxSize() throws InterruptedException { TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); client.enqueue(bigMessage); - Message tinyMessage = TrackMessage.builder("Tinny Event").userId("bar").build(); - client.enqueue(tinyMessage); wait(messageQueue); - verify(messageQueue, times(1)).put(any(Message.class)); + assertThat(captureBatch(networkExecutor).batch()).hasSize(1); } @Test From 2cb8c329285f7adaa7bd9ccc5c704796561041eb Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Wed, 20 Jan 2021 18:40:54 -0300 Subject: [PATCH 048/272] renaming variable to maxRetries to keep consistent --- .../segment/analytics/internal/AnalyticsClient.java | 12 ++++++------ .../analytics/internal/AnalyticsClientTest.java | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 7939811a..a4b85e12 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -250,17 +250,17 @@ static class BatchUploadTask implements Runnable { private final AnalyticsClient client; private final Backo backo; final Batch batch; - private final int maximumFlushAttempts; + private final int maxRetries; - static BatchUploadTask create(AnalyticsClient client, Batch batch, int maximumFlushAttempts) { - return new BatchUploadTask(client, BACKO, batch, maximumFlushAttempts); + static BatchUploadTask create(AnalyticsClient client, Batch batch, int maxRetries) { + return new BatchUploadTask(client, BACKO, batch, maxRetries); } - BatchUploadTask(AnalyticsClient client, Backo backo, Batch batch, int maximumRetries) { + BatchUploadTask(AnalyticsClient client, Backo backo, Batch batch, int maxRetries) { this.client = client; this.batch = batch; this.backo = backo; - this.maximumFlushAttempts = maximumRetries; + this.maxRetries = maxRetries; } private void notifyCallbacksWithException(Batch batch, Exception exception) { @@ -323,7 +323,7 @@ boolean upload() { @Override public void run() { int attempt = 0; - for (; attempt <= maximumFlushAttempts; attempt++) { + for (; attempt <= maxRetries; attempt++) { boolean retry = upload(); if (!retry) return; try { diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index ec62f125..93053a48 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -358,7 +358,7 @@ public Call answer(InvocationOnMock invocation) { BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, 10); batchUploadTask.run(); - // DEFAULT_RETRIES == maximumFlushAttempts + // DEFAULT_RETRIES == maxRetries // tries 11(one normal run + 10 retries) even though default is 50 in AnalyticsClient.java verify(segmentService, times(11)).upload(batch); verify(callback) From 230cb2ddffbec30d4763c54ab580acabd426d7e6 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Sun, 24 Jan 2021 21:17:25 -0300 Subject: [PATCH 049/272] spotless --- .../java/com/segment/analytics/internal/AnalyticsClientTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 7d6607ed..93053a48 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -209,7 +209,6 @@ public void dontEnqueueWhenReachesMaxSize() throws InterruptedException { wait(messageQueue); assertThat(captureBatch(networkExecutor).batch()).hasSize(1); - } @Test From 6375e3dfe4e4bf1a65fb3c71be0d2126e582f5df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Feb 2021 06:18:04 +0000 Subject: [PATCH 050/272] Bump logging-interceptor from 4.0.1 to 4.9.1 Bumps [logging-interceptor](https://github.com/square/okhttp) from 4.0.1 to 4.9.1. - [Release notes](https://github.com/square/okhttp/releases) - [Changelog](https://github.com/square/okhttp/blob/master/CHANGELOG.md) - [Commits](https://github.com/square/okhttp/compare/parent-4.0.1...parent-4.9.1) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e2e8fe5d..243c51fd 100644 --- a/pom.xml +++ b/pom.xml @@ -36,7 +36,7 @@ 3.0.1 2.8.6 4.0.1 - 4.0.1 + 4.9.1 26.0-jre 1.0.0 1.2.5.RELEASE From c76b1aad9bb7041086003798d1b8880a2bbbd288 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Feb 2021 05:57:44 +0000 Subject: [PATCH 051/272] Bump spotless-maven-plugin from 1.14.0 to 2.8.1 Bumps [spotless-maven-plugin](https://github.com/diffplug/project) from 1.14.0 to 2.8.1. - [Release notes](https://github.com/diffplug/project/releases) - [Commits](https://github.com/diffplug/project/commits) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e2e8fe5d..5e3fc8f9 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ UTF-8 8 1.2.60 - 1.14.0 + 2.8.1 2.9.0 1.7.1 From eac0b03a220790fc30d52ebbf804434be8aeab0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Feb 2021 18:44:23 +0000 Subject: [PATCH 052/272] Bump junit from 4.13.1 to 4.13.2 Bumps [junit](https://github.com/junit-team/junit4) from 4.13.1 to 4.13.2. - [Release notes](https://github.com/junit-team/junit4/releases) - [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.13.1.md) - [Commits](https://github.com/junit-team/junit4/compare/r4.13.1...r4.13.2) Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e2e8fe5d..38caac4b 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ UTF-8 8 1.2.60 - 1.14.0 + 2.8.1 2.9.0 1.7.1 @@ -43,7 +43,7 @@ 0.6.0.20150202 - 4.13.1 + 4.13.2 1.0.2 2.0.0 3.6.28 From da3da44d724c72b82443756766eb763bae641067 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Feb 2021 18:44:38 +0000 Subject: [PATCH 053/272] Bump okhttp from 4.0.1 to 4.9.1 Bumps [okhttp](https://github.com/square/okhttp) from 4.0.1 to 4.9.1. - [Release notes](https://github.com/square/okhttp/releases) - [Changelog](https://github.com/square/okhttp/blob/master/CHANGELOG.md) - [Commits](https://github.com/square/okhttp/compare/parent-4.0.1...parent-4.9.1) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 538b81c2..1f53c089 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ 3.0.1 2.8.6 - 4.0.1 + 4.9.1 4.9.1 26.0-jre 1.0.0 From 0b5391ce88094fcca10fd09bd4304788a7038250 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Feb 2021 18:45:08 +0000 Subject: [PATCH 054/272] Bump kotlin.version from 1.2.60 to 1.4.30 Bumps `kotlin.version` from 1.2.60 to 1.4.30. Updates `kotlin-stdlib` from 1.2.60 to 1.4.30 - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/compare/v1.2.60...v1.4.30) Updates `kotlin-maven-plugin` from 1.2.60 to 1.4.30 Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 538b81c2..e30865d1 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ UTF-8 8 - 1.2.60 + 1.4.30 2.8.1 2.9.0 1.7.1 From fcb4280eb5e3f146037d3323e75f26d2d2b9fa5a Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Thu, 25 Feb 2021 00:47:29 -0300 Subject: [PATCH 055/272] adding circleci badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7e0bdfcb..47edcd2d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -analytics-java +analytics-java [![CircleCI](https://circleci.com/gh/segmentio/analytics-java.svg?style=svg&circle-token=14e898d7ee1eb35ff07d2f6e0f7153a547c179fb)](https://circleci.com/gh/segmentio/analytics-java) ============== analytics-java is a Java client for [Segment](https://segment.com) From 80a53bca781e385a10902e705b99ef3713c9e483 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Sat, 27 Feb 2021 04:13:11 -0300 Subject: [PATCH 056/272] cant put dot in Retrofits service --- .../com/segment/analytics/http/SegmentService.java | 2 +- .../main/java/com/segment/analytics/Analytics.java | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java b/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java index 5b66e330..92687268 100644 --- a/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java +++ b/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java @@ -7,6 +7,6 @@ /** REST interface for the Segment API. */ public interface SegmentService { - @POST("") + @POST(".") Call upload(@Body Batch batch); } diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index c92a92dd..430960d0 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -124,7 +124,8 @@ private Message buildMessage(MessageBuilder builder) { /** Fluent API for creating {@link Analytics} instances. */ public static class Builder { - private static final HttpUrl DEFAULT_ENDPOINT = HttpUrl.parse("https://api.segment.io"); + private static final String DEFAULT_ENDPOINT = "https://api.segment.io"; + private static final String DEFAULT_PATH = "/v1/import/"; private static final String DEFAULT_USER_AGENT = "analytics-java/" + AnalyticsVersion.get(); private final String writeKey; @@ -176,7 +177,7 @@ public Builder endpoint(String endpoint) { if (endpoint == null || endpoint.trim().length() == 0) { throw new NullPointerException("endpoint cannot be null or empty."); } - this.endpoint = HttpUrl.parse(endpoint + "/v1/import/"); + this.endpoint = HttpUrl.parse(endpoint + DEFAULT_PATH); return this; } @@ -324,16 +325,17 @@ public Analytics build() { .create(); if (endpoint == null) { - endpoint = DEFAULT_ENDPOINT; + endpoint = HttpUrl.parse(DEFAULT_ENDPOINT + DEFAULT_PATH); + } - if (uploadURL != null) { - endpoint = uploadURL; - } + if (endpoint == null && uploadURL != null) { + endpoint = uploadURL; } if (client == null) { client = Platform.get().defaultClient(); } + if (log == null) { log = Log.NONE; } From dc9128cc871b3b1bc22573914cf355be7c57cc46 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Mar 2021 07:20:47 +0000 Subject: [PATCH 057/272] Bump burst.version from 1.0.2 to 1.2.0 Bumps `burst.version` from 1.0.2 to 1.2.0. Updates `burst-junit4` from 1.0.2 to 1.2.0 - [Release notes](https://github.com/square/burst/releases) - [Changelog](https://github.com/square/burst/blob/master/CHANGELOG.md) - [Commits](https://github.com/square/burst/compare/burst-parent-1.0.2...burst-parent-1.2.0) Updates `burst` from 1.0.2 to 1.2.0 - [Release notes](https://github.com/square/burst/releases) - [Changelog](https://github.com/square/burst/blob/master/CHANGELOG.md) - [Commits](https://github.com/square/burst/compare/burst-parent-1.0.2...burst-parent-1.2.0) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cd72614d..e0da5960 100644 --- a/pom.xml +++ b/pom.xml @@ -44,7 +44,7 @@ 4.13.2 - 1.0.2 + 1.2.0 2.0.0 3.6.28 From 545a9b733f7a4a4b37a6ab0e798716ea85104f42 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Mar 2021 19:38:18 +0000 Subject: [PATCH 058/272] Bump guava from 26.0-jre to 30.1-jre Bumps [guava](https://github.com/google/guava) from 26.0-jre to 30.1-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e0da5960..804b428b 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ 2.8.6 4.0.1 4.9.1 - 26.0-jre + 30.1-jre 1.0.0 1.2.5.RELEASE 0.6.0.20150202 From eca94264f6ca49a4cfa5eade53bccf7be484c613 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Mar 2021 19:38:19 +0000 Subject: [PATCH 059/272] Bump kotlin.version from 1.4.30 to 1.4.31 Bumps `kotlin.version` from 1.4.30 to 1.4.31. Updates `kotlin-stdlib` from 1.4.30 to 1.4.31 - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/v1.4.31/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/compare/v1.4.30...v1.4.31) Updates `kotlin-maven-plugin` from 1.4.30 to 1.4.31 Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e0da5960..34f1527e 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ UTF-8 8 - 1.4.30 + 1.4.31 2.8.1 2.9.0 1.7.1 From 83fa8095c7cdeac911f2f9114bb3710a282f2a1e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Mar 2021 19:38:21 +0000 Subject: [PATCH 060/272] Bump assertj-core from 2.0.0 to 3.19.0 Bumps [assertj-core](https://github.com/assertj/assertj-core) from 2.0.0 to 3.19.0. - [Release notes](https://github.com/assertj/assertj-core/releases) - [Commits](https://github.com/assertj/assertj-core/compare/assertj-core-2.0.0...assertj-core-3.19.0) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e0da5960..353c53bc 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ 4.13.2 1.2.0 - 2.0.0 + 3.19.0 3.6.28 From 091bb69fc5af46c2d89b8f121287bedd3f7950fb Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Sun, 7 Mar 2021 22:43:55 -0300 Subject: [PATCH 061/272] bumping okhttp client to the highest version possible --- .gitignore | 3 +++ pom.xml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 916c0699..f2d6d468 100644 --- a/.gitignore +++ b/.gitignore @@ -83,6 +83,9 @@ $RECYCLE.BIN/ *.iml +# Vim +*.orig + ## Directory-based project format: .idea/ # if you remove the above rule, at least ignore the following: diff --git a/pom.xml b/pom.xml index 1f53c089..8468fd64 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ 3.0.1 2.8.6 - 4.9.1 + 4.2.0 4.9.1 26.0-jre 1.0.0 From 51863631590cb349af08c75e4c47f754a05c79df Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Sun, 7 Mar 2021 23:34:39 -0300 Subject: [PATCH 062/272] adding code coverage badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 47edcd2d..471d16c2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -analytics-java [![CircleCI](https://circleci.com/gh/segmentio/analytics-java.svg?style=svg&circle-token=14e898d7ee1eb35ff07d2f6e0f7153a547c179fb)](https://circleci.com/gh/segmentio/analytics-java) +analytics-java [![CircleCI](https://circleci.com/gh/segmentio/analytics-java.svg?style=svg&circle-token=14e898d7ee1eb35ff07d2f6e0f7153a547c179fb)](https://circleci.com/gh/segmentio/analytics-java) [![codecov](https://codecov.io/gh/segmentio/analytics-java/branch/master/graph/badge.svg?token=804hPfMd0C)](https://codecov.io/gh/segmentio/analytics-java) ============== analytics-java is a Java client for [Segment](https://segment.com) From 88f9f6271d477464cd2a3cdada8bc7151480280a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Mar 2021 06:00:05 +0000 Subject: [PATCH 063/272] Bump maven-release-plugin from 2.5 to 2.5.3 Bumps maven-release-plugin from 2.5 to 2.5.3. Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 34f1527e..00f71cbc 100644 --- a/pom.xml +++ b/pom.xml @@ -243,7 +243,7 @@ org.apache.maven.plugins maven-release-plugin - 2.5 + 2.5.3 true From 60675c96f0cdea9f77a82a3353109339de868652 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Mar 2021 18:47:12 +0000 Subject: [PATCH 064/272] Bump templating-maven-plugin from 1.0-alpha-3 to 1.0.0 Bumps [templating-maven-plugin](https://github.com/mojohaus/templating-maven-plugin) from 1.0-alpha-3 to 1.0.0. - [Release notes](https://github.com/mojohaus/templating-maven-plugin/releases) - [Commits](https://github.com/mojohaus/templating-maven-plugin/commits/templating-maven-plugin-1.0.0) Signed-off-by: dependabot[bot] --- analytics/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analytics/pom.xml b/analytics/pom.xml index 9713d8b1..bd2479e4 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -76,7 +76,7 @@ org.codehaus.mojo templating-maven-plugin - 1.0-alpha-3 + 1.0.0 From 622315cef591ad0924841b312335f0b8b5b9c6fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Mar 2021 18:47:52 +0000 Subject: [PATCH 065/272] Bump spotless-maven-plugin from 2.8.1 to 2.9.0 Bumps [spotless-maven-plugin](https://github.com/diffplug/project) from 2.8.1 to 2.9.0. - [Release notes](https://github.com/diffplug/project/releases) - [Commits](https://github.com/diffplug/project/commits) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8a1986d7..e67fcfee 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ UTF-8 8 1.4.31 - 2.8.1 + 2.9.0 2.9.0 1.7.1 From a2fedb56ea12c6eae5c4bd7337d419ffce3baa9e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Mar 2021 18:47:55 +0000 Subject: [PATCH 066/272] Bump mockito-core from 3.6.28 to 3.8.0 Bumps [mockito-core](https://github.com/mockito/mockito) from 3.6.28 to 3.8.0. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v3.6.28...v3.8.0) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4474ab4c..41c29798 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ 4.13.2 1.2.0 3.19.0 - 3.6.28 + 3.8.0 From bfcd38c74fcecc0915373acc9568e9d573fffba3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Mar 2021 18:40:13 +0000 Subject: [PATCH 067/272] Bump maven-surefire-plugin from 2.18.1 to 2.22.2 Bumps [maven-surefire-plugin](https://github.com/apache/maven-surefire) from 2.18.1 to 2.22.2. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-2.18.1...surefire-2.22.2) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 19f10be8..0789b9ff 100644 --- a/pom.xml +++ b/pom.xml @@ -278,7 +278,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.18.1 + 2.22.2 false From 9a70a2ce3d05f53b77ffeb2995f0a18a2a4f1673 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Mar 2021 06:01:51 +0000 Subject: [PATCH 068/272] Bump spring-boot-autoconfigure from 1.2.5.RELEASE to 2.4.3 Bumps [spring-boot-autoconfigure](https://github.com/spring-projects/spring-boot) from 1.2.5.RELEASE to 2.4.3. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v1.2.5.RELEASE...v2.4.3) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index eadf3da1..125992cd 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ 4.9.1 30.1-jre 1.0.0 - 1.2.5.RELEASE + 2.4.3 0.6.0.20150202 From 050338c7ed4645da089ddd85b1dab2d291daa7e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Mar 2021 06:02:00 +0000 Subject: [PATCH 069/272] Bump auto.version from 1.7.1 to 1.7.4 Bumps `auto.version` from 1.7.1 to 1.7.4. Updates `auto-value` from 1.7.1 to 1.7.4 - [Release notes](https://github.com/google/auto/releases) - [Commits](https://github.com/google/auto/compare/auto-value-1.7.1...auto-value-1.7.4) Updates `auto-value-annotations` from 1.7.1 to 1.7.4 - [Release notes](https://github.com/google/auto/releases) - [Commits](https://github.com/google/auto/compare/auto-value-1.7.1...auto-value-1.7.4) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index eadf3da1..6bd70657 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 1.4.31 2.9.0 2.9.0 - 1.7.1 + 1.7.4 3.0.1 2.8.6 From 224e998144ea9d3ca6d5a8873b3bdb4445e3193e Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Wed, 17 Mar 2021 14:01:04 -0300 Subject: [PATCH 070/272] upgrading okhttp to version 4.3.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 125992cd..fb8bf7cd 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ 3.0.1 2.8.6 - 4.2.0 + 4.3.0 4.9.1 30.1-jre 1.0.0 From c4a5d30afc2a60284fe0343f770c0ace152481ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Mar 2021 05:57:31 +0000 Subject: [PATCH 071/272] Bump spring-boot-autoconfigure from 2.4.3 to 2.4.4 Bumps [spring-boot-autoconfigure](https://github.com/spring-projects/spring-boot) from 2.4.3 to 2.4.4. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v2.4.3...v2.4.4) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dbcb033a..19ed4647 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ 4.9.1 30.1-jre 1.0.0 - 2.4.3 + 2.4.4 0.6.0.20150202 From 4c74809502efc951cd867eea50cbacc9c7657d7d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Mar 2021 05:57:35 +0000 Subject: [PATCH 072/272] Bump guava from 30.1-jre to 30.1.1-jre Bumps [guava](https://github.com/google/guava) from 30.1-jre to 30.1.1-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dbcb033a..2d56922e 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ 2.8.6 4.3.0 4.9.1 - 30.1-jre + 30.1.1-jre 1.0.0 2.4.3 0.6.0.20150202 From 0a643a762e437b4a80389bfdae76bbb7e94e2647 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Fri, 26 Mar 2021 01:53:51 -0300 Subject: [PATCH 073/272] Applied https://patch-diff.githubusercontent.com/raw/segmentio/analytics-java/pull/158.patch. --- .../src/main/java/com/segment/analytics/Analytics.java | 2 +- .../java/com/segment/analytics/AnalyticsBuilderTest.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index 430960d0..1de13c3c 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -187,7 +187,7 @@ public Builder endpoint(String endpoint) { */ public Builder setUploadURL(String uploadURL) { if (uploadURL == null || uploadURL.trim().length() == 0) { - throw new NullPointerException("endpoint cannot be null or empty."); + throw new NullPointerException("Upload URL cannot be null or empty."); } this.uploadURL = HttpUrl.parse(uploadURL); return this; diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java index 2764c025..e910f0af 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java @@ -295,7 +295,7 @@ public void nullHostAndPrefixEndpoint() { builder.setUploadURL(null); fail("Should fail for null endpoint"); } catch (NullPointerException e) { - assertThat(e).hasMessage("endpoint cannot be null or empty."); + assertThat(e).hasMessage("Upload URL cannot be null or empty."); } } @@ -305,14 +305,14 @@ public void emptyHostAndPrefixEndpoint() { builder.setUploadURL(""); fail("Should fail for empty endpoint"); } catch (NullPointerException e) { - assertThat(e).hasMessage("endpoint cannot be null or empty."); + assertThat(e).hasMessage("Upload URL cannot be null or empty."); } try { builder.setUploadURL(" "); fail("Should fail for empty endpoint"); } catch (NullPointerException e) { - assertThat(e).hasMessage("endpoint cannot be null or empty."); + assertThat(e).hasMessage("Upload URL cannot be null or empty."); } } From b93f760b9f2aa298e8031a56779fd55e96d57bd7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Mar 2021 09:09:09 +0000 Subject: [PATCH 074/272] Bump auto.version from 1.7.4 to 1.7.5 Bumps `auto.version` from 1.7.4 to 1.7.5. Updates `auto-value` from 1.7.4 to 1.7.5 - [Release notes](https://github.com/google/auto/releases) - [Commits](https://github.com/google/auto/compare/auto-value-1.7.4...auto-value-1.7.5) Updates `auto-value-annotations` from 1.7.4 to 1.7.5 - [Release notes](https://github.com/google/auto/releases) - [Commits](https://github.com/google/auto/compare/auto-value-1.7.4...auto-value-1.7.5) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dbcb033a..52b7be69 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 1.4.31 2.9.0 2.9.0 - 1.7.4 + 1.7.5 3.0.1 2.8.6 From c5839051bb6e941a24181b8878fe3809f282d264 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Mar 2021 09:11:33 +0000 Subject: [PATCH 075/272] Bump kotlin.version from 1.4.31 to 1.4.32 Bumps `kotlin.version` from 1.4.31 to 1.4.32. Updates `kotlin-stdlib` from 1.4.31 to 1.4.32 - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/commits) Updates `kotlin-maven-plugin` from 1.4.31 to 1.4.32 Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dbcb033a..88c742a9 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ UTF-8 8 - 1.4.31 + 1.4.32 2.9.0 2.9.0 1.7.4 From 7799a04a90fe62ff31470c617c6cdabcd6bbcfa5 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Mon, 29 Mar 2021 23:27:22 -0300 Subject: [PATCH 076/272] traits was defined twice --- analytics-cli/src/main/kotlin/cli/Main.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analytics-cli/src/main/kotlin/cli/Main.kt b/analytics-cli/src/main/kotlin/cli/Main.kt index 8a2b2ff6..c099fc38 100644 --- a/analytics-cli/src/main/kotlin/cli/Main.kt +++ b/analytics-cli/src/main/kotlin/cli/Main.kt @@ -13,7 +13,7 @@ val usage = """ Analytics Java CLI Usage: - analytics --writeKey= --type= --userId= [--event=] [--properties=] [--name=] [--traits=] [--groupId=] [--previousId=] [--anonymousId=] [--integrations=] [--traits=] [--context=] + analytics --writeKey= --type= --userId= [--event=] [--properties=] [--name=] [--traits=] [--groupId=] [--previousId=] [--anonymousId=] [--integrations=] [--context=] analytics -h | --help From c6485daeea8ad0db5e6d55a4e215f09e1705edf3 Mon Sep 17 00:00:00 2001 From: Hunter Medney Date: Mon, 29 Mar 2021 22:28:16 -0400 Subject: [PATCH 077/272] defer userId and anonymousId check to build() --- .../java/com/segment/analytics/messages/MessageBuilder.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java b/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java index 96f27005..494aa775 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java @@ -128,9 +128,6 @@ public V anonymousId(UUID anonymousId) { * @see Anonymous ID */ public V anonymousId(String anonymousId) { - if (isNullOrEmpty(anonymousId)) { - throw new IllegalArgumentException("anonymousId cannot be null or empty."); - } this.anonymousId = anonymousId; return self(); } @@ -142,9 +139,6 @@ public V anonymousId(String anonymousId) { * @see User ID */ public V userId(String userId) { - if (isNullOrEmpty(userId)) { - throw new IllegalArgumentException("userId cannot be null or empty."); - } this.userId = userId; return self(); } From b31c3de21203d191940b1fcd26628d9483b103fd Mon Sep 17 00:00:00 2001 From: Hunter Medney Date: Mon, 29 Mar 2021 22:29:09 -0400 Subject: [PATCH 078/272] include empty strings in id check --- .../java/com/segment/analytics/messages/MessageBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java b/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java index 494aa775..0b8d946c 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java @@ -194,8 +194,8 @@ protected abstract T realBuild( * @throws IllegalStateException if both anonymousId and userId are not provided. */ public T build() { - if (anonymousId == null && userId == null) { - throw new IllegalStateException("Either anonymousId or userId must be provided."); + if (isNullOrEmpty(anonymousId) && isNullOrEmpty(null)) { + throw new IllegalArgumentException("Either anonymousId or userId must be provided."); } Date timestamp = this.timestamp; From f7d2dc28392e1d62e9d91e18193b8c23dcaeef3a Mon Sep 17 00:00:00 2001 From: Hunter Medney Date: Mon, 29 Mar 2021 22:32:45 -0400 Subject: [PATCH 079/272] add userIdOrAnonymousIdIsRequired test --- .../analytics/messages/TrackMessageTest.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/analytics-core/src/test/java/com/segment/analytics/messages/TrackMessageTest.java b/analytics-core/src/test/java/com/segment/analytics/messages/TrackMessageTest.java index def40565..5040a62c 100644 --- a/analytics-core/src/test/java/com/segment/analytics/messages/TrackMessageTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/messages/TrackMessageTest.java @@ -1,6 +1,7 @@ package com.segment.analytics.messages; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; import com.google.common.collect.ImmutableMap; import org.junit.Test; @@ -37,4 +38,30 @@ public void toBuilder() { assertThat(copy.event()).isEqualTo("event"); assertThat(copy.properties()).isEqualTo(ImmutableMap.of("foo", "bar")); } + + @Test + public void userIdOrAnonymousIdIsRequired() { + final String exceptionMessage = "Either anonymousId or userId must be provided."; + + try { + TrackMessage.builder("event").build(); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage(exceptionMessage); + } + + try { + TrackMessage.builder("event").userId(null).anonymousId((String) null).build(); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage(exceptionMessage); + } + + try { + TrackMessage.builder("event").userId("").anonymousId("").build(); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage(exceptionMessage); + } + } } From db7d2a2dcb2ddf7d72e6cc65b07272071013be9e Mon Sep 17 00:00:00 2001 From: Hunter Medney Date: Mon, 29 Mar 2021 22:33:30 -0400 Subject: [PATCH 080/272] add userIdOrAnonymousIdIsRequired test --- .../messages/IdentifyMessageTest.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/analytics-core/src/test/java/com/segment/analytics/messages/IdentifyMessageTest.java b/analytics-core/src/test/java/com/segment/analytics/messages/IdentifyMessageTest.java index 015eaa55..27a6ae6d 100644 --- a/analytics-core/src/test/java/com/segment/analytics/messages/IdentifyMessageTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/messages/IdentifyMessageTest.java @@ -1,6 +1,7 @@ package com.segment.analytics.messages; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; import com.google.common.collect.ImmutableMap; import org.junit.Test; @@ -25,6 +26,32 @@ public void userIdOrTraitsAreRequired() { } } + @Test + public void userIdOrAnonymousIdIsRequired() { + final String exceptionMessage = "Either anonymousId or userId must be provided."; + + try { + IdentifyMessage.builder().build(); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage(exceptionMessage); + } + + try { + IdentifyMessage.builder().userId(null).anonymousId((String) null).build(); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage(exceptionMessage); + } + + try { + IdentifyMessage.builder().userId("").anonymousId("").build(); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage(exceptionMessage); + } + } + @Test public void toBuilder() { IdentifyMessage original = From 1ac7c4674d79195c40e70e4de146b7e504fdeec3 Mon Sep 17 00:00:00 2001 From: Hunter Medney Date: Mon, 29 Mar 2021 22:39:08 -0400 Subject: [PATCH 081/272] bug fix --- .../java/com/segment/analytics/messages/MessageBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java b/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java index 0b8d946c..d209ff14 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java @@ -194,7 +194,7 @@ protected abstract T realBuild( * @throws IllegalStateException if both anonymousId and userId are not provided. */ public T build() { - if (isNullOrEmpty(anonymousId) && isNullOrEmpty(null)) { + if (isNullOrEmpty(anonymousId) && isNullOrEmpty(userId)) { throw new IllegalArgumentException("Either anonymousId or userId must be provided."); } From 59c0132a69ede53e3507b2dc2c20620969fa0e70 Mon Sep 17 00:00:00 2001 From: Hunter Medney Date: Mon, 29 Mar 2021 22:44:34 -0400 Subject: [PATCH 082/272] expect IllegalArgumentException --- .../java/com/segment/analytics/messages/MessageBuilderTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analytics-core/src/test/java/com/segment/analytics/messages/MessageBuilderTest.java b/analytics-core/src/test/java/com/segment/analytics/messages/MessageBuilderTest.java index 858ad2f0..b9ea6420 100644 --- a/analytics-core/src/test/java/com/segment/analytics/messages/MessageBuilderTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/messages/MessageBuilderTest.java @@ -124,7 +124,7 @@ public void missingUserIdAndAnonymousIdThrowsException(TestUtils.MessageBuilderF try { builder.get().build(); fail(); - } catch (IllegalStateException e) { + } catch (IllegalArgumentException e) { assertThat(e).hasMessage("Either anonymousId or userId must be provided."); } } From b9a6366e4aa8c71a891777af29cbdac5d042d94b Mon Sep 17 00:00:00 2001 From: Hunter Medney Date: Mon, 29 Mar 2021 22:46:00 -0400 Subject: [PATCH 083/272] remove individual id null/empty checks userId or anonymousId are requried; one can be null/empty --- .../messages/MessageBuilderTest.java | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/analytics-core/src/test/java/com/segment/analytics/messages/MessageBuilderTest.java b/analytics-core/src/test/java/com/segment/analytics/messages/MessageBuilderTest.java index b9ea6420..0d84b1e5 100644 --- a/analytics-core/src/test/java/com/segment/analytics/messages/MessageBuilderTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/messages/MessageBuilderTest.java @@ -89,26 +89,6 @@ public void stringAnonymousId(TestUtils.MessageBuilderFactory builder) { assertThat(message.anonymousId()).isEqualTo("anonymousId"); } - @Test - public void nullStringAnonymousIdThrowsException(TestUtils.MessageBuilderFactory builder) { - try { - builder.get().anonymousId((String) null); - fail(); - } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("anonymousId cannot be null or empty."); - } - } - - @Test - public void emptyStringAnonymousIdThrowsException(TestUtils.MessageBuilderFactory builder) { - try { - builder.get().anonymousId(""); - fail(); - } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("anonymousId cannot be null or empty."); - } - } - @Test public void nullUUIDAnonymousIdThrowsException(TestUtils.MessageBuilderFactory builder) { try { @@ -139,16 +119,6 @@ public void nullTimestampThrowsError(TestUtils.MessageBuilderFactory builder) { } } - @Test - public void invalidUserIdThrows(TestUtils.MessageBuilderFactory builder) { - try { - builder.get().userId(null); - fail(); - } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("userId cannot be null or empty."); - } - } - @Test public void timestamp(TestUtils.MessageBuilderFactory builder) { Date date = newDate(1985, 4, 12, 23, 20, 50, 520, 0); From 4bdf2d6f1ed8ece67a70f0759969061ad819d8d0 Mon Sep 17 00:00:00 2001 From: Hunter Medney Date: Tue, 30 Mar 2021 15:21:52 -0400 Subject: [PATCH 084/272] add happy path tests --- .../analytics/messages/IdentifyMessageTest.java | 7 +++++++ .../segment/analytics/messages/TrackMessageTest.java | 10 +++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/analytics-core/src/test/java/com/segment/analytics/messages/IdentifyMessageTest.java b/analytics-core/src/test/java/com/segment/analytics/messages/IdentifyMessageTest.java index 27a6ae6d..297b2da3 100644 --- a/analytics-core/src/test/java/com/segment/analytics/messages/IdentifyMessageTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/messages/IdentifyMessageTest.java @@ -50,6 +50,13 @@ public void userIdOrAnonymousIdIsRequired() { } catch (IllegalArgumentException e) { assertThat(e).hasMessage(exceptionMessage); } + + IdentifyMessage message = IdentifyMessage.builder().userId("theUserId").build(); + assertThat(message.userId()).isEqualTo("theUserId"); + + message = IdentifyMessage.builder().anonymousId("theAnonymousId").traits(ImmutableMap.of("foo", "bar")).build(); + assertThat(message.anonymousId()).isEqualTo("theAnonymousId"); + assertThat(message.traits()).isEqualTo(ImmutableMap.of("foo", "bar")); } @Test diff --git a/analytics-core/src/test/java/com/segment/analytics/messages/TrackMessageTest.java b/analytics-core/src/test/java/com/segment/analytics/messages/TrackMessageTest.java index 5040a62c..1def5cfa 100644 --- a/analytics-core/src/test/java/com/segment/analytics/messages/TrackMessageTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/messages/TrackMessageTest.java @@ -38,7 +38,7 @@ public void toBuilder() { assertThat(copy.event()).isEqualTo("event"); assertThat(copy.properties()).isEqualTo(ImmutableMap.of("foo", "bar")); } - + @Test public void userIdOrAnonymousIdIsRequired() { final String exceptionMessage = "Either anonymousId or userId must be provided."; @@ -63,5 +63,13 @@ public void userIdOrAnonymousIdIsRequired() { } catch (IllegalArgumentException e) { assertThat(e).hasMessage(exceptionMessage); } + + TrackMessage message = TrackMessage.builder("event").userId("theUserId").build(); + assertThat(message.userId()).isEqualTo("theUserId"); + assertThat(message.event()).isEqualTo("event"); + + message = TrackMessage.builder("event").anonymousId("theAnonymousId").build(); + assertThat(message.anonymousId()).isEqualTo("theAnonymousId"); + assertThat(message.event()).isEqualTo("event"); } } From 33e1bc21cb6854a30d182bb1487c723f3e720822 Mon Sep 17 00:00:00 2001 From: Hunter Medney Date: Tue, 30 Mar 2021 15:32:04 -0400 Subject: [PATCH 085/272] fix formatting --- .../com/segment/analytics/messages/IdentifyMessageTest.java | 6 +++++- .../com/segment/analytics/messages/TrackMessageTest.java | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/analytics-core/src/test/java/com/segment/analytics/messages/IdentifyMessageTest.java b/analytics-core/src/test/java/com/segment/analytics/messages/IdentifyMessageTest.java index 297b2da3..7fc3a0b2 100644 --- a/analytics-core/src/test/java/com/segment/analytics/messages/IdentifyMessageTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/messages/IdentifyMessageTest.java @@ -54,7 +54,11 @@ public void userIdOrAnonymousIdIsRequired() { IdentifyMessage message = IdentifyMessage.builder().userId("theUserId").build(); assertThat(message.userId()).isEqualTo("theUserId"); - message = IdentifyMessage.builder().anonymousId("theAnonymousId").traits(ImmutableMap.of("foo", "bar")).build(); + message = + IdentifyMessage.builder() + .anonymousId("theAnonymousId") + .traits(ImmutableMap.of("foo", "bar")) + .build(); assertThat(message.anonymousId()).isEqualTo("theAnonymousId"); assertThat(message.traits()).isEqualTo(ImmutableMap.of("foo", "bar")); } diff --git a/analytics-core/src/test/java/com/segment/analytics/messages/TrackMessageTest.java b/analytics-core/src/test/java/com/segment/analytics/messages/TrackMessageTest.java index 1def5cfa..b51aba62 100644 --- a/analytics-core/src/test/java/com/segment/analytics/messages/TrackMessageTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/messages/TrackMessageTest.java @@ -38,7 +38,7 @@ public void toBuilder() { assertThat(copy.event()).isEqualTo("event"); assertThat(copy.properties()).isEqualTo(ImmutableMap.of("foo", "bar")); } - + @Test public void userIdOrAnonymousIdIsRequired() { final String exceptionMessage = "Either anonymousId or userId must be provided."; From 6d408f862d285f03384b7a4619de6b949441ada9 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Thu, 1 Apr 2021 13:25:37 -0300 Subject: [PATCH 086/272] cli wasnt setting event fields --- analytics-cli/src/main/kotlin/cli/Main.kt | 30 ++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/analytics-cli/src/main/kotlin/cli/Main.kt b/analytics-cli/src/main/kotlin/cli/Main.kt index c099fc38..c6cef2c6 100644 --- a/analytics-cli/src/main/kotlin/cli/Main.kt +++ b/analytics-cli/src/main/kotlin/cli/Main.kt @@ -41,7 +41,14 @@ fun main(rawArgs: Array) { messageBuilder.properties(parseJson(properties as String)) } } - "page", "screen" -> { + "page" -> { + messageBuilder = PageMessage.builder(args["--name"] as String) + val properties = args["--properties"] + if (properties != null) { + messageBuilder.properties(parseJson(properties as String)) + } + } + "screen" -> { messageBuilder = ScreenMessage.builder(args["--name"] as String) val properties = args["--properties"] if (properties != null) { @@ -75,6 +82,27 @@ fun main(rawArgs: Array) { messageBuilder.userId(userId as String) } + val anonymousId = args["--anonymousId"] + if (anonymousId != null) { + messageBuilder.anonymousId(anonymousId as String) + } + + val integrations = args["--integrations"] + if (integrations != null) { + val integrationsMap = parseJson(integrations as String) + for ((name, options) in integrationsMap) { + messageBuilder.integrationOptions(name, options as Map) + } + } + + val context = args["--context"] + if (context != null) { + val contextMap = parseJson(context as String) + for ((name, options) in contextMap) { + messageBuilder.context(contextMap) + } + } + val writeKey = args["--writeKey"] as String val phaser = Phaser(1) From 7e9d9acdb738b9db73c1806266cb759ea5444d5a Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Tue, 13 Apr 2021 20:18:06 -0300 Subject: [PATCH 087/272] generating changelog --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 482a89f4..a9b95f4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,21 @@ +Version 3.0.0 (April 13, 2021) +============================== + +**Breaking Changes:** +- SegmentService now has no url path. If you're using it directly we recommend using setUploadURL + +**Pull Requests Merged:** + * [New](https://github.com/segmentio/analytics-java/pull/192) Allow processing of already buffered messages on shutdown + * [New](https://github.com/segmentio/analytics-java/pull/190) Configurable message queue size + * [New](https://github.com/segmentio/analytics-java/pull/189) Configurable retry count + * [New](https://github.com/segmentio/analytics-java/pull/183) Add functionality to set custom endpoint with host and prefix + * [New](https://github.com/segmentio/analytics-java/pull/178) Limit by bytes + + * [Fix](https://github.com/segmentio/analytics-java/pull/223) cli wasnt setting event fields + * [Fix](https://github.com/segmentio/analytics-java/pull/222) e2e fix - traits was defined twice in command line opts + * [Fix](https://github.com/segmentio/analytics-java/pull/221) Require either userId or anonymousId \(aligns with other Segment SDK conventions\) + Version 2.1.1 (April 19, 2018) ============================== From 8c5ca48122933893234a7f435eb111574916efd0 Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Thu, 15 Apr 2021 10:25:33 -0700 Subject: [PATCH 088/272] [maven-release-plugin] prepare release analytics-parent-3.0.0 --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 6 +++--- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 775b25c8..521b80c8 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 2.1.2-SNAPSHOT + 3.0.0 analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index b241d58c..fb386d0f 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 2.1.2-SNAPSHOT + 3.0.0 analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index cf1f6615..6d7b45ee 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 2.1.2-SNAPSHOT + 3.0.0 analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index eb8478c0..d66190cd 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 2.1.2-SNAPSHOT + 3.0.0 analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index bd2479e4..0bfe8c19 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 2.1.2-SNAPSHOT + 3.0.0 analytics diff --git a/pom.xml b/pom.xml index 8dcc92b1..2a5256f9 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 2.1.2-SNAPSHOT + 3.0.0 pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - HEAD + analytics-parent-3.0.0 @@ -189,7 +189,7 @@ 1.5 - + From d6b37acdef848b26d3d637080bdce04ef39748b1 Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Thu, 15 Apr 2021 10:25:39 -0700 Subject: [PATCH 089/272] [maven-release-plugin] prepare for next development iteration --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 521b80c8..8a801d16 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.0.0 + 3.0.1-SNAPSHOT analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index fb386d0f..d11fc492 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.0.0 + 3.0.1-SNAPSHOT analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 6d7b45ee..3013e923 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.0.0 + 3.0.1-SNAPSHOT analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index d66190cd..0ac39cd6 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.0.0 + 3.0.1-SNAPSHOT analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index 0bfe8c19..cb7612a0 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.0.0 + 3.0.1-SNAPSHOT analytics diff --git a/pom.xml b/pom.xml index 2a5256f9..80796670 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.0.0 + 3.0.1-SNAPSHOT pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - analytics-parent-3.0.0 + HEAD From a12bca4913425af2efdeefb7d7aaec496a3556ea Mon Sep 17 00:00:00 2001 From: Brandon Sneed Date: Thu, 15 Apr 2021 12:02:23 -0700 Subject: [PATCH 090/272] Remove circleci config --- .circleci/config.yml | 134 ------------------------------------------- 1 file changed, 134 deletions(-) delete mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index ad2d29ce..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,134 +0,0 @@ -version: 2 -jobs: - java-base-test: &java-base-test - working_directory: ~/analytics-java - docker: - - image: circleci/openjdk:8-jdk-browsers - steps: - - checkout - - restore_cache: - key: maven-dep-cache-{{ checksum "pom.xml" }} - - run: mvn spotless:check animal-sniffer:check test verify - - run: - name: Test Failed - when: on_fail - command: | - wget https://raw.githubusercontent.com/segmentio/circleci-notifications/master/slack-notify-branch.sh - chmod u+x slack-notify-branch.sh - BUILD_STATUS="Failed" NOTIFY_BRANCH="master" ./slack-notify-branch.sh - - run: mvn package -B - - save_cache: - key: maven-dep-cache-{{ checksum "pom.xml" }} - paths: - - ~/.m2 - - persist_to_workspace: - root: . - paths: [.] - - test-jdklatest: - <<: *java-base-test - docker: - - image: circleci/openjdk - - test-jdk11: - <<: *java-base-test - docker: - - image: circleci/openjdk:11-jdk-browsers - - test-jdk8: - <<: *java-base-test - docker: - - image: circleci/openjdk:8-jdk-browsers - - test: - <<: *java-base-test - docker: - - image: circleci/openjdk:11-jdk-browsers - - publish: - <<: *java-base-test - docker: - - image: circleci/openjdk:8-jdk-browsers - environment: - CIRCLE_JDK_VERSION: oraclejdk8 - steps: - - checkout - - attach_workspace: { at: . } - - run: .buildscript/deploy_snapshot.sh - - coverage: - <<: *java-base-test - docker: - - image: circleci/openjdk:8-jdk-browsers - steps: - - checkout - - attach_workspace: { at: . } - - run: mvn cobertura:cobertura - - run: bash <(curl -s https://codecov.io/bash) - - e2e: - <<: *java-base-test - docker: - - image: circleci/openjdk:8-jdk-browsers - steps: - - checkout - - attach_workspace: { at: . } - - run: .buildscript/e2e.sh - - snyk: - <<: *java-base-test - docker: - - image: circleci/openjdk:8-jdk-browsers - steps: - - checkout - - attach_workspace: { at: . } - - run: - name: Snyk - command: curl -sL https://raw.githubusercontent.com/segmentio/snyk_helpers/master/initialization/snyk.sh | sh - environment: - SNYK_FAIL_ON: upgradable - SNYK_SEVERITY_THRESHOLD: high - -workflows: - version: 2 - multi-test: - jobs: - - test-jdklatest - - test-jdk11 - - test-jdk8 - static_analysis: - jobs: - - test - - coverage: - requires: - - test - - snyk: - context: snyk - requires: - - test - test_and_publish: - jobs: - - test: - filters: - branches: - only: master - - publish: - requires: - - test - filters: - branches: - only: master - scheduled_e2e_test: - triggers: - - schedule: - cron: "5 * * * *" - filters: - branches: - only: - - master - - scheduled_e2e_testing - jobs: - - test - - e2e: - requires: - - test From b72fd6b6147cc76b0123558456fc84ed667bd433 Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Wed, 21 Apr 2021 14:47:15 -0700 Subject: [PATCH 091/272] Update Changelog Fix the release date. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9b95f4c..5255e2fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ -Version 3.0.0 (April 13, 2021) +Version 3.0.0 (April 21, 2021) ============================== **Breaking Changes:** From c9637e2c05e8aac10d4bcbc428633e929c83657f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Apr 2021 06:01:44 +0000 Subject: [PATCH 092/272] Bump auto.version from 1.7.5 to 1.8.1 Bumps `auto.version` from 1.7.5 to 1.8.1. Updates `auto-value` from 1.7.5 to 1.8.1 - [Release notes](https://github.com/google/auto/releases) - [Commits](https://github.com/google/auto/compare/auto-value-1.7.5...auto-value-1.8.1) Updates `auto-value-annotations` from 1.7.5 to 1.8.1 - [Release notes](https://github.com/google/auto/releases) - [Commits](https://github.com/google/auto/compare/auto-value-1.7.5...auto-value-1.8.1) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 80796670..482d9ad2 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 1.4.32 2.9.0 2.9.0 - 1.7.5 + 1.8.1 3.0.1 2.8.6 From 02609c438bbb6436f8c9c07fad80e763d5c7936d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 May 2021 06:05:15 +0000 Subject: [PATCH 093/272] Bump kotlin.version from 1.4.32 to 1.5.0 Bumps `kotlin.version` from 1.4.32 to 1.5.0. Updates `kotlin-stdlib` from 1.4.32 to 1.5.0 - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/commits) Updates `kotlin-maven-plugin` from 1.4.32 to 1.5.0 Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 80796670..c87ebc38 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ UTF-8 8 - 1.4.32 + 1.5.0 2.9.0 2.9.0 1.7.5 From 80bbfbdf283f2af8c8d9ea9866fac33e714f41fe Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Fri, 7 May 2021 18:46:06 -0300 Subject: [PATCH 094/272] defaults queue max size to be over 50kb --- .../java/com/segment/analytics/Analytics.java | 18 ++++++++++++++ .../analytics/internal/AnalyticsClient.java | 9 ++++--- .../internal/AnalyticsClientTest.java | 24 ++++++++++++++++--- 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index 1de13c3c..43415f45 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -127,6 +127,7 @@ public static class Builder { private static final String DEFAULT_ENDPOINT = "https://api.segment.io"; private static final String DEFAULT_PATH = "/v1/import/"; private static final String DEFAULT_USER_AGENT = "analytics-java/" + AnalyticsVersion.get(); + private static final int MESSAGE_QUEUE_MAX_BYTE_SIZE = 1024 * 500; private final String writeKey; private OkHttpClient client; @@ -140,6 +141,7 @@ public static class Builder { private ThreadFactory threadFactory; private int flushQueueSize; private int maximumFlushAttempts; + private int maximumQueueSizeInBytes; private long flushIntervalInMillis; private List callbacks; private int queueCapacity; @@ -252,6 +254,16 @@ public Builder flushQueueSize(int flushQueueSize) { return this; } + /** Set the queueSize at which flushes should be triggered. */ + @Beta + public Builder maximumQueueSizeInBytes(int bytes) { + if (bytes < 1) { + throw new IllegalArgumentException("maximumQueueSizeInBytes must not be less than 1."); + } + this.maximumQueueSizeInBytes = bytes; + return this; + } + /** Set the interval at which the queue should be flushed. */ @Beta public Builder flushInterval(long flushInterval, TimeUnit unit) { @@ -332,6 +344,7 @@ public Analytics build() { endpoint = uploadURL; } + if (client == null) { client = Platform.get().defaultClient(); } @@ -348,6 +361,9 @@ public Analytics build() { if (flushQueueSize == 0) { flushQueueSize = Platform.get().defaultFlushQueueSize(); } + if (maximumQueueSizeInBytes == 0) { + maximumQueueSizeInBytes = MESSAGE_QUEUE_MAX_BYTE_SIZE; + } if (messageTransformers == null) { messageTransformers = Collections.emptyList(); } else { @@ -404,10 +420,12 @@ public void log(String message) { flushQueueSize, flushIntervalInMillis, maximumFlushAttempts, + maximumQueueSizeInBytes, log, threadFactory, networkExecutor, callbacks); + return new Analytics(analyticsClient, messageTransformers, messageInterceptors, log); } } diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index be1085f9..1a02f16d 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -31,7 +31,6 @@ public class AnalyticsClient { private static final Map CONTEXT; - private static final int MESSAGE_QUEUE_MAX_BYTE_SIZE = 1024 * 32; static { Map library = new LinkedHashMap<>(); @@ -46,6 +45,7 @@ public class AnalyticsClient { private final SegmentService service; private final int size; private final int maximumRetries; + private final int maximumQueueByteSize; private final Log log; private final List callbacks; private final ExecutorService networkExecutor; @@ -59,6 +59,7 @@ public static AnalyticsClient create( int flushQueueSize, long flushIntervalInMillis, int maximumRetries, + int maximumQueueSizeInBytes, Log log, ThreadFactory threadFactory, ExecutorService networkExecutor, @@ -69,6 +70,7 @@ public static AnalyticsClient create( flushQueueSize, flushIntervalInMillis, maximumRetries, + maximumQueueSizeInBytes, log, threadFactory, networkExecutor, @@ -82,6 +84,7 @@ public static AnalyticsClient create( int maxQueueSize, long flushIntervalInMillis, int maximumRetries, + int maximumQueueSizeInBytes, Log log, ThreadFactory threadFactory, ExecutorService networkExecutor, @@ -91,6 +94,7 @@ public static AnalyticsClient create( this.service = service; this.size = maxQueueSize; this.maximumRetries = maximumRetries; + this.maximumQueueByteSize = maximumQueueSizeInBytes; this.log = log; this.callbacks = callbacks; this.looperExecutor = Executors.newSingleThreadExecutor(threadFactory); @@ -125,7 +129,7 @@ private Boolean isBackPressured(List messages) { messageQueueSize += messageSizeInBytes(message); } - return messageQueueSize >= MESSAGE_QUEUE_MAX_BYTE_SIZE; + return messageQueueSize >= this.maximumQueueByteSize; } public boolean offer(Message message) { @@ -250,7 +254,6 @@ static class BatchUploadTask implements Runnable { .cap(TimeUnit.HOURS, 1) // .jitter(1) // .build(); - private static final int MAX_ATTEMPTS = 50; // Max 50 hours ~ 2 days private final AnalyticsClient client; private final Backo backo; diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 93053a48..5bd6aaad 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -60,6 +60,7 @@ public class AnalyticsClientTest { Backo.builder().base(TimeUnit.NANOSECONDS, 1).factor(1).build(); private int DEFAULT_RETRIES = 10; + private int MAX_BYTE_SIZE = 1024 * 50; // 50kb Log log = Log.NONE; ThreadFactory threadFactory; @@ -89,6 +90,7 @@ AnalyticsClient newClient() { 50, TimeUnit.HOURS.toMillis(1), DEFAULT_RETRIES, + MAX_BYTE_SIZE, log, threadFactory, networkExecutor, @@ -185,7 +187,7 @@ public void shouldBeAbleToCalculateMessageSize() { AnalyticsClient client = newClient(); Map properties = new HashMap(); - properties.put("dummy-property", generateMassDataOfSize(1024 * 33)); + properties.put("property1", generateMassDataOfSize(1024 * 33)); TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); @@ -196,11 +198,27 @@ public void shouldBeAbleToCalculateMessageSize() { } @Test - public void dontEnqueueWhenReachesMaxSize() throws InterruptedException { + public void dontFlushUntilReachesMaxSize() throws InterruptedException { AnalyticsClient client = newClient(); Map properties = new HashMap(); - properties.put("dummy-property", generateMassDataOfSize(1024 * 33)); + properties.put("property2", generateMassDataOfSize(MAX_BYTE_SIZE - 10)); + + TrackMessage bigMessage = + TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); + client.enqueue(bigMessage); + + wait(messageQueue); + + verify(networkExecutor, never()).submit(any(Runnable.class)); + } + + @Test + public void flushWhenReachesMaxSize() throws InterruptedException { + AnalyticsClient client = newClient(); + Map properties = new HashMap(); + + properties.put("property3", generateMassDataOfSize(MAX_BYTE_SIZE + 10)); TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); From 0414b11e836baa3d808f35988712972d2728a7ae Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Fri, 7 May 2021 18:50:33 -0300 Subject: [PATCH 095/272] spotless fixes --- analytics/src/main/java/com/segment/analytics/Analytics.java | 1 - 1 file changed, 1 deletion(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index 43415f45..1ffd8f28 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -344,7 +344,6 @@ public Analytics build() { endpoint = uploadURL; } - if (client == null) { client = Platform.get().defaultClient(); } From 7446edcb42595e39ec45e4c82b88a53789d4fb05 Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Mon, 10 May 2021 13:36:15 -0700 Subject: [PATCH 096/272] Update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5255e2fb..b94fc04c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +Version 3.1.0 (May 10, 2021) +============================== +**Pull Requests Merged:** + * [New](https://github.com/segmentio/analytics-java/pull/235) defaults queue max size to be over 500kb + Version 3.0.0 (April 21, 2021) ============================== From b540b0104611950a39159c607a54128eca8168a0 Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Mon, 10 May 2021 13:47:33 -0700 Subject: [PATCH 097/272] [maven-release-plugin] prepare release analytics-parent-3.1.0 --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 8 ++++++-- 6 files changed, 11 insertions(+), 7 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 8a801d16..96e6a0a1 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.0.1-SNAPSHOT + 3.1.0 analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index d11fc492..adf3c477 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.0.1-SNAPSHOT + 3.1.0 analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 3013e923..34e4eacf 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.0.1-SNAPSHOT + 3.1.0 analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 0ac39cd6..66f43c5a 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.0.1-SNAPSHOT + 3.1.0 analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index cb7612a0..2d0fad69 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.0.1-SNAPSHOT + 3.1.0 analytics diff --git a/pom.xml b/pom.xml index 80796670..4443b346 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.0.1-SNAPSHOT + 3.1.0 pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - HEAD + analytics-parent-3.1.0 @@ -246,6 +246,10 @@ 2.5.3 true + + pom.xml + .buildscript/settings.xml + From ab94ee6eef45c488e7dbcff1fad3a7fe6919b90d Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Mon, 10 May 2021 13:47:39 -0700 Subject: [PATCH 098/272] [maven-release-plugin] prepare for next development iteration --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 96e6a0a1..5d1dbecd 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.0 + 3.1.1-SNAPSHOT analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index adf3c477..624b3473 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.0 + 3.1.1-SNAPSHOT analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 34e4eacf..01bf2d95 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.0 + 3.1.1-SNAPSHOT analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 66f43c5a..574da47e 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.0 + 3.1.1-SNAPSHOT analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index 2d0fad69..7fff4f43 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.0 + 3.1.1-SNAPSHOT analytics diff --git a/pom.xml b/pom.xml index 4443b346..76500542 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.1.0 + 3.1.1-SNAPSHOT pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - analytics-parent-3.1.0 + HEAD From 01a1507bdf4bfa71899c90ccb79d26b44e8cff36 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Fri, 28 May 2021 23:15:42 -0300 Subject: [PATCH 099/272] maintaining size state of queue --- .../analytics/internal/AnalyticsClient.java | 27 ++++++++++--------- .../internal/AnalyticsClientTest.java | 25 ++++++++--------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 1a02f16d..dbd15944 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -46,6 +46,7 @@ public class AnalyticsClient { private final int size; private final int maximumRetries; private final int maximumQueueByteSize; + private int currentQueueSizeInBytes; private final Log log; private final List callbacks; private final ExecutorService networkExecutor; @@ -101,6 +102,8 @@ public static AnalyticsClient create( this.networkExecutor = networkExecutor; this.isShutDown = isShutDown; + this.currentQueueSizeInBytes = 0; + looperExecutor.submit(new Looper()); flushScheduler = Executors.newScheduledThreadPool(1, threadFactory); @@ -122,14 +125,8 @@ public int messageSizeInBytes(Message message) { return stringifiedMessage.length(); } - private Boolean isBackPressured(List messages) { - int messageQueueSize = 0; - - for (Message message : messages) { - messageQueueSize += messageSizeInBytes(message); - } - - return messageQueueSize >= this.maximumQueueByteSize; + private Boolean isBackPressured() { + return this.currentQueueSizeInBytes >= this.maximumQueueByteSize; } public boolean offer(Message message) { @@ -144,6 +141,14 @@ public void enqueue(Message message) { try { messageQueue.put(message); + currentQueueSizeInBytes =+ messageSizeInBytes(message); + + if (isBackPressured()) { + log.print(VERBOSE, "Maximum storage size has been hit. Flushing..."); + + enqueue(FlushMessage.POISON); + currentQueueSizeInBytes = 0; + } } catch (InterruptedException e) { log.print(ERROR, e, "Interrupted while adding message %s.", message); Thread.currentThread().interrupt(); @@ -222,11 +227,6 @@ public void run() { Boolean isBlockingSignal = message == FlushMessage.POISON || message == StopMessage.STOP; Boolean isOverflow = messages.size() >= size; - if (isBackPressured(messages)) { - log.print(VERBOSE, "Maximum storage size has been hit. Flushing"); - isOverflow = true; - } - if (!messages.isEmpty() && (isOverflow || isBlockingSignal)) { Batch batch = Batch.create(CONTEXT, messages); log.print( @@ -317,6 +317,7 @@ boolean upload() { return false; } catch (IOException error) { client.log.print(DEBUG, error, "Could not upload batch %s. Retrying.", batch.sequence()); + notifyCallbacksWithException(batch, error); return true; } catch (Exception exception) { diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 5bd6aaad..4fcb61f9 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -145,6 +145,13 @@ static Batch captureBatch(ExecutorService executor) { return task.batch; } + private static String generateMassDataOfSize(int msgSize) { + char[] chars = new char[msgSize]; + Arrays.fill(chars, 'a'); + + return new String(chars); + } + @Test public void flushSubmitsToExecutor() { messageQueue = new LinkedBlockingQueue<>(); @@ -175,13 +182,6 @@ public void enqueueMaxTriggersFlush() { assertThat(captureBatch(networkExecutor).batch()).hasSize(50); } - private static String generateMassDataOfSize(int msgSize) { - char[] chars = new char[msgSize]; - Arrays.fill(chars, 'a'); - - return new String(chars); - } - @Test public void shouldBeAbleToCalculateMessageSize() { AnalyticsClient client = newClient(); @@ -202,7 +202,7 @@ public void dontFlushUntilReachesMaxSize() throws InterruptedException { AnalyticsClient client = newClient(); Map properties = new HashMap(); - properties.put("property2", generateMassDataOfSize(MAX_BYTE_SIZE - 10)); + properties.put("property2", generateMassDataOfSize(MAX_BYTE_SIZE - 500)); TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); @@ -220,13 +220,14 @@ public void flushWhenReachesMaxSize() throws InterruptedException { properties.put("property3", generateMassDataOfSize(MAX_BYTE_SIZE + 10)); - TrackMessage bigMessage = - TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); - client.enqueue(bigMessage); + for (int i = 0; i < 10; i++) { + TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); + client.enqueue(bigMessage); + } wait(messageQueue); - assertThat(captureBatch(networkExecutor).batch()).hasSize(1); + verify(networkExecutor, times(10)).submit(any(Runnable.class)); } @Test From 13ee8a41f9fedf76f2662e7b81f916060bada34d Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Mon, 31 May 2021 15:26:45 -0700 Subject: [PATCH 100/272] 3.1.1 --- CHANGELOG.md | 99 +++++++++++++++++++++++++--------------------------- 1 file changed, 48 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b94fc04c..54b0fb77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,37 +1,42 @@ -Version 3.1.0 (May 10, 2021) -============================== +# Version 3.1.1 (May 31, 2021) + **Pull Requests Merged:** - * [New](https://github.com/segmentio/analytics-java/pull/235) defaults queue max size to be over 500kb +- [Fix](https://github.com/segmentio/analytics-java/pull/241) maintaining size state of queue + +# Version 3.1.0 (May 10, 2021) + +**Pull Requests Merged:** -Version 3.0.0 (April 21, 2021) -============================== +- [New](https://github.com/segmentio/analytics-java/pull/235) defaults queue max size to be over 500kb + +# Version 3.0.0 (April 21, 2021) **Breaking Changes:** + - SegmentService now has no url path. If you're using it directly we recommend using setUploadURL **Pull Requests Merged:** - * [New](https://github.com/segmentio/analytics-java/pull/192) Allow processing of already buffered messages on shutdown - * [New](https://github.com/segmentio/analytics-java/pull/190) Configurable message queue size - * [New](https://github.com/segmentio/analytics-java/pull/189) Configurable retry count - * [New](https://github.com/segmentio/analytics-java/pull/183) Add functionality to set custom endpoint with host and prefix - * [New](https://github.com/segmentio/analytics-java/pull/178) Limit by bytes - * [Fix](https://github.com/segmentio/analytics-java/pull/223) cli wasnt setting event fields - * [Fix](https://github.com/segmentio/analytics-java/pull/222) e2e fix - traits was defined twice in command line opts - * [Fix](https://github.com/segmentio/analytics-java/pull/221) Require either userId or anonymousId \(aligns with other Segment SDK conventions\) +- [New](https://github.com/segmentio/analytics-java/pull/192) Allow processing of already buffered messages on shutdown +- [New](https://github.com/segmentio/analytics-java/pull/190) Configurable message queue size +- [New](https://github.com/segmentio/analytics-java/pull/189) Configurable retry count +- [New](https://github.com/segmentio/analytics-java/pull/183) Add functionality to set custom endpoint with host and prefix +- [New](https://github.com/segmentio/analytics-java/pull/178) Limit by bytes + +- [Fix](https://github.com/segmentio/analytics-java/pull/223) cli wasnt setting event fields +- [Fix](https://github.com/segmentio/analytics-java/pull/222) e2e fix - traits was defined twice in command line opts +- [Fix](https://github.com/segmentio/analytics-java/pull/221) Require either userId or anonymousId \(aligns with other Segment SDK conventions\) -Version 2.1.1 (April 19, 2018) -============================== +# Version 2.1.1 (April 19, 2018) - * [Fix](https://github.com/segmentio/analytics-java/pull/117): This fix gracefully retries temporary HTTP errors such as 5xx server errors. Previously such HTTP errors were not being retried. +- [Fix](https://github.com/segmentio/analytics-java/pull/117): This fix gracefully retries temporary HTTP errors such as 5xx server errors. Previously such HTTP errors were not being retried. -Version 2.1.0 (November 10, 2017) -================================= +# Version 2.1.0 (November 10, 2017) - * [New](https://github.com/segmentio/analytics-java/pull/113): Allow setting `String` message and anonymous IDs. Previously only UUIDs were accepted. This is a breaking API change and might require you to update your code if you were accessing the `messageId` or `anonymousId` in a transformer or interceptor. +- [New](https://github.com/segmentio/analytics-java/pull/113): Allow setting `String` message and anonymous IDs. Previously only UUIDs were accepted. This is a breaking API change and might require you to update your code if you were accessing the `messageId` or `anonymousId` in a transformer or interceptor. - * [New](https://github.com/segmentio/analytics-java/pull/109): Set a custom user-agent for HTTP requests. The default user agent is "analytics-java/version". This user agent is also customizable and can be override for special cases. +- [New](https://github.com/segmentio/analytics-java/pull/109): Set a custom user-agent for HTTP requests. The default user agent is "analytics-java/version". This user agent is also customizable and can be override for special cases. ```java final Analytics analytics = Analytics.builder(writeKey) // @@ -39,25 +44,22 @@ final Analytics analytics = Analytics.builder(writeKey) // .build(); ``` - * [Fix](https://github.com/segmentio/analytics-java/pull/112): Previously the version was being sent as "analytics/version" instead of simply "version". +- [Fix](https://github.com/segmentio/analytics-java/pull/112): Previously the version was being sent as "analytics/version" instead of simply "version". -Version 2.0.0 (April 4th, 2017) -=============================== +# Version 2.0.0 (April 4th, 2017) - * [New](https://github.com/segmentio/analytics-java/pull/99): Make endpoint configurable. - * [New](https://github.com/segmentio/analytics-java/pull/101): Allow setting a custom message ID. - * [New](https://github.com/segmentio/analytics-java/pull/58): Allow setting a custom timestamp. +- [New](https://github.com/segmentio/analytics-java/pull/99): Make endpoint configurable. +- [New](https://github.com/segmentio/analytics-java/pull/101): Allow setting a custom message ID. +- [New](https://github.com/segmentio/analytics-java/pull/58): Allow setting a custom timestamp. -Version 2.0.0-RC7 (August 22nd, 2016) -===================================== +# Version 2.0.0-RC7 (August 22nd, 2016) - * Fix: Previously, logging Retrofit messages could cause errors if the message contained formatting directives. +- Fix: Previously, logging Retrofit messages could cause errors if the message contained formatting directives. -Version 2.0.0-RC6 (August 18th, 2016) -===================================== +# Version 2.0.0-RC6 (August 18th, 2016) - * New: Add ability to set multiple Callback instances. - * New: Add plugin API. +- New: Add ability to set multiple Callback instances. +- New: Add plugin API. ```java class LoggingPlugin implements Plugin { @@ -91,30 +93,25 @@ final Analytics analytics = Analytics.builder(writeKey) // .build(); ``` -Version 2.0.0-RC5 (August 12th, 2016) -===================================== +# Version 2.0.0-RC5 (August 12th, 2016) - * Fix: Correctly format and parse dates as per ISO 8601. +- Fix: Correctly format and parse dates as per ISO 8601. -Version 2.0.0-RC4 (May 19th, 2016) -================================== +# Version 2.0.0-RC4 (May 19th, 2016) - * New: Add Page API. +- New: Add Page API. -Version 2.0.0-RC3 (Dec 15th, 2015) -================================== +# Version 2.0.0-RC3 (Dec 15th, 2015) - * Fix: Force ISO 8601 format for dates. - * Use a single thread by default to upload events in the background. Clients can still set their own executor to override this behaviour. +- Fix: Force ISO 8601 format for dates. +- Use a single thread by default to upload events in the background. Clients can still set their own executor to override this behaviour. -Version 2.0.0-RC2 (Oct 31st, 2015) -================================== +# Version 2.0.0-RC2 (Oct 31st, 2015) - * New: Add Callback API. - * Fix: Backpressure behaviour. Enqueuing events on a full queue will block instead of throwing an exception. - * Removed Guava dependency. +- New: Add Callback API. +- Fix: Backpressure behaviour. Enqueuing events on a full queue will block instead of throwing an exception. +- Removed Guava dependency. -Version 2.0.0-RC1 (Aug 26th, 2015) -================================== +# Version 2.0.0-RC1 (Aug 26th, 2015) - * Internal: Rename enums with lowercase. +- Internal: Rename enums with lowercase. From 331c1c6a43b4874fafa41918ca50c0b215b1079a Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Mon, 31 May 2021 15:29:22 -0700 Subject: [PATCH 101/272] [maven-release-plugin] prepare release analytics-parent-3.1.1 --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 5d1dbecd..7b6f0d39 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.1-SNAPSHOT + 3.1.1 analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index 624b3473..edab56af 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.1-SNAPSHOT + 3.1.1 analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 01bf2d95..9ea926a9 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.1-SNAPSHOT + 3.1.1 analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 574da47e..c4be102e 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.1-SNAPSHOT + 3.1.1 analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index 7fff4f43..f1038914 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.1-SNAPSHOT + 3.1.1 analytics diff --git a/pom.xml b/pom.xml index 76500542..4374c2da 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.1.1-SNAPSHOT + 3.1.1 pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - HEAD + analytics-parent-3.1.1 From 83ee40bf078c33d8fdf8b7a2e888e153503b52b4 Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Mon, 31 May 2021 15:29:27 -0700 Subject: [PATCH 102/272] [maven-release-plugin] prepare for next development iteration --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 7b6f0d39..3314dcab 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.1 + 3.1.2-SNAPSHOT analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index edab56af..5214e28f 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.1 + 3.1.2-SNAPSHOT analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 9ea926a9..2dfba6d1 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.1 + 3.1.2-SNAPSHOT analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index c4be102e..efcf65a1 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.1 + 3.1.2-SNAPSHOT analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index f1038914..d6cb1fe5 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.1 + 3.1.2-SNAPSHOT analytics diff --git a/pom.xml b/pom.xml index 4374c2da..5c462170 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.1.1 + 3.1.2-SNAPSHOT pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - analytics-parent-3.1.1 + HEAD From 4de8118280f289ba5c168872149d4f713cc9f787 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Sun, 6 Jun 2021 22:35:40 -0300 Subject: [PATCH 103/272] setting up circleci once again --- .circleci/config.yml | 134 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..ad2d29ce --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,134 @@ +version: 2 +jobs: + java-base-test: &java-base-test + working_directory: ~/analytics-java + docker: + - image: circleci/openjdk:8-jdk-browsers + steps: + - checkout + - restore_cache: + key: maven-dep-cache-{{ checksum "pom.xml" }} + - run: mvn spotless:check animal-sniffer:check test verify + - run: + name: Test Failed + when: on_fail + command: | + wget https://raw.githubusercontent.com/segmentio/circleci-notifications/master/slack-notify-branch.sh + chmod u+x slack-notify-branch.sh + BUILD_STATUS="Failed" NOTIFY_BRANCH="master" ./slack-notify-branch.sh + - run: mvn package -B + - save_cache: + key: maven-dep-cache-{{ checksum "pom.xml" }} + paths: + - ~/.m2 + - persist_to_workspace: + root: . + paths: [.] + + test-jdklatest: + <<: *java-base-test + docker: + - image: circleci/openjdk + + test-jdk11: + <<: *java-base-test + docker: + - image: circleci/openjdk:11-jdk-browsers + + test-jdk8: + <<: *java-base-test + docker: + - image: circleci/openjdk:8-jdk-browsers + + test: + <<: *java-base-test + docker: + - image: circleci/openjdk:11-jdk-browsers + + publish: + <<: *java-base-test + docker: + - image: circleci/openjdk:8-jdk-browsers + environment: + CIRCLE_JDK_VERSION: oraclejdk8 + steps: + - checkout + - attach_workspace: { at: . } + - run: .buildscript/deploy_snapshot.sh + + coverage: + <<: *java-base-test + docker: + - image: circleci/openjdk:8-jdk-browsers + steps: + - checkout + - attach_workspace: { at: . } + - run: mvn cobertura:cobertura + - run: bash <(curl -s https://codecov.io/bash) + + e2e: + <<: *java-base-test + docker: + - image: circleci/openjdk:8-jdk-browsers + steps: + - checkout + - attach_workspace: { at: . } + - run: .buildscript/e2e.sh + + snyk: + <<: *java-base-test + docker: + - image: circleci/openjdk:8-jdk-browsers + steps: + - checkout + - attach_workspace: { at: . } + - run: + name: Snyk + command: curl -sL https://raw.githubusercontent.com/segmentio/snyk_helpers/master/initialization/snyk.sh | sh + environment: + SNYK_FAIL_ON: upgradable + SNYK_SEVERITY_THRESHOLD: high + +workflows: + version: 2 + multi-test: + jobs: + - test-jdklatest + - test-jdk11 + - test-jdk8 + static_analysis: + jobs: + - test + - coverage: + requires: + - test + - snyk: + context: snyk + requires: + - test + test_and_publish: + jobs: + - test: + filters: + branches: + only: master + - publish: + requires: + - test + filters: + branches: + only: master + scheduled_e2e_test: + triggers: + - schedule: + cron: "5 * * * *" + filters: + branches: + only: + - master + - scheduled_e2e_testing + jobs: + - test + - e2e: + requires: + - test From a800df00e9f05dc1510b035f6afc66e50505d9f0 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Sun, 6 Jun 2021 22:36:47 -0300 Subject: [PATCH 104/272] spotless --- .../java/com/segment/analytics/internal/AnalyticsClient.java | 2 +- .../com/segment/analytics/internal/AnalyticsClientTest.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index dbd15944..292d54a7 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -141,7 +141,7 @@ public void enqueue(Message message) { try { messageQueue.put(message); - currentQueueSizeInBytes =+ messageSizeInBytes(message); + currentQueueSizeInBytes = +messageSizeInBytes(message); if (isBackPressured()) { log.print(VERBOSE, "Maximum storage size has been hit. Flushing..."); diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 4fcb61f9..20c4926d 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -221,7 +221,8 @@ public void flushWhenReachesMaxSize() throws InterruptedException { properties.put("property3", generateMassDataOfSize(MAX_BYTE_SIZE + 10)); for (int i = 0; i < 10; i++) { - TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); + TrackMessage bigMessage = + TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); client.enqueue(bigMessage); } From 6a7b4bccd0083705efcdbcf721a2c3f5188613f4 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Fri, 11 Jun 2021 22:36:54 -0300 Subject: [PATCH 105/272] fixing calculation of payload size --- .../java/com/segment/analytics/Analytics.java | 3 +++ .../analytics/internal/AnalyticsClient.java | 18 +++++++++------- .../internal/AnalyticsClientTest.java | 21 +++++++++++++++++-- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index 1ffd8f28..02cfffc8 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -260,6 +260,9 @@ public Builder maximumQueueSizeInBytes(int bytes) { if (bytes < 1) { throw new IllegalArgumentException("maximumQueueSizeInBytes must not be less than 1."); } + if (bytes > 500 * 1024) { + throw new IllegalArgumentException("Segment can only allows a maximum payload size of 500kb per batch request"); + } this.maximumQueueSizeInBytes = bytes; return this; } diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 292d54a7..6cdd755a 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -104,6 +104,7 @@ public static AnalyticsClient create( this.currentQueueSizeInBytes = 0; + looperExecutor.submit(new Looper()); flushScheduler = Executors.newScheduledThreadPool(1, threadFactory); @@ -125,8 +126,9 @@ public int messageSizeInBytes(Message message) { return stringifiedMessage.length(); } - private Boolean isBackPressured() { - return this.currentQueueSizeInBytes >= this.maximumQueueByteSize; + private Boolean isBackPressuredAfterSize(int incomingSize) { + int POISON_BYTE_SIZE = messageSizeInBytes(FlushMessage.POISON); + return (this.currentQueueSizeInBytes + incomingSize + POISON_BYTE_SIZE) >= this.maximumQueueByteSize; } public boolean offer(Message message) { @@ -141,13 +143,15 @@ public void enqueue(Message message) { try { messageQueue.put(message); - currentQueueSizeInBytes = +messageSizeInBytes(message); - if (isBackPressured()) { - log.print(VERBOSE, "Maximum storage size has been hit. Flushing..."); + int messageByteSize = messageSizeInBytes(message); + if (isBackPressuredAfterSize(messageByteSize)) { + currentQueueSizeInBytes = messageByteSize; + messageQueue.put(FlushMessage.POISON); - enqueue(FlushMessage.POISON); - currentQueueSizeInBytes = 0; + log.print(VERBOSE, String.format("Maximum storage size has been hit %d. Flushing...", currentQueueSizeInBytes)); + } else { + currentQueueSizeInBytes += messageByteSize; } } catch (InterruptedException e) { log.print(ERROR, e, "Interrupted while adding message %s.", message); diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 20c4926d..06316280 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -202,7 +202,7 @@ public void dontFlushUntilReachesMaxSize() throws InterruptedException { AnalyticsClient client = newClient(); Map properties = new HashMap(); - properties.put("property2", generateMassDataOfSize(MAX_BYTE_SIZE - 500)); + properties.put("property2", generateMassDataOfSize(MAX_BYTE_SIZE - 200)); TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); @@ -218,7 +218,7 @@ public void flushWhenReachesMaxSize() throws InterruptedException { AnalyticsClient client = newClient(); Map properties = new HashMap(); - properties.put("property3", generateMassDataOfSize(MAX_BYTE_SIZE + 10)); + properties.put("property3", generateMassDataOfSize(MAX_BYTE_SIZE)); for (int i = 0; i < 10; i++) { TrackMessage bigMessage = @@ -231,6 +231,23 @@ public void flushWhenReachesMaxSize() throws InterruptedException { verify(networkExecutor, times(10)).submit(any(Runnable.class)); } + @Test + public void flushWhenMultipleMessagesReachesMaxSize() throws InterruptedException { + AnalyticsClient client = newClient(); + Map properties = new HashMap(); + properties.put("property3", generateMassDataOfSize((MAX_BYTE_SIZE - 190) / 10)); + + for (int i = 0; i < 10; i++) { + TrackMessage bigMessage = + TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); + client.enqueue(bigMessage); + } + + wait(messageQueue); + + verify(networkExecutor, times(1)).submit(any(Runnable.class)); + } + @Test public void enqueueBeforeMaxDoesNotTriggerFlush() { messageQueue = new LinkedBlockingQueue<>(); From c547f63ebee1d285b82ffafdc2e7a32fd627271b Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Fri, 11 Jun 2021 23:19:49 -0300 Subject: [PATCH 106/272] fixing queue size log report --- .../com/segment/analytics/internal/AnalyticsClient.java | 7 ++++--- .../segment/analytics/internal/AnalyticsClientTest.java | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 6cdd755a..297cc8af 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -144,14 +144,15 @@ public void enqueue(Message message) { try { messageQueue.put(message); + int tempSize = this.currentQueueSizeInBytes; int messageByteSize = messageSizeInBytes(message); if (isBackPressuredAfterSize(messageByteSize)) { - currentQueueSizeInBytes = messageByteSize; + this.currentQueueSizeInBytes = messageByteSize; messageQueue.put(FlushMessage.POISON); - log.print(VERBOSE, String.format("Maximum storage size has been hit %d. Flushing...", currentQueueSizeInBytes)); + log.print(VERBOSE, "Maximum storage size has been hit Flushing..."); } else { - currentQueueSizeInBytes += messageByteSize; + this.currentQueueSizeInBytes += messageByteSize; } } catch (InterruptedException e) { log.print(ERROR, e, "Interrupted while adding message %s.", message); diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 06316280..f925622b 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -235,7 +235,7 @@ public void flushWhenReachesMaxSize() throws InterruptedException { public void flushWhenMultipleMessagesReachesMaxSize() throws InterruptedException { AnalyticsClient client = newClient(); Map properties = new HashMap(); - properties.put("property3", generateMassDataOfSize((MAX_BYTE_SIZE - 190) / 10)); + properties.put("property3", generateMassDataOfSize(MAX_BYTE_SIZE / 9)); for (int i = 0; i < 10; i++) { TrackMessage bigMessage = From ab39ec19372f662a1ced74d8d370ee4036c3ffa7 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Fri, 11 Jun 2021 23:20:30 -0300 Subject: [PATCH 107/272] comment --- .../com/segment/analytics/internal/AnalyticsClientTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index f925622b..4a2a2ace 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -60,9 +60,10 @@ public class AnalyticsClientTest { Backo.builder().base(TimeUnit.NANOSECONDS, 1).factor(1).build(); private int DEFAULT_RETRIES = 10; - private int MAX_BYTE_SIZE = 1024 * 50; // 50kb + private int MAX_BYTE_SIZE = 1024 * 500; // 500kb Log log = Log.NONE; + ThreadFactory threadFactory; @Mock BlockingQueue messageQueue; @Mock SegmentService segmentService; From 741aabe4b87778a3b8de0bf6f366312e482ec809 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Fri, 11 Jun 2021 23:23:23 -0300 Subject: [PATCH 108/272] spotless --- analytics/src/main/java/com/segment/analytics/Analytics.java | 3 ++- .../java/com/segment/analytics/internal/AnalyticsClient.java | 4 ++-- .../com/segment/analytics/internal/AnalyticsClientTest.java | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index 02cfffc8..2b6061ab 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -261,7 +261,8 @@ public Builder maximumQueueSizeInBytes(int bytes) { throw new IllegalArgumentException("maximumQueueSizeInBytes must not be less than 1."); } if (bytes > 500 * 1024) { - throw new IllegalArgumentException("Segment can only allows a maximum payload size of 500kb per batch request"); + throw new IllegalArgumentException( + "Segment can only allows a maximum payload size of 500kb per batch request"); } this.maximumQueueSizeInBytes = bytes; return this; diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 297cc8af..79856906 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -104,7 +104,6 @@ public static AnalyticsClient create( this.currentQueueSizeInBytes = 0; - looperExecutor.submit(new Looper()); flushScheduler = Executors.newScheduledThreadPool(1, threadFactory); @@ -128,7 +127,8 @@ public int messageSizeInBytes(Message message) { private Boolean isBackPressuredAfterSize(int incomingSize) { int POISON_BYTE_SIZE = messageSizeInBytes(FlushMessage.POISON); - return (this.currentQueueSizeInBytes + incomingSize + POISON_BYTE_SIZE) >= this.maximumQueueByteSize; + int sizeAfterAdd = this.currentQueueSizeInBytes + incomingSize + POISON_BYTE_SIZE; + return sizeAfterAdd >= this.maximumQueueByteSize; } public boolean offer(Message message) { diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 4a2a2ace..02bc84b6 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -63,7 +63,7 @@ public class AnalyticsClientTest { private int MAX_BYTE_SIZE = 1024 * 500; // 500kb Log log = Log.NONE; - + ThreadFactory threadFactory; @Mock BlockingQueue messageQueue; @Mock SegmentService segmentService; From d2638a36b0f44bbf4c39fa12b857c62e8a569ff8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Jun 2021 05:45:24 +0000 Subject: [PATCH 109/272] Bump mockito-core from 3.8.0 to 3.11.1 Bumps [mockito-core](https://github.com/mockito/mockito) from 3.8.0 to 3.11.1. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v3.8.0...v3.11.1) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5c462170..269ef10d 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ 4.13.2 1.2.0 3.19.0 - 3.8.0 + 3.11.1 From ac37ef583d14a308847bedfe4ffbcd98832cd34b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Jun 2021 05:46:52 +0000 Subject: [PATCH 110/272] Bump spring-boot-autoconfigure from 2.4.4 to 2.5.1 Bumps [spring-boot-autoconfigure](https://github.com/spring-projects/spring-boot) from 2.4.4 to 2.5.1. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v2.4.4...v2.5.1) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-autoconfigure dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5c462170..37613c69 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ 4.9.1 30.1.1-jre 1.0.0 - 2.4.4 + 2.5.1 0.6.0.20150202 From 7be2b1293cdd0f5b1f6a58cbdd9f0a29cd25fafe Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Mon, 14 Jun 2021 16:13:53 -0700 Subject: [PATCH 111/272] Changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54b0fb77..7ad4a855 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# Version 3.1.2 (June 14, 2021) + +**Pull Requests Merged:** + +- [Fix](https://github.com/segmentio/analytics-java/pull/245) Fix issues around backpressure calculation + # Version 3.1.1 (May 31, 2021) **Pull Requests Merged:** From 2d295cbec2cb2a5137e33112b9a6b2d54838457b Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Mon, 14 Jun 2021 16:14:40 -0700 Subject: [PATCH 112/272] [maven-release-plugin] prepare release analytics-parent-3.1.2 --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 3314dcab..2b307405 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.2-SNAPSHOT + 3.1.2 analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index 5214e28f..48940c30 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.2-SNAPSHOT + 3.1.2 analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 2dfba6d1..343b0d89 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.2-SNAPSHOT + 3.1.2 analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index efcf65a1..028a3931 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.2-SNAPSHOT + 3.1.2 analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index d6cb1fe5..86c9a348 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.2-SNAPSHOT + 3.1.2 analytics diff --git a/pom.xml b/pom.xml index 5c462170..1ec8f30b 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.1.2-SNAPSHOT + 3.1.2 pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - HEAD + analytics-parent-3.1.2 From 16c04e4511793a7945cfab96f62c74585b1420ff Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Mon, 14 Jun 2021 16:14:46 -0700 Subject: [PATCH 113/272] [maven-release-plugin] prepare for next development iteration --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 2b307405..137df7b2 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.2 + 3.1.3-SNAPSHOT analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index 48940c30..d68b656f 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.2 + 3.1.3-SNAPSHOT analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 343b0d89..35fbf4a5 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.2 + 3.1.3-SNAPSHOT analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 028a3931..1f6d0d8d 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.2 + 3.1.3-SNAPSHOT analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index 86c9a348..92ce0151 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.2 + 3.1.3-SNAPSHOT analytics diff --git a/pom.xml b/pom.xml index 1ec8f30b..d8589e42 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.1.2 + 3.1.3-SNAPSHOT pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - analytics-parent-3.1.2 + HEAD From 9741e38f5c65f76ee75f56d80809009a730f2866 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Jun 2021 23:23:59 +0000 Subject: [PATCH 114/272] Bump spotless-maven-plugin from 2.9.0 to 2.12.0 Bumps [spotless-maven-plugin](https://github.com/diffplug/spotless) from 2.9.0 to 2.12.0. - [Release notes](https://github.com/diffplug/spotless/releases) - [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md) - [Commits](https://github.com/diffplug/spotless/compare/lib/2.9.0...lib/2.12.0) --- updated-dependencies: - dependency-name: com.diffplug.spotless:spotless-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 97efa9dc..0e2afba5 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ UTF-8 8 1.5.0 - 2.9.0 + 2.12.0 2.9.0 1.8.1 From ceaa38070ba9831d50bc30e04ba3a393377257ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Jun 2021 23:24:09 +0000 Subject: [PATCH 115/272] Bump gson from 2.8.6 to 2.8.7 Bumps [gson](https://github.com/google/gson) from 2.8.6 to 2.8.7. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.8.6...gson-parent-2.8.7) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index d8589e42..1b60c2db 100644 --- a/pom.xml +++ b/pom.xml @@ -31,10 +31,10 @@ 1.4.32 2.9.0 2.9.0 - 1.7.5 + 1.8.1 3.0.1 - 2.8.6 + 2.8.7 4.3.0 4.9.1 30.1.1-jre From 1075dcecded6bd7547d0c8621b81a4bd2c163c13 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Jun 2021 16:02:03 +0000 Subject: [PATCH 116/272] Bump spotless-maven-plugin from 2.12.0 to 2.12.1 Bumps [spotless-maven-plugin](https://github.com/diffplug/spotless) from 2.12.0 to 2.12.1. - [Release notes](https://github.com/diffplug/spotless/releases) - [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md) - [Commits](https://github.com/diffplug/spotless/compare/lib/2.12.0...lib/2.12.1) --- updated-dependencies: - dependency-name: com.diffplug.spotless:spotless-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 937415c8..d34cf41a 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ UTF-8 8 1.5.0 - 2.12.0 + 2.12.1 2.9.0 1.8.1 From a9c3fd0bfd64ec72849c96ceef46718f5d4cbdcf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Jun 2021 16:02:08 +0000 Subject: [PATCH 117/272] Bump mockito-core from 3.11.1 to 3.11.2 Bumps [mockito-core](https://github.com/mockito/mockito) from 3.11.1 to 3.11.2. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v3.11.1...v3.11.2) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 937415c8..b7eedaa4 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ 4.13.2 1.2.0 3.19.0 - 3.11.1 + 3.11.2 From c26e027bcbfe45f7a80f2d920c778979405fa813 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Jun 2021 18:26:49 +0000 Subject: [PATCH 118/272] Bump assertj-core from 3.19.0 to 3.20.2 Bumps [assertj-core](https://github.com/assertj/assertj-core) from 3.19.0 to 3.20.2. - [Release notes](https://github.com/assertj/assertj-core/releases) - [Commits](https://github.com/assertj/assertj-core/compare/assertj-core-3.19.0...assertj-core-3.20.2) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7f378d1e..a27285df 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ 4.13.2 1.2.0 - 3.19.0 + 3.20.2 3.11.2 From 1b5cc2dcc87639ee1b0b39e0e22d8d99ff5658f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Jun 2021 16:02:04 +0000 Subject: [PATCH 119/272] Bump kotlin.version from 1.5.0 to 1.5.20 Bumps `kotlin.version` from 1.5.0 to 1.5.20. Updates `kotlin-stdlib` from 1.5.0 to 1.5.20 - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/v1.5.20/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/compare/v1.5.0...v1.5.20) Updates `kotlin-maven-plugin` from 1.5.0 to 1.5.20 --- updated-dependencies: - dependency-name: org.jetbrains.kotlin:kotlin-stdlib dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.jetbrains.kotlin:kotlin-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7f378d1e..3502e49f 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ UTF-8 8 - 1.5.0 + 1.5.20 2.12.1 2.9.0 1.8.1 From d635bf793024d7d123a35422b9b6dc32b544056b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Jun 2021 16:02:11 +0000 Subject: [PATCH 120/272] Bump spring-boot-autoconfigure from 2.5.1 to 2.5.2 Bumps [spring-boot-autoconfigure](https://github.com/spring-projects/spring-boot) from 2.5.1 to 2.5.2. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v2.5.1...v2.5.2) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-autoconfigure dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7f378d1e..2a403919 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ 4.9.1 30.1.1-jre 1.0.0 - 2.5.1 + 2.5.2 0.6.0.20150202 From 8f497c61fdd36e8b5802de9ca12dcfd4360f3d81 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Mon, 28 Jun 2021 23:02:37 -0300 Subject: [PATCH 121/272] retry should have a default set to 3 --- .../java/com/segment/analytics/Analytics.java | 3 ++ .../analytics/AnalyticsBuilderTest.java | 2 +- .../internal/AnalyticsClientTest.java | 36 ++++++++++++++++++- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index 2b6061ab..b52e42dc 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -367,6 +367,9 @@ public Analytics build() { if (maximumQueueSizeInBytes == 0) { maximumQueueSizeInBytes = MESSAGE_QUEUE_MAX_BYTE_SIZE; } + if (maximumFlushAttempts == 0) { + maximumFlushAttempts = 3; + } if (messageTransformers == null) { messageTransformers = Collections.emptyList(); } else { diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java index e910f0af..206bd425 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java @@ -96,7 +96,7 @@ public void nullLog() { } @Test - public void negativeRetryCount() { + public void invalidRetryCount() { try { builder.retries(0); fail("Should fail for retries less than 1"); diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 02bc84b6..eb7d1fdd 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -90,7 +90,7 @@ AnalyticsClient newClient() { segmentService, 50, TimeUnit.HOURS.toMillis(1), - DEFAULT_RETRIES, + 0, MAX_BYTE_SIZE, log, threadFactory, @@ -411,6 +411,40 @@ public boolean matches(IOException exception) { })); } + @Test + public void hasDefaultRetriesSetTo3() { + AnalyticsClient client = newClient(); + TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); + Batch batch = batchFor(trackMessage); + + when(segmentService.upload(batch)) + .thenAnswer( + new Answer>() { + public Call answer(InvocationOnMock invocation) { + Response failResponse = + Response.error(429, ResponseBody.create(null, "Not Found")); + return Calls.response(failResponse); + } + }); + + BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, 3); + batchUploadTask.run(); + + // DEFAULT_RETRIES == maxRetries + // tries 11(one normal run + 10 retries) + verify(segmentService, times(4)).upload(batch); + verify(callback) + .failure( + eq(trackMessage), + argThat( + new ArgumentMatcher() { + @Override + public boolean matches(IOException exception) { + return exception.getMessage().equals("4 retries exhausted"); + } + })); + } + @Test public void flushWhenNotShutDown() throws InterruptedException { AnalyticsClient client = newClient(); From 7f737a20a93b762c145345bffb4ccb6bf21d2ee9 Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Fri, 9 Jul 2021 11:34:52 -0700 Subject: [PATCH 122/272] update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ad4a855..7ebd7554 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# Version 3.1.3 (July 9, 2021) + +- [Fix](https://github.com/segmentio/analytics-java/pull/256) Set the default retries to 3 +- [Chore] Dependency upgrades + # Version 3.1.2 (June 14, 2021) **Pull Requests Merged:** From 801b666968f2f030f4c9d2f7a139a0894158a50d Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Fri, 9 Jul 2021 11:35:36 -0700 Subject: [PATCH 123/272] [maven-release-plugin] prepare release analytics-parent-3.1.3 --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 137df7b2..ef888389 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.3-SNAPSHOT + 3.1.3 analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index d68b656f..fc120d48 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.3-SNAPSHOT + 3.1.3 analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 35fbf4a5..74873165 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.3-SNAPSHOT + 3.1.3 analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 1f6d0d8d..17ecc21c 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.3-SNAPSHOT + 3.1.3 analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index 92ce0151..ecf5b6a2 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.3-SNAPSHOT + 3.1.3 analytics diff --git a/pom.xml b/pom.xml index cd8405fb..6aabad2e 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.1.3-SNAPSHOT + 3.1.3 pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - HEAD + analytics-parent-3.1.3 From 5c01b182aee87c96d9410afef1c63ea0d8fdd5cc Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Fri, 9 Jul 2021 11:35:42 -0700 Subject: [PATCH 124/272] [maven-release-plugin] prepare for next development iteration --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index ef888389..010f05ca 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.3 + 3.1.4-SNAPSHOT analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index fc120d48..e6b891c1 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.3 + 3.1.4-SNAPSHOT analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 74873165..0de43157 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.3 + 3.1.4-SNAPSHOT analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 17ecc21c..1d98319d 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.3 + 3.1.4-SNAPSHOT analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index ecf5b6a2..4a6c55df 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.3 + 3.1.4-SNAPSHOT analytics diff --git a/pom.xml b/pom.xml index 6aabad2e..db6fd7e9 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.1.3 + 3.1.4-SNAPSHOT pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - analytics-parent-3.1.3 + HEAD From c8deceb095ff8160169777eacd79a65ed16dde5b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jul 2021 16:02:14 +0000 Subject: [PATCH 125/272] Bump kotlin.version from 1.5.20 to 1.5.21 Bumps `kotlin.version` from 1.5.20 to 1.5.21. Updates `kotlin-stdlib` from 1.5.20 to 1.5.21 - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/compare/v1.5.20...v1.5.21) Updates `kotlin-maven-plugin` from 1.5.20 to 1.5.21 --- updated-dependencies: - dependency-name: org.jetbrains.kotlin:kotlin-stdlib dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.jetbrains.kotlin:kotlin-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index db6fd7e9..32390dcb 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ UTF-8 8 - 1.5.20 + 1.5.21 2.12.1 2.9.0 1.8.1 From fa06587049896208d16be3d1510fc43701b48464 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jul 2021 16:02:24 +0000 Subject: [PATCH 126/272] Bump auto.version from 1.8.1 to 1.8.2 Bumps `auto.version` from 1.8.1 to 1.8.2. Updates `auto-value` from 1.8.1 to 1.8.2 - [Release notes](https://github.com/google/auto/releases) - [Commits](https://github.com/google/auto/compare/auto-value-1.8.1...auto-value-1.8.2) Updates `auto-value-annotations` from 1.8.1 to 1.8.2 - [Release notes](https://github.com/google/auto/releases) - [Commits](https://github.com/google/auto/compare/auto-value-1.8.1...auto-value-1.8.2) --- updated-dependencies: - dependency-name: com.google.auto.value:auto-value dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.google.auto.value:auto-value-annotations dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index db6fd7e9..a9559bbc 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 1.5.20 2.12.1 2.9.0 - 1.8.1 + 1.8.2 3.0.1 2.8.7 From 40612183d779a9bb2aa56f88021dfd4abd9185be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 May 2021 06:05:15 +0000 Subject: [PATCH 127/272] Bump kotlin.version from 1.4.32 to 1.5.0 Bumps `kotlin.version` from 1.4.32 to 1.5.0. Updates `kotlin-stdlib` from 1.4.32 to 1.5.0 - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/commits) Updates `kotlin-maven-plugin` from 1.4.32 to 1.5.0 Signed-off-by: dependabot[bot] --- pom.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index a7c0a071..7c4f5fa7 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.1.4-SNAPSHOT + 3.1.3-SNAPSHOT pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -28,25 +28,25 @@ UTF-8 8 - 1.5.21 - 2.12.1 + 1.5.0 + 2.9.0 2.9.0 - 1.8.2 + 1.8.1 3.0.1 - 2.8.7 + 2.8.6 4.3.0 4.9.1 30.1.1-jre 1.0.0 - 2.5.2 + 2.4.4 0.6.0.20150202 4.13.2 1.2.0 - 3.20.2 - 3.11.2 + 3.19.0 + 3.8.0 From fff550963b30597a5a51ef3f0441323be3644623 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Jun 2021 23:24:09 +0000 Subject: [PATCH 128/272] Bump gson from 2.8.6 to 2.8.7 Bumps [gson](https://github.com/google/gson) from 2.8.6 to 2.8.7. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.8.6...gson-parent-2.8.7) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7c4f5fa7..f0b804cd 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ 1.8.1 3.0.1 - 2.8.6 + 2.8.7 4.3.0 4.9.1 30.1.1-jre From 17885ceef1a829b3d9be7b6f2a5452da526beec8 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Sun, 15 Aug 2021 22:01:29 -0300 Subject: [PATCH 129/272] batching queue to regard to api limits --- .../java/com/segment/analytics/Analytics.java | 5 +--- .../analytics/internal/AnalyticsClient.java | 2 +- .../internal/AnalyticsClientTest.java | 30 +++++++++++++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index b52e42dc..ff6a640f 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -260,10 +260,7 @@ public Builder maximumQueueSizeInBytes(int bytes) { if (bytes < 1) { throw new IllegalArgumentException("maximumQueueSizeInBytes must not be less than 1."); } - if (bytes > 500 * 1024) { - throw new IllegalArgumentException( - "Segment can only allows a maximum payload size of 500kb per batch request"); - } + this.maximumQueueSizeInBytes = bytes; return this; } diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 79856906..51ca9858 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -128,7 +128,7 @@ public int messageSizeInBytes(Message message) { private Boolean isBackPressuredAfterSize(int incomingSize) { int POISON_BYTE_SIZE = messageSizeInBytes(FlushMessage.POISON); int sizeAfterAdd = this.currentQueueSizeInBytes + incomingSize + POISON_BYTE_SIZE; - return sizeAfterAdd >= this.maximumQueueByteSize; + return sizeAfterAdd >= Math.min(this.maximumQueueByteSize, 1024 * 500); } public boolean offer(Message message) { diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index eb7d1fdd..3ca28430 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -232,6 +232,36 @@ public void flushWhenReachesMaxSize() throws InterruptedException { verify(networkExecutor, times(10)).submit(any(Runnable.class)); } + @Test + public void flushHowManyTimesNecessaryToStayWithinLimit() throws InterruptedException { + AnalyticsClient client = new AnalyticsClient( + messageQueue, + segmentService, + 50, + TimeUnit.HOURS.toMillis(1), + 0, + MAX_BYTE_SIZE * 4, + log, + threadFactory, + networkExecutor, + Collections.singletonList(callback), + isShutDown); + + Map properties = new HashMap(); + + properties.put("property3", generateMassDataOfSize(MAX_BYTE_SIZE)); + + for (int i = 0; i < 4; i++) { + TrackMessage bigMessage = + TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); + client.enqueue(bigMessage); + } + + wait(messageQueue); + + verify(networkExecutor, times(4)).submit(any(Runnable.class)); + } + @Test public void flushWhenMultipleMessagesReachesMaxSize() throws InterruptedException { AnalyticsClient client = newClient(); From 124adce39d204ed7277514ae1b41dd8df908158c Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Sun, 15 Aug 2021 22:08:05 -0300 Subject: [PATCH 130/272] using dependency versions that already exists --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- .../internal/AnalyticsClientTest.java | 25 ++++++++++--------- 6 files changed, 18 insertions(+), 17 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 010f05ca..ef888389 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.4-SNAPSHOT + 3.1.3 analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index e6b891c1..fc120d48 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.4-SNAPSHOT + 3.1.3 analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 0de43157..74873165 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.4-SNAPSHOT + 3.1.3 analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 1d98319d..17ecc21c 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.4-SNAPSHOT + 3.1.3 analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index 4a6c55df..ecf5b6a2 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.4-SNAPSHOT + 3.1.3 analytics diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 3ca28430..3851d066 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -234,18 +234,19 @@ public void flushWhenReachesMaxSize() throws InterruptedException { @Test public void flushHowManyTimesNecessaryToStayWithinLimit() throws InterruptedException { - AnalyticsClient client = new AnalyticsClient( - messageQueue, - segmentService, - 50, - TimeUnit.HOURS.toMillis(1), - 0, - MAX_BYTE_SIZE * 4, - log, - threadFactory, - networkExecutor, - Collections.singletonList(callback), - isShutDown); + AnalyticsClient client = + new AnalyticsClient( + messageQueue, + segmentService, + 50, + TimeUnit.HOURS.toMillis(1), + 0, + MAX_BYTE_SIZE * 4, + log, + threadFactory, + networkExecutor, + Collections.singletonList(callback), + isShutDown); Map properties = new HashMap(); From d5147d785881e9232a9ab64cdf85d36f34382e22 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 16:02:05 +0000 Subject: [PATCH 131/272] Bump spring-boot-autoconfigure from 2.4.4 to 2.5.4 Bumps [spring-boot-autoconfigure](https://github.com/spring-projects/spring-boot) from 2.4.4 to 2.5.4. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v2.4.4...v2.5.4) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-autoconfigure dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f0b804cd..35745bc9 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ 4.9.1 30.1.1-jre 1.0.0 - 2.4.4 + 2.5.4 0.6.0.20150202 From 284cba1e33f5cba3b19788a003c1dc62ab7d946a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 16:02:12 +0000 Subject: [PATCH 132/272] Bump auto.version from 1.8.1 to 1.8.2 Bumps `auto.version` from 1.8.1 to 1.8.2. Updates `auto-value` from 1.8.1 to 1.8.2 - [Release notes](https://github.com/google/auto/releases) - [Commits](https://github.com/google/auto/compare/auto-value-1.8.1...auto-value-1.8.2) Updates `auto-value-annotations` from 1.8.1 to 1.8.2 - [Release notes](https://github.com/google/auto/releases) - [Commits](https://github.com/google/auto/compare/auto-value-1.8.1...auto-value-1.8.2) --- updated-dependencies: - dependency-name: com.google.auto.value:auto-value dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.google.auto.value:auto-value-annotations dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f0b804cd..30452138 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 1.5.0 2.9.0 2.9.0 - 1.8.1 + 1.8.2 3.0.1 2.8.7 From 79224bfed2b0065345b54c344091b3c3e0dd4ed8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 16:02:15 +0000 Subject: [PATCH 133/272] Bump assertj-core from 3.19.0 to 3.20.2 Bumps [assertj-core](https://github.com/assertj/assertj-core) from 3.19.0 to 3.20.2. - [Release notes](https://github.com/assertj/assertj-core/releases) - [Commits](https://github.com/assertj/assertj-core/compare/assertj-core-3.19.0...assertj-core-3.20.2) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f0b804cd..51f60e90 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ 4.13.2 1.2.0 - 3.19.0 + 3.20.2 3.8.0 From 82d3d9a3b60ef2e7a36cc9b3c5b6bf2e0a42e06d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 16:02:18 +0000 Subject: [PATCH 134/272] Bump gson from 2.8.7 to 2.8.8 Bumps [gson](https://github.com/google/gson) from 2.8.7 to 2.8.8. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.8.7...gson-parent-2.8.8) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f0b804cd..fa8f051b 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ 1.8.1 3.0.1 - 2.8.7 + 2.8.8 4.3.0 4.9.1 30.1.1-jre From 6cd8c03a35dafe04e32aa5f925902a41df26743c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 16:02:58 +0000 Subject: [PATCH 135/272] Bump spotless-maven-plugin from 2.9.0 to 2.12.3 Bumps [spotless-maven-plugin](https://github.com/diffplug/spotless) from 2.9.0 to 2.12.3. - [Release notes](https://github.com/diffplug/spotless/releases) - [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md) - [Commits](https://github.com/diffplug/spotless/compare/lib/2.9.0...maven/2.12.3) --- updated-dependencies: - dependency-name: com.diffplug.spotless:spotless-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f0b804cd..2db3705b 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ UTF-8 8 1.5.0 - 2.9.0 + 2.12.3 2.9.0 1.8.1 From 8e4fee563b546c9788b02ac71ef7502cc451d70a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Aug 2021 17:37:47 +0000 Subject: [PATCH 136/272] Bump kotlin.version from 1.5.0 to 1.5.30 Bumps `kotlin.version` from 1.5.0 to 1.5.30. Updates `kotlin-stdlib` from 1.5.0 to 1.5.30 - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/compare/v1.5.0...v1.5.30) Updates `kotlin-maven-plugin` from 1.5.0 to 1.5.30 --- updated-dependencies: - dependency-name: org.jetbrains.kotlin:kotlin-stdlib dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.jetbrains.kotlin:kotlin-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index f0b804cd..831d2e0c 100644 --- a/pom.xml +++ b/pom.xml @@ -28,10 +28,10 @@ UTF-8 8 - 1.5.0 + 1.5.30 2.9.0 2.9.0 - 1.8.1 + 1.8.2 3.0.1 2.8.7 @@ -39,7 +39,7 @@ 4.9.1 30.1.1-jre 1.0.0 - 2.4.4 + 2.5.4 0.6.0.20150202 From cd0db70642dd806c7945d498d92817bf6a955e61 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Aug 2021 17:37:53 +0000 Subject: [PATCH 137/272] Bump mockito-core from 3.8.0 to 3.12.4 Bumps [mockito-core](https://github.com/mockito/mockito) from 3.8.0 to 3.12.4. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v3.8.0...v3.12.4) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index f0b804cd..62b2fe9e 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 1.5.0 2.9.0 2.9.0 - 1.8.1 + 1.8.2 3.0.1 2.8.7 @@ -39,14 +39,14 @@ 4.9.1 30.1.1-jre 1.0.0 - 2.4.4 + 2.5.4 0.6.0.20150202 4.13.2 1.2.0 3.19.0 - 3.8.0 + 3.12.4 From a4721690a3840b5d34645f425cca7c65f06f7245 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Thu, 26 Aug 2021 20:17:34 -0300 Subject: [PATCH 138/272] should priotize uploadURL over endpoint --- .../java/com/segment/analytics/Analytics.java | 10 +++++----- .../analytics/AnalyticsBuilderTest.java | 20 +++++++++++++++++++ pom.xml | 2 +- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index ff6a640f..a3449fb3 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -338,11 +338,11 @@ public Analytics build() { .create(); if (endpoint == null) { - endpoint = HttpUrl.parse(DEFAULT_ENDPOINT + DEFAULT_PATH); - } - - if (endpoint == null && uploadURL != null) { - endpoint = uploadURL; + if (uploadURL != null) { + endpoint = uploadURL; + } else { + endpoint = HttpUrl.parse(DEFAULT_ENDPOINT + DEFAULT_PATH); + } } if (client == null) { diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java index 206bd425..59b17ccc 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java @@ -3,6 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -282,6 +283,25 @@ public void buildsWithValidUploadURL() { assertThat(analytics).isNotNull(); } + @Test + public void buildsCorrectEndpointWithUploadURL() { + builder.setUploadURL("https://dummy.url/api/v1/segment/").build(); + String expectedURL = "https://dummy.url/api/v1/segment/"; + assertEquals(expectedURL, builder.endpoint.toString()); + } + + @Test + public void shouldPriotizeUploadURLOverEndpoint() { + builder + .endpoint("this wont be set anyway") + .setUploadURL("https://dummy.url/api/v1/segment/") + .build(); + String expectedURL = "https://dummy.url/api/v1/segment/"; + + assertEquals(expectedURL, builder.uploadURL.toString()); + assertNotEquals(expectedURL, "this wont be set anyway"); + } + @Test public void buildsCorrectURLWithUploadURL() { builder.setUploadURL("https://example.com/v2/batch/").build(); diff --git a/pom.xml b/pom.xml index 42c34612..3747e580 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.1.3-SNAPSHOT + 3.1.3 pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. From d309d6492b63b672e335312e3038d1c3c973c733 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Thu, 26 Aug 2021 20:30:34 -0300 Subject: [PATCH 139/272] had wrong assrt on test --- .../test/java/com/segment/analytics/AnalyticsBuilderTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java index 59b17ccc..05356e7b 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java @@ -299,7 +299,7 @@ public void shouldPriotizeUploadURLOverEndpoint() { String expectedURL = "https://dummy.url/api/v1/segment/"; assertEquals(expectedURL, builder.uploadURL.toString()); - assertNotEquals(expectedURL, "this wont be set anyway"); + assertNotEquals("this wont be set anyway", builder.endpoint.toString()); } @Test From 6c869634e01f5dec361574eea4b5937b0ec9c72e Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Tue, 31 Aug 2021 18:50:00 -0300 Subject: [PATCH 140/272] Update analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java --- .../test/java/com/segment/analytics/AnalyticsBuilderTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java index 05356e7b..6cee3590 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java @@ -291,7 +291,7 @@ public void buildsCorrectEndpointWithUploadURL() { } @Test - public void shouldPriotizeUploadURLOverEndpoint() { + public void shouldPrioritizeUploadURLOverEndpoint() { builder .endpoint("this wont be set anyway") .setUploadURL("https://dummy.url/api/v1/segment/") From 0c19726549204965b75de349b8754a97c7c80447 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Sep 2021 16:01:35 +0000 Subject: [PATCH 141/272] Bump spotless-maven-plugin from 2.12.3 to 2.13.0 Bumps [spotless-maven-plugin](https://github.com/diffplug/spotless) from 2.12.3 to 2.13.0. - [Release notes](https://github.com/diffplug/spotless/releases) - [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md) - [Commits](https://github.com/diffplug/spotless/compare/maven/2.12.3...lib/2.13.0) --- updated-dependencies: - dependency-name: com.diffplug.spotless:spotless-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c2f229f4..e3b40b4e 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ UTF-8 8 1.5.30 - 2.12.3 + 2.13.0 2.9.0 1.8.2 From 1060e535e2323928800418975b60498da5983f1b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Sep 2021 16:02:01 +0000 Subject: [PATCH 142/272] Bump kotlin.version from 1.5.30 to 1.5.31 Bumps `kotlin.version` from 1.5.30 to 1.5.31. Updates `kotlin-stdlib` from 1.5.30 to 1.5.31 - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/v1.5.31/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/compare/v1.5.30...v1.5.31) Updates `kotlin-maven-plugin` from 1.5.30 to 1.5.31 --- updated-dependencies: - dependency-name: org.jetbrains.kotlin:kotlin-stdlib dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.jetbrains.kotlin:kotlin-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e3b40b4e..cc2a775e 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ UTF-8 8 - 1.5.30 + 1.5.31 2.13.0 2.9.0 1.8.2 From 17f23c886b70f4c6634770e13f24148064bb76ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Sep 2021 16:02:08 +0000 Subject: [PATCH 143/272] Bump assertj-core from 3.20.2 to 3.21.0 Bumps [assertj-core](https://github.com/assertj/assertj-core) from 3.20.2 to 3.21.0. - [Release notes](https://github.com/assertj/assertj-core/releases) - [Commits](https://github.com/assertj/assertj-core/compare/assertj-core-3.20.2...assertj-core-3.21.0) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e3b40b4e..3bfe0682 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ 4.13.2 1.2.0 3.12.4 - 3.20.2 + 3.21.0 From 7f4686342d591486aca50381fb38afa9304973d5 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Wed, 22 Sep 2021 23:33:30 -0300 Subject: [PATCH 144/272] sending error code on exception --- .../java/com/segment/analytics/internal/AnalyticsClient.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 51ca9858..8f27d104 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -146,6 +146,7 @@ public void enqueue(Message message) { int tempSize = this.currentQueueSizeInBytes; int messageByteSize = messageSizeInBytes(message); + if (isBackPressuredAfterSize(messageByteSize)) { this.currentQueueSizeInBytes = messageByteSize; messageQueue.put(FlushMessage.POISON); @@ -316,8 +317,7 @@ boolean upload() { } client.log.print(DEBUG, "Could not upload batch %s. Giving up.", batch.sequence()); - - notifyCallbacksWithException(batch, new IOException("HTTP Error")); + notifyCallbacksWithException(batch, new IOException(response.errorBody().string())); return false; } catch (IOException error) { From 040154f2b814dc90d17cd72a7406b858bc4be324 Mon Sep 17 00:00:00 2001 From: Niall Moore Date: Thu, 23 Sep 2021 14:12:25 +0100 Subject: [PATCH 145/272] update PageMessage to allow for setting of category --- .../segment/analytics/messages/PageMessage.java | 15 ++++++++++++++- .../analytics/messages/PageMessageTest.java | 11 +++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java index 14692d90..c8f467fd 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java @@ -34,6 +34,9 @@ public static Builder builder(String name) { @Nullable public abstract Map properties(); + @Nullable + public abstract String category(); + public Builder toBuilder() { return new Builder(this); } @@ -42,11 +45,13 @@ public Builder toBuilder() { public static class Builder extends MessageBuilder { private String name; private Map properties; + private String category; private Builder(PageMessage page) { super(page); name = page.name(); properties = page.properties(); + category = page.category(); } private Builder(String name) { @@ -70,6 +75,14 @@ public Builder properties(Map properties) { return this; } + public Builder category(String category) { + if (category == null) { + throw new NullPointerException("Null category"); + } + this.category = category; + return this; + } + @Override Builder self() { return this; @@ -85,7 +98,7 @@ protected PageMessage realBuild( String userId, Map integrations) { return new AutoValue_PageMessage( - type, messageId, timestamp, context, anonymousId, userId, integrations, name, properties); + type, messageId, timestamp, context, anonymousId, userId, integrations, name, properties, category); } } } diff --git a/analytics-core/src/test/java/com/segment/analytics/messages/PageMessageTest.java b/analytics-core/src/test/java/com/segment/analytics/messages/PageMessageTest.java index 17e00c1e..b027d250 100644 --- a/analytics-core/src/test/java/com/segment/analytics/messages/PageMessageTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/messages/PageMessageTest.java @@ -25,16 +25,27 @@ public void invalidNameThrows() { } } + @Test + public void invalidCategoryThrows() { + try { + PageMessage.builder("name").category(null); + } catch (NullPointerException e) { + assertThat(e).hasMessage("Null category"); + } + } + @Test public void toBuilder() { PageMessage original = PageMessage.builder("name") .properties(ImmutableMap.of("foo", "bar")) .userId("userId") + .category("foobar") .build(); PageMessage copy = original.toBuilder().build(); assertThat(copy.name()).isEqualTo("name"); assertThat(copy.properties()).isEqualTo(ImmutableMap.of("foo", "bar")); + assertThat(copy.category()).isEqualTo("foobar"); } } From e70571d58607c4d7d63e1e0a11690522fc85b1db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Sep 2021 16:02:01 +0000 Subject: [PATCH 146/272] Bump spring-boot-autoconfigure from 2.5.4 to 2.5.5 Bumps [spring-boot-autoconfigure](https://github.com/spring-projects/spring-boot) from 2.5.4 to 2.5.5. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v2.5.4...v2.5.5) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-autoconfigure dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e3b40b4e..71f9a241 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ 4.9.1 30.1.1-jre 1.0.0 - 2.5.4 + 2.5.5 0.6.0.20150202 From 652b7b18a3620d3c58c48ee3ea3db0531cbaf60e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Sep 2021 16:02:10 +0000 Subject: [PATCH 147/272] Bump guava from 30.1.1-jre to 31.0-jre Bumps [guava](https://github.com/google/guava) from 30.1.1-jre to 31.0-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) --- updated-dependencies: - dependency-name: com.google.guava:guava dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e3b40b4e..fb795c73 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ 2.8.8 4.3.0 4.9.1 - 30.1.1-jre + 31.0-jre 1.0.0 2.5.4 0.6.0.20150202 From c582a763b4e360aa43ec53a40bdcc103a6d16ae1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Sep 2021 17:39:37 +0000 Subject: [PATCH 148/272] Bump spotless-maven-plugin from 2.13.0 to 2.14.0 Bumps [spotless-maven-plugin](https://github.com/diffplug/spotless) from 2.13.0 to 2.14.0. - [Release notes](https://github.com/diffplug/spotless/releases) - [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md) - [Commits](https://github.com/diffplug/spotless/compare/lib/2.13.0...lib/2.14.0) --- updated-dependencies: - dependency-name: com.diffplug.spotless:spotless-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9ced2539..2b392250 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ UTF-8 8 1.5.31 - 2.13.0 + 2.14.0 2.9.0 1.8.2 From 7c8fe0eaed40f29dfe4cdc7291fdf006f27bc381 Mon Sep 17 00:00:00 2001 From: Patrick Bassut Date: Sun, 3 Oct 2021 23:55:32 -0300 Subject: [PATCH 149/272] spotless fixes --- .../com/segment/analytics/messages/PageMessage.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java index c8f467fd..55fef551 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java @@ -98,7 +98,16 @@ protected PageMessage realBuild( String userId, Map integrations) { return new AutoValue_PageMessage( - type, messageId, timestamp, context, anonymousId, userId, integrations, name, properties, category); + type, + messageId, + timestamp, + context, + anonymousId, + userId, + integrations, + name, + properties, + category); } } } From 8ee755bf59e95513ef53c5cb82adec3f204ab34a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Nov 2021 16:02:18 +0000 Subject: [PATCH 150/272] Bump spotless-maven-plugin from 2.14.0 to 2.17.3 Bumps [spotless-maven-plugin](https://github.com/diffplug/spotless) from 2.14.0 to 2.17.3. - [Release notes](https://github.com/diffplug/spotless/releases) - [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md) - [Commits](https://github.com/diffplug/spotless/compare/lib/2.14.0...maven/2.17.3) --- updated-dependencies: - dependency-name: com.diffplug.spotless:spotless-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2b392250..af5b43ed 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ UTF-8 8 1.5.31 - 2.14.0 + 2.17.3 2.9.0 1.8.2 From d3cfe5aad27f444552f5acd1b79c7d4623fb9a7c Mon Sep 17 00:00:00 2001 From: Jorge Rodriguera Date: Thu, 11 Nov 2021 15:28:52 -0600 Subject: [PATCH 151/272] Initial PR intended as a draft please review approach and let me know if I should go ahead with implementing changes --- .../analytics/internal/AnalyticsClient.java | 31 +++++++++++++++++-- .../internal/AnalyticsClientTest.java | 29 ++++++++++++++--- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 8f27d104..4ce197c2 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -13,6 +13,7 @@ import com.segment.analytics.messages.Message; import com.segment.backo.Backo; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; @@ -120,14 +121,18 @@ public void run() { } public int messageSizeInBytes(Message message) { + //@jorgen25 test idea: Check if this is correctly testing byte size and not just char length with regular characters Gson gson = new Gson(); String stringifiedMessage = gson.toJson(message); - return stringifiedMessage.length(); + + int sizeInBytes = stringifiedMessage.getBytes(StandardCharsets.UTF_8).length; + return sizeInBytes; } private Boolean isBackPressuredAfterSize(int incomingSize) { int POISON_BYTE_SIZE = messageSizeInBytes(FlushMessage.POISON); int sizeAfterAdd = this.currentQueueSizeInBytes + incomingSize + POISON_BYTE_SIZE; + //@jorgen25 we should have this loose ints in a constant return sizeAfterAdd >= Math.min(this.maximumQueueByteSize, 1024 * 500); } @@ -141,12 +146,20 @@ public void enqueue(Message message) { return; } + //@jorgen25 test ideas: happy path: several messages did not go over limit + // sad path 1: many messages did not go over limit but last one makes it go over the limit + //sad path 2: single message that is way over the limit try { + //@jorgen25 message here could be regular msg, POISON or STOP, maybe just do regular logic if its regular + //message and if its POISON/STOP put message in and return? messageQueue.put(message); int tempSize = this.currentQueueSizeInBytes; int messageByteSize = messageSizeInBytes(message); + //@jorgen25 also if its regular message, size of this last incoming message could make queue go over + //the 500KB limit and we already put it in the queue. Even if we are measuring correctly we could go over the limit + //by adding BEFORE checking which could still work if we have another check while creating the batch to submit if (isBackPressuredAfterSize(messageByteSize)) { this.currentQueueSizeInBytes = messageByteSize; messageQueue.put(FlushMessage.POISON); @@ -215,6 +228,8 @@ public Looper() { @Override public void run() { List messages = new ArrayList<>(); + //@jorgen25 have a linkedList for pendingMessages (so we can poll() from it later FIFO order) + //and a currentMessagesSizeInBytes int for original messages list try { while (!stop) { Message message = messageQueue.take(); @@ -228,12 +243,24 @@ public void run() { } } else { messages.add(message); + //@jorgen25 check message size here too, if incoming message will increase messages size above the limit + //put message in pendingMessages list, also check if single incoming message by itself is over the limit. + //If it is then log and discard???? } Boolean isBlockingSignal = message == FlushMessage.POISON || message == StopMessage.STOP; - Boolean isOverflow = messages.size() >= size; + Boolean isOverflow = messages.size() >= size; //@jorgen25 isOverflow should also check if pendingMessages is not empty + //if it is it means isOverflow = true as well if (!messages.isEmpty() && (isOverflow || isBlockingSignal)) { + //@jorgen25 - create test case to check size for batch size, as it is now there is nothing guaranteeing + //entire batch did not go over 500KB limit at this point + + //@jorgen25 What about a single massive message which goes over the limit, do we log it and discard it ?? + + //@jorgen25 have while loop before this line for while (!pendingMessages.isEmpty()) + // poll message and send pending message in batch by itself + //also only go to this block below if !messages.isEmpty() Batch batch = Batch.create(CONTEXT, messages); log.print( VERBOSE, diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 3851d066..8182e394 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -28,11 +28,7 @@ import com.segment.backo.Backo; import com.squareup.burst.BurstJUnit4; import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Queue; +import java.util.*; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -594,4 +590,27 @@ public boolean matches(IOException exception) { } })); } + + + @Test + public void enqueueSingleHugeMessageWhenNotShutdown(MessageBuilderTest builder) + throws InterruptedException { + AnalyticsClient client = newClient(); + + final String massData = generateMassDataOfSize(1024 * 510); + Map integrationOpts = new HashMap<>(); + integrationOpts.put("massData", massData); + Message message = builder.get().userId("foo").integrationOptions("someKey", integrationOpts).build(); + + int size = client.messageSizeInBytes(message); + //will be slightly bigger than expected, which is ok + client.enqueue(message); + + verify(messageQueue).put(message); + verify(networkExecutor).submit(any(AnalyticsClient.BatchUploadTask.class)); + //we verified that huge above the limit message is going into the queue AND that the message is + //getting submitted in the batch, need to modify the enqueue method or the logic when creating batch + } + + } From bf038aa00e468c5c112df0b4b48711ae48aa0818 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguera Date: Fri, 19 Nov 2021 18:25:07 -0600 Subject: [PATCH 152/272] Modified logic for size check for each message before adding to queue, also checks size for the batch creation and test cases I have a bunch of comments that i will remove before merge if PR gets approved. --- .../analytics/internal/AnalyticsClient.java | 193 ++++++-- .../internal/AnalyticsClientTest.java | 458 ++++++++++++++++-- 2 files changed, 564 insertions(+), 87 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 4ce197c2..3405b96f 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -13,12 +13,15 @@ import com.segment.analytics.messages.Message; import com.segment.backo.Backo; import java.io.IOException; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.ArrayList; +import java.util.LinkedList; import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; +import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -27,11 +30,17 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + import retrofit2.Call; import retrofit2.Response; public class AnalyticsClient { private static final Map CONTEXT; + private static final int BATCH_MAX_SIZE = 1024 * 500; + private static final int MSG_MAX_SIZE = 1024 * 32; + private static final Charset ENCODING = StandardCharsets.UTF_8; + private static Gson gsonInstance; static { Map library = new LinkedHashMap<>(); @@ -120,20 +129,30 @@ public void run() { TimeUnit.MILLISECONDS); } + /** + * Creating GSON object everytime we check the size seems costly, create one static instance + * @return static gson instance + */ + public static Gson getGsonInstance() { + if (gsonInstance == null) { + gsonInstance = new Gson(); + } + return gsonInstance; + } + + public int messageSizeInBytes(Message message) { - //@jorgen25 test idea: Check if this is correctly testing byte size and not just char length with regular characters - Gson gson = new Gson(); + Gson gson = getGsonInstance(); String stringifiedMessage = gson.toJson(message); - int sizeInBytes = stringifiedMessage.getBytes(StandardCharsets.UTF_8).length; + int sizeInBytes = stringifiedMessage.getBytes(ENCODING).length; return sizeInBytes; } private Boolean isBackPressuredAfterSize(int incomingSize) { int POISON_BYTE_SIZE = messageSizeInBytes(FlushMessage.POISON); int sizeAfterAdd = this.currentQueueSizeInBytes + incomingSize + POISON_BYTE_SIZE; - //@jorgen25 we should have this loose ints in a constant - return sizeAfterAdd >= Math.min(this.maximumQueueByteSize, 1024 * 500); + return sizeAfterAdd >= Math.min(this.maximumQueueByteSize, BATCH_MAX_SIZE); } public boolean offer(Message message) { @@ -146,27 +165,28 @@ public void enqueue(Message message) { return; } - //@jorgen25 test ideas: happy path: several messages did not go over limit - // sad path 1: many messages did not go over limit but last one makes it go over the limit - //sad path 2: single message that is way over the limit try { - //@jorgen25 message here could be regular msg, POISON or STOP, maybe just do regular logic if its regular - //message and if its POISON/STOP put message in and return? - messageQueue.put(message); + //@jorgen25 message here could be regular msg, POISON or STOP. Only do regular logic if its valid message + if (message != StopMessage.STOP && message != FlushMessage.POISON) { + int messageByteSize = messageSizeInBytes(message); - int tempSize = this.currentQueueSizeInBytes; - int messageByteSize = messageSizeInBytes(message); + //@jorgen25 check if message is below 32kb limit for individual messages, no need to check for extra characters + if (messageByteSize <= MSG_MAX_SIZE) { + messageQueue.put(message); - //@jorgen25 also if its regular message, size of this last incoming message could make queue go over - //the 500KB limit and we already put it in the queue. Even if we are measuring correctly we could go over the limit - //by adding BEFORE checking which could still work if we have another check while creating the batch to submit - if (isBackPressuredAfterSize(messageByteSize)) { - this.currentQueueSizeInBytes = messageByteSize; - messageQueue.put(FlushMessage.POISON); + if (isBackPressuredAfterSize(messageByteSize)) { + this.currentQueueSizeInBytes = messageByteSize; + messageQueue.put(FlushMessage.POISON); - log.print(VERBOSE, "Maximum storage size has been hit Flushing..."); + log.print(VERBOSE, "Maximum storage size has been hit Flushing..."); + } else { + this.currentQueueSizeInBytes += messageByteSize; + } + } else { + log.print(ERROR, "Message was above individual limit. MessageId: %s", message.messageId()); + } } else { - this.currentQueueSizeInBytes += messageByteSize; + messageQueue.put(message); } } catch (InterruptedException e) { log.print(ERROR, e, "Interrupted while adding message %s.", message); @@ -227,9 +247,12 @@ public Looper() { @Override public void run() { - List messages = new ArrayList<>(); - //@jorgen25 have a linkedList for pendingMessages (so we can poll() from it later FIFO order) - //and a currentMessagesSizeInBytes int for original messages list + LinkedList messages = new LinkedList<>(); + //@jorgen25 we could check size at the moment we are creating batch but it will be very time consuming. + //its better to check as we take messages and since Message does not implement hashcode we can use messageId + Map messageIdSizeMap = new HashMap<>(); + AtomicInteger sequenceCounter = new AtomicInteger(1); + int contextSize = getGsonInstance().toJson(CONTEXT).getBytes(ENCODING).length; try { while (!stop) { Message message = messageQueue.take(); @@ -242,34 +265,26 @@ public void run() { log.print(VERBOSE, "Flushing messages."); } } else { + messageIdSizeMap.put(message.messageId(), messageSizeInBytes(message)); messages.add(message); - //@jorgen25 check message size here too, if incoming message will increase messages size above the limit - //put message in pendingMessages list, also check if single incoming message by itself is over the limit. - //If it is then log and discard???? } Boolean isBlockingSignal = message == FlushMessage.POISON || message == StopMessage.STOP; - Boolean isOverflow = messages.size() >= size; //@jorgen25 isOverflow should also check if pendingMessages is not empty - //if it is it means isOverflow = true as well + Boolean isOverflow = messages.size() >= size; if (!messages.isEmpty() && (isOverflow || isBlockingSignal)) { - //@jorgen25 - create test case to check size for batch size, as it is now there is nothing guaranteeing - //entire batch did not go over 500KB limit at this point - - //@jorgen25 What about a single massive message which goes over the limit, do we log it and discard it ?? - - //@jorgen25 have while loop before this line for while (!pendingMessages.isEmpty()) - // poll message and send pending message in batch by itself - //also only go to this block below if !messages.isEmpty() - Batch batch = Batch.create(CONTEXT, messages); - log.print( - VERBOSE, - "Batching %s message(s) into batch %s.", - messages.size(), - batch.sequence()); - networkExecutor.submit( - BatchUploadTask.create(AnalyticsClient.this, batch, maximumRetries)); - messages = new ArrayList<>(); + while(!messages.isEmpty()) { + Batch batch = BatchUtility.createBatch(messages, messageIdSizeMap, contextSize, sequenceCounter); + log.print( + VERBOSE, + "Batching %s message(s) into batch %s.", + batch.batch().size(), + batch.sequence()); + networkExecutor.submit( + BatchUploadTask.create(AnalyticsClient.this, batch, maximumRetries)); + } + messages = new LinkedList<>(); + messageIdSizeMap.clear(); } } } catch (InterruptedException e) { @@ -278,6 +293,11 @@ public void run() { } log.print(VERBOSE, "Looper stopped"); } + + + + + } static class BatchUploadTask implements Runnable { @@ -385,4 +405,81 @@ private static boolean is5xx(int status) { return status >= 500 && status < 600; } } + + + public static class BatchUtility { + /** + * Method to create a batch considering threshold of 500Kb for entire batch + * @param list + * @return batch object + */ + public static Batch createBatch(LinkedList list, Map messageIdSizeMap, + int contextSize, AtomicInteger sequenceCounter) { + List messagesForBatch = new ArrayList<>(); + Batch batch = null; + + int currentBatchSize = 0; + + //since we are handling max size of 32 kbs when enqueing msg, one single msg will not be above limit + while(list.size() > 0 && currentBatchSize <= BATCH_MAX_SIZE) { + Message msg = list.peek(); + int msgSize = messageIdSizeMap.get(msg.messageId()); + int defaultBatchSizeSoFar = getBatchDefaultSize(contextSize, messagesForBatch.size() + 1, sequenceCounter); + if ((currentBatchSize + msgSize + defaultBatchSizeSoFar) < BATCH_MAX_SIZE) { + messagesForBatch.add(list.poll()); + currentBatchSize+=msgSize; + } + else { + break; + } + } + batch = Batch.create(CONTEXT, messagesForBatch); + sequenceCounter.set(batch.sequence()); + + return batch; + } + + + /** + * Method to determine what is the expected default size of the batch regardless of messages + * + * Sample batch: + {"batch":[{"type":"alias","messageId":"fc9198f9-d827-47fb-96c8-095bd3405d93","timestamp":"Nov 18, 2021, + 2:45:07 PM","userId":"jorgen25","integrations":{"someKey":{"data":"aaaaa"}},"previousId":"foo"},{"type":"alias", + "messageId":"3ce6f88c-36cb-4991-83f8-157e10261a89","timestamp":"Nov 18, 2021, 2:45:07 PM","userId":"jorgen25", + "integrations":{"someKey":{"data":"aaaaa"}},"previousId":"foo"},{"type":"alias", + "messageId":"a328d339-899a-4a14-9835-ec91e303ac4d","timestamp":"Nov 18, 2021, 2:45:07 PM", + "userId":"jorgen25","integrations":{"someKey":{"data":"aaaaa"}},"previousId":"foo"},{"type":"alias", + "messageId":"57b0ceb4-a1cf-4599-9fba-0a44c7041004","timestamp":"Nov 18, 2021, 2:45:07 PM", + "userId":"jorgen25","integrations":{"someKey":{"data":"aaaaa"}},"previousId":"foo"}], + "sentAt":"Nov 18, 2021, 2:45:07 PM","context":{"library":{"name":"analytics-java","version":"3.1.3"}},"sequence":1} + + * total size of batch : 886 + * + * BREAKDOWN: + * {"batch":[MESSAGE1,MESSAGE2,MESSAGE3,MESSAGE4],"sentAt":"MMM dd, yyyy, HH:mm:ss tt","context":CONTEXT,"sequence":1} + * + * so we need to account for: + * 1 -message size: 189 * 4 = 756 + * 2 -context object size = 55 in this sample -> 756 + 55 = 811 + * 3 -Metadata (This has the sent data/sequence characters) + extra chars (these are chars like "batch":[] or "context": etc and will be pretty much the same length in every batch -> size is 73 --> 811 + 73 = 884 + * (well 72 actually, char 73 is the sequence digit which we account for in point 5) + * 4 -Commas between each message, the total number of commas is number_of_msgs - 1 = 3 -> 884 + 3 = 887 (sample is 886 because the hour in sentData this time happens to be 2:45 but it could be 12:45 + * 5 -Sequence Number increments with every batch created + * + * so formulae to determine the expected default size of the batch is + * + * @return: defaultSize = messages size + context size + metadata size + comma number + sequence digits + * + * @return + */ + private static int getBatchDefaultSize(int contextSize, int currentMessageNumber, AtomicInteger sequenceCounter) { + // sample data: {"batch":[],"sentAt":"MMM dd, yyyy, HH:mm:ss tt","context":,"sequence":1} - 73 + int metadataExtraCharsSize = 73; + int commaNumber = currentMessageNumber - 1; + + return contextSize + metadataExtraCharsSize + commaNumber + String.valueOf(sequenceCounter.incrementAndGet()).length(); + } + } + } diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 8182e394..8b6dc48a 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -15,7 +15,6 @@ import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; - import com.segment.analytics.Callback; import com.segment.analytics.Log; import com.segment.analytics.TestUtils.MessageBuilderTest; @@ -27,8 +26,17 @@ import com.segment.analytics.messages.TrackMessage; import com.segment.backo.Backo; import com.squareup.burst.BurstJUnit4; + +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.Random; +import java.util.Queue; +import java.util.Map; +import java.util.HashMap; import java.io.IOException; -import java.util.*; +import java.nio.charset.StandardCharsets; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -36,6 +44,8 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + import okhttp3.ResponseBody; import org.junit.Before; import org.junit.Test; @@ -56,7 +66,9 @@ public class AnalyticsClientTest { Backo.builder().base(TimeUnit.NANOSECONDS, 1).factor(1).build(); private int DEFAULT_RETRIES = 10; - private int MAX_BYTE_SIZE = 1024 * 500; // 500kb + private int MAX_BATCH_SIZE = 1024 * 500; // 500kb + private int MAX_MSG_SIZE = 1024 * 32; // 32kb //This is the limit for a message object + private int MSG_MAX_CREATE_SIZE = MAX_MSG_SIZE - 200; //Once we create msg object with this size it barely below 32 threshold so good for tests Log log = Log.NONE; @@ -87,7 +99,7 @@ AnalyticsClient newClient() { 50, TimeUnit.HOURS.toMillis(1), 0, - MAX_BYTE_SIZE, + MAX_BATCH_SIZE, log, threadFactory, networkExecutor, @@ -142,13 +154,48 @@ static Batch captureBatch(ExecutorService executor) { return task.batch; } - private static String generateMassDataOfSize(int msgSize) { + private static String generateDataOfSize(int msgSize) { char[] chars = new char[msgSize]; Arrays.fill(chars, 'a'); return new String(chars); } + private static String generateDataOfSizeSpecialChars(int sizeInBytes, boolean slightlyBelowLimit) { + StringBuilder builder = new StringBuilder(); + Character[] specialChars = new Character[]{'$', '¢', 'ह', '€', '한', '©' ,'¶'}; + int currentSize = 0; + String smileyFace = "\uD83D\uDE01"; + //😁 = '\uD83D\uDE01'; + Random rand = new Random(); + int loopCount = 1; + while (currentSize < sizeInBytes) { + int randomNum; + //decide if regular/special character + if (loopCount > 3 && loopCount % 4 == 0) { + randomNum = rand.nextInt(((specialChars.length - 1) - 0) + 1) + 0; + builder.append(specialChars[randomNum]); + } + else if (loopCount > 9 && loopCount % 10 == 0) { + builder.append(smileyFace); + } + else { + //random letter from a - z + randomNum = rand.nextInt(('z' - 'a') + 1) + 'a'; + builder.append((char)randomNum); + } + + //check size so far + String temp = builder.toString(); + currentSize = temp.getBytes(StandardCharsets.UTF_8).length; + if (slightlyBelowLimit && ((sizeInBytes - currentSize) < 500)) { + break; + } + loopCount++; + } + return builder.toString(); + } + @Test public void flushSubmitsToExecutor() { messageQueue = new LinkedBlockingQueue<>(); @@ -184,7 +231,7 @@ public void shouldBeAbleToCalculateMessageSize() { AnalyticsClient client = newClient(); Map properties = new HashMap(); - properties.put("property1", generateMassDataOfSize(1024 * 33)); + properties.put("property1", generateDataOfSize(1024 * 33)); TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); @@ -199,7 +246,7 @@ public void dontFlushUntilReachesMaxSize() throws InterruptedException { AnalyticsClient client = newClient(); Map properties = new HashMap(); - properties.put("property2", generateMassDataOfSize(MAX_BYTE_SIZE - 200)); + properties.put("property2", generateDataOfSize(MAX_BATCH_SIZE - 200)); TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); @@ -210,24 +257,45 @@ public void dontFlushUntilReachesMaxSize() throws InterruptedException { verify(networkExecutor, never()).submit(any(Runnable.class)); } - @Test - public void flushWhenReachesMaxSize() throws InterruptedException { - AnalyticsClient client = newClient(); - Map properties = new HashMap(); - - properties.put("property3", generateMassDataOfSize(MAX_BYTE_SIZE)); - - for (int i = 0; i < 10; i++) { - TrackMessage bigMessage = - TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); - client.enqueue(bigMessage); - } - - wait(messageQueue); + /** + * Planning to remove this test case since logic change makes test case unnecessary. The purpose of the test case was to + * test scenario when one BIG message (of MAX_BYTE_SIZE = 1024 * 500) would backpressure queue for each message put in queue + * so it would be backpressured 10 times, then flushed 10 times and 10 batches would be submitted + * + * Since logic changed to not allow msgs larger than 32kbs abd batches over 500kb this test case would be the exact same + * one as flushWhenMultipleMessagesReachesMaxSize test case + * @throws InterruptedException + */ +// @Test +// public void flushWhenReachesMaxSize() throws InterruptedException { +// AnalyticsClient client = newClient(); +// Map properties = new HashMap(); +// +// properties.put("property3", generateMassDataOfSize(MAX_BYTE_SIZE)); +// +// for (int i = 0; i < 10; i++) { +// TrackMessage bigMessage = +// TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); +// client.enqueue(bigMessage); +// } +// +// wait(messageQueue); +// +// verify(networkExecutor, times(10)).submit(any(Runnable.class)); +// } - verify(networkExecutor, times(10)).submit(any(Runnable.class)); - } + /** + * Modified this test case since we are changing logic to NOT allow messages bigger than 32 kbs individually to be enqueued, + * hence had to lower the size of the generated msg here. + * chose MSG_MAX_CREATE_SIZE because it will generate a message just below the limit of 32 kb after it creates a Message object + * modified the number of events that will be created since the batch creation logic was also changed to not allow batches + * larger than 500 kb + * meaning every 15/16 events the queue will be backPressured and poisoned/flushed (3 times) (purpose of test) + * AND there will be 4 batches submitted (15 msgs, 1 msg, 15 msg, 15 msg) + * so purpose of test case stands + * @throws InterruptedException + */ @Test public void flushHowManyTimesNecessaryToStayWithinLimit() throws InterruptedException { AnalyticsClient client = @@ -237,7 +305,7 @@ public void flushHowManyTimesNecessaryToStayWithinLimit() throws InterruptedExce 50, TimeUnit.HOURS.toMillis(1), 0, - MAX_BYTE_SIZE * 4, + MAX_BATCH_SIZE * 4, log, threadFactory, networkExecutor, @@ -246,12 +314,13 @@ public void flushHowManyTimesNecessaryToStayWithinLimit() throws InterruptedExce Map properties = new HashMap(); - properties.put("property3", generateMassDataOfSize(MAX_BYTE_SIZE)); + properties.put("property3", generateDataOfSize(MSG_MAX_CREATE_SIZE)); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 46; i++) { TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); client.enqueue(bigMessage); + verify(messageQueue).put(bigMessage); } wait(messageQueue); @@ -259,23 +328,32 @@ public void flushHowManyTimesNecessaryToStayWithinLimit() throws InterruptedExce verify(networkExecutor, times(4)).submit(any(Runnable.class)); } + + /** + * Had to slightly change test case since we are now modifying the logic to NOT allow messages above 32 KB in size + * So needed to change size of generated msg to MSG_MAX_CREATE_SIZE to keep purpose of test case intact which is to test + * the scenario for several messages eventually filling up the queue and flushing. + * Batches submitted will change from 1 to 2 because the queue will be backpressured at 16 (at this point queue is over the 500KB batch limit + * so its flushed and when batch is created 16 will be above 500kbs limit so it creates one batch for 15 msg and another + * one for the remaining single message so 500kb limit per batch is not violated + * @throws InterruptedException + */ @Test public void flushWhenMultipleMessagesReachesMaxSize() throws InterruptedException { AnalyticsClient client = newClient(); Map properties = new HashMap(); - properties.put("property3", generateMassDataOfSize(MAX_BYTE_SIZE / 9)); + properties.put("property3", generateDataOfSize(MSG_MAX_CREATE_SIZE)); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 16; i++) { TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); client.enqueue(bigMessage); } - wait(messageQueue); - - verify(networkExecutor, times(1)).submit(any(Runnable.class)); + verify(networkExecutor, times(2)).submit(any(Runnable.class)); } + @Test public void enqueueBeforeMaxDoesNotTriggerFlush() { messageQueue = new LinkedBlockingQueue<>(); @@ -592,25 +670,327 @@ public boolean matches(IOException exception) { } + /************************************************************************************************ + * Test cases for Size check + ***********************************************************************************************/ + + /** + * Individual Size check happy path regular chars + */ + @Test + public void checkForIndividualMessageSizeLessThanLimit() { + AnalyticsClient client = newClient(); + int msgSize = 1024 * 31; //31KB + int sizeLimit = MAX_MSG_SIZE; //32KB = 32768 + Map properties = new HashMap(); + + properties.put("property1", generateDataOfSize(msgSize)); + + TrackMessage bigMessage = TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); + client.enqueue(bigMessage); + + int msgActualSize = client.messageSizeInBytes(bigMessage); + assertThat(msgActualSize).isLessThanOrEqualTo(sizeLimit); + } + + + /** + * Individual Size check sad path regular chars (over the limit) + */ + @Test + public void checkForIndividualMessageSizeOverLimit() { + AnalyticsClient client = newClient(); + int msgSize = MAX_MSG_SIZE + 1; //BARELY over the limit + int sizeLimit = MAX_MSG_SIZE; //32KB = 32768 + Map properties = new HashMap(); + + properties.put("property1", generateDataOfSize(msgSize)); + + TrackMessage bigMessage = TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); + client.enqueue(bigMessage); + + int msgActualSize = client.messageSizeInBytes(bigMessage); + assertThat(msgActualSize).isGreaterThan(sizeLimit); + } + + + /** + * Individual Size check happy path special chars + */ + @Test + public void checkForIndividualMessageSizeSpecialCharsLessThanLimit() { + AnalyticsClient client = newClient(); + int msgSize = MAX_MSG_SIZE; //32KB + int sizeLimit = MAX_MSG_SIZE; //32KB = 32768 + + Map properties = new HashMap(); + properties.put("property1", generateDataOfSizeSpecialChars(msgSize, true)); + + TrackMessage bigMessage = TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); + client.enqueue(bigMessage); + + int msgActualSize = client.messageSizeInBytes(bigMessage); + assertThat(msgActualSize).isLessThanOrEqualTo(sizeLimit); + } + + + /** + * Individual Size check sad path special chars (over the limit) + */ @Test - public void enqueueSingleHugeMessageWhenNotShutdown(MessageBuilderTest builder) + public void checkForIndividualMessageSizeSpecialCharsAboveLimit() { + AnalyticsClient client = newClient(); + int msgSize = MAX_MSG_SIZE; //32KB + int sizeLimit = MAX_MSG_SIZE; //32KB = 32768 + Map properties = new HashMap(); + + properties.put("property1", generateDataOfSizeSpecialChars(msgSize, false)); + + TrackMessage bigMessage = TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); + client.enqueue(bigMessage); + + int msgActualSize = client.messageSizeInBytes(bigMessage); + assertThat(msgActualSize).isGreaterThan(sizeLimit); + } + + + + /******************************************************************************************************************* + * Test cases for enqueue modified logic + *****************************************************************************************************************/ + + @Test + public void enqueueVerifyPoisonIsNotCheckedForSize() throws InterruptedException { + AnalyticsClient clientSpy = spy(newClient()); + + clientSpy.enqueue(POISON); + verify(messageQueue).put(POISON); + verify(clientSpy, never()).messageSizeInBytes(POISON); + } + + + @Test + public void enqueueVerifyStopIsNotCheckedForSize() throws InterruptedException { + AnalyticsClient clientSpy = spy(newClient()); + + clientSpy.enqueue(STOP); + verify(messageQueue).put(STOP); + verify(clientSpy, never()).messageSizeInBytes(STOP); + } + + + @Test + public void enqueueVerifyRegularMessageIsEnqueuedAndCheckedForSize(MessageBuilderTest builder) throws InterruptedException { + AnalyticsClient clientSpy = spy(newClient()); + + Message message = builder.get().userId("jorgen25").build(); + clientSpy.enqueue(message); + verify(messageQueue).put(message); + verify(clientSpy, times(1)).messageSizeInBytes(message); + } + + + + + /** + * This test case was to prove the limit in batch is not being respected so will probably delete it later + * NOTE: Used to be a test case created to prove huge messages above the limit are still being submitted in batch + * modified it to prove they are not anymore after changing logic in analyticsClient + * @param builder + * @throws InterruptedException + */ + @Test + public void enqueueSingleMessageAboveLimitWhenNotShutdown(MessageBuilderTest builder) throws InterruptedException { AnalyticsClient client = newClient(); - final String massData = generateMassDataOfSize(1024 * 510); + //Message is above batch limit + final String massData = generateDataOfSizeSpecialChars(MAX_MSG_SIZE, false); Map integrationOpts = new HashMap<>(); integrationOpts.put("massData", massData); Message message = builder.get().userId("foo").integrationOptions("someKey", integrationOpts).build(); - int size = client.messageSizeInBytes(message); - //will be slightly bigger than expected, which is ok client.enqueue(message); - verify(messageQueue).put(message); - verify(networkExecutor).submit(any(AnalyticsClient.BatchUploadTask.class)); - //we verified that huge above the limit message is going into the queue AND that the message is - //getting submitted in the batch, need to modify the enqueue method or the logic when creating batch + wait(messageQueue); + + //Message is above MSG/BATCH size limit so it should not be put in queue + verify(messageQueue, never()).put(message); + //And since it was never in the queue, it was never submitted in batch + verify(networkExecutor, never()).submit(any(AnalyticsClient.BatchUploadTask.class)); + } + + + @Test + public void enqueueVerifyRegularMessagesSpecialCharactersBelowLimit(MessageBuilderTest builder) throws InterruptedException { + AnalyticsClient client = newClient(); + int msgSize = 1024 * 18; //18KB + + for (int i = 0; i < 2; i++) { + final String data = generateDataOfSizeSpecialChars(msgSize, true); + Map integrationOpts = new HashMap<>(); + integrationOpts.put("data", data); + Message message = builder.get().userId("jorgen25").integrationOptions("someKey", integrationOpts).build(); + client.enqueue(message); + verify(messageQueue).put(message); + } + client.enqueue(POISON); + verify(messageQueue).put(POISON); + + wait(messageQueue); + + verify(networkExecutor, times(1)).submit(any(AnalyticsClient.BatchUploadTask.class)); + } + + + + + /******************************************************************************************************************** + * Test cases for Batch creation logic + ******************************************************************************************************************/ + + /** + * This takes time since its getting size of each message and each batch created + * @param builder + */ + @Test + public void createBatchConfirmSizeNotViolated(MessageBuilderTest builder) { + + int msgSize = 1024 * 18; //18KB + LinkedList messages = new LinkedList<>(); + Map messageIdSizeMap = new HashMap<>(); + AtomicInteger sequenceCounter = new AtomicInteger(); + + //Create context + Map library = new LinkedHashMap<>(); + library.put("name", "analytics-java"); + library.put("version", AnalyticsVersion.get()); + Map context = new LinkedHashMap<>(); + context.put("library", Collections.unmodifiableMap(library)); + Map CONTEXT = Collections.unmodifiableMap(context); + int contextSize = AnalyticsClient.getGsonInstance().toJson(CONTEXT).getBytes(StandardCharsets.UTF_8).length; + + for (int i = 0; i < 40; i++) { + final String data = generateDataOfSizeSpecialChars(msgSize, true); + Map integrationOpts = new HashMap<>(); + integrationOpts.put("data", data); + Message message = builder.get().userId("jorgen25").integrationOptions("someKey", integrationOpts).build(); + messageIdSizeMap.put(message.messageId(),newClient().messageSizeInBytes(message)); + messages.add(message); + } + + while (!messages.isEmpty()) { + Batch batch = AnalyticsClient.BatchUtility.createBatch(messages, messageIdSizeMap, contextSize, sequenceCounter); + int batchSize = AnalyticsClient.getGsonInstance().toJson(batch).getBytes(StandardCharsets.UTF_8).length; + assertThat(batchSize).isLessThan(MAX_BATCH_SIZE); + } } + /** + * Several messages are enqueued and then submitted in a batch + * @throws InterruptedException + */ + @Test + public void submitBatchBelowThreshold() throws InterruptedException { + AnalyticsClient client = + new AnalyticsClient( + messageQueue, + segmentService, + 50, + TimeUnit.HOURS.toMillis(1), + 0, + MAX_BATCH_SIZE * 4, + log, + threadFactory, + networkExecutor, + Collections.singletonList(callback), + isShutDown); + + Map properties = new HashMap(); + properties.put("property3", generateDataOfSizeSpecialChars(MAX_MSG_SIZE, true)); + + for (int i = 0; i < 15; i++) { + TrackMessage bigMessage = + TrackMessage.builder("Big Event").userId("jorgen25").properties(properties).build(); + client.enqueue(bigMessage); + verify(messageQueue).put(bigMessage); + } + client.enqueue(POISON); + wait(messageQueue); + verify(networkExecutor, times(1)).submit(any(Runnable.class)); + } + + + /** + * Enqueued several messages above threshold of 500Kbs so queue gets backpressured at some point and several batches have to be created + * to not violate threshold + * @throws InterruptedException + */ + @Test + public void submitBatchAboveThreshold() throws InterruptedException { + AnalyticsClient client = + new AnalyticsClient( + messageQueue, + segmentService, + 50, + TimeUnit.HOURS.toMillis(1), + 0, + MAX_BATCH_SIZE * 4, + log, + threadFactory, + networkExecutor, + Collections.singletonList(callback), + isShutDown); + + Map properties = new HashMap(); + properties.put("property3", generateDataOfSizeSpecialChars(MAX_MSG_SIZE, true)); + + for (int i = 0; i < 100; i++) { + TrackMessage message = + TrackMessage.builder("Big Event").userId("jorgen25").properties(properties).build(); + client.enqueue(message); + verify(messageQueue).put(message); + } + wait(messageQueue); + client.shutdown(); + while(!isShutDown.get()){} + + verify(networkExecutor, times(8)).submit(any(Runnable.class)); + } + + + + @Test + public void submitManySmallMessagesBatchAboveThreshold() throws InterruptedException { + AnalyticsClient client = + new AnalyticsClient( + messageQueue, + segmentService, + 50, + TimeUnit.HOURS.toMillis(1), + 0, + MAX_BATCH_SIZE * 4, + log, + threadFactory, + networkExecutor, + Collections.singletonList(callback), + isShutDown); + + Map properties = new HashMap(); + properties.put("property3", generateDataOfSizeSpecialChars(1024 * 8, true)); + + for (int i = 0; i < 600; i++) { + TrackMessage message = + TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); + client.enqueue(message); + verify(messageQueue).put(message); + } + wait(messageQueue); + client.shutdown(); + while(!isShutDown.get()){} + + verify(networkExecutor, times(19)).submit(any(Runnable.class)); + } + } From 2e8e61bdcb15813f4909c4e754ad206f18a34089 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguera Date: Fri, 19 Nov 2021 18:30:18 -0600 Subject: [PATCH 153/272] ran mvn spotless:apply to fix circlet errors --- .../analytics/internal/AnalyticsClient.java | 131 +++---- .../internal/AnalyticsClientTest.java | 340 +++++++++--------- 2 files changed, 240 insertions(+), 231 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 3405b96f..1b329d3f 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -15,13 +15,13 @@ import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.util.List; import java.util.ArrayList; -import java.util.LinkedList; import java.util.Collections; -import java.util.Map; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -31,7 +31,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; - import retrofit2.Call; import retrofit2.Response; @@ -131,6 +130,7 @@ public void run() { /** * Creating GSON object everytime we check the size seems costly, create one static instance + * * @return static gson instance */ public static Gson getGsonInstance() { @@ -140,7 +140,6 @@ public static Gson getGsonInstance() { return gsonInstance; } - public int messageSizeInBytes(Message message) { Gson gson = getGsonInstance(); String stringifiedMessage = gson.toJson(message); @@ -166,11 +165,13 @@ public void enqueue(Message message) { } try { - //@jorgen25 message here could be regular msg, POISON or STOP. Only do regular logic if its valid message + // @jorgen25 message here could be regular msg, POISON or STOP. Only do regular logic if its + // valid message if (message != StopMessage.STOP && message != FlushMessage.POISON) { int messageByteSize = messageSizeInBytes(message); - //@jorgen25 check if message is below 32kb limit for individual messages, no need to check for extra characters + // @jorgen25 check if message is below 32kb limit for individual messages, no need to check + // for extra characters if (messageByteSize <= MSG_MAX_SIZE) { messageQueue.put(message); @@ -183,7 +184,8 @@ public void enqueue(Message message) { this.currentQueueSizeInBytes += messageByteSize; } } else { - log.print(ERROR, "Message was above individual limit. MessageId: %s", message.messageId()); + log.print( + ERROR, "Message was above individual limit. MessageId: %s", message.messageId()); } } else { messageQueue.put(message); @@ -248,9 +250,11 @@ public Looper() { @Override public void run() { LinkedList messages = new LinkedList<>(); - //@jorgen25 we could check size at the moment we are creating batch but it will be very time consuming. - //its better to check as we take messages and since Message does not implement hashcode we can use messageId - Map messageIdSizeMap = new HashMap<>(); + // @jorgen25 we could check size at the moment we are creating batch but it will be very time + // consuming. + // its better to check as we take messages and since Message does not implement hashcode we + // can use messageId + Map messageIdSizeMap = new HashMap<>(); AtomicInteger sequenceCounter = new AtomicInteger(1); int contextSize = getGsonInstance().toJson(CONTEXT).getBytes(ENCODING).length; try { @@ -273,15 +277,17 @@ public void run() { Boolean isOverflow = messages.size() >= size; if (!messages.isEmpty() && (isOverflow || isBlockingSignal)) { - while(!messages.isEmpty()) { - Batch batch = BatchUtility.createBatch(messages, messageIdSizeMap, contextSize, sequenceCounter); + while (!messages.isEmpty()) { + Batch batch = + BatchUtility.createBatch( + messages, messageIdSizeMap, contextSize, sequenceCounter); log.print( - VERBOSE, - "Batching %s message(s) into batch %s.", - batch.batch().size(), - batch.sequence()); + VERBOSE, + "Batching %s message(s) into batch %s.", + batch.batch().size(), + batch.sequence()); networkExecutor.submit( - BatchUploadTask.create(AnalyticsClient.this, batch, maximumRetries)); + BatchUploadTask.create(AnalyticsClient.this, batch, maximumRetries)); } messages = new LinkedList<>(); messageIdSizeMap.clear(); @@ -293,11 +299,6 @@ public void run() { } log.print(VERBOSE, "Looper stopped"); } - - - - - } static class BatchUploadTask implements Runnable { @@ -406,30 +407,34 @@ private static boolean is5xx(int status) { } } - public static class BatchUtility { /** * Method to create a batch considering threshold of 500Kb for entire batch + * * @param list * @return batch object */ - public static Batch createBatch(LinkedList list, Map messageIdSizeMap, - int contextSize, AtomicInteger sequenceCounter) { + public static Batch createBatch( + LinkedList list, + Map messageIdSizeMap, + int contextSize, + AtomicInteger sequenceCounter) { List messagesForBatch = new ArrayList<>(); Batch batch = null; int currentBatchSize = 0; - //since we are handling max size of 32 kbs when enqueing msg, one single msg will not be above limit - while(list.size() > 0 && currentBatchSize <= BATCH_MAX_SIZE) { + // since we are handling max size of 32 kbs when enqueing msg, one single msg will not be + // above limit + while (list.size() > 0 && currentBatchSize <= BATCH_MAX_SIZE) { Message msg = list.peek(); int msgSize = messageIdSizeMap.get(msg.messageId()); - int defaultBatchSizeSoFar = getBatchDefaultSize(contextSize, messagesForBatch.size() + 1, sequenceCounter); + int defaultBatchSizeSoFar = + getBatchDefaultSize(contextSize, messagesForBatch.size() + 1, sequenceCounter); if ((currentBatchSize + msgSize + defaultBatchSizeSoFar) < BATCH_MAX_SIZE) { messagesForBatch.add(list.poll()); - currentBatchSize+=msgSize; - } - else { + currentBatchSize += msgSize; + } else { break; } } @@ -439,47 +444,53 @@ public static Batch createBatch(LinkedList list, Map m return batch; } - - /** + /** * Method to determine what is the expected default size of the batch regardless of messages * - * Sample batch: - {"batch":[{"type":"alias","messageId":"fc9198f9-d827-47fb-96c8-095bd3405d93","timestamp":"Nov 18, 2021, - 2:45:07 PM","userId":"jorgen25","integrations":{"someKey":{"data":"aaaaa"}},"previousId":"foo"},{"type":"alias", - "messageId":"3ce6f88c-36cb-4991-83f8-157e10261a89","timestamp":"Nov 18, 2021, 2:45:07 PM","userId":"jorgen25", - "integrations":{"someKey":{"data":"aaaaa"}},"previousId":"foo"},{"type":"alias", - "messageId":"a328d339-899a-4a14-9835-ec91e303ac4d","timestamp":"Nov 18, 2021, 2:45:07 PM", - "userId":"jorgen25","integrations":{"someKey":{"data":"aaaaa"}},"previousId":"foo"},{"type":"alias", - "messageId":"57b0ceb4-a1cf-4599-9fba-0a44c7041004","timestamp":"Nov 18, 2021, 2:45:07 PM", - "userId":"jorgen25","integrations":{"someKey":{"data":"aaaaa"}},"previousId":"foo"}], - "sentAt":"Nov 18, 2021, 2:45:07 PM","context":{"library":{"name":"analytics-java","version":"3.1.3"}},"sequence":1} - - * total size of batch : 886 + *

Sample batch: + * {"batch":[{"type":"alias","messageId":"fc9198f9-d827-47fb-96c8-095bd3405d93","timestamp":"Nov + * 18, 2021, 2:45:07 + * PM","userId":"jorgen25","integrations":{"someKey":{"data":"aaaaa"}},"previousId":"foo"},{"type":"alias", + * "messageId":"3ce6f88c-36cb-4991-83f8-157e10261a89","timestamp":"Nov 18, 2021, 2:45:07 + * PM","userId":"jorgen25", + * "integrations":{"someKey":{"data":"aaaaa"}},"previousId":"foo"},{"type":"alias", + * "messageId":"a328d339-899a-4a14-9835-ec91e303ac4d","timestamp":"Nov 18, 2021, 2:45:07 PM", + * "userId":"jorgen25","integrations":{"someKey":{"data":"aaaaa"}},"previousId":"foo"},{"type":"alias", + * "messageId":"57b0ceb4-a1cf-4599-9fba-0a44c7041004","timestamp":"Nov 18, 2021, 2:45:07 PM", + * "userId":"jorgen25","integrations":{"someKey":{"data":"aaaaa"}},"previousId":"foo"}], + * "sentAt":"Nov 18, 2021, 2:45:07 + * PM","context":{"library":{"name":"analytics-java","version":"3.1.3"}},"sequence":1} * - * BREAKDOWN: - * {"batch":[MESSAGE1,MESSAGE2,MESSAGE3,MESSAGE4],"sentAt":"MMM dd, yyyy, HH:mm:ss tt","context":CONTEXT,"sequence":1} + *

total size of batch : 886 * - * so we need to account for: - * 1 -message size: 189 * 4 = 756 - * 2 -context object size = 55 in this sample -> 756 + 55 = 811 - * 3 -Metadata (This has the sent data/sequence characters) + extra chars (these are chars like "batch":[] or "context": etc and will be pretty much the same length in every batch -> size is 73 --> 811 + 73 = 884 - * (well 72 actually, char 73 is the sequence digit which we account for in point 5) - * 4 -Commas between each message, the total number of commas is number_of_msgs - 1 = 3 -> 884 + 3 = 887 (sample is 886 because the hour in sentData this time happens to be 2:45 but it could be 12:45 - * 5 -Sequence Number increments with every batch created + *

BREAKDOWN: {"batch":[MESSAGE1,MESSAGE2,MESSAGE3,MESSAGE4],"sentAt":"MMM dd, yyyy, HH:mm:ss + * tt","context":CONTEXT,"sequence":1} * - * so formulae to determine the expected default size of the batch is + *

so we need to account for: 1 -message size: 189 * 4 = 756 2 -context object size = 55 in + * this sample -> 756 + 55 = 811 3 -Metadata (This has the sent data/sequence characters) + + * extra chars (these are chars like "batch":[] or "context": etc and will be pretty much the + * same length in every batch -> size is 73 --> 811 + 73 = 884 (well 72 actually, char 73 is the + * sequence digit which we account for in point 5) 4 -Commas between each message, the total + * number of commas is number_of_msgs - 1 = 3 -> 884 + 3 = 887 (sample is 886 because the hour + * in sentData this time happens to be 2:45 but it could be 12:45 5 -Sequence Number increments + * with every batch created * - * @return: defaultSize = messages size + context size + metadata size + comma number + sequence digits + *

so formulae to determine the expected default size of the batch is * + * @return: defaultSize = messages size + context size + metadata size + comma number + sequence + * digits * @return */ - private static int getBatchDefaultSize(int contextSize, int currentMessageNumber, AtomicInteger sequenceCounter) { + private static int getBatchDefaultSize( + int contextSize, int currentMessageNumber, AtomicInteger sequenceCounter) { // sample data: {"batch":[],"sentAt":"MMM dd, yyyy, HH:mm:ss tt","context":,"sequence":1} - 73 int metadataExtraCharsSize = 73; int commaNumber = currentMessageNumber - 1; - return contextSize + metadataExtraCharsSize + commaNumber + String.valueOf(sequenceCounter.incrementAndGet()).length(); + return contextSize + + metadataExtraCharsSize + + commaNumber + + String.valueOf(sequenceCounter.incrementAndGet()).length(); } } - } diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 8b6dc48a..7f2de5bc 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -15,6 +15,7 @@ import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; + import com.segment.analytics.Callback; import com.segment.analytics.Log; import com.segment.analytics.TestUtils.MessageBuilderTest; @@ -26,17 +27,16 @@ import com.segment.analytics.messages.TrackMessage; import com.segment.backo.Backo; import com.squareup.burst.BurstJUnit4; - +import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedList; -import java.util.Random; -import java.util.Queue; import java.util.Map; -import java.util.HashMap; -import java.io.IOException; -import java.nio.charset.StandardCharsets; +import java.util.Queue; +import java.util.Random; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -45,7 +45,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; - import okhttp3.ResponseBody; import org.junit.Before; import org.junit.Test; @@ -68,7 +67,10 @@ public class AnalyticsClientTest { private int DEFAULT_RETRIES = 10; private int MAX_BATCH_SIZE = 1024 * 500; // 500kb private int MAX_MSG_SIZE = 1024 * 32; // 32kb //This is the limit for a message object - private int MSG_MAX_CREATE_SIZE = MAX_MSG_SIZE - 200; //Once we create msg object with this size it barely below 32 threshold so good for tests + private int MSG_MAX_CREATE_SIZE = + MAX_MSG_SIZE + - 200; // Once we create msg object with this size it barely below 32 threshold so good + // for tests Log log = Log.NONE; @@ -161,31 +163,30 @@ private static String generateDataOfSize(int msgSize) { return new String(chars); } - private static String generateDataOfSizeSpecialChars(int sizeInBytes, boolean slightlyBelowLimit) { + private static String generateDataOfSizeSpecialChars( + int sizeInBytes, boolean slightlyBelowLimit) { StringBuilder builder = new StringBuilder(); - Character[] specialChars = new Character[]{'$', '¢', 'ह', '€', '한', '©' ,'¶'}; + Character[] specialChars = new Character[] {'$', '¢', 'ह', '€', '한', '©', '¶'}; int currentSize = 0; String smileyFace = "\uD83D\uDE01"; - //😁 = '\uD83D\uDE01'; + // 😁 = '\uD83D\uDE01'; Random rand = new Random(); int loopCount = 1; while (currentSize < sizeInBytes) { int randomNum; - //decide if regular/special character + // decide if regular/special character if (loopCount > 3 && loopCount % 4 == 0) { randomNum = rand.nextInt(((specialChars.length - 1) - 0) + 1) + 0; builder.append(specialChars[randomNum]); - } - else if (loopCount > 9 && loopCount % 10 == 0) { + } else if (loopCount > 9 && loopCount % 10 == 0) { builder.append(smileyFace); - } - else { - //random letter from a - z + } else { + // random letter from a - z randomNum = rand.nextInt(('z' - 'a') + 1) + 'a'; - builder.append((char)randomNum); + builder.append((char) randomNum); } - //check size so far + // check size so far String temp = builder.toString(); currentSize = temp.getBytes(StandardCharsets.UTF_8).length; if (slightlyBelowLimit && ((sizeInBytes - currentSize) < 500)) { @@ -258,42 +259,44 @@ public void dontFlushUntilReachesMaxSize() throws InterruptedException { } /** - * Planning to remove this test case since logic change makes test case unnecessary. The purpose of the test case was to - * test scenario when one BIG message (of MAX_BYTE_SIZE = 1024 * 500) would backpressure queue for each message put in queue - * so it would be backpressured 10 times, then flushed 10 times and 10 batches would be submitted + * Planning to remove this test case since logic change makes test case unnecessary. The purpose + * of the test case was to test scenario when one BIG message (of MAX_BYTE_SIZE = 1024 * 500) + * would backpressure queue for each message put in queue so it would be backpressured 10 times, + * then flushed 10 times and 10 batches would be submitted + * + *

Since logic changed to not allow msgs larger than 32kbs abd batches over 500kb this test + * case would be the exact same one as flushWhenMultipleMessagesReachesMaxSize test case * - * Since logic changed to not allow msgs larger than 32kbs abd batches over 500kb this test case would be the exact same - * one as flushWhenMultipleMessagesReachesMaxSize test case * @throws InterruptedException */ -// @Test -// public void flushWhenReachesMaxSize() throws InterruptedException { -// AnalyticsClient client = newClient(); -// Map properties = new HashMap(); -// -// properties.put("property3", generateMassDataOfSize(MAX_BYTE_SIZE)); -// -// for (int i = 0; i < 10; i++) { -// TrackMessage bigMessage = -// TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); -// client.enqueue(bigMessage); -// } -// -// wait(messageQueue); -// -// verify(networkExecutor, times(10)).submit(any(Runnable.class)); -// } - + // @Test + // public void flushWhenReachesMaxSize() throws InterruptedException { + // AnalyticsClient client = newClient(); + // Map properties = new HashMap(); + // + // properties.put("property3", generateMassDataOfSize(MAX_BYTE_SIZE)); + // + // for (int i = 0; i < 10; i++) { + // TrackMessage bigMessage = + // TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); + // client.enqueue(bigMessage); + // } + // + // wait(messageQueue); + // + // verify(networkExecutor, times(10)).submit(any(Runnable.class)); + // } /** - * Modified this test case since we are changing logic to NOT allow messages bigger than 32 kbs individually to be enqueued, - * hence had to lower the size of the generated msg here. - * chose MSG_MAX_CREATE_SIZE because it will generate a message just below the limit of 32 kb after it creates a Message object - * modified the number of events that will be created since the batch creation logic was also changed to not allow batches - * larger than 500 kb - * meaning every 15/16 events the queue will be backPressured and poisoned/flushed (3 times) (purpose of test) - * AND there will be 4 batches submitted (15 msgs, 1 msg, 15 msg, 15 msg) - * so purpose of test case stands + * Modified this test case since we are changing logic to NOT allow messages bigger than 32 kbs + * individually to be enqueued, hence had to lower the size of the generated msg here. chose + * MSG_MAX_CREATE_SIZE because it will generate a message just below the limit of 32 kb after it + * creates a Message object modified the number of events that will be created since the batch + * creation logic was also changed to not allow batches larger than 500 kb meaning every 15/16 + * events the queue will be backPressured and poisoned/flushed (3 times) (purpose of test) AND + * there will be 4 batches submitted (15 msgs, 1 msg, 15 msg, 15 msg) so purpose of test case + * stands + * * @throws InterruptedException */ @Test @@ -328,14 +331,15 @@ public void flushHowManyTimesNecessaryToStayWithinLimit() throws InterruptedExce verify(networkExecutor, times(4)).submit(any(Runnable.class)); } - /** - * Had to slightly change test case since we are now modifying the logic to NOT allow messages above 32 KB in size - * So needed to change size of generated msg to MSG_MAX_CREATE_SIZE to keep purpose of test case intact which is to test - * the scenario for several messages eventually filling up the queue and flushing. - * Batches submitted will change from 1 to 2 because the queue will be backpressured at 16 (at this point queue is over the 500KB batch limit - * so its flushed and when batch is created 16 will be above 500kbs limit so it creates one batch for 15 msg and another - * one for the remaining single message so 500kb limit per batch is not violated + * Had to slightly change test case since we are now modifying the logic to NOT allow messages + * above 32 KB in size So needed to change size of generated msg to MSG_MAX_CREATE_SIZE to keep + * purpose of test case intact which is to test the scenario for several messages eventually + * filling up the queue and flushing. Batches submitted will change from 1 to 2 because the queue + * will be backpressured at 16 (at this point queue is over the 500KB batch limit so its flushed + * and when batch is created 16 will be above 500kbs limit so it creates one batch for 15 msg and + * another one for the remaining single message so 500kb limit per batch is not violated + * * @throws InterruptedException */ @Test @@ -353,7 +357,6 @@ public void flushWhenMultipleMessagesReachesMaxSize() throws InterruptedExceptio verify(networkExecutor, times(2)).submit(any(Runnable.class)); } - @Test public void enqueueBeforeMaxDoesNotTriggerFlush() { messageQueue = new LinkedBlockingQueue<>(); @@ -669,96 +672,89 @@ public boolean matches(IOException exception) { })); } - - /************************************************************************************************ - * Test cases for Size check - ***********************************************************************************************/ - /** - * Individual Size check happy path regular chars + * ********************************************************************************************** + * Test cases for Size check + * ********************************************************************************************* */ + + /** Individual Size check happy path regular chars */ @Test public void checkForIndividualMessageSizeLessThanLimit() { AnalyticsClient client = newClient(); - int msgSize = 1024 * 31; //31KB - int sizeLimit = MAX_MSG_SIZE; //32KB = 32768 + int msgSize = 1024 * 31; // 31KB + int sizeLimit = MAX_MSG_SIZE; // 32KB = 32768 Map properties = new HashMap(); properties.put("property1", generateDataOfSize(msgSize)); - TrackMessage bigMessage = TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); + TrackMessage bigMessage = + TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); client.enqueue(bigMessage); int msgActualSize = client.messageSizeInBytes(bigMessage); assertThat(msgActualSize).isLessThanOrEqualTo(sizeLimit); } - - /** - * Individual Size check sad path regular chars (over the limit) - */ + /** Individual Size check sad path regular chars (over the limit) */ @Test public void checkForIndividualMessageSizeOverLimit() { AnalyticsClient client = newClient(); - int msgSize = MAX_MSG_SIZE + 1; //BARELY over the limit - int sizeLimit = MAX_MSG_SIZE; //32KB = 32768 + int msgSize = MAX_MSG_SIZE + 1; // BARELY over the limit + int sizeLimit = MAX_MSG_SIZE; // 32KB = 32768 Map properties = new HashMap(); properties.put("property1", generateDataOfSize(msgSize)); - TrackMessage bigMessage = TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); + TrackMessage bigMessage = + TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); client.enqueue(bigMessage); int msgActualSize = client.messageSizeInBytes(bigMessage); assertThat(msgActualSize).isGreaterThan(sizeLimit); } - - /** - * Individual Size check happy path special chars - */ + /** Individual Size check happy path special chars */ @Test public void checkForIndividualMessageSizeSpecialCharsLessThanLimit() { AnalyticsClient client = newClient(); - int msgSize = MAX_MSG_SIZE; //32KB - int sizeLimit = MAX_MSG_SIZE; //32KB = 32768 + int msgSize = MAX_MSG_SIZE; // 32KB + int sizeLimit = MAX_MSG_SIZE; // 32KB = 32768 Map properties = new HashMap(); properties.put("property1", generateDataOfSizeSpecialChars(msgSize, true)); - TrackMessage bigMessage = TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); + TrackMessage bigMessage = + TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); client.enqueue(bigMessage); int msgActualSize = client.messageSizeInBytes(bigMessage); assertThat(msgActualSize).isLessThanOrEqualTo(sizeLimit); } - - /** - * Individual Size check sad path special chars (over the limit) - */ + /** Individual Size check sad path special chars (over the limit) */ @Test public void checkForIndividualMessageSizeSpecialCharsAboveLimit() { AnalyticsClient client = newClient(); - int msgSize = MAX_MSG_SIZE; //32KB - int sizeLimit = MAX_MSG_SIZE; //32KB = 32768 + int msgSize = MAX_MSG_SIZE; // 32KB + int sizeLimit = MAX_MSG_SIZE; // 32KB = 32768 Map properties = new HashMap(); properties.put("property1", generateDataOfSizeSpecialChars(msgSize, false)); - TrackMessage bigMessage = TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); + TrackMessage bigMessage = + TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); client.enqueue(bigMessage); int msgActualSize = client.messageSizeInBytes(bigMessage); assertThat(msgActualSize).isGreaterThan(sizeLimit); } - - - /******************************************************************************************************************* + /** + * ***************************************************************************************************************** * Test cases for enqueue modified logic - *****************************************************************************************************************/ - + * *************************************************************************************************************** + */ @Test public void enqueueVerifyPoisonIsNotCheckedForSize() throws InterruptedException { AnalyticsClient clientSpy = spy(newClient()); @@ -768,7 +764,6 @@ public void enqueueVerifyPoisonIsNotCheckedForSize() throws InterruptedException verify(clientSpy, never()).messageSizeInBytes(POISON); } - @Test public void enqueueVerifyStopIsNotCheckedForSize() throws InterruptedException { AnalyticsClient clientSpy = spy(newClient()); @@ -778,9 +773,9 @@ public void enqueueVerifyStopIsNotCheckedForSize() throws InterruptedException { verify(clientSpy, never()).messageSizeInBytes(STOP); } - @Test - public void enqueueVerifyRegularMessageIsEnqueuedAndCheckedForSize(MessageBuilderTest builder) throws InterruptedException { + public void enqueueVerifyRegularMessageIsEnqueuedAndCheckedForSize(MessageBuilderTest builder) + throws InterruptedException { AnalyticsClient clientSpy = spy(newClient()); Message message = builder.get().userId("jorgen25").build(); @@ -789,48 +784,49 @@ public void enqueueVerifyRegularMessageIsEnqueuedAndCheckedForSize(MessageBuilde verify(clientSpy, times(1)).messageSizeInBytes(message); } - - - /** - * This test case was to prove the limit in batch is not being respected so will probably delete it later - * NOTE: Used to be a test case created to prove huge messages above the limit are still being submitted in batch - * modified it to prove they are not anymore after changing logic in analyticsClient + * This test case was to prove the limit in batch is not being respected so will probably delete + * it later NOTE: Used to be a test case created to prove huge messages above the limit are still + * being submitted in batch modified it to prove they are not anymore after changing logic in + * analyticsClient + * * @param builder * @throws InterruptedException */ @Test public void enqueueSingleMessageAboveLimitWhenNotShutdown(MessageBuilderTest builder) - throws InterruptedException { + throws InterruptedException { AnalyticsClient client = newClient(); - //Message is above batch limit + // Message is above batch limit final String massData = generateDataOfSizeSpecialChars(MAX_MSG_SIZE, false); Map integrationOpts = new HashMap<>(); integrationOpts.put("massData", massData); - Message message = builder.get().userId("foo").integrationOptions("someKey", integrationOpts).build(); + Message message = + builder.get().userId("foo").integrationOptions("someKey", integrationOpts).build(); client.enqueue(message); wait(messageQueue); - //Message is above MSG/BATCH size limit so it should not be put in queue + // Message is above MSG/BATCH size limit so it should not be put in queue verify(messageQueue, never()).put(message); - //And since it was never in the queue, it was never submitted in batch + // And since it was never in the queue, it was never submitted in batch verify(networkExecutor, never()).submit(any(AnalyticsClient.BatchUploadTask.class)); } - @Test - public void enqueueVerifyRegularMessagesSpecialCharactersBelowLimit(MessageBuilderTest builder) throws InterruptedException { + public void enqueueVerifyRegularMessagesSpecialCharactersBelowLimit(MessageBuilderTest builder) + throws InterruptedException { AnalyticsClient client = newClient(); - int msgSize = 1024 * 18; //18KB + int msgSize = 1024 * 18; // 18KB for (int i = 0; i < 2; i++) { final String data = generateDataOfSizeSpecialChars(msgSize, true); Map integrationOpts = new HashMap<>(); integrationOpts.put("data", data); - Message message = builder.get().userId("jorgen25").integrationOptions("someKey", integrationOpts).build(); + Message message = + builder.get().userId("jorgen25").integrationOptions("someKey", integrationOpts).build(); client.enqueue(message); verify(messageQueue).put(message); } @@ -841,78 +837,83 @@ public void enqueueVerifyRegularMessagesSpecialCharactersBelowLimit(MessageBuild verify(networkExecutor, times(1)).submit(any(AnalyticsClient.BatchUploadTask.class)); } - - - - /******************************************************************************************************************** + /** + * ****************************************************************************************************************** * Test cases for Batch creation logic - ******************************************************************************************************************/ + * **************************************************************************************************************** + */ /** * This takes time since its getting size of each message and each batch created + * * @param builder */ @Test public void createBatchConfirmSizeNotViolated(MessageBuilderTest builder) { - int msgSize = 1024 * 18; //18KB + int msgSize = 1024 * 18; // 18KB LinkedList messages = new LinkedList<>(); Map messageIdSizeMap = new HashMap<>(); AtomicInteger sequenceCounter = new AtomicInteger(); - //Create context + // Create context Map library = new LinkedHashMap<>(); library.put("name", "analytics-java"); library.put("version", AnalyticsVersion.get()); Map context = new LinkedHashMap<>(); context.put("library", Collections.unmodifiableMap(library)); Map CONTEXT = Collections.unmodifiableMap(context); - int contextSize = AnalyticsClient.getGsonInstance().toJson(CONTEXT).getBytes(StandardCharsets.UTF_8).length; + int contextSize = + AnalyticsClient.getGsonInstance().toJson(CONTEXT).getBytes(StandardCharsets.UTF_8).length; for (int i = 0; i < 40; i++) { final String data = generateDataOfSizeSpecialChars(msgSize, true); Map integrationOpts = new HashMap<>(); integrationOpts.put("data", data); - Message message = builder.get().userId("jorgen25").integrationOptions("someKey", integrationOpts).build(); - messageIdSizeMap.put(message.messageId(),newClient().messageSizeInBytes(message)); + Message message = + builder.get().userId("jorgen25").integrationOptions("someKey", integrationOpts).build(); + messageIdSizeMap.put(message.messageId(), newClient().messageSizeInBytes(message)); messages.add(message); } while (!messages.isEmpty()) { - Batch batch = AnalyticsClient.BatchUtility.createBatch(messages, messageIdSizeMap, contextSize, sequenceCounter); - int batchSize = AnalyticsClient.getGsonInstance().toJson(batch).getBytes(StandardCharsets.UTF_8).length; + Batch batch = + AnalyticsClient.BatchUtility.createBatch( + messages, messageIdSizeMap, contextSize, sequenceCounter); + int batchSize = + AnalyticsClient.getGsonInstance().toJson(batch).getBytes(StandardCharsets.UTF_8).length; assertThat(batchSize).isLessThan(MAX_BATCH_SIZE); } } - /** * Several messages are enqueued and then submitted in a batch + * * @throws InterruptedException */ @Test public void submitBatchBelowThreshold() throws InterruptedException { AnalyticsClient client = - new AnalyticsClient( - messageQueue, - segmentService, - 50, - TimeUnit.HOURS.toMillis(1), - 0, - MAX_BATCH_SIZE * 4, - log, - threadFactory, - networkExecutor, - Collections.singletonList(callback), - isShutDown); + new AnalyticsClient( + messageQueue, + segmentService, + 50, + TimeUnit.HOURS.toMillis(1), + 0, + MAX_BATCH_SIZE * 4, + log, + threadFactory, + networkExecutor, + Collections.singletonList(callback), + isShutDown); Map properties = new HashMap(); properties.put("property3", generateDataOfSizeSpecialChars(MAX_MSG_SIZE, true)); for (int i = 0; i < 15; i++) { TrackMessage bigMessage = - TrackMessage.builder("Big Event").userId("jorgen25").properties(properties).build(); + TrackMessage.builder("Big Event").userId("jorgen25").properties(properties).build(); client.enqueue(bigMessage); verify(messageQueue).put(bigMessage); } @@ -921,76 +922,73 @@ public void submitBatchBelowThreshold() throws InterruptedException { verify(networkExecutor, times(1)).submit(any(Runnable.class)); } - /** - * Enqueued several messages above threshold of 500Kbs so queue gets backpressured at some point and several batches have to be created - * to not violate threshold + * Enqueued several messages above threshold of 500Kbs so queue gets backpressured at some point + * and several batches have to be created to not violate threshold + * * @throws InterruptedException */ @Test public void submitBatchAboveThreshold() throws InterruptedException { AnalyticsClient client = - new AnalyticsClient( - messageQueue, - segmentService, - 50, - TimeUnit.HOURS.toMillis(1), - 0, - MAX_BATCH_SIZE * 4, - log, - threadFactory, - networkExecutor, - Collections.singletonList(callback), - isShutDown); + new AnalyticsClient( + messageQueue, + segmentService, + 50, + TimeUnit.HOURS.toMillis(1), + 0, + MAX_BATCH_SIZE * 4, + log, + threadFactory, + networkExecutor, + Collections.singletonList(callback), + isShutDown); Map properties = new HashMap(); properties.put("property3", generateDataOfSizeSpecialChars(MAX_MSG_SIZE, true)); for (int i = 0; i < 100; i++) { TrackMessage message = - TrackMessage.builder("Big Event").userId("jorgen25").properties(properties).build(); + TrackMessage.builder("Big Event").userId("jorgen25").properties(properties).build(); client.enqueue(message); verify(messageQueue).put(message); } wait(messageQueue); client.shutdown(); - while(!isShutDown.get()){} + while (!isShutDown.get()) {} verify(networkExecutor, times(8)).submit(any(Runnable.class)); } - - @Test public void submitManySmallMessagesBatchAboveThreshold() throws InterruptedException { AnalyticsClient client = - new AnalyticsClient( - messageQueue, - segmentService, - 50, - TimeUnit.HOURS.toMillis(1), - 0, - MAX_BATCH_SIZE * 4, - log, - threadFactory, - networkExecutor, - Collections.singletonList(callback), - isShutDown); + new AnalyticsClient( + messageQueue, + segmentService, + 50, + TimeUnit.HOURS.toMillis(1), + 0, + MAX_BATCH_SIZE * 4, + log, + threadFactory, + networkExecutor, + Collections.singletonList(callback), + isShutDown); Map properties = new HashMap(); properties.put("property3", generateDataOfSizeSpecialChars(1024 * 8, true)); for (int i = 0; i < 600; i++) { TrackMessage message = - TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); + TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); client.enqueue(message); verify(messageQueue).put(message); } wait(messageQueue); client.shutdown(); - while(!isShutDown.get()){} + while (!isShutDown.get()) {} verify(networkExecutor, times(19)).submit(any(Runnable.class)); } - } From d9d0d826b15b7d262a84e061dc517bb2ad71e088 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguera Date: Fri, 19 Nov 2021 18:43:24 -0600 Subject: [PATCH 154/272] Test case succeeds locally, forcing test to wait to guarantee interaction happens --- .../com/segment/analytics/internal/AnalyticsClientTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 7f2de5bc..769bf19e 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -834,6 +834,8 @@ public void enqueueVerifyRegularMessagesSpecialCharactersBelowLimit(MessageBuild verify(messageQueue).put(POISON); wait(messageQueue); + client.shutdown(); + while(!isShutDown.get()) {} verify(networkExecutor, times(1)).submit(any(AnalyticsClient.BatchUploadTask.class)); } From 40928249c9d40b88bd0e773efab7cd2ac49523bb Mon Sep 17 00:00:00 2001 From: Jorge Rodriguera Date: Fri, 19 Nov 2021 18:46:54 -0600 Subject: [PATCH 155/272] fix circlet code violation with mvn spotless apply --- .../com/segment/analytics/internal/AnalyticsClientTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 769bf19e..accd3f2b 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -835,7 +835,7 @@ public void enqueueVerifyRegularMessagesSpecialCharactersBelowLimit(MessageBuild wait(messageQueue); client.shutdown(); - while(!isShutDown.get()) {} + while (!isShutDown.get()) {} verify(networkExecutor, times(1)).submit(any(AnalyticsClient.BatchUploadTask.class)); } From 75fb976c4db017317bdbbb420d1586f251a14b59 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguera Date: Fri, 19 Nov 2021 19:39:16 -0600 Subject: [PATCH 156/272] forced wait to guarantee interaction in test --- .../com/segment/analytics/internal/AnalyticsClientTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index accd3f2b..100bccab 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -354,6 +354,8 @@ public void flushWhenMultipleMessagesReachesMaxSize() throws InterruptedExceptio client.enqueue(bigMessage); } wait(messageQueue); + client.shutdown(); + while (!isShutDown.get()) {} verify(networkExecutor, times(2)).submit(any(Runnable.class)); } From 5f9ae86850c34d258596a6d3b6c15f4c581a7013 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Nov 2021 16:03:37 +0000 Subject: [PATCH 157/272] Bump okhttp from 4.3.0 to 4.9.3 Bumps [okhttp](https://github.com/square/okhttp) from 4.3.0 to 4.9.3. - [Release notes](https://github.com/square/okhttp/releases) - [Changelog](https://github.com/square/okhttp/blob/master/CHANGELOG.md) - [Commits](https://github.com/square/okhttp/compare/parent-4.3.0...parent-4.9.3) --- updated-dependencies: - dependency-name: com.squareup.okhttp3:okhttp dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index af5b43ed..50d90505 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ 3.0.1 2.8.8 - 4.3.0 + 4.9.3 4.9.1 31.0-jre 1.0.0 From ca95853fd520ee718faa598ab6f58ea46173998c Mon Sep 17 00:00:00 2001 From: Jorge Rodriguera Date: Wed, 8 Dec 2021 12:15:08 -0600 Subject: [PATCH 158/272] Bugfix for TLS version error (protocol not supported error) Added a method to the Analytics Builder class forceTlsVersion1() - name subject to change Usage - Analytics.Builder builder = Analytics.builder("someKey"); Analytics analytics = builder.userAgent("someUserAgent") .client(someClient) .endpoint("some endpoint") .anotherAlreadyExistingMethod(someParam) .forceTlsVersion1() .build(); this new method forces the httpClient to be created using ConnectionSpec of MODERN_TLS and including Tls Versions: TLS_1_0, TLS_1_1, TLS_1_2, TLS_1_3 Also added a simple test case --- .../java/com/segment/analytics/Analytics.java | 27 ++++++++++++++++--- .../analytics/AnalyticsBuilderTest.java | 7 ++++- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index a3449fb3..6759eef2 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -9,15 +9,18 @@ import com.segment.analytics.internal.AnalyticsVersion; import com.segment.analytics.messages.Message; import com.segment.analytics.messages.MessageBuilder; +import java.util.List; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Date; -import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; -import okhttp3.HttpUrl; +import okhttp3.ConnectionSpec; import okhttp3.OkHttpClient; +import okhttp3.HttpUrl; +import okhttp3.TlsVersion; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; @@ -145,6 +148,7 @@ public static class Builder { private long flushIntervalInMillis; private List callbacks; private int queueCapacity; + private boolean forceTlsV1 = false; Builder(String writeKey) { if (writeKey == null || writeKey.trim().length() == 0) { @@ -329,6 +333,12 @@ public Builder plugin(Plugin plugin) { return this; } + /** Specify if need TlsV1 */ + public Builder forceTlsVersion1() { + forceTlsV1 = true; + return this; + } + /** Create a {@link Analytics} client. */ public Analytics build() { Gson gson = @@ -400,13 +410,22 @@ public void log(String message) { interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC); - client = + OkHttpClient.Builder builder = client .newBuilder() .addInterceptor(new AnalyticsRequestInterceptor(writeKey, userAgent)) - .addInterceptor(interceptor) + .addInterceptor(interceptor); + + if (forceTlsV1) { + ConnectionSpec connectionSpec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) + .tlsVersions(TlsVersion.TLS_1_0, TlsVersion.TLS_1_1, TlsVersion.TLS_1_2, TlsVersion.TLS_1_3) .build(); + builder = builder.connectionSpecs(Arrays.asList(connectionSpec)); + } + + client = builder.build(); + Retrofit restAdapter = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create(gson)) diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java index 6cee3590..f0252bb4 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java @@ -6,7 +6,6 @@ import static org.junit.Assert.assertNotEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; - import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; @@ -378,6 +377,12 @@ public void buildsWithValidCallback() { assertThat(analytics).isNotNull(); } + @Test + public void buildsWithForceTlsV1() { + Analytics analytics = builder.forceTlsVersion1().build(); + assertThat(analytics).isNotNull(); + } + @Test public void multipleCallbacks() { Analytics analytics = From 7da597e3995b0a3fe133a9fb9fb75d9638bd4978 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguera Date: Wed, 8 Dec 2021 12:18:20 -0600 Subject: [PATCH 159/272] run maven spotless:apply --- .../main/java/com/segment/analytics/Analytics.java | 12 +++++++----- .../com/segment/analytics/AnalyticsBuilderTest.java | 1 + 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index 6759eef2..f5fe74f3 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -9,17 +9,17 @@ import com.segment.analytics.internal.AnalyticsVersion; import com.segment.analytics.messages.Message; import com.segment.analytics.messages.MessageBuilder; -import java.util.List; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; +import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import okhttp3.ConnectionSpec; -import okhttp3.OkHttpClient; import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; import okhttp3.TlsVersion; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Retrofit; @@ -417,9 +417,11 @@ public void log(String message) { .addInterceptor(interceptor); if (forceTlsV1) { - ConnectionSpec connectionSpec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) - .tlsVersions(TlsVersion.TLS_1_0, TlsVersion.TLS_1_1, TlsVersion.TLS_1_2, TlsVersion.TLS_1_3) - .build(); + ConnectionSpec connectionSpec = + new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) + .tlsVersions( + TlsVersion.TLS_1_0, TlsVersion.TLS_1_1, TlsVersion.TLS_1_2, TlsVersion.TLS_1_3) + .build(); builder = builder.connectionSpecs(Arrays.asList(connectionSpec)); } diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java index f0252bb4..dc1b12be 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java @@ -6,6 +6,7 @@ import static org.junit.Assert.assertNotEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; + import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; From 27922cc46d49330893364035eab7ab6c333a1bf9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Dec 2021 16:03:19 +0000 Subject: [PATCH 160/272] Bump spring-boot-autoconfigure from 2.5.5 to 2.6.2 Bumps [spring-boot-autoconfigure](https://github.com/spring-projects/spring-boot) from 2.5.5 to 2.6.2. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v2.5.5...v2.6.2) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-autoconfigure dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index af5b43ed..b21bbb58 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ 4.9.1 31.0-jre 1.0.0 - 2.5.5 + 2.6.2 0.6.0.20150202 From 292cbfc95409e10181843af431f4c498d2608bc3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jan 2022 16:01:43 +0000 Subject: [PATCH 161/272] Bump auto.version from 1.8.2 to 1.9 Bumps `auto.version` from 1.8.2 to 1.9. Updates `auto-value` from 1.8.2 to 1.9 - [Release notes](https://github.com/google/auto/releases) - [Commits](https://github.com/google/auto/compare/auto-value-1.8.2...auto-value-1.9) Updates `auto-value-annotations` from 1.8.2 to 1.9 - [Release notes](https://github.com/google/auto/releases) - [Commits](https://github.com/google/auto/compare/auto-value-1.8.2...auto-value-1.9) --- updated-dependencies: - dependency-name: com.google.auto.value:auto-value dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.google.auto.value:auto-value-annotations dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index af5b43ed..828d0cb5 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 1.5.31 2.17.3 2.9.0 - 1.8.2 + 1.9 3.0.1 2.8.8 From 9503d9bf13bbc13c00f2c32d5114e028128d9bf9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Jan 2022 18:44:57 +0000 Subject: [PATCH 162/272] Bump logging-interceptor from 4.9.1 to 4.9.3 Bumps [logging-interceptor](https://github.com/square/okhttp) from 4.9.1 to 4.9.3. - [Release notes](https://github.com/square/okhttp/releases) - [Changelog](https://github.com/square/okhttp/blob/master/CHANGELOG.md) - [Commits](https://github.com/square/okhttp/compare/parent-4.9.1...parent-4.9.3) --- updated-dependencies: - dependency-name: com.squareup.okhttp3:logging-interceptor dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b1a9b07a..5a1de7f5 100644 --- a/pom.xml +++ b/pom.xml @@ -36,7 +36,7 @@ 3.0.1 2.8.8 4.9.3 - 4.9.1 + 4.9.3 31.0-jre 1.0.0 2.6.2 From f312214f3e173c4ce73a98b1fc9ef3c6dc181518 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Jan 2022 18:45:33 +0000 Subject: [PATCH 163/272] Bump maven-compiler-plugin from 3.8.1 to 3.9.0 Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.8.1 to 3.9.0. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.8.1...maven-compiler-plugin-3.9.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5a1de7f5..8dc128ab 100644 --- a/pom.xml +++ b/pom.xml @@ -170,7 +170,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.9.0 true ${java.version} From 73d703286a1f6dc172de24841faed689731d4ae1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Jan 2022 18:46:08 +0000 Subject: [PATCH 164/272] Bump kotlin.version from 1.5.31 to 1.6.10 Bumps `kotlin.version` from 1.5.31 to 1.6.10. Updates `kotlin-stdlib` from 1.5.31 to 1.6.10 - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/compare/v1.5.31...v1.6.10) Updates `kotlin-maven-plugin` from 1.5.31 to 1.6.10 --- updated-dependencies: - dependency-name: org.jetbrains.kotlin:kotlin-stdlib dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.jetbrains.kotlin:kotlin-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5a1de7f5..d71e9255 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ UTF-8 8 - 1.5.31 + 1.6.10 2.17.3 2.9.0 1.8.2 From 12bd55411319d0d19b344c5701481870ae436101 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Jan 2022 18:39:45 +0000 Subject: [PATCH 165/272] Bump assertj-core from 3.21.0 to 3.22.0 Bumps [assertj-core](https://github.com/assertj/assertj-core) from 3.21.0 to 3.22.0. - [Release notes](https://github.com/assertj/assertj-core/releases) - [Commits](https://github.com/assertj/assertj-core/compare/assertj-core-3.21.0...assertj-core-3.22.0) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5a1de7f5..302a24a7 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 1.5.31 2.17.3 2.9.0 - 1.8.2 + 1.9 3.0.1 2.8.8 @@ -46,7 +46,7 @@ 4.13.2 1.2.0 3.12.4 - 3.21.0 + 3.22.0 From 14e45f1e610f448e09f2d6de47f2c45ca74021db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Jan 2022 18:39:50 +0000 Subject: [PATCH 166/272] Bump spring-boot-autoconfigure from 2.6.2 to 2.6.3 Bumps [spring-boot-autoconfigure](https://github.com/spring-projects/spring-boot) from 2.6.2 to 2.6.3. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v2.6.2...v2.6.3) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-autoconfigure dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5a1de7f5..67542f54 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 1.5.31 2.17.3 2.9.0 - 1.8.2 + 1.9 3.0.1 2.8.8 @@ -39,7 +39,7 @@ 4.9.3 31.0-jre 1.0.0 - 2.6.2 + 2.6.3 0.6.0.20150202 From de25029799e0f916d4d73ba47b31c1fe35f7df05 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Jan 2022 18:39:54 +0000 Subject: [PATCH 167/272] Bump gson from 2.8.8 to 2.8.9 Bumps [gson](https://github.com/google/gson) from 2.8.8 to 2.8.9. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.8.8...gson-parent-2.8.9) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5a1de7f5..a9e5cee0 100644 --- a/pom.xml +++ b/pom.xml @@ -31,10 +31,10 @@ 1.5.31 2.17.3 2.9.0 - 1.8.2 + 1.9 3.0.1 - 2.8.8 + 2.8.9 4.9.3 4.9.3 31.0-jre From 544deb0113a9727e2d7a4d2f900e0e5c8daecb06 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Jan 2022 18:40:11 +0000 Subject: [PATCH 168/272] Bump spotless-maven-plugin from 2.17.3 to 2.20.0 Bumps [spotless-maven-plugin](https://github.com/diffplug/spotless) from 2.17.3 to 2.20.0. - [Release notes](https://github.com/diffplug/spotless/releases) - [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md) - [Commits](https://github.com/diffplug/spotless/compare/maven/2.17.3...lib/2.20.0) --- updated-dependencies: - dependency-name: com.diffplug.spotless:spotless-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f6b5433e..fe863a64 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ UTF-8 8 1.6.10 - 2.17.3 + 2.20.0 2.9.0 1.9 From a506212d18a2f0dfb1975c9eb51090114ffac24d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Jan 2022 18:42:57 +0000 Subject: [PATCH 169/272] Bump mockito-core from 3.12.4 to 4.3.1 Bumps [mockito-core](https://github.com/mockito/mockito) from 3.12.4 to 4.3.1. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v3.12.4...v4.3.1) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 338668a1..835ff74b 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ 4.13.2 1.2.0 - 3.12.4 + 4.3.1 3.22.0 From 666042cd27cb3190513501ebbc2dc2525094dee4 Mon Sep 17 00:00:00 2001 From: jorgen25 Date: Wed, 26 Jan 2022 13:17:32 -0700 Subject: [PATCH 170/272] based on PR: https://github.com/segmentio/analytics-java/pull/316 fixed compile errors: mockito version is upgraded so some methods are not named the same example: verifyZeroInteractions became verifyNoInteractions --- .../test/java/com/segment/analytics/AnalyticsTest.java | 2 +- .../analytics/internal/AnalyticsClientTest.java | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsTest.java index bb954c86..2eccc24b 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsTest.java @@ -1,6 +1,6 @@ package com.segment.analytics; -import static org.mockito.Matchers.any; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 3851d066..4237fd45 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -3,16 +3,16 @@ import static com.segment.analytics.internal.FlushMessage.POISON; import static com.segment.analytics.internal.StopMessage.STOP; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.argThat; -import static org.mockito.Matchers.eq; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; @@ -534,7 +534,7 @@ public void shutdownWhenAlreadyShutDown() throws InterruptedException { client.shutdown(); verify(messageQueue, times(0)).put(any(Message.class)); - verifyZeroInteractions(networkExecutor, callback, segmentService); + verifyNoInteractions(networkExecutor, callback, segmentService); } @Test From 76550a044d16bf93e9451ba0e73eec7db4bbd362 Mon Sep 17 00:00:00 2001 From: jorgen25 Date: Wed, 26 Jan 2022 13:22:57 -0700 Subject: [PATCH 171/272] run mvn:spotless apply --- .../com/segment/analytics/internal/AnalyticsClientTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 4237fd45..b1b04b02 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -4,15 +4,15 @@ import static com.segment.analytics.internal.StopMessage.STOP; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; From af6555382be014c395879f965ebd94e4851742cf Mon Sep 17 00:00:00 2001 From: jorgen25 Date: Fri, 28 Jan 2022 10:09:35 -0700 Subject: [PATCH 172/272] removed inner loop,sequence counter and modified test cases --- .../analytics/internal/AnalyticsClient.java | 45 ++++++------------- .../internal/AnalyticsClientTest.java | 32 ++++++++----- 2 files changed, 34 insertions(+), 43 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 1b329d3f..81d467bf 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -30,7 +30,6 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; import retrofit2.Call; import retrofit2.Response; @@ -250,12 +249,7 @@ public Looper() { @Override public void run() { LinkedList messages = new LinkedList<>(); - // @jorgen25 we could check size at the moment we are creating batch but it will be very time - // consuming. - // its better to check as we take messages and since Message does not implement hashcode we - // can use messageId Map messageIdSizeMap = new HashMap<>(); - AtomicInteger sequenceCounter = new AtomicInteger(1); int contextSize = getGsonInstance().toJson(CONTEXT).getBytes(ENCODING).length; try { while (!stop) { @@ -277,20 +271,14 @@ public void run() { Boolean isOverflow = messages.size() >= size; if (!messages.isEmpty() && (isOverflow || isBlockingSignal)) { - while (!messages.isEmpty()) { - Batch batch = - BatchUtility.createBatch( - messages, messageIdSizeMap, contextSize, sequenceCounter); - log.print( - VERBOSE, - "Batching %s message(s) into batch %s.", - batch.batch().size(), - batch.sequence()); - networkExecutor.submit( - BatchUploadTask.create(AnalyticsClient.this, batch, maximumRetries)); - } - messages = new LinkedList<>(); - messageIdSizeMap.clear(); + Batch batch = BatchUtility.createBatch(messages, messageIdSizeMap, contextSize); + log.print( + VERBOSE, + "Batching %s message(s) into batch %s.", + batch.batch().size(), + batch.sequence()); + networkExecutor.submit( + BatchUploadTask.create(AnalyticsClient.this, batch, maximumRetries)); } } } catch (InterruptedException e) { @@ -415,31 +403,27 @@ public static class BatchUtility { * @return batch object */ public static Batch createBatch( - LinkedList list, - Map messageIdSizeMap, - int contextSize, - AtomicInteger sequenceCounter) { + LinkedList list, Map messageIdSizeMap, int contextSize) { List messagesForBatch = new ArrayList<>(); Batch batch = null; int currentBatchSize = 0; - // since we are handling max size of 32 kbs when enqueing msg, one single msg will not be + // since we are handling max size of 32 kbs when enqueuing msg, one single msg will not be // above limit while (list.size() > 0 && currentBatchSize <= BATCH_MAX_SIZE) { Message msg = list.peek(); int msgSize = messageIdSizeMap.get(msg.messageId()); - int defaultBatchSizeSoFar = - getBatchDefaultSize(contextSize, messagesForBatch.size() + 1, sequenceCounter); + int defaultBatchSizeSoFar = getBatchDefaultSize(contextSize, messagesForBatch.size() + 1); if ((currentBatchSize + msgSize + defaultBatchSizeSoFar) < BATCH_MAX_SIZE) { messagesForBatch.add(list.poll()); currentBatchSize += msgSize; + messageIdSizeMap.remove(msg.messageId()); } else { break; } } batch = Batch.create(CONTEXT, messagesForBatch); - sequenceCounter.set(batch.sequence()); return batch; } @@ -481,8 +465,7 @@ public static Batch createBatch( * digits * @return */ - private static int getBatchDefaultSize( - int contextSize, int currentMessageNumber, AtomicInteger sequenceCounter) { + private static int getBatchDefaultSize(int contextSize, int currentMessageNumber) { // sample data: {"batch":[],"sentAt":"MMM dd, yyyy, HH:mm:ss tt","context":,"sequence":1} - 73 int metadataExtraCharsSize = 73; int commaNumber = currentMessageNumber - 1; @@ -490,7 +473,7 @@ private static int getBatchDefaultSize( return contextSize + metadataExtraCharsSize + commaNumber - + String.valueOf(sequenceCounter.incrementAndGet()).length(); + + String.valueOf(Integer.MAX_VALUE).length(); } } } diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 100bccab..044907aa 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -3,16 +3,16 @@ import static com.segment.analytics.internal.FlushMessage.POISON; import static com.segment.analytics.internal.StopMessage.STOP; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.argThat; -import static org.mockito.Matchers.eq; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; @@ -44,7 +44,6 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; import okhttp3.ResponseBody; import org.junit.Before; import org.junit.Test; @@ -327,8 +326,13 @@ public void flushHowManyTimesNecessaryToStayWithinLimit() throws InterruptedExce } wait(messageQueue); - - verify(networkExecutor, times(4)).submit(any(Runnable.class)); + /** + * modified from expected 4 to expected 3 times, since we removed the inner loop. The inner loop + * was forcing to message list created from the queue to keep making batches even if its a 1 + * message batch until the message list is empty, that was forcing the code to make one last + * batch of 1 msg in size bumping the number of times a batch would be submitted from 3 to 4 + */ + verify(networkExecutor, times(3)).submit(any(Runnable.class)); } /** @@ -613,7 +617,7 @@ public void shutdownWhenAlreadyShutDown() throws InterruptedException { client.shutdown(); verify(messageQueue, times(0)).put(any(Message.class)); - verifyZeroInteractions(networkExecutor, callback, segmentService); + verifyNoInteractions(networkExecutor, callback, segmentService); } @Test @@ -859,7 +863,6 @@ public void createBatchConfirmSizeNotViolated(MessageBuilderTest builder) { int msgSize = 1024 * 18; // 18KB LinkedList messages = new LinkedList<>(); Map messageIdSizeMap = new HashMap<>(); - AtomicInteger sequenceCounter = new AtomicInteger(); // Create context Map library = new LinkedHashMap<>(); @@ -883,8 +886,7 @@ public void createBatchConfirmSizeNotViolated(MessageBuilderTest builder) { while (!messages.isEmpty()) { Batch batch = - AnalyticsClient.BatchUtility.createBatch( - messages, messageIdSizeMap, contextSize, sequenceCounter); + AnalyticsClient.BatchUtility.createBatch(messages, messageIdSizeMap, contextSize); int batchSize = AnalyticsClient.getGsonInstance().toJson(batch).getBytes(StandardCharsets.UTF_8).length; assertThat(batchSize).isLessThan(MAX_BATCH_SIZE); @@ -961,7 +963,13 @@ public void submitBatchAboveThreshold() throws InterruptedException { client.shutdown(); while (!isShutDown.get()) {} - verify(networkExecutor, times(8)).submit(any(Runnable.class)); + /** + * modified from expected 8 to expected 7 times, since we removed the inner loop. The inner loop + * was forcing to message list created from the queue to keep making batches even if its a 1 + * message batch until the message list is empty, that was forcing the code to make one last + * batch of 1 msg in size bumping the number of times a batch would be submitted from 7 to 8 + */ + verify(networkExecutor, times(7)).submit(any(Runnable.class)); } @Test From 41051839b027fb00835b716319026741f345eb45 Mon Sep 17 00:00:00 2001 From: jorgen25 Date: Fri, 28 Jan 2022 10:13:12 -0700 Subject: [PATCH 173/272] ran mvn spotless apply` --- .../com/segment/analytics/internal/AnalyticsClientTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 044907aa..bc494457 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -11,8 +11,8 @@ import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; From 20dad36a454943692926abe2b0adc0513a90dd14 Mon Sep 17 00:00:00 2001 From: jorgen25 Date: Fri, 28 Jan 2022 10:47:55 -0700 Subject: [PATCH 174/272] waiting to confirm interaction on mock --- .../com/segment/analytics/internal/AnalyticsClientTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index bc494457..eaf155ea 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -925,6 +925,9 @@ public void submitBatchBelowThreshold() throws InterruptedException { } client.enqueue(POISON); wait(messageQueue); + + client.shutdown(); + while (!isShutDown.get()) {} verify(networkExecutor, times(1)).submit(any(Runnable.class)); } From 090dac9db046d95acb9615032468e0494a9dc587 Mon Sep 17 00:00:00 2001 From: jorgen25 Date: Tue, 1 Feb 2022 12:05:32 -0700 Subject: [PATCH 175/272] removed hashmap from loop --- .../analytics/internal/AnalyticsClient.java | 72 +++++++++---------- .../internal/AnalyticsClientTest.java | 71 ------------------ 2 files changed, 34 insertions(+), 109 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 81d467bf..8f8e9707 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -17,7 +17,6 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; @@ -30,6 +29,7 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import retrofit2.Call; import retrofit2.Response; @@ -172,14 +172,16 @@ public void enqueue(Message message) { // @jorgen25 check if message is below 32kb limit for individual messages, no need to check // for extra characters if (messageByteSize <= MSG_MAX_SIZE) { - messageQueue.put(message); + // messageQueue.put(message); if (isBackPressuredAfterSize(messageByteSize)) { this.currentQueueSizeInBytes = messageByteSize; messageQueue.put(FlushMessage.POISON); + messageQueue.put(message); log.print(VERBOSE, "Maximum storage size has been hit Flushing..."); } else { + messageQueue.put(message); this.currentQueueSizeInBytes += messageByteSize; } } else { @@ -249,7 +251,8 @@ public Looper() { @Override public void run() { LinkedList messages = new LinkedList<>(); - Map messageIdSizeMap = new HashMap<>(); + AtomicInteger currentBatchSize = new AtomicInteger(); + boolean batchSizeLimitReached = false; int contextSize = getGsonInstance().toJson(CONTEXT).getBytes(ENCODING).length; try { while (!stop) { @@ -263,15 +266,29 @@ public void run() { log.print(VERBOSE, "Flushing messages."); } } else { - messageIdSizeMap.put(message.messageId(), messageSizeInBytes(message)); - messages.add(message); + // we do +1 because we are accounting for this new message we just took from the queue + // which is not in list yet + // need to check if this message is going to make us go over the limit considering + // default batch size as well + int defaultBatchSize = + BatchUtility.getBatchDefaultSize(contextSize, messages.size() + 1); + int msgSize = messageSizeInBytes(message); + if (currentBatchSize.get() + msgSize + defaultBatchSize <= BATCH_MAX_SIZE) { + messages.add(message); + currentBatchSize.addAndGet(msgSize); + } else { + // put message that did not make the cut this time back on the queue, we already took + // this message if we dont put it back its lost + // we take care of that after submitting the batch + batchSizeLimitReached = true; + } } Boolean isBlockingSignal = message == FlushMessage.POISON || message == StopMessage.STOP; Boolean isOverflow = messages.size() >= size; - if (!messages.isEmpty() && (isOverflow || isBlockingSignal)) { - Batch batch = BatchUtility.createBatch(messages, messageIdSizeMap, contextSize); + if (!messages.isEmpty() && (isOverflow || isBlockingSignal || batchSizeLimitReached)) { + Batch batch = Batch.create(CONTEXT, new ArrayList<>(messages)); log.print( VERBOSE, "Batching %s message(s) into batch %s.", @@ -279,6 +296,16 @@ public void run() { batch.sequence()); networkExecutor.submit( BatchUploadTask.create(AnalyticsClient.this, batch, maximumRetries)); + + currentBatchSize.set(0); + messages.clear(); + if (batchSizeLimitReached) { + // If this is true that means the last message that would make us go over the limit + // was not added, + // add it to the now cleared messages list so its not lost + messages.add(message); + } + batchSizeLimitReached = false; } } } catch (InterruptedException e) { @@ -396,37 +423,6 @@ private static boolean is5xx(int status) { } public static class BatchUtility { - /** - * Method to create a batch considering threshold of 500Kb for entire batch - * - * @param list - * @return batch object - */ - public static Batch createBatch( - LinkedList list, Map messageIdSizeMap, int contextSize) { - List messagesForBatch = new ArrayList<>(); - Batch batch = null; - - int currentBatchSize = 0; - - // since we are handling max size of 32 kbs when enqueuing msg, one single msg will not be - // above limit - while (list.size() > 0 && currentBatchSize <= BATCH_MAX_SIZE) { - Message msg = list.peek(); - int msgSize = messageIdSizeMap.get(msg.messageId()); - int defaultBatchSizeSoFar = getBatchDefaultSize(contextSize, messagesForBatch.size() + 1); - if ((currentBatchSize + msgSize + defaultBatchSizeSoFar) < BATCH_MAX_SIZE) { - messagesForBatch.add(list.poll()); - currentBatchSize += msgSize; - messageIdSizeMap.remove(msg.messageId()); - } else { - break; - } - } - batch = Batch.create(CONTEXT, messagesForBatch); - - return batch; - } /** * Method to determine what is the expected default size of the batch regardless of messages diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index eaf155ea..dc29e4dc 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -32,8 +32,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.LinkedList; import java.util.Map; import java.util.Queue; import java.util.Random; @@ -257,34 +255,6 @@ public void dontFlushUntilReachesMaxSize() throws InterruptedException { verify(networkExecutor, never()).submit(any(Runnable.class)); } - /** - * Planning to remove this test case since logic change makes test case unnecessary. The purpose - * of the test case was to test scenario when one BIG message (of MAX_BYTE_SIZE = 1024 * 500) - * would backpressure queue for each message put in queue so it would be backpressured 10 times, - * then flushed 10 times and 10 batches would be submitted - * - *

Since logic changed to not allow msgs larger than 32kbs abd batches over 500kb this test - * case would be the exact same one as flushWhenMultipleMessagesReachesMaxSize test case - * - * @throws InterruptedException - */ - // @Test - // public void flushWhenReachesMaxSize() throws InterruptedException { - // AnalyticsClient client = newClient(); - // Map properties = new HashMap(); - // - // properties.put("property3", generateMassDataOfSize(MAX_BYTE_SIZE)); - // - // for (int i = 0; i < 10; i++) { - // TrackMessage bigMessage = - // TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); - // client.enqueue(bigMessage); - // } - // - // wait(messageQueue); - // - // verify(networkExecutor, times(10)).submit(any(Runnable.class)); - // } /** * Modified this test case since we are changing logic to NOT allow messages bigger than 32 kbs @@ -852,47 +822,6 @@ public void enqueueVerifyRegularMessagesSpecialCharactersBelowLimit(MessageBuild * **************************************************************************************************************** */ - /** - * This takes time since its getting size of each message and each batch created - * - * @param builder - */ - @Test - public void createBatchConfirmSizeNotViolated(MessageBuilderTest builder) { - - int msgSize = 1024 * 18; // 18KB - LinkedList messages = new LinkedList<>(); - Map messageIdSizeMap = new HashMap<>(); - - // Create context - Map library = new LinkedHashMap<>(); - library.put("name", "analytics-java"); - library.put("version", AnalyticsVersion.get()); - Map context = new LinkedHashMap<>(); - context.put("library", Collections.unmodifiableMap(library)); - Map CONTEXT = Collections.unmodifiableMap(context); - int contextSize = - AnalyticsClient.getGsonInstance().toJson(CONTEXT).getBytes(StandardCharsets.UTF_8).length; - - for (int i = 0; i < 40; i++) { - final String data = generateDataOfSizeSpecialChars(msgSize, true); - Map integrationOpts = new HashMap<>(); - integrationOpts.put("data", data); - Message message = - builder.get().userId("jorgen25").integrationOptions("someKey", integrationOpts).build(); - messageIdSizeMap.put(message.messageId(), newClient().messageSizeInBytes(message)); - messages.add(message); - } - - while (!messages.isEmpty()) { - Batch batch = - AnalyticsClient.BatchUtility.createBatch(messages, messageIdSizeMap, contextSize); - int batchSize = - AnalyticsClient.getGsonInstance().toJson(batch).getBytes(StandardCharsets.UTF_8).length; - assertThat(batchSize).isLessThan(MAX_BATCH_SIZE); - } - } - /** * Several messages are enqueued and then submitted in a batch * From 7e6903c8a63a7f257d5270bad03feafaa9a7a220 Mon Sep 17 00:00:00 2001 From: jorgen25 Date: Tue, 1 Feb 2022 16:04:47 -0700 Subject: [PATCH 176/272] ran mvn spotless --- .../java/com/segment/analytics/internal/AnalyticsClientTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index dc29e4dc..aa84cf81 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -255,7 +255,6 @@ public void dontFlushUntilReachesMaxSize() throws InterruptedException { verify(networkExecutor, never()).submit(any(Runnable.class)); } - /** * Modified this test case since we are changing logic to NOT allow messages bigger than 32 kbs * individually to be enqueued, hence had to lower the size of the generated msg here. chose From 7e3fc1115263201e1071f8323d04af3f48157be0 Mon Sep 17 00:00:00 2001 From: jorgen25 Date: Thu, 10 Feb 2022 09:46:54 -0700 Subject: [PATCH 177/272] Creating PR from https://github.com/segmentio/analytics-java/pull/305/ --- .../segment/analytics/internal/AnalyticsClient.java | 2 +- .../analytics/internal/AnalyticsClientTest.java | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 8f27d104..2beb1d88 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -104,7 +104,7 @@ public static AnalyticsClient create( this.currentQueueSizeInBytes = 0; - looperExecutor.submit(new Looper()); + if (!isShutDown.get()) looperExecutor.submit(new Looper()); flushScheduler = Executors.newScheduledThreadPool(1, threadFactory); flushScheduler.scheduleAtFixedRate( diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index b1b04b02..e9fc6e69 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -7,14 +7,13 @@ import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; +import static org.mockito.MockitoAnnotations.openMocks; import com.segment.analytics.Callback; import com.segment.analytics.Log; @@ -33,7 +32,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Queue; -import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; @@ -47,6 +45,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatcher; import org.mockito.Mock; +import org.mockito.Spy; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import retrofit2.Call; @@ -65,7 +64,7 @@ public class AnalyticsClientTest { Log log = Log.NONE; ThreadFactory threadFactory; - @Mock BlockingQueue messageQueue; + @Spy LinkedBlockingQueue messageQueue; @Mock SegmentService segmentService; @Mock ExecutorService networkExecutor; @Mock Callback callback; @@ -75,10 +74,9 @@ public class AnalyticsClientTest { @Before public void setUp() { - initMocks(this); + openMocks(this); isShutDown = new AtomicBoolean(false); - messageQueue = spy(new LinkedBlockingQueue()); threadFactory = Executors.defaultThreadFactory(); } From 181a825293bb555c88bf8a144889e31b706170e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Feb 2022 16:02:37 +0000 Subject: [PATCH 178/272] Bump gson from 2.8.9 to 2.9.0 Bumps [gson](https://github.com/google/gson) from 2.8.9 to 2.9.0. - [Release notes](https://github.com/google/gson/releases) - [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/gson/compare/gson-parent-2.8.9...gson-parent-2.9.0) --- updated-dependencies: - dependency-name: com.google.code.gson:gson dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 028005fe..ab0e6943 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ 1.9 3.0.1 - 2.8.9 + 2.9.0 4.9.3 4.9.3 31.0-jre From 27190a2c73631cd1bfd4bbd2456b68595759a91d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Feb 2022 16:02:40 +0000 Subject: [PATCH 179/272] Bump spotless-maven-plugin from 2.20.0 to 2.20.2 Bumps [spotless-maven-plugin](https://github.com/diffplug/spotless) from 2.20.0 to 2.20.2. - [Release notes](https://github.com/diffplug/spotless/releases) - [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md) - [Commits](https://github.com/diffplug/spotless/compare/lib/2.20.0...lib/2.20.2) --- updated-dependencies: - dependency-name: com.diffplug.spotless:spotless-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 028005fe..5104e02f 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ UTF-8 8 1.6.10 - 2.20.0 + 2.20.2 2.9.0 1.9 From 6ac2949f3951072d9374b47e2b1ef77a171985db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Feb 2022 16:02:47 +0000 Subject: [PATCH 180/272] Bump maven-compiler-plugin from 3.9.0 to 3.10.0 Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.9.0 to 3.10.0. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.9.0...maven-compiler-plugin-3.10.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 028005fe..c74ee1d4 100644 --- a/pom.xml +++ b/pom.xml @@ -170,7 +170,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.9.0 + 3.10.0 true ${java.version} From b8eac1071353deb96728e64bdfe9a75e694ea60c Mon Sep 17 00:00:00 2001 From: jorgen25 Date: Wed, 16 Feb 2022 13:19:19 -0700 Subject: [PATCH 181/272] ran mvn spotless:apply --- .../com/segment/analytics/internal/AnalyticsClientTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 69d4ea0f..47ee1bcb 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -7,6 +7,7 @@ import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -34,7 +35,6 @@ import java.util.Map; import java.util.Queue; import java.util.Random; -import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; From 71fa6e75da47e0bec34f552c4ec28f6ba8497399 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Feb 2022 16:02:15 +0000 Subject: [PATCH 182/272] Bump spotless-maven-plugin from 2.20.2 to 2.21.0 Bumps [spotless-maven-plugin](https://github.com/diffplug/spotless) from 2.20.2 to 2.21.0. - [Release notes](https://github.com/diffplug/spotless/releases) - [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md) - [Commits](https://github.com/diffplug/spotless/compare/lib/2.20.2...lib/2.21.0) --- updated-dependencies: - dependency-name: com.diffplug.spotless:spotless-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 08c6e973..791b5e0d 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ UTF-8 8 1.6.10 - 2.20.2 + 2.21.0 2.9.0 1.9 From dbd4c1bdbdddb14fe403763a0b1b353310bb30b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Feb 2022 16:02:23 +0000 Subject: [PATCH 183/272] Bump spring-boot-autoconfigure from 2.6.3 to 2.6.4 Bumps [spring-boot-autoconfigure](https://github.com/spring-projects/spring-boot) from 2.6.3 to 2.6.4. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v2.6.3...v2.6.4) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-autoconfigure dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 08c6e973..ca62757e 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ 4.9.3 31.0-jre 1.0.0 - 2.6.3 + 2.6.4 0.6.0.20150202 From cdf350c33d71759ae883b03fc341912f91a1f5f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Mar 2022 16:02:29 +0000 Subject: [PATCH 184/272] Bump guava from 31.0-jre to 31.1-jre Bumps [guava](https://github.com/google/guava) from 31.0-jre to 31.1-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) --- updated-dependencies: - dependency-name: com.google.guava:guava dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 951012fa..f6f468ab 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ 2.9.0 4.9.3 4.9.3 - 31.0-jre + 31.1-jre 1.0.0 2.6.4 0.6.0.20150202 From 9d6f8076982a4754ad161c684197da76b936110a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Mar 2022 16:01:53 +0000 Subject: [PATCH 185/272] Bump maven-compiler-plugin from 3.10.0 to 3.10.1 Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.10.0 to 3.10.1. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.10.0...maven-compiler-plugin-3.10.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f6f468ab..939e99dd 100644 --- a/pom.xml +++ b/pom.xml @@ -170,7 +170,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.10.0 + 3.10.1 true ${java.version} From 0eb93c6e16eb3ea05ed008473e681e475aa7acb4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Mar 2022 16:02:01 +0000 Subject: [PATCH 186/272] Bump mockito-core from 4.3.1 to 4.4.0 Bumps [mockito-core](https://github.com/mockito/mockito) from 4.3.1 to 4.4.0. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v4.3.1...v4.4.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f6f468ab..75ad8bff 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ 4.13.2 1.2.0 - 4.3.1 + 4.4.0 3.22.0 From 16fd898a5afa0b85b399a74fbf8fedb40086b49d Mon Sep 17 00:00:00 2001 From: jorgen25 Date: Fri, 25 Mar 2022 16:54:21 -0700 Subject: [PATCH 187/272] Removed the line for failure callback method --- .../java/com/segment/analytics/internal/AnalyticsClient.java | 1 - 1 file changed, 1 deletion(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index bb81db98..32828cc4 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -385,7 +385,6 @@ boolean upload() { return false; } catch (IOException error) { client.log.print(DEBUG, error, "Could not upload batch %s. Retrying.", batch.sequence()); - notifyCallbacksWithException(batch, error); return true; } catch (Exception exception) { From 22e31091e4ad661dadb6c351d69abd1eb2924415 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Mar 2022 16:02:45 +0000 Subject: [PATCH 188/272] Bump spring-boot-autoconfigure from 2.6.4 to 2.6.5 Bumps [spring-boot-autoconfigure](https://github.com/spring-projects/spring-boot) from 2.6.4 to 2.6.5. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v2.6.4...v2.6.5) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-autoconfigure dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 99826b78..83bc1640 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ 4.9.3 31.1-jre 1.0.0 - 2.6.4 + 2.6.5 0.6.0.20150202 From ab0f7058c53ba376bb1bf38cba4712d936522483 Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Thu, 31 Mar 2022 12:01:02 -0700 Subject: [PATCH 189/272] Update pom.xml --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 83bc1640..9073a34c 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ 4.9.3 31.1-jre 1.0.0 - 2.6.5 + 2.6.6 0.6.0.20150202 From 7441e0af7f85218288a19736d5e9faccc26c4596 Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Thu, 31 Mar 2022 22:23:37 -0700 Subject: [PATCH 190/272] fix pom file --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9073a34c..a695f024 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.1.3 + 3.1.3-SNAPSHOT pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. From afe2f4b88209c09aa8e602382fe78a51b3365db9 Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Thu, 31 Mar 2022 22:24:54 -0700 Subject: [PATCH 191/272] [maven-release-plugin] prepare release analytics-parent-3.2.0 --- analytics-cli/pom.xml | 6 +++++- analytics-core/pom.xml | 6 +++++- analytics-sample/pom.xml | 6 +++++- analytics-spring-boot-starter/pom.xml | 6 +++++- analytics/pom.xml | 6 +++++- pom.xml | 4 ++-- 6 files changed, 27 insertions(+), 7 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index ef888389..03867ba7 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.3 + 3.2.0 analytics-cli @@ -79,4 +79,8 @@ + + + analytics-parent-3.2.0 + diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index fc120d48..77248950 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.3 + 3.2.0 analytics-core @@ -68,4 +68,8 @@ + + + analytics-parent-3.2.0 + diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 74873165..6f0afcc2 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.1.3 + 3.2.0 analytics-sample @@ -47,4 +47,8 @@ + + + analytics-parent-3.2.0 + diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 17ecc21c..fc57cb86 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.3 + 3.2.0 analytics-spring-boot-starter @@ -26,4 +26,8 @@ ${spring.boot.version} + + + analytics-parent-3.2.0 + diff --git a/analytics/pom.xml b/analytics/pom.xml index ecf5b6a2..263766cc 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.1.3 + 3.2.0 analytics @@ -88,4 +88,8 @@ + + + analytics-parent-3.2.0 + diff --git a/pom.xml b/pom.xml index a695f024..fced175e 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.1.3-SNAPSHOT + 3.2.0 pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - HEAD + analytics-parent-3.2.0 From a7b9fcba3fb403e0a0cd850d7280e80ef7a258ca Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Thu, 31 Mar 2022 22:25:00 -0700 Subject: [PATCH 192/272] [maven-release-plugin] prepare for next development iteration --- analytics-cli/pom.xml | 8 ++------ analytics-core/pom.xml | 8 ++------ analytics-sample/pom.xml | 8 ++------ analytics-spring-boot-starter/pom.xml | 7 ++----- analytics/pom.xml | 8 ++------ pom.xml | 4 ++-- 6 files changed, 12 insertions(+), 31 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 03867ba7..45b5f96f 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,10 +6,11 @@ analytics-parent com.segment.analytics.java - 3.2.0 + 3.2.1-SNAPSHOT analytics-cli + 3.1.3 Analytics Java CLI @@ -78,9 +79,4 @@ - - - - analytics-parent-3.2.0 - diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index 77248950..588e44d4 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,10 +6,11 @@ com.segment.analytics.java analytics-parent - 3.2.0 + 3.2.1-SNAPSHOT analytics-core + 3.1.3 Analytics for Java (Core) @@ -67,9 +68,4 @@ test - - - - analytics-parent-3.2.0 - diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 6f0afcc2..2e17a07f 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,10 +6,11 @@ analytics-parent com.segment.analytics.java - 3.2.0 + 3.2.1-SNAPSHOT analytics-sample + 3.1.3 Analytics Sample @@ -46,9 +47,4 @@ - - - - analytics-parent-3.2.0 - diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index fc57cb86..9405afa2 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,10 +6,11 @@ com.segment.analytics.java analytics-parent - 3.2.0 + 3.2.1-SNAPSHOT analytics-spring-boot-starter + 3.1.3 Spring Boot starter for Segment Analytics for Java @@ -26,8 +27,4 @@ ${spring.boot.version} - - - analytics-parent-3.2.0 - diff --git a/analytics/pom.xml b/analytics/pom.xml index 263766cc..8e9ac29d 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,10 +6,11 @@ com.segment.analytics.java analytics-parent - 3.2.0 + 3.2.1-SNAPSHOT analytics + 3.1.3 Analytics for Java @@ -87,9 +88,4 @@ - - - - analytics-parent-3.2.0 - diff --git a/pom.xml b/pom.xml index fced175e..818c89a7 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.2.0 + 3.2.1-SNAPSHOT pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - analytics-parent-3.2.0 + HEAD From 4d7e197bcb3399eb43c2b68b5c6df217f2a1a3c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Apr 2022 16:03:26 +0000 Subject: [PATCH 193/272] Bump spotless-maven-plugin from 2.21.0 to 2.22.0 Bumps [spotless-maven-plugin](https://github.com/diffplug/spotless) from 2.21.0 to 2.22.0. - [Release notes](https://github.com/diffplug/spotless/releases) - [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md) - [Commits](https://github.com/diffplug/spotless/compare/lib/2.21.0...lib/2.22.0) --- updated-dependencies: - dependency-name: com.diffplug.spotless:spotless-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 818c89a7..0e271b7e 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ UTF-8 8 1.6.10 - 2.21.0 + 2.22.0 2.9.0 1.9 From 7538ebf82bb849519fce2bc144f128d262a3dec6 Mon Sep 17 00:00:00 2001 From: jorgen25 Date: Wed, 6 Apr 2022 20:48:46 -0600 Subject: [PATCH 194/272] removed wildcards --- .../com/segment/analytics/AnalyticsTest.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsTest.java index 2eccc24b..03ccbb5e 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsTest.java @@ -4,6 +4,8 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.spy; import static org.mockito.MockitoAnnotations.initMocks; import com.segment.analytics.TestUtils.MessageBuilderTest; @@ -11,7 +13,15 @@ import com.segment.analytics.messages.Message; import com.segment.analytics.messages.MessageBuilder; import com.squareup.burst.BurstJUnit4; + +import java.lang.reflect.Field; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.Collections; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -102,4 +112,40 @@ public void offerIsDispatched(MessageBuilderTest builder) { verify(messageInterceptor).intercept(any(Message.class)); verify(client).offer(message); } + + @Test + public void threadSafeTest(MessageBuilderTest builder) throws NoSuchFieldException, IllegalAccessException, InterruptedException { + //we want to test if msgs get lost during a multithreaded env + Analytics analytics = Analytics.builder("testWriteKeyForIssue321").build(); + //So we just want to spy on the client of an Analytics object created normally + Field clientField = analytics.getClass().getDeclaredField("client"); + clientField.setAccessible(true); + AnalyticsClient spy = spy((AnalyticsClient)clientField.get(analytics)); + clientField.set(analytics, spy); + + //we are going to run this test for a specific amount of seconds + int millisRunning = 200; + LocalDateTime initialTime = LocalDateTime.now(); + LocalDateTime now; + + //and a set number of threads will be using the library + ExecutorService service = Executors.newFixedThreadPool(20); + AtomicInteger counter = new AtomicInteger(); + + MessageBuilder messageBuilder = builder.get().userId("jorgen25"); + + do { + service.submit(() -> { + analytics.enqueue(messageBuilder); + counter.incrementAndGet(); + }); + now = LocalDateTime.now(); + } while(initialTime.until(now, ChronoUnit.MILLIS) < millisRunning); + + service.shutdown(); + while (!service.isShutdown() || !service.isTerminated()) { + + } + verify(spy, times(counter.get())).enqueue(any(Message.class)); + } } From 0db220006e16613290a27e1be49ab2928acb37ee Mon Sep 17 00:00:00 2001 From: jorgen25 Date: Wed, 6 Apr 2022 20:52:54 -0600 Subject: [PATCH 195/272] run spotless --- .../com/segment/analytics/AnalyticsTest.java | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsTest.java index 03ccbb5e..8be3012e 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsTest.java @@ -2,10 +2,10 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.spy; import static org.mockito.MockitoAnnotations.initMocks; import com.segment.analytics.TestUtils.MessageBuilderTest; @@ -13,7 +13,6 @@ import com.segment.analytics.messages.Message; import com.segment.analytics.messages.MessageBuilder; import com.squareup.burst.BurstJUnit4; - import java.lang.reflect.Field; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; @@ -21,7 +20,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -114,38 +112,39 @@ public void offerIsDispatched(MessageBuilderTest builder) { } @Test - public void threadSafeTest(MessageBuilderTest builder) throws NoSuchFieldException, IllegalAccessException, InterruptedException { - //we want to test if msgs get lost during a multithreaded env + public void threadSafeTest(MessageBuilderTest builder) + throws NoSuchFieldException, IllegalAccessException, InterruptedException { + // we want to test if msgs get lost during a multithreaded env Analytics analytics = Analytics.builder("testWriteKeyForIssue321").build(); - //So we just want to spy on the client of an Analytics object created normally + // So we just want to spy on the client of an Analytics object created normally Field clientField = analytics.getClass().getDeclaredField("client"); clientField.setAccessible(true); - AnalyticsClient spy = spy((AnalyticsClient)clientField.get(analytics)); + AnalyticsClient spy = spy((AnalyticsClient) clientField.get(analytics)); clientField.set(analytics, spy); - //we are going to run this test for a specific amount of seconds + // we are going to run this test for a specific amount of seconds int millisRunning = 200; LocalDateTime initialTime = LocalDateTime.now(); LocalDateTime now; - //and a set number of threads will be using the library + // and a set number of threads will be using the library ExecutorService service = Executors.newFixedThreadPool(20); AtomicInteger counter = new AtomicInteger(); MessageBuilder messageBuilder = builder.get().userId("jorgen25"); do { - service.submit(() -> { - analytics.enqueue(messageBuilder); - counter.incrementAndGet(); - }); + service.submit( + () -> { + analytics.enqueue(messageBuilder); + counter.incrementAndGet(); + }); now = LocalDateTime.now(); - } while(initialTime.until(now, ChronoUnit.MILLIS) < millisRunning); + } while (initialTime.until(now, ChronoUnit.MILLIS) < millisRunning); service.shutdown(); - while (!service.isShutdown() || !service.isTerminated()) { + while (!service.isShutdown() || !service.isTerminated()) {} - } verify(spy, times(counter.get())).enqueue(any(Message.class)); } } From ee1fc3734b828c9311ada98af205f71c370c416c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Apr 2022 16:03:16 +0000 Subject: [PATCH 196/272] Bump spotless-maven-plugin from 2.22.0 to 2.22.1 Bumps [spotless-maven-plugin](https://github.com/diffplug/spotless) from 2.22.0 to 2.22.1. - [Release notes](https://github.com/diffplug/spotless/releases) - [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md) - [Commits](https://github.com/diffplug/spotless/compare/lib/2.22.0...lib/2.22.1) --- updated-dependencies: - dependency-name: com.diffplug.spotless:spotless-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0e271b7e..7611b984 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ UTF-8 8 1.6.10 - 2.22.0 + 2.22.1 2.9.0 1.9 From 5ae39b82069cc22e3e281024e99e1c54e46168d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Apr 2022 17:48:29 +0000 Subject: [PATCH 197/272] Bump kotlin.version from 1.6.10 to 1.6.21 Bumps `kotlin.version` from 1.6.10 to 1.6.21. Updates `kotlin-stdlib` from 1.6.10 to 1.6.21 - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/v1.6.21/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/compare/v1.6.10...v1.6.21) Updates `kotlin-maven-plugin` from 1.6.10 to 1.6.21 --- updated-dependencies: - dependency-name: org.jetbrains.kotlin:kotlin-stdlib dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.jetbrains.kotlin:kotlin-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7611b984..0f30f3e8 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ UTF-8 8 - 1.6.10 + 1.6.21 2.22.1 2.9.0 1.9 From 3fc0d85444c3819683c20cbb58663f2f1ef89d95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEdson?= Date: Thu, 28 Apr 2022 23:18:21 -0500 Subject: [PATCH 198/272] Override method create on Batch class to lend to user define his own date on sentAt field or use a null value --- .../java/com/segment/analytics/messages/Batch.java | 7 +++++++ .../com/segment/analytics/messages/BatchTest.java | 13 +++++++++++++ 2 files changed, 20 insertions(+) diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java b/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java index 3e47bccf..8a157b17 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java @@ -7,6 +7,8 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; +import javax.annotation.Nullable; + @AutoValue @AutoGson public abstract class Batch { @@ -15,9 +17,14 @@ public abstract class Batch { public static Batch create(Map context, List batch) { return new AutoValue_Batch(batch, new Date(), context, SEQUENCE_GENERATOR.incrementAndGet()); } + + public static Batch create(Map context, List batch, Date sentAt) { + return new AutoValue_Batch(batch, sentAt, context, SEQUENCE_GENERATOR.incrementAndGet()); + } public abstract List batch(); + @Nullable public abstract Date sentAt(); public abstract Map context(); diff --git a/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java b/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java index a810f094..7f1f1faf 100644 --- a/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java @@ -6,6 +6,8 @@ import com.google.common.collect.ImmutableMap; import com.segment.analytics.TestUtils; import com.squareup.burst.BurstJUnit4; + +import java.util.Date; import java.util.List; import java.util.Map; import org.junit.Test; @@ -25,6 +27,17 @@ public void create(TestUtils.MessageBuilderFactory factory) { assertThat(batch.batch()).isEqualTo(messages); assertThat(batch.context()).isEqualTo(context); } + + @Test + public void createSentAtNull(TestUtils.MessageBuilderFactory factory) { + Message message = factory.get().userId("userId").build(); + Map context = ImmutableMap.of("foo", "bar"); + List messages = ImmutableList.of(message); + + Batch batch = Batch.create(context, messages, null); + + assertThat(batch.sentAt()).isNull(); + } @Test public void sequence(TestUtils.MessageBuilderFactory factory) { From 85441126cac14300414caff608f6ad5e24c3e9f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEdson?= Date: Thu, 5 May 2022 14:36:09 -0500 Subject: [PATCH 199/272] Modify MessageBuilder to lend set sentAt value --- .../analytics/messages/AliasMessage.java | 5 +++-- .../com/segment/analytics/messages/Batch.java | 11 +++++----- .../analytics/messages/GroupMessage.java | 3 ++- .../analytics/messages/IdentifyMessage.java | 3 ++- .../segment/analytics/messages/Message.java | 5 ++++- .../analytics/messages/MessageBuilder.java | 17 +++++++++++++- .../analytics/messages/PageMessage.java | 22 ++++++++++--------- .../analytics/messages/ScreenMessage.java | 3 ++- .../analytics/messages/TrackMessage.java | 10 +++++---- .../segment/analytics/messages/BatchTest.java | 16 +++++++++----- .../analytics/internal/FlushMessage.java | 6 +++++ .../analytics/internal/StopMessage.java | 7 ++++++ 12 files changed, 76 insertions(+), 32 deletions(-) diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/AliasMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/AliasMessage.java index 2de18840..cb439986 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/AliasMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/AliasMessage.java @@ -56,13 +56,14 @@ private Builder(String previousId) { protected AliasMessage realBuild( Type type, String messageId, + Date sentAt, Date timestamp, Map context, String anonymousId, String userId, Map integrations) { - return new AutoValue_AliasMessage( - type, messageId, timestamp, context, anonymousId, userId, integrations, previousId); + return new AutoValue_AliasMessage(anonymousId, context, integrations, messageId, sentAt, + timestamp, type, userId, previousId); } @Override diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java b/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java index 8a157b17..4fe0335f 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java @@ -15,11 +15,12 @@ public abstract class Batch { private static final AtomicInteger SEQUENCE_GENERATOR = new AtomicInteger(); public static Batch create(Map context, List batch) { - return new AutoValue_Batch(batch, new Date(), context, SEQUENCE_GENERATOR.incrementAndGet()); - } - - public static Batch create(Map context, List batch, Date sentAt) { - return new AutoValue_Batch(batch, sentAt, context, SEQUENCE_GENERATOR.incrementAndGet()); + Message sentAtNull = batch.stream() + .filter(message -> message.sentAt() != null ) + .findAny() + .orElse(null); + + return new AutoValue_Batch(batch, sentAtNull == null ? new Date() : sentAtNull.sentAt(), context, SEQUENCE_GENERATOR.incrementAndGet()); } public abstract List batch(); diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java index 96190e21..8f6cae34 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java @@ -76,13 +76,14 @@ public Builder traits(Map traits) { protected GroupMessage realBuild( Type type, String messageId, + Date sentAt, Date timestamp, Map context, String anonymousId, String userId, Map integrations) { return new AutoValue_GroupMessage( - type, messageId, timestamp, context, anonymousId, userId, integrations, groupId, traits); + anonymousId, context, integrations, messageId, sentAt, timestamp, type, userId, groupId, traits); } @Override diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/IdentifyMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/IdentifyMessage.java index e298bd8e..ce9f5702 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/IdentifyMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/IdentifyMessage.java @@ -60,6 +60,7 @@ public Builder traits(Map traits) { protected IdentifyMessage realBuild( Type type, String messageId, + Date sentAt, Date timestamp, Map context, String anonymousId, @@ -70,7 +71,7 @@ protected IdentifyMessage realBuild( } return new AutoValue_IdentifyMessage( - type, messageId, timestamp, context, anonymousId, userId, integrations, traits); + anonymousId, context, integrations, messageId, sentAt, timestamp, type, userId, traits); } @Override diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/Message.java b/analytics-core/src/main/java/com/segment/analytics/messages/Message.java index c735f43b..be663c26 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/Message.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/Message.java @@ -26,9 +26,12 @@ public interface Message { @Nonnull String messageId(); + @Nullable + Date sentAt(); + @Nonnull Date timestamp(); - + @Nullable Map context(); diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java b/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java index d209ff14..614c5556 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java @@ -16,6 +16,7 @@ public abstract class MessageBuilder { private final Message.Type type; private String messageId; + private Date sentAt; private Date timestamp; private Map context; private String anonymousId; @@ -72,6 +73,17 @@ public V messageId(String messageId) { return self(); } + /** + * Set a sentAt for the event. By default, the current sentAt is used, but you may override + * it for historical import. + * + * @see SentAt + */ + public V sentAt(Date sentAt) { + this.sentAt = sentAt; + return self(); + } + /** * Set a timestamp for the event. By default, the current timestamp is used, but you may override * it for historical import. @@ -180,6 +192,7 @@ public V integrationOptions(String key, Map options) { protected abstract T realBuild( Message.Type type, String messageId, + Date sentAt, Date timestamp, Map context, String anonymousId, @@ -202,6 +215,8 @@ public T build() { if (timestamp == null) { timestamp = new Date(); } + + Date sentAt = this.sentAt; String messageId = this.messageId; if (messageId == null) { @@ -215,7 +230,7 @@ public T build() { integrations = ImmutableMap.copyOf(this.integrations); } - return realBuild(type, messageId, timestamp, context, anonymousId, userId, integrations); + return realBuild(type, messageId, sentAt, timestamp, context, anonymousId, userId, integrations); } /** Returns the {@link Message.Type} of the message this builder is constructing. */ diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java index 55fef551..7f961031 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java @@ -92,22 +92,24 @@ Builder self() { protected PageMessage realBuild( Type type, String messageId, + Date sentAt, Date timestamp, Map context, String anonymousId, String userId, Map integrations) { return new AutoValue_PageMessage( - type, - messageId, - timestamp, - context, - anonymousId, - userId, - integrations, - name, - properties, - category); + anonymousId, + context, + integrations, + messageId, + sentAt, + timestamp, + type, + userId, + name, + properties, + category); } } } diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/ScreenMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/ScreenMessage.java index 465537dc..8b391a7e 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/ScreenMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/ScreenMessage.java @@ -79,13 +79,14 @@ Builder self() { protected ScreenMessage realBuild( Type type, String messageId, + Date sentAt, Date timestamp, Map context, String anonymousId, String userId, Map integrations) { return new AutoValue_ScreenMessage( - type, messageId, timestamp, context, anonymousId, userId, integrations, name, properties); + anonymousId, context, integrations, messageId, sentAt, timestamp, type, userId, name, properties); } } } diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/TrackMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/TrackMessage.java index abfdb7a7..d2b4d8bb 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/TrackMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/TrackMessage.java @@ -79,19 +79,21 @@ Builder self() { protected TrackMessage realBuild( Type type, String messageId, + Date sentAt, Date timestamp, Map context, String anonymousId, String userId, Map integrations) { return new AutoValue_TrackMessage( - type, + anonymousId, + context, + integrations, messageId, + sentAt, timestamp, - context, - anonymousId, + type, userId, - integrations, event, properties); } diff --git a/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java b/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java index 7f1f1faf..bd38ecc0 100644 --- a/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java @@ -7,7 +7,8 @@ import com.segment.analytics.TestUtils; import com.squareup.burst.BurstJUnit4; -import java.util.Date; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.List; import java.util.Map; import org.junit.Test; @@ -29,14 +30,17 @@ public void create(TestUtils.MessageBuilderFactory factory) { } @Test - public void createSentAtNull(TestUtils.MessageBuilderFactory factory) { - Message message = factory.get().userId("userId").build(); + public void createWithSentAt(TestUtils.MessageBuilderFactory factory) throws ParseException { + Message message = factory.get() + .userId("userId") + .sentAt( new SimpleDateFormat("yyyy-MM-dd").parse("2022-04-01") ) + .build(); Map context = ImmutableMap.of("foo", "bar"); List messages = ImmutableList.of(message); - Batch batch = Batch.create(context, messages, null); - - assertThat(batch.sentAt()).isNull(); + Batch batch = Batch.create(context, messages); + + assertThat(batch.sentAt()).isEqualTo(messages.get(0).sentAt()); } @Test diff --git a/analytics/src/main/java/com/segment/analytics/internal/FlushMessage.java b/analytics/src/main/java/com/segment/analytics/internal/FlushMessage.java index 5c89bb7b..b3ee9dc2 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/FlushMessage.java +++ b/analytics/src/main/java/com/segment/analytics/internal/FlushMessage.java @@ -23,6 +23,12 @@ public String messageId() { throw new UnsupportedOperationException(); } + @Nullable + @Override + public Date sentAt() { + throw new UnsupportedOperationException(); + } + @Nonnull @Override public Date timestamp() { diff --git a/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java b/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java index 39dea83b..f7c66aff 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java +++ b/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java @@ -22,6 +22,12 @@ public Type type() { public String messageId() { throw new UnsupportedOperationException(); } + + @Nullable + @Override + public Date sentAt() { + throw new UnsupportedOperationException(); + } @Nonnull @Override @@ -57,4 +63,5 @@ public Map integrations() { public String toString() { return "StopMessage{}"; } + } From 3ae6d59c3ecbe056cf1ceffb9366b2a20b72031c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEdson?= Date: Thu, 5 May 2022 14:43:30 -0500 Subject: [PATCH 200/272] Apply spotless library to organize the code --- analytics-core/.factorypath | 31 +++++++++++++++++++ .../analytics/messages/AliasMessage.java | 12 +++++-- .../com/segment/analytics/messages/Batch.java | 15 ++++----- .../analytics/messages/GroupMessage.java | 11 ++++++- .../segment/analytics/messages/Message.java | 4 +-- .../analytics/messages/MessageBuilder.java | 11 ++++--- .../analytics/messages/PageMessage.java | 22 ++++++------- .../analytics/messages/ScreenMessage.java | 11 ++++++- .../segment/analytics/messages/BatchTest.java | 13 ++++---- .../analytics/internal/StopMessage.java | 3 +- 10 files changed, 96 insertions(+), 37 deletions(-) create mode 100644 analytics-core/.factorypath diff --git a/analytics-core/.factorypath b/analytics-core/.factorypath new file mode 100644 index 00000000..9decab0c --- /dev/null +++ b/analytics-core/.factorypath @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/AliasMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/AliasMessage.java index cb439986..3a6bff53 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/AliasMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/AliasMessage.java @@ -62,8 +62,16 @@ protected AliasMessage realBuild( String anonymousId, String userId, Map integrations) { - return new AutoValue_AliasMessage(anonymousId, context, integrations, messageId, sentAt, - timestamp, type, userId, previousId); + return new AutoValue_AliasMessage( + anonymousId, + context, + integrations, + messageId, + sentAt, + timestamp, + type, + userId, + previousId); } @Override diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java b/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java index 4fe0335f..76e02d73 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java @@ -6,7 +6,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; - import javax.annotation.Nullable; @AutoValue @@ -15,12 +14,14 @@ public abstract class Batch { private static final AtomicInteger SEQUENCE_GENERATOR = new AtomicInteger(); public static Batch create(Map context, List batch) { - Message sentAtNull = batch.stream() - .filter(message -> message.sentAt() != null ) - .findAny() - .orElse(null); - - return new AutoValue_Batch(batch, sentAtNull == null ? new Date() : sentAtNull.sentAt(), context, SEQUENCE_GENERATOR.incrementAndGet()); + Message sentAtNull = + batch.stream().filter(message -> message.sentAt() != null).findAny().orElse(null); + + return new AutoValue_Batch( + batch, + sentAtNull == null ? new Date() : sentAtNull.sentAt(), + context, + SEQUENCE_GENERATOR.incrementAndGet()); } public abstract List batch(); diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java index 8f6cae34..77d1ca81 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java @@ -83,7 +83,16 @@ protected GroupMessage realBuild( String userId, Map integrations) { return new AutoValue_GroupMessage( - anonymousId, context, integrations, messageId, sentAt, timestamp, type, userId, groupId, traits); + anonymousId, + context, + integrations, + messageId, + sentAt, + timestamp, + type, + userId, + groupId, + traits); } @Override diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/Message.java b/analytics-core/src/main/java/com/segment/analytics/messages/Message.java index be663c26..4e6197ba 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/Message.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/Message.java @@ -28,10 +28,10 @@ public interface Message { @Nullable Date sentAt(); - + @Nonnull Date timestamp(); - + @Nullable Map context(); diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java b/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java index 614c5556..f9d3704c 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/MessageBuilder.java @@ -74,8 +74,8 @@ public V messageId(String messageId) { } /** - * Set a sentAt for the event. By default, the current sentAt is used, but you may override - * it for historical import. + * Set a sentAt for the event. By default, the current sentAt is used, but you may override it for + * historical import. * * @see SentAt */ @@ -83,7 +83,7 @@ public V sentAt(Date sentAt) { this.sentAt = sentAt; return self(); } - + /** * Set a timestamp for the event. By default, the current timestamp is used, but you may override * it for historical import. @@ -215,7 +215,7 @@ public T build() { if (timestamp == null) { timestamp = new Date(); } - + Date sentAt = this.sentAt; String messageId = this.messageId; @@ -230,7 +230,8 @@ public T build() { integrations = ImmutableMap.copyOf(this.integrations); } - return realBuild(type, messageId, sentAt, timestamp, context, anonymousId, userId, integrations); + return realBuild( + type, messageId, sentAt, timestamp, context, anonymousId, userId, integrations); } /** Returns the {@link Message.Type} of the message this builder is constructing. */ diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java index 7f961031..8d4d3a4b 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java @@ -99,17 +99,17 @@ protected PageMessage realBuild( String userId, Map integrations) { return new AutoValue_PageMessage( - anonymousId, - context, - integrations, - messageId, - sentAt, - timestamp, - type, - userId, - name, - properties, - category); + anonymousId, + context, + integrations, + messageId, + sentAt, + timestamp, + type, + userId, + name, + properties, + category); } } } diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/ScreenMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/ScreenMessage.java index 8b391a7e..4f318211 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/ScreenMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/ScreenMessage.java @@ -86,7 +86,16 @@ protected ScreenMessage realBuild( String userId, Map integrations) { return new AutoValue_ScreenMessage( - anonymousId, context, integrations, messageId, sentAt, timestamp, type, userId, name, properties); + anonymousId, + context, + integrations, + messageId, + sentAt, + timestamp, + type, + userId, + name, + properties); } } } diff --git a/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java b/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java index bd38ecc0..07f0bea6 100644 --- a/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java @@ -6,7 +6,6 @@ import com.google.common.collect.ImmutableMap; import com.segment.analytics.TestUtils; import com.squareup.burst.BurstJUnit4; - import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.List; @@ -28,13 +27,15 @@ public void create(TestUtils.MessageBuilderFactory factory) { assertThat(batch.batch()).isEqualTo(messages); assertThat(batch.context()).isEqualTo(context); } - + @Test public void createWithSentAt(TestUtils.MessageBuilderFactory factory) throws ParseException { - Message message = factory.get() - .userId("userId") - .sentAt( new SimpleDateFormat("yyyy-MM-dd").parse("2022-04-01") ) - .build(); + Message message = + factory + .get() + .userId("userId") + .sentAt(new SimpleDateFormat("yyyy-MM-dd").parse("2022-04-01")) + .build(); Map context = ImmutableMap.of("foo", "bar"); List messages = ImmutableList.of(message); diff --git a/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java b/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java index f7c66aff..eccd278c 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java +++ b/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java @@ -22,7 +22,7 @@ public Type type() { public String messageId() { throw new UnsupportedOperationException(); } - + @Nullable @Override public Date sentAt() { @@ -63,5 +63,4 @@ public Map integrations() { public String toString() { return "StopMessage{}"; } - } From 8de5e0d27645dc48a9d46f2fba58cae7c65400e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEdson?= Date: Thu, 5 May 2022 16:07:56 -0500 Subject: [PATCH 201/272] Changed order for params from all AutoValue classes --- analytics-core/.factorypath | 31 ------------------- .../analytics/messages/AliasMessage.java | 8 ++--- .../analytics/messages/GroupMessage.java | 8 ++--- .../analytics/messages/IdentifyMessage.java | 2 +- .../analytics/messages/PageMessage.java | 8 ++--- .../analytics/messages/ScreenMessage.java | 8 ++--- .../analytics/messages/TrackMessage.java | 8 ++--- 7 files changed, 21 insertions(+), 52 deletions(-) delete mode 100644 analytics-core/.factorypath diff --git a/analytics-core/.factorypath b/analytics-core/.factorypath deleted file mode 100644 index 9decab0c..00000000 --- a/analytics-core/.factorypath +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/AliasMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/AliasMessage.java index 3a6bff53..0f640096 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/AliasMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/AliasMessage.java @@ -63,14 +63,14 @@ protected AliasMessage realBuild( String userId, Map integrations) { return new AutoValue_AliasMessage( - anonymousId, - context, - integrations, + type, messageId, sentAt, timestamp, - type, + context, + anonymousId, userId, + integrations, previousId); } diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java index 77d1ca81..55cbb04d 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java @@ -83,14 +83,14 @@ protected GroupMessage realBuild( String userId, Map integrations) { return new AutoValue_GroupMessage( - anonymousId, - context, - integrations, + type, messageId, sentAt, timestamp, - type, + context, + anonymousId, userId, + integrations, groupId, traits); } diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/IdentifyMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/IdentifyMessage.java index ce9f5702..a0ca23db 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/IdentifyMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/IdentifyMessage.java @@ -71,7 +71,7 @@ protected IdentifyMessage realBuild( } return new AutoValue_IdentifyMessage( - anonymousId, context, integrations, messageId, sentAt, timestamp, type, userId, traits); + type, messageId, timestamp, context, anonymousId, userId, integrations, traits); } @Override diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java index 8d4d3a4b..0c3d4a3b 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java @@ -99,14 +99,14 @@ protected PageMessage realBuild( String userId, Map integrations) { return new AutoValue_PageMessage( - anonymousId, - context, - integrations, + type, messageId, sentAt, timestamp, - type, + context, + anonymousId, userId, + integrations, name, properties, category); diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/ScreenMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/ScreenMessage.java index 4f318211..4ae95091 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/ScreenMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/ScreenMessage.java @@ -86,14 +86,14 @@ protected ScreenMessage realBuild( String userId, Map integrations) { return new AutoValue_ScreenMessage( - anonymousId, - context, - integrations, + type, messageId, sentAt, timestamp, - type, + context, + anonymousId, userId, + integrations, name, properties); } diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/TrackMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/TrackMessage.java index d2b4d8bb..6caddf5f 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/TrackMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/TrackMessage.java @@ -86,14 +86,14 @@ protected TrackMessage realBuild( String userId, Map integrations) { return new AutoValue_TrackMessage( - anonymousId, - context, - integrations, + type, messageId, sentAt, timestamp, - type, + context, + anonymousId, userId, + integrations, event, properties); } From a3645bbe3dd7b64752197516594841c632aa605d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEdson?= Date: Thu, 5 May 2022 16:09:51 -0500 Subject: [PATCH 202/272] Added value sentAt param on IdentifyMessage --- .../java/com/segment/analytics/messages/IdentifyMessage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/IdentifyMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/IdentifyMessage.java index a0ca23db..024b2e85 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/IdentifyMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/IdentifyMessage.java @@ -71,7 +71,7 @@ protected IdentifyMessage realBuild( } return new AutoValue_IdentifyMessage( - type, messageId, timestamp, context, anonymousId, userId, integrations, traits); + type, messageId, sentAt, timestamp, context, anonymousId, userId, integrations, traits); } @Override From 7ff547912fe5baa0e21361a54047076468e06023 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEdson?= Date: Thu, 5 May 2022 17:00:41 -0500 Subject: [PATCH 203/272] Remove Nullable from sentAt om Batch, add Test for sentAt null --- .../java/com/segment/analytics/messages/Batch.java | 2 -- .../com/segment/analytics/messages/BatchTest.java | 12 ++++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java b/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java index 76e02d73..f9604007 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java @@ -6,7 +6,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -import javax.annotation.Nullable; @AutoValue @AutoGson @@ -26,7 +25,6 @@ public static Batch create(Map context, List batch) { public abstract List batch(); - @Nullable public abstract Date sentAt(); public abstract Map context(); diff --git a/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java b/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java index 07f0bea6..68b3d880 100644 --- a/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java @@ -8,6 +8,7 @@ import com.squareup.burst.BurstJUnit4; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.Date; import java.util.List; import java.util.Map; import org.junit.Test; @@ -44,6 +45,17 @@ public void createWithSentAt(TestUtils.MessageBuilderFactory factory) throws Par assertThat(batch.sentAt()).isEqualTo(messages.get(0).sentAt()); } + @Test + public void createWithSentAtNull(TestUtils.MessageBuilderFactory factory) throws ParseException { + Message message = factory.get().userId("userId").sentAt(null).build(); + Map context = ImmutableMap.of("foo", "bar"); + List messages = ImmutableList.of(message); + + Batch batch = Batch.create(context, messages); + + assertThat(batch.sentAt()).isEqualTo(new Date()); + } + @Test public void sequence(TestUtils.MessageBuilderFactory factory) { Message message = factory.get().userId("userId").build(); From c757d2a729e358d8fb686a076b8f779b2ed00071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEdson?= Date: Tue, 10 May 2022 22:14:49 -0500 Subject: [PATCH 204/272] Add throw interrupted exception when event exceeds 32kb to stop Thread --- .../java/com/segment/analytics/internal/AnalyticsClient.java | 1 + 1 file changed, 1 insertion(+) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 32828cc4..81e9f8f9 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -187,6 +187,7 @@ public void enqueue(Message message) { } else { log.print( ERROR, "Message was above individual limit. MessageId: %s", message.messageId()); + throw new InterruptedException("Message was above individual limit. MessageId: " + message.messageId()); } } else { messageQueue.put(message); From 9a34ff25f94f60d8f55eee6883a5013a9bf221c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEdson?= Date: Thu, 12 May 2022 12:13:37 -0500 Subject: [PATCH 205/272] Update the history on CHANGELOG.md to 3.3 version --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ebd7554..5d5e147e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# Version 3.3.0 (May 12, 2022) +- [Chore] Dependency upgrades +- [New](https://github.com/segmentio/analytics-java/pull/345) Add option to sentAt field to be null +- [New](https://github.com/segmentio/analytics-java/pull/349) Add throw interrupted exception when event exceeds 32kb to stop Thread + +# Version 3.2.0 (Apr 4, 2022) +- [Chore] Dependency upgrades +- [Fix](https://github.com/segmentio/analytics-java/pull/264) Batching queue to regard to api limits +- [Fix](https://github.com/segmentio/analytics-java/pull/298) Correctly measure the size of message queue +- [Fix](https://github.com/segmentio/analytics-java/pull/304) Bugfix for TLS version error (protocol not supported error) +- [Fix](https://github.com/segmentio/analytics-java/pull/305) AnalyticsClient Looper won't start if isShutdown is true + # Version 3.1.3 (July 9, 2021) - [Fix](https://github.com/segmentio/analytics-java/pull/256) Set the default retries to 3 From fea1c3bc2d695806e0b159d9e15d5817791ab379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEdson?= Date: Mon, 30 May 2022 09:59:53 -0500 Subject: [PATCH 206/272] Change line structure from exception on AnalyticsClient --- .../java/com/segment/analytics/internal/AnalyticsClient.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 81e9f8f9..ab50da44 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -187,7 +187,8 @@ public void enqueue(Message message) { } else { log.print( ERROR, "Message was above individual limit. MessageId: %s", message.messageId()); - throw new InterruptedException("Message was above individual limit. MessageId: " + message.messageId()); + throw new InterruptedException( + "Message was above individual limit. MessageId: " + message.messageId()); } } else { messageQueue.put(message); From 54b70f1a3726e77d3eb55f6e7543bc2ff2afa744 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jun 2022 16:01:52 +0000 Subject: [PATCH 207/272] Bump assertj-core from 3.22.0 to 3.23.1 Bumps [assertj-core](https://github.com/assertj/assertj-core) from 3.22.0 to 3.23.1. - [Release notes](https://github.com/assertj/assertj-core/releases) - [Commits](https://github.com/assertj/assertj-core/compare/assertj-core-3.22.0...assertj-core-3.23.1) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0f30f3e8..6786e113 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ 4.13.2 1.2.0 4.4.0 - 3.22.0 + 3.23.1 From 5817aa875a4215dca97fef2649262b7d771d039f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Jun 2022 16:02:58 +0000 Subject: [PATCH 208/272] Bump logging-interceptor from 4.9.3 to 4.10.0 Bumps [logging-interceptor](https://github.com/square/okhttp) from 4.9.3 to 4.10.0. - [Release notes](https://github.com/square/okhttp/releases) - [Changelog](https://github.com/square/okhttp/blob/master/CHANGELOG.md) - [Commits](https://github.com/square/okhttp/compare/parent-4.9.3...parent-4.10.0) --- updated-dependencies: - dependency-name: com.squareup.okhttp3:logging-interceptor dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0f30f3e8..9f4b72cc 100644 --- a/pom.xml +++ b/pom.xml @@ -36,7 +36,7 @@ 3.0.1 2.9.0 4.9.3 - 4.9.3 + 4.10.0 31.1-jre 1.0.0 2.6.6 From 65062e0f6bfaf21426e730c024c20d8caaae61ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEdson?= Date: Tue, 28 Jun 2022 17:15:35 -0500 Subject: [PATCH 209/272] Add test for semerujdk11 --- .circleci/config.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index ad2d29ce..6bce9426 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -45,6 +45,11 @@ jobs: docker: - image: circleci/openjdk:11-jdk-browsers + test-semerujdk11: + <<: *java-base-test + docker: + - image: ibm-semeru-runtimes:open-11.0.15_10-jdk-centos7 + publish: <<: *java-base-test docker: @@ -96,6 +101,7 @@ workflows: - test-jdklatest - test-jdk11 - test-jdk8 + - test-semerujdk11 static_analysis: jobs: - test From 4770dc9edfcd26c4b94647c094fcaf5c28a9ff82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEdson?= Date: Tue, 28 Jun 2022 19:25:12 -0500 Subject: [PATCH 210/272] Change validation on BatchTest on createWithSentAtNull --- .../src/test/java/com/segment/analytics/messages/BatchTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java b/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java index 68b3d880..a9b11f2b 100644 --- a/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java @@ -53,7 +53,7 @@ public void createWithSentAtNull(TestUtils.MessageBuilderFactory factory) throws Batch batch = Batch.create(context, messages); - assertThat(batch.sentAt()).isEqualTo(new Date()); + assertThat(batch.sentAt()).isEqualToIgnoringHours(new Date()); } @Test From 68dd9fb59adcffaab8cfe96c733acd495a39e9db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Jun 2022 17:38:19 +0000 Subject: [PATCH 211/272] Bump mockito-core from 4.4.0 to 4.6.1 Bumps [mockito-core](https://github.com/mockito/mockito) from 4.4.0 to 4.6.1. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v4.4.0...v4.6.1) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5c6dc772..1fbe464e 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ 4.13.2 1.2.0 - 4.4.0 + 4.6.1 3.23.1 From 62287bb8277b10a8c6805ca626d096f681f90727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEdson?= Date: Wed, 6 Jul 2022 08:58:40 -0500 Subject: [PATCH 212/272] =?UTF-8?q?Bump=20spotless-maven-plugin=20from=202?= =?UTF-8?q?.22.1=20to=202.23.0=C2=A0=C2=A0=20Bump=20okhttp=20from=204.9.3?= =?UTF-8?q?=20to=204.10.0=C2=A0=C2=A0=20Bump=20kotlin.version=20from=201.6?= =?UTF-8?q?.21=20to=201.7.0=20Bump=20spring-boot-autoconfigure=20from=202.?= =?UTF-8?q?6.6=20to=202.7.1=20Bump=20mockito-core=20from=204.4.0=20to=204.?= =?UTF-8?q?6.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 5c6dc772..8b7f9d87 100644 --- a/pom.xml +++ b/pom.xml @@ -28,24 +28,24 @@ UTF-8 8 - 1.6.21 - 2.22.1 + 1.7.0 + 2.23.0 2.9.0 1.9 3.0.1 2.9.0 - 4.9.3 + 4.10.0 4.10.0 31.1-jre 1.0.0 - 2.6.6 + 2.7.1 0.6.0.20150202 4.13.2 1.2.0 - 4.4.0 + 4.6.1 3.23.1 From a82f25b03aa97e1f9cad1db8bba9088f8b5f4df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEdson?= Date: Tue, 26 Jul 2022 10:28:22 -0500 Subject: [PATCH 213/272] Update dependabot library and remove semeru image test for circleci --- .circleci/config.yml | 6 ------ pom.xml | 4 ++-- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6bce9426..ad2d29ce 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -45,11 +45,6 @@ jobs: docker: - image: circleci/openjdk:11-jdk-browsers - test-semerujdk11: - <<: *java-base-test - docker: - - image: ibm-semeru-runtimes:open-11.0.15_10-jdk-centos7 - publish: <<: *java-base-test docker: @@ -101,7 +96,6 @@ workflows: - test-jdklatest - test-jdk11 - test-jdk8 - - test-semerujdk11 static_analysis: jobs: - test diff --git a/pom.xml b/pom.xml index 8b7f9d87..5ed0f926 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ UTF-8 8 - 1.7.0 + 1.7.10 2.23.0 2.9.0 1.9 @@ -39,7 +39,7 @@ 4.10.0 31.1-jre 1.0.0 - 2.7.1 + 2.7.2 0.6.0.20150202 From 9e414c95f74131a81aa2e1d35101d6b84b060b86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CEdson?= Date: Tue, 2 Aug 2022 17:31:28 -0500 Subject: [PATCH 214/272] Update version from gson and spotless-maven-pligun --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5ed0f926..c1287393 100644 --- a/pom.xml +++ b/pom.xml @@ -29,12 +29,12 @@ UTF-8 8 1.7.10 - 2.23.0 + 2.24.0 2.9.0 1.9 3.0.1 - 2.9.0 + 2.9.1 4.10.0 4.10.0 31.1-jre From e0c202362a0b7bfcfa47b213e83db52a8b32c06a Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Thu, 11 Aug 2022 16:50:31 -0700 Subject: [PATCH 215/272] [maven-release-plugin] prepare release analytics-parent-3.3.0 --- analytics-cli/pom.xml | 4 ++-- analytics-core/pom.xml | 4 ++-- analytics-sample/pom.xml | 4 ++-- analytics-spring-boot-starter/pom.xml | 4 ++-- analytics/pom.xml | 4 ++-- pom.xml | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 45b5f96f..f1517512 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,11 +6,11 @@ analytics-parent com.segment.analytics.java - 3.2.1-SNAPSHOT + 3.3.0 analytics-cli - 3.1.3 + 3.3.0 Analytics Java CLI diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index 588e44d4..6f1d7423 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,11 +6,11 @@ com.segment.analytics.java analytics-parent - 3.2.1-SNAPSHOT + 3.3.0 analytics-core - 3.1.3 + 3.3.0 Analytics for Java (Core) diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 2e17a07f..95f7882e 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,11 +6,11 @@ analytics-parent com.segment.analytics.java - 3.2.1-SNAPSHOT + 3.3.0 analytics-sample - 3.1.3 + 3.3.0 Analytics Sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 9405afa2..167c1b6c 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,11 +6,11 @@ com.segment.analytics.java analytics-parent - 3.2.1-SNAPSHOT + 3.3.0 analytics-spring-boot-starter - 3.1.3 + 3.3.0 Spring Boot starter for Segment Analytics for Java diff --git a/analytics/pom.xml b/analytics/pom.xml index 8e9ac29d..710e3cdd 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,11 +6,11 @@ com.segment.analytics.java analytics-parent - 3.2.1-SNAPSHOT + 3.3.0 analytics - 3.1.3 + 3.3.0 Analytics for Java diff --git a/pom.xml b/pom.xml index c1287393..0c6195c9 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.2.1-SNAPSHOT + 3.3.0 pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - HEAD + analytics-parent-3.3.0 From 79c62ca9a61ee50cd12dbf2e7f36f16090b62468 Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Thu, 11 Aug 2022 16:50:34 -0700 Subject: [PATCH 216/272] [maven-release-plugin] prepare for next development iteration --- analytics-cli/pom.xml | 4 ++-- analytics-core/pom.xml | 4 ++-- analytics-sample/pom.xml | 4 ++-- analytics-spring-boot-starter/pom.xml | 4 ++-- analytics/pom.xml | 4 ++-- pom.xml | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index f1517512..7c5eba29 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,11 +6,11 @@ analytics-parent com.segment.analytics.java - 3.3.0 + 3.3.1-SNAPSHOT analytics-cli - 3.3.0 + 3.1.3 Analytics Java CLI diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index 6f1d7423..4e4b8c11 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,11 +6,11 @@ com.segment.analytics.java analytics-parent - 3.3.0 + 3.3.1-SNAPSHOT analytics-core - 3.3.0 + 3.1.3 Analytics for Java (Core) diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 95f7882e..f513a1c2 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,11 +6,11 @@ analytics-parent com.segment.analytics.java - 3.3.0 + 3.3.1-SNAPSHOT analytics-sample - 3.3.0 + 3.1.3 Analytics Sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 167c1b6c..06afe018 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,11 +6,11 @@ com.segment.analytics.java analytics-parent - 3.3.0 + 3.3.1-SNAPSHOT analytics-spring-boot-starter - 3.3.0 + 3.1.3 Spring Boot starter for Segment Analytics for Java diff --git a/analytics/pom.xml b/analytics/pom.xml index 710e3cdd..1136d8f6 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,11 +6,11 @@ com.segment.analytics.java analytics-parent - 3.3.0 + 3.3.1-SNAPSHOT analytics - 3.3.0 + 3.1.3 Analytics for Java diff --git a/pom.xml b/pom.xml index 0c6195c9..13b78d74 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.3.0 + 3.3.1-SNAPSHOT pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - analytics-parent-3.3.0 + HEAD From f25a34b7f50e1e8eefddbad68696da362b3b621d Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Thu, 11 Aug 2022 17:04:46 -0700 Subject: [PATCH 217/272] [maven-release-plugin] prepare release analytics-parent-3.3.1 --- analytics-cli/pom.xml | 4 ++-- analytics-core/pom.xml | 4 ++-- analytics-sample/pom.xml | 4 ++-- analytics-spring-boot-starter/pom.xml | 4 ++-- analytics/pom.xml | 4 ++-- pom.xml | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 7c5eba29..f9aa2cf9 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,11 +6,11 @@ analytics-parent com.segment.analytics.java - 3.3.1-SNAPSHOT + 3.3.1 analytics-cli - 3.1.3 + 3.3.1 Analytics Java CLI diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index 4e4b8c11..7d0d9684 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,11 +6,11 @@ com.segment.analytics.java analytics-parent - 3.3.1-SNAPSHOT + 3.3.1 analytics-core - 3.1.3 + 3.3.1 Analytics for Java (Core) diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index f513a1c2..96e3b36d 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,11 +6,11 @@ analytics-parent com.segment.analytics.java - 3.3.1-SNAPSHOT + 3.3.1 analytics-sample - 3.1.3 + 3.3.1 Analytics Sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 06afe018..f569597e 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,11 +6,11 @@ com.segment.analytics.java analytics-parent - 3.3.1-SNAPSHOT + 3.3.1 analytics-spring-boot-starter - 3.1.3 + 3.3.1 Spring Boot starter for Segment Analytics for Java diff --git a/analytics/pom.xml b/analytics/pom.xml index 1136d8f6..e5e374cd 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,11 +6,11 @@ com.segment.analytics.java analytics-parent - 3.3.1-SNAPSHOT + 3.3.1 analytics - 3.1.3 + 3.3.1 Analytics for Java diff --git a/pom.xml b/pom.xml index 13b78d74..669cc056 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.3.1-SNAPSHOT + 3.3.1 pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - HEAD + analytics-parent-3.3.1 From 246ebabf03d40a11d232699b1fa11dafa684504f Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Thu, 11 Aug 2022 17:04:49 -0700 Subject: [PATCH 218/272] [maven-release-plugin] prepare for next development iteration --- analytics-cli/pom.xml | 4 ++-- analytics-core/pom.xml | 4 ++-- analytics-sample/pom.xml | 4 ++-- analytics-spring-boot-starter/pom.xml | 4 ++-- analytics/pom.xml | 4 ++-- pom.xml | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index f9aa2cf9..06bfe504 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,11 +6,11 @@ analytics-parent com.segment.analytics.java - 3.3.1 + 3.3.2-SNAPSHOT analytics-cli - 3.3.1 + 3.1.3 Analytics Java CLI diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index 7d0d9684..bc922bab 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,11 +6,11 @@ com.segment.analytics.java analytics-parent - 3.3.1 + 3.3.2-SNAPSHOT analytics-core - 3.3.1 + 3.1.3 Analytics for Java (Core) diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 96e3b36d..92951ce1 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,11 +6,11 @@ analytics-parent com.segment.analytics.java - 3.3.1 + 3.3.2-SNAPSHOT analytics-sample - 3.3.1 + 3.1.3 Analytics Sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index f569597e..10f56d12 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,11 +6,11 @@ com.segment.analytics.java analytics-parent - 3.3.1 + 3.3.2-SNAPSHOT analytics-spring-boot-starter - 3.3.1 + 3.1.3 Spring Boot starter for Segment Analytics for Java diff --git a/analytics/pom.xml b/analytics/pom.xml index e5e374cd..47883ff4 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,11 +6,11 @@ com.segment.analytics.java analytics-parent - 3.3.1 + 3.3.2-SNAPSHOT analytics - 3.3.1 + 3.1.3 Analytics for Java diff --git a/pom.xml b/pom.xml index 669cc056..f92e2bd6 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.3.1 + 3.3.2-SNAPSHOT pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - analytics-parent-3.3.1 + HEAD From ff795671ed2bae6a77beb4c275295cea19dcf6da Mon Sep 17 00:00:00 2001 From: Pooya Jaferian Date: Thu, 11 Aug 2022 17:10:16 -0700 Subject: [PATCH 219/272] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d5e147e..751977bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# Version 3.3.0 (May 12, 2022) +# Version 3.3.1 (Aug 11, 2022) - [Chore] Dependency upgrades - [New](https://github.com/segmentio/analytics-java/pull/345) Add option to sentAt field to be null - [New](https://github.com/segmentio/analytics-java/pull/349) Add throw interrupted exception when event exceeds 32kb to stop Thread From 02f2c18bb8f437db8bf0048db4027c646729c779 Mon Sep 17 00:00:00 2001 From: Olivier Lamy Date: Sat, 15 Oct 2022 07:51:04 +1000 Subject: [PATCH 220/272] in dev projects must use -SNAPSHOT or depends on -SNAPSHOT parent (#386) * in dev projects must use -SNAPSHOT or depends on -SNAPSHOT parent Signed-off-by: Olivier Lamy * touch to trigger a build Signed-off-by: Olivier Lamy Signed-off-by: Olivier Lamy --- analytics-cli/pom.xml | 1 - analytics-core/pom.xml | 1 - analytics-sample/pom.xml | 1 - analytics-spring-boot-starter/pom.xml | 1 - analytics/pom.xml | 2 -- 5 files changed, 6 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 06bfe504..1b35b5d7 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -10,7 +10,6 @@ analytics-cli - 3.1.3 Analytics Java CLI diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index bc922bab..ca496c01 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -10,7 +10,6 @@ analytics-core - 3.1.3 Analytics for Java (Core) diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 92951ce1..07cfa6fa 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -10,7 +10,6 @@ analytics-sample - 3.1.3 Analytics Sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 10f56d12..685d871a 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -10,7 +10,6 @@ analytics-spring-boot-starter - 3.1.3 Spring Boot starter for Segment Analytics for Java diff --git a/analytics/pom.xml b/analytics/pom.xml index 47883ff4..c461f671 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -10,7 +10,6 @@ analytics - 3.1.3 Analytics for Java @@ -44,7 +43,6 @@ com.segment.backo backo - junit junit From 779f3fb2e4d830ab29b94fe13e78d563be00af62 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Oct 2022 17:51:45 -0400 Subject: [PATCH 221/272] Bump spring-boot-autoconfigure from 2.7.2 to 2.7.4 (#382) Bumps [spring-boot-autoconfigure](https://github.com/spring-projects/spring-boot) from 2.7.2 to 2.7.4. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v2.7.2...v2.7.4) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-autoconfigure dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f92e2bd6..5d4fae68 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ 4.10.0 31.1-jre 1.0.0 - 2.7.2 + 2.7.4 0.6.0.20150202 From 5b9cf2e190c979a3c45152d5ee1af822da90e277 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Oct 2022 17:52:36 -0400 Subject: [PATCH 222/272] Bump mockito-core from 4.6.1 to 4.8.0 (#380) Bumps [mockito-core](https://github.com/mockito/mockito) from 4.6.1 to 4.8.0. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v4.6.1...v4.8.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5d4fae68..5e02f735 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ 4.13.2 1.2.0 - 4.6.1 + 4.8.0 3.23.1 From 2f89e139fdbcef707e058b32c6e7ea4a62098d1f Mon Sep 17 00:00:00 2001 From: David Menear Date: Wed, 16 Nov 2022 07:37:13 -0800 Subject: [PATCH 223/272] Call upload URL using Retrofit's @Url annotation (#391) * call upload URL using Retrofit's @Url annotation * fix formatting Co-authored-by: David Menear --- .../analytics/http/SegmentService.java | 6 ++- .../java/com/segment/analytics/Analytics.java | 3 +- .../analytics/internal/AnalyticsClient.java | 8 +++- .../internal/AnalyticsClientTest.java | 37 +++++++++++-------- 4 files changed, 34 insertions(+), 20 deletions(-) diff --git a/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java b/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java index 92687268..c96cbef2 100644 --- a/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java +++ b/analytics-core/src/main/java/com/segment/analytics/http/SegmentService.java @@ -1,12 +1,14 @@ package com.segment.analytics.http; import com.segment.analytics.messages.Batch; +import okhttp3.HttpUrl; import retrofit2.Call; import retrofit2.http.Body; import retrofit2.http.POST; +import retrofit2.http.Url; /** REST interface for the Segment API. */ public interface SegmentService { - @POST(".") - Call upload(@Body Batch batch); + @POST + Call upload(@Url HttpUrl uploadUrl, @Body Batch batch); } diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index f5fe74f3..76a73c13 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -431,7 +431,7 @@ public void log(String message) { Retrofit restAdapter = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create(gson)) - .baseUrl(endpoint) + .baseUrl(DEFAULT_ENDPOINT) .client(client) .build(); @@ -439,6 +439,7 @@ public void log(String message) { AnalyticsClient analyticsClient = AnalyticsClient.create( + endpoint, segmentService, queueCapacity, flushQueueSize, diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index ab50da44..c3c65c9b 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -30,6 +30,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import okhttp3.HttpUrl; import retrofit2.Call; import retrofit2.Response; @@ -50,6 +51,7 @@ public class AnalyticsClient { } private final BlockingQueue messageQueue; + private final HttpUrl uploadUrl; private final SegmentService service; private final int size; private final int maximumRetries; @@ -63,6 +65,7 @@ public class AnalyticsClient { private final AtomicBoolean isShutDown; public static AnalyticsClient create( + HttpUrl uploadUrl, SegmentService segmentService, int queueCapacity, int flushQueueSize, @@ -75,6 +78,7 @@ public static AnalyticsClient create( List callbacks) { return new AnalyticsClient( new LinkedBlockingQueue(queueCapacity), + uploadUrl, segmentService, flushQueueSize, flushIntervalInMillis, @@ -89,6 +93,7 @@ public static AnalyticsClient create( AnalyticsClient( BlockingQueue messageQueue, + HttpUrl uploadUrl, SegmentService service, int maxQueueSize, long flushIntervalInMillis, @@ -100,6 +105,7 @@ public static AnalyticsClient create( List callbacks, AtomicBoolean isShutDown) { this.messageQueue = messageQueue; + this.uploadUrl = uploadUrl; this.service = service; this.size = maxQueueSize; this.maximumRetries = maximumRetries; @@ -355,7 +361,7 @@ boolean upload() { client.log.print(VERBOSE, "Uploading batch %s.", batch.sequence()); try { - Call call = client.service.upload(batch); + Call call = client.service.upload(client.uploadUrl, batch); Response response = call.execute(); if (response.isSuccessful()) { diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 47ee1bcb..9bb0fdf0 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -93,6 +93,7 @@ public void setUp() { AnalyticsClient newClient() { return new AnalyticsClient( messageQueue, + null, segmentService, 50, TimeUnit.HOURS.toMillis(1), @@ -271,6 +272,7 @@ public void flushHowManyTimesNecessaryToStayWithinLimit() throws InterruptedExce AnalyticsClient client = new AnalyticsClient( messageQueue, + null, segmentService, 50, TimeUnit.HOURS.toMillis(1), @@ -360,7 +362,7 @@ public void batchRetriesForNetworkErrors() { Response failureResponse = Response.error(429, ResponseBody.create(null, "")); // Throw a network error 3 times. - when(segmentService.upload(batch)) + when(segmentService.upload(null, batch)) .thenReturn(Calls.response(failureResponse)) .thenReturn(Calls.response(failureResponse)) .thenReturn(Calls.response(failureResponse)) @@ -370,7 +372,7 @@ public void batchRetriesForNetworkErrors() { batchUploadTask.run(); // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. - verify(segmentService, times(4)).upload(batch); + verify(segmentService, times(4)).upload(null, batch); verify(callback).success(trackMessage); } @@ -385,7 +387,7 @@ public void batchRetriesForHTTP5xxErrors() { Response successResponse = Response.success(200, response); Response failResponse = Response.error(500, ResponseBody.create(null, "Server Error")); - when(segmentService.upload(batch)) + when(segmentService.upload(null, batch)) .thenReturn(Calls.response(failResponse)) .thenReturn(Calls.response(failResponse)) .thenReturn(Calls.response(failResponse)) @@ -395,7 +397,7 @@ public void batchRetriesForHTTP5xxErrors() { batchUploadTask.run(); // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. - verify(segmentService, times(4)).upload(batch); + verify(segmentService, times(4)).upload(null, batch); verify(callback).success(trackMessage); } @@ -409,7 +411,7 @@ public void batchRetriesForHTTP429Errors() { Response successResponse = Response.success(200, response); Response failResponse = Response.error(429, ResponseBody.create(null, "Rate Limited")); - when(segmentService.upload(batch)) + when(segmentService.upload(null, batch)) .thenReturn(Calls.response(failResponse)) .thenReturn(Calls.response(failResponse)) .thenReturn(Calls.response(failResponse)) @@ -419,7 +421,7 @@ public void batchRetriesForHTTP429Errors() { batchUploadTask.run(); // Verify that we tried to upload 4 times, 3 failed and 1 succeeded. - verify(segmentService, times(4)).upload(batch); + verify(segmentService, times(4)).upload(null, batch); verify(callback).success(trackMessage); } @@ -432,13 +434,13 @@ public void batchDoesNotRetryForNon5xxAndNon429HTTPErrors() { // Throw a HTTP error that should not be retried. Response failResponse = Response.error(404, ResponseBody.create(null, "Not Found")); - when(segmentService.upload(batch)).thenReturn(Calls.response(failResponse)); + when(segmentService.upload(null, batch)).thenReturn(Calls.response(failResponse)); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); batchUploadTask.run(); // Verify we only tried to upload once. - verify(segmentService).upload(batch); + verify(segmentService).upload(null, batch); verify(callback).failure(eq(trackMessage), any(IOException.class)); } @@ -449,13 +451,13 @@ public void batchDoesNotRetryForNonNetworkErrors() { Batch batch = batchFor(trackMessage); Call networkFailure = Calls.failure(new RuntimeException()); - when(segmentService.upload(batch)).thenReturn(networkFailure); + when(segmentService.upload(null, batch)).thenReturn(networkFailure); BatchUploadTask batchUploadTask = new BatchUploadTask(client, BACKO, batch, DEFAULT_RETRIES); batchUploadTask.run(); // Verify we only tried to upload once. - verify(segmentService).upload(batch); + verify(segmentService).upload(null, batch); verify(callback).failure(eq(trackMessage), any(RuntimeException.class)); } @@ -465,7 +467,7 @@ public void givesUpAfterMaxRetries() { TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); Batch batch = batchFor(trackMessage); - when(segmentService.upload(batch)) + when(segmentService.upload(null, batch)) .thenAnswer( new Answer>() { public Call answer(InvocationOnMock invocation) { @@ -480,7 +482,7 @@ public Call answer(InvocationOnMock invocation) { // DEFAULT_RETRIES == maxRetries // tries 11(one normal run + 10 retries) even though default is 50 in AnalyticsClient.java - verify(segmentService, times(11)).upload(batch); + verify(segmentService, times(11)).upload(null, batch); verify(callback) .failure( eq(trackMessage), @@ -499,7 +501,7 @@ public void hasDefaultRetriesSetTo3() { TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); Batch batch = batchFor(trackMessage); - when(segmentService.upload(batch)) + when(segmentService.upload(null, batch)) .thenAnswer( new Answer>() { public Call answer(InvocationOnMock invocation) { @@ -514,7 +516,7 @@ public Call answer(InvocationOnMock invocation) { // DEFAULT_RETRIES == maxRetries // tries 11(one normal run + 10 retries) - verify(segmentService, times(4)).upload(batch); + verify(segmentService, times(4)).upload(null, batch); verify(callback) .failure( eq(trackMessage), @@ -619,7 +621,7 @@ public void neverRetries() { TrackMessage trackMessage = TrackMessage.builder("foo").userId("bar").build(); Batch batch = batchFor(trackMessage); - when(segmentService.upload(batch)) + when(segmentService.upload(null, batch)) .thenAnswer( new Answer>() { public Call answer(InvocationOnMock invocation) { @@ -633,7 +635,7 @@ public Call answer(InvocationOnMock invocation) { batchUploadTask.run(); // runs once but never retries - verify(segmentService, times(1)).upload(batch); + verify(segmentService, times(1)).upload(null, batch); verify(callback) .failure( eq(trackMessage), @@ -830,6 +832,7 @@ public void submitBatchBelowThreshold() throws InterruptedException { AnalyticsClient client = new AnalyticsClient( messageQueue, + null, segmentService, 50, TimeUnit.HOURS.toMillis(1), @@ -869,6 +872,7 @@ public void submitBatchAboveThreshold() throws InterruptedException { AnalyticsClient client = new AnalyticsClient( messageQueue, + null, segmentService, 50, TimeUnit.HOURS.toMillis(1), @@ -907,6 +911,7 @@ public void submitManySmallMessagesBatchAboveThreshold() throws InterruptedExcep AnalyticsClient client = new AnalyticsClient( messageQueue, + null, segmentService, 50, TimeUnit.HOURS.toMillis(1), From d8757cfc3d6051339a23106dfbfcb1e53f2ed72a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Nov 2022 10:37:42 -0500 Subject: [PATCH 224/272] Bump mockito-core from 4.8.0 to 4.8.1 (#390) Bumps [mockito-core](https://github.com/mockito/mockito) from 4.8.0 to 4.8.1. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v4.8.0...v4.8.1) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5e02f735..39a59325 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ 4.13.2 1.2.0 - 4.8.0 + 4.8.1 3.23.1 From eee7117ff51fe6bda1e28f61ce8c21e7b910bff2 Mon Sep 17 00:00:00 2001 From: Edson Amaya Date: Wed, 16 Nov 2022 09:38:59 -0600 Subject: [PATCH 225/272] Update libraries to fix test (#392) --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 39a59325..3af3b395 100644 --- a/pom.xml +++ b/pom.xml @@ -28,10 +28,10 @@ UTF-8 8 - 1.7.10 - 2.24.0 + 1.7.20 + 2.27.2 2.9.0 - 1.9 + 1.10 3.0.1 2.9.1 From e981dd0f8f9daaa5cf09ae2956b6f8fec16beb57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Nov 2022 22:25:04 -0500 Subject: [PATCH 226/272] Bump spring-boot-autoconfigure from 2.7.4 to 2.7.5 (#389) Bumps [spring-boot-autoconfigure](https://github.com/spring-projects/spring-boot) from 2.7.4 to 2.7.5. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v2.7.4...v2.7.5) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-autoconfigure dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3af3b395..0d499eaa 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ 4.10.0 31.1-jre 1.0.0 - 2.7.4 + 2.7.5 0.6.0.20150202 From a32e21dbb31c14d1a83ec56458c161fb244d132c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Dec 2022 18:55:36 -0500 Subject: [PATCH 227/272] Bump mockito-core from 4.8.1 to 4.9.0 (#393) Bumps [mockito-core](https://github.com/mockito/mockito) from 4.8.1 to 4.9.0. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v4.8.1...v4.9.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0d499eaa..2f934f24 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ 4.13.2 1.2.0 - 4.8.1 + 4.9.0 3.23.1 From 3622654ddb04627f4c3568e88b305d6ea50e0598 Mon Sep 17 00:00:00 2001 From: Edson Amaya Date: Wed, 4 Jan 2023 22:56:39 -0600 Subject: [PATCH 228/272] Change method static to public to create a GSON instance (#400) --- .../com/segment/analytics/internal/AnalyticsClient.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index c3c65c9b..ff10f01c 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -91,7 +91,7 @@ public static AnalyticsClient create( new AtomicBoolean(false)); } - AnalyticsClient( + public AnalyticsClient( BlockingQueue messageQueue, HttpUrl uploadUrl, SegmentService service, @@ -134,11 +134,11 @@ public void run() { } /** - * Creating GSON object everytime we check the size seems costly, create one static instance + * Creating GSON object everytime we check the size seems costly * - * @return static gson instance + * @return gson instance */ - public static Gson getGsonInstance() { + public Gson getGsonInstance() { if (gsonInstance == null) { gsonInstance = new Gson(); } From feeb287cf2b15842f5ee2429f65b8806279420fa Mon Sep 17 00:00:00 2001 From: Edson Amaya Date: Wed, 25 Jan 2023 12:42:18 -0600 Subject: [PATCH 229/272] Update version assertj-core to 3.24.2 (#403) * Update version assertj-core to 3.24.1 * Update version assertj-core to 3.24.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2f934f24..79e20023 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ 4.13.2 1.2.0 4.9.0 - 3.23.1 + 3.24.2 From e2887fbe6210df4af2215b06903d2073fb9e373a Mon Sep 17 00:00:00 2001 From: Edson Amaya Date: Wed, 25 Jan 2023 12:43:10 -0600 Subject: [PATCH 230/272] Change exception to identify the limited exceed for the message and handle externly (#406) --- .../analytics/internal/AnalyticsClient.java | 2 +- .../internal/AnalyticsClientTest.java | 41 ++++++++++++++----- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index ff10f01c..edc81bb3 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -193,7 +193,7 @@ public void enqueue(Message message) { } else { log.print( ERROR, "Message was above individual limit. MessageId: %s", message.messageId()); - throw new InterruptedException( + throw new IllegalArgumentException( "Message was above individual limit. MessageId: " + message.messageId()); } } else { diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 9bb0fdf0..934fb8ab 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -233,7 +233,11 @@ public void shouldBeAbleToCalculateMessageSize() { TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); - client.enqueue(bigMessage); + try { + client.enqueue(bigMessage); + } catch (IllegalArgumentException e) { + assertThat(e).isExactlyInstanceOf(e.getClass()); + } // can't test for exact size cause other attributes come in play assertThat(client.messageSizeInBytes(bigMessage)).isGreaterThan(1024 * 33); @@ -248,7 +252,11 @@ public void dontFlushUntilReachesMaxSize() throws InterruptedException { TrackMessage bigMessage = TrackMessage.builder("Big Event").userId("bar").properties(properties).build(); - client.enqueue(bigMessage); + try { + client.enqueue(bigMessage); + } catch (IllegalArgumentException e) { + // throw new InterruptedException(e.getMessage()); + } wait(messageQueue); @@ -674,7 +682,7 @@ public void checkForIndividualMessageSizeLessThanLimit() { /** Individual Size check sad path regular chars (over the limit) */ @Test - public void checkForIndividualMessageSizeOverLimit() { + public void checkForIndividualMessageSizeOverLimit() throws IllegalArgumentException { AnalyticsClient client = newClient(); int msgSize = MAX_MSG_SIZE + 1; // BARELY over the limit int sizeLimit = MAX_MSG_SIZE; // 32KB = 32768 @@ -684,7 +692,11 @@ public void checkForIndividualMessageSizeOverLimit() { TrackMessage bigMessage = TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); - client.enqueue(bigMessage); + try { + client.enqueue(bigMessage); + } catch (IllegalArgumentException e) { + assertThat(e).isExactlyInstanceOf(e.getClass()); + } int msgActualSize = client.messageSizeInBytes(bigMessage); assertThat(msgActualSize).isGreaterThan(sizeLimit); @@ -720,7 +732,12 @@ public void checkForIndividualMessageSizeSpecialCharsAboveLimit() { TrackMessage bigMessage = TrackMessage.builder("Event").userId("jorgen25").properties(properties).build(); - client.enqueue(bigMessage); + + try { + client.enqueue(bigMessage); + } catch (IllegalArgumentException e) { + assertThat(e).isExactlyInstanceOf(e.getClass()); + } int msgActualSize = client.messageSizeInBytes(bigMessage); assertThat(msgActualSize).isGreaterThan(sizeLimit); @@ -771,7 +788,7 @@ public void enqueueVerifyRegularMessageIsEnqueuedAndCheckedForSize(MessageBuilde */ @Test public void enqueueSingleMessageAboveLimitWhenNotShutdown(MessageBuilderTest builder) - throws InterruptedException { + throws InterruptedException, IllegalArgumentException { AnalyticsClient client = newClient(); // Message is above batch limit @@ -781,7 +798,11 @@ public void enqueueSingleMessageAboveLimitWhenNotShutdown(MessageBuilderTest bui Message message = builder.get().userId("foo").integrationOptions("someKey", integrationOpts).build(); - client.enqueue(message); + try { + client.enqueue(message); + } catch (IllegalArgumentException e) { + assertThat(e).isExactlyInstanceOf(e.getClass()); + } wait(messageQueue); @@ -793,7 +814,7 @@ public void enqueueSingleMessageAboveLimitWhenNotShutdown(MessageBuilderTest bui @Test public void enqueueVerifyRegularMessagesSpecialCharactersBelowLimit(MessageBuilderTest builder) - throws InterruptedException { + throws InterruptedException, IllegalArgumentException { AnalyticsClient client = newClient(); int msgSize = 1024 * 18; // 18KB @@ -828,7 +849,7 @@ public void enqueueVerifyRegularMessagesSpecialCharactersBelowLimit(MessageBuild * @throws InterruptedException */ @Test - public void submitBatchBelowThreshold() throws InterruptedException { + public void submitBatchBelowThreshold() throws InterruptedException, IllegalArgumentException { AnalyticsClient client = new AnalyticsClient( messageQueue, @@ -868,7 +889,7 @@ public void submitBatchBelowThreshold() throws InterruptedException { * @throws InterruptedException */ @Test - public void submitBatchAboveThreshold() throws InterruptedException { + public void submitBatchAboveThreshold() throws InterruptedException, IllegalArgumentException { AnalyticsClient client = new AnalyticsClient( messageQueue, From ec8d1fc0b9778a8456969fc1feae585b8b51129b Mon Sep 17 00:00:00 2001 From: Edson Amaya Date: Mon, 6 Feb 2023 13:05:27 -0600 Subject: [PATCH 231/272] Remove writeKey from header, add writeKey on payload(batch) (#408) * Remove writeKey from header, add writeKey on payload(batch), add instanceId * Update CHANGELOG with last changes --- CHANGELOG.md | 6 ++++++ .../com/segment/analytics/messages/Batch.java | 7 +++++-- .../segment/analytics/messages/BatchTest.java | 12 +++++++----- .../java/com/segment/analytics/Analytics.java | 5 +++-- .../AnalyticsRequestInterceptor.java | 13 ++----------- .../analytics/internal/AnalyticsClient.java | 16 ++++++++++++---- .../AnalyticsRequestInterceptorTest.java | 4 +--- .../internal/AnalyticsClientTest.java | 19 +++++++++++++------ 8 files changed, 49 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 751977bb..cb34af5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# Version 3.4.0 (Feb 04, 2023) +- [Chore] Dependency upgrades +- [New](https://github.com/segmentio/analytics-java/pull/408) Remove writeKey from header, add writeKey on payload(batch) +- [New](https://github.com/segmentio/analytics-java/pull/406) Change exception to identify the limited exceed for the message +- [New](https://github.com/segmentio/analytics-java/pull/400) Change method static to public to create a GSON instance + # Version 3.3.1 (Aug 11, 2022) - [Chore] Dependency upgrades - [New](https://github.com/segmentio/analytics-java/pull/345) Add option to sentAt field to be null diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java b/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java index f9604007..3be0f4f1 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/Batch.java @@ -12,7 +12,7 @@ public abstract class Batch { private static final AtomicInteger SEQUENCE_GENERATOR = new AtomicInteger(); - public static Batch create(Map context, List batch) { + public static Batch create(Map context, List batch, String writeKey) { Message sentAtNull = batch.stream().filter(message -> message.sentAt() != null).findAny().orElse(null); @@ -20,7 +20,8 @@ public static Batch create(Map context, List batch) { batch, sentAtNull == null ? new Date() : sentAtNull.sentAt(), context, - SEQUENCE_GENERATOR.incrementAndGet()); + SEQUENCE_GENERATOR.incrementAndGet(), + writeKey); } public abstract List batch(); @@ -30,4 +31,6 @@ public static Batch create(Map context, List batch) { public abstract Map context(); public abstract int sequence(); + + public abstract String writeKey(); } diff --git a/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java b/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java index a9b11f2b..8f6bffd0 100644 --- a/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java +++ b/analytics-core/src/test/java/com/segment/analytics/messages/BatchTest.java @@ -17,13 +17,15 @@ @RunWith(BurstJUnit4.class) public class BatchTest { + private static final String writeKey = "writeKey"; + @Test public void create(TestUtils.MessageBuilderFactory factory) { Message message = factory.get().userId("userId").build(); Map context = ImmutableMap.of("foo", "bar"); List messages = ImmutableList.of(message); - Batch batch = Batch.create(context, messages); + Batch batch = Batch.create(context, messages, writeKey); assertThat(batch.batch()).isEqualTo(messages); assertThat(batch.context()).isEqualTo(context); @@ -40,7 +42,7 @@ public void createWithSentAt(TestUtils.MessageBuilderFactory factory) throws Par Map context = ImmutableMap.of("foo", "bar"); List messages = ImmutableList.of(message); - Batch batch = Batch.create(context, messages); + Batch batch = Batch.create(context, messages, writeKey); assertThat(batch.sentAt()).isEqualTo(messages.get(0).sentAt()); } @@ -51,7 +53,7 @@ public void createWithSentAtNull(TestUtils.MessageBuilderFactory factory) throws Map context = ImmutableMap.of("foo", "bar"); List messages = ImmutableList.of(message); - Batch batch = Batch.create(context, messages); + Batch batch = Batch.create(context, messages, writeKey); assertThat(batch.sentAt()).isEqualToIgnoringHours(new Date()); } @@ -62,8 +64,8 @@ public void sequence(TestUtils.MessageBuilderFactory factory) { Map context = ImmutableMap.of("foo", "bar"); List messages = ImmutableList.of(message); - Batch first = Batch.create(context, messages); - Batch second = Batch.create(context, messages); + Batch first = Batch.create(context, messages, writeKey); + Batch second = Batch.create(context, messages, writeKey); assertThat(first.sequence() + 1).isEqualTo(second.sequence()); } diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index 76a73c13..faa0eabb 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -413,7 +413,7 @@ public void log(String message) { OkHttpClient.Builder builder = client .newBuilder() - .addInterceptor(new AnalyticsRequestInterceptor(writeKey, userAgent)) + .addInterceptor(new AnalyticsRequestInterceptor(userAgent)) .addInterceptor(interceptor); if (forceTlsV1) { @@ -449,7 +449,8 @@ public void log(String message) { log, threadFactory, networkExecutor, - callbacks); + callbacks, + writeKey); return new Analytics(analyticsClient, messageTransformers, messageInterceptors, log); } diff --git a/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java b/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java index d4c2e895..e9b9d561 100644 --- a/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java +++ b/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java @@ -2,31 +2,22 @@ import java.io.IOException; import javax.annotation.Nonnull; -import okhttp3.Credentials; import okhttp3.Interceptor; import okhttp3.Request; class AnalyticsRequestInterceptor implements Interceptor { - private static final String AUTHORIZATION_HEADER = "Authorization"; private static final String USER_AGENT_HEADER = "User-Agent"; - private final @Nonnull String writeKey; private final @Nonnull String userAgent; - AnalyticsRequestInterceptor(@Nonnull String writeKey, @Nonnull String userAgent) { - this.writeKey = writeKey; + AnalyticsRequestInterceptor(@Nonnull String userAgent) { this.userAgent = userAgent; } @Override public okhttp3.Response intercept(Chain chain) throws IOException { Request request = chain.request(); - Request newRequest = - request - .newBuilder() - .addHeader(AUTHORIZATION_HEADER, Credentials.basic(writeKey, "")) - .addHeader(USER_AGENT_HEADER, userAgent) - .build(); + Request newRequest = request.newBuilder().addHeader(USER_AGENT_HEADER, userAgent).build(); return chain.proceed(newRequest); } diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index edc81bb3..7c7370d7 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -21,6 +21,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -40,6 +41,7 @@ public class AnalyticsClient { private static final int MSG_MAX_SIZE = 1024 * 32; private static final Charset ENCODING = StandardCharsets.UTF_8; private static Gson gsonInstance; + private static final String instanceId = UUID.randomUUID().toString(); static { Map library = new LinkedHashMap<>(); @@ -47,6 +49,7 @@ public class AnalyticsClient { library.put("version", AnalyticsVersion.get()); Map context = new LinkedHashMap<>(); context.put("library", Collections.unmodifiableMap(library)); + context.put("instanceId", instanceId); CONTEXT = Collections.unmodifiableMap(context); } @@ -63,6 +66,7 @@ public class AnalyticsClient { private final ExecutorService looperExecutor; private final ScheduledExecutorService flushScheduler; private final AtomicBoolean isShutDown; + private final String writeKey; public static AnalyticsClient create( HttpUrl uploadUrl, @@ -75,7 +79,8 @@ public static AnalyticsClient create( Log log, ThreadFactory threadFactory, ExecutorService networkExecutor, - List callbacks) { + List callbacks, + String writeKey) { return new AnalyticsClient( new LinkedBlockingQueue(queueCapacity), uploadUrl, @@ -88,7 +93,8 @@ public static AnalyticsClient create( threadFactory, networkExecutor, callbacks, - new AtomicBoolean(false)); + new AtomicBoolean(false), + writeKey); } public AnalyticsClient( @@ -103,7 +109,8 @@ public AnalyticsClient( ThreadFactory threadFactory, ExecutorService networkExecutor, List callbacks, - AtomicBoolean isShutDown) { + AtomicBoolean isShutDown, + String writeKey) { this.messageQueue = messageQueue; this.uploadUrl = uploadUrl; this.service = service; @@ -115,6 +122,7 @@ public AnalyticsClient( this.looperExecutor = Executors.newSingleThreadExecutor(threadFactory); this.networkExecutor = networkExecutor; this.isShutDown = isShutDown; + this.writeKey = writeKey; this.currentQueueSizeInBytes = 0; @@ -296,7 +304,7 @@ public void run() { Boolean isOverflow = messages.size() >= size; if (!messages.isEmpty() && (isOverflow || isBlockingSignal || batchSizeLimitReached)) { - Batch batch = Batch.create(CONTEXT, new ArrayList<>(messages)); + Batch batch = Batch.create(CONTEXT, new ArrayList<>(messages), writeKey); log.print( VERBOSE, "Batching %s message(s) into batch %s.", diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsRequestInterceptorTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsRequestInterceptorTest.java index cd884bb3..5741b6e0 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsRequestInterceptorTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsRequestInterceptorTest.java @@ -16,8 +16,7 @@ public class AnalyticsRequestInterceptorTest { @Test public void testInterceptor() throws IOException { - AnalyticsRequestInterceptor interceptor = - new AnalyticsRequestInterceptor("writeKey", "userAgent"); + AnalyticsRequestInterceptor interceptor = new AnalyticsRequestInterceptor("userAgent"); final Request request = new Request.Builder().url("https://api.segment.io").get().build(); @@ -25,7 +24,6 @@ public void testInterceptor() throws IOException { new ChainAdapter(request, mockConnection) { @Override public Response proceed(Request request) throws IOException { - assertThat(request.header("Authorization"), Is.is("Basic d3JpdGVLZXk6")); assertThat(request.header("User-Agent"), Is.is("userAgent")); return null; } diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index 934fb8ab..d559d737 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -68,6 +68,7 @@ public class AnalyticsClientTest { MAX_MSG_SIZE - 200; // Once we create msg object with this size it barely below 32 threshold so good // for tests + private static String writeKey = "writeKey"; Log log = Log.NONE; @@ -103,7 +104,8 @@ AnalyticsClient newClient() { threadFactory, networkExecutor, Collections.singletonList(callback), - isShutDown); + isShutDown, + writeKey); } @Test @@ -290,7 +292,8 @@ public void flushHowManyTimesNecessaryToStayWithinLimit() throws InterruptedExce threadFactory, networkExecutor, Collections.singletonList(callback), - isShutDown); + isShutDown, + writeKey); Map properties = new HashMap(); @@ -357,7 +360,8 @@ public void enqueueBeforeMaxDoesNotTriggerFlush() { } static Batch batchFor(Message message) { - return Batch.create(Collections.emptyMap(), Collections.singletonList(message)); + return Batch.create( + Collections.emptyMap(), Collections.singletonList(message), writeKey); } @Test @@ -863,7 +867,8 @@ public void submitBatchBelowThreshold() throws InterruptedException, IllegalArgu threadFactory, networkExecutor, Collections.singletonList(callback), - isShutDown); + isShutDown, + writeKey); Map properties = new HashMap(); properties.put("property3", generateDataOfSizeSpecialChars(MAX_MSG_SIZE, true)); @@ -903,7 +908,8 @@ public void submitBatchAboveThreshold() throws InterruptedException, IllegalArgu threadFactory, networkExecutor, Collections.singletonList(callback), - isShutDown); + isShutDown, + writeKey); Map properties = new HashMap(); properties.put("property3", generateDataOfSizeSpecialChars(MAX_MSG_SIZE, true)); @@ -942,7 +948,8 @@ public void submitManySmallMessagesBatchAboveThreshold() throws InterruptedExcep threadFactory, networkExecutor, Collections.singletonList(callback), - isShutDown); + isShutDown, + writeKey); Map properties = new HashMap(); properties.put("property3", generateDataOfSizeSpecialChars(1024 * 8, true)); From e90fac987e81880e7805a34d6e8925dd7c201084 Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Mon, 6 Feb 2023 21:37:59 -0500 Subject: [PATCH 232/272] [maven-release-plugin] prepare release analytics-parent-3.4.0 --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 1b35b5d7..bc01a45e 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.3.2-SNAPSHOT + 3.4.0 analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index ca496c01..b4a8dd8b 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.3.2-SNAPSHOT + 3.4.0 analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 07cfa6fa..56973ea5 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.3.2-SNAPSHOT + 3.4.0 analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 685d871a..9a2b9317 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.3.2-SNAPSHOT + 3.4.0 analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index c461f671..4375d352 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.3.2-SNAPSHOT + 3.4.0 analytics diff --git a/pom.xml b/pom.xml index 79e20023..882baa5e 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.3.2-SNAPSHOT + 3.4.0 pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - HEAD + analytics-parent-3.4.0 From 1de3a03ac6df7a885b926f349e8a107ad39d291d Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Mon, 6 Feb 2023 21:39:16 -0500 Subject: [PATCH 233/272] [maven-release-plugin] prepare for next development iteration --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index bc01a45e..e4852544 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.4.0 + 3.4.1-SNAPSHOT analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index b4a8dd8b..e6de4dc0 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.4.0 + 3.4.1-SNAPSHOT analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 56973ea5..d0cccc12 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.4.0 + 3.4.1-SNAPSHOT analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 9a2b9317..d8c44600 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.4.0 + 3.4.1-SNAPSHOT analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index 4375d352..e642ebf8 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.4.0 + 3.4.1-SNAPSHOT analytics diff --git a/pom.xml b/pom.xml index 882baa5e..87835dd8 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.4.0 + 3.4.1-SNAPSHOT pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - analytics-parent-3.4.0 + HEAD From cae0b6d12e09d1cc1655756724b68cfcc4d2c70d Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Wed, 22 Feb 2023 20:01:48 -0500 Subject: [PATCH 234/272] Adding auth info for nexus repo name required for release (#410) --- .buildscript/settings.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.buildscript/settings.xml b/.buildscript/settings.xml index 4f18cc59..97ec83d7 100644 --- a/.buildscript/settings.xml +++ b/.buildscript/settings.xml @@ -5,5 +5,10 @@ ${env.CI_DEPLOY_USERNAME} ${env.CI_DEPLOY_PASSWORD} + + sonatype-nexus-staging + ${env.CI_DEPLOY_USERNAME} + ${env.CI_DEPLOY_PASSWORD} + - \ No newline at end of file + From c46d85dc98b749415e64d6db1684593d7fd61a01 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Mar 2023 14:49:57 -0400 Subject: [PATCH 235/272] Bump maven-surefire-plugin from 2.22.2 to 3.0.0 (#416) Bumps [maven-surefire-plugin](https://github.com/apache/maven-surefire) from 2.22.2 to 3.0.0. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-2.22.2...surefire-3.0.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 87835dd8..e8f06c2a 100644 --- a/pom.xml +++ b/pom.xml @@ -282,7 +282,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.22.2 + 3.0.0 false From 9e9492faa71486a7c4a133422d6ca57ded3f8093 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Mar 2023 14:50:53 -0400 Subject: [PATCH 236/272] Bump maven-compiler-plugin from 3.10.1 to 3.11.0 (#413) Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.10.1 to 3.11.0. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.10.1...maven-compiler-plugin-3.11.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e8f06c2a..8cf9d80f 100644 --- a/pom.xml +++ b/pom.xml @@ -170,7 +170,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.10.1 + 3.11.0 true ${java.version} From 4cbf144963892e98cc36aa9dea4b822ae57b06bf Mon Sep 17 00:00:00 2001 From: Edson Amaya Date: Wed, 10 May 2023 10:42:41 -0600 Subject: [PATCH 237/272] Convert circleci to github actions (#428) * Add github actions files to test java versions * Add workflows for coverage, e2e, publish, snky --- .github/workflows/coverage.yaml | 37 +++++++++++++++++++++++++++++++ .github/workflows/e2e.yaml | 39 +++++++++++++++++++++++++++++++++ .github/workflows/java11.yml | 33 ++++++++++++++++++++++++++++ .github/workflows/java17.yml | 33 ++++++++++++++++++++++++++++ .github/workflows/java8.yml | 33 ++++++++++++++++++++++++++++ .github/workflows/publish.yaml | 36 ++++++++++++++++++++++++++++++ .github/workflows/snyk.yaml | 39 +++++++++++++++++++++++++++++++++ 7 files changed, 250 insertions(+) create mode 100644 .github/workflows/coverage.yaml create mode 100644 .github/workflows/e2e.yaml create mode 100644 .github/workflows/java11.yml create mode 100644 .github/workflows/java17.yml create mode 100644 .github/workflows/java8.yml create mode 100644 .github/workflows/publish.yaml create mode 100644 .github/workflows/snyk.yaml diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml new file mode 100644 index 00000000..00e26a59 --- /dev/null +++ b/.github/workflows/coverage.yaml @@ -0,0 +1,37 @@ +name: Coverage process + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK 8 + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'temurin' + cache: maven + + - id: spotless + run: mvn spotless:check animal-sniffer:check test verify + # - if: failure() + # name: Test Spotless Failed + # run: | + # wget https://raw.githubusercontent.com/segmentio/circleci-notifications/master/slack-notify-branch.sh + # chmod u+x slack-notify-branch.sh + # BUILD_STATUS="Failed" NOTIFY_BRANCH="master" ./slack-notify-branch.sh + - if: steps.spotless.conclusion == 'success' + run: mvn -B package + + - name: Run command cobertura + run: mvn cobertura:cobertura + - run: bash <(curl -s https://codecov.io/bash) \ No newline at end of file diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml new file mode 100644 index 00000000..b7dae73d --- /dev/null +++ b/.github/workflows/e2e.yaml @@ -0,0 +1,39 @@ +name: e2e process + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + schedule: + - cron: "5 * * * *" + branches: [master, scheduled_e2_testing] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK 8 + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'temurin' + cache: maven + + - id: spotless + run: mvn spotless:check animal-sniffer:check test verify + # - if: failure() + # name: Test Spotless Failed + # run: | + # wget https://raw.githubusercontent.com/segmentio/circleci-notifications/master/slack-notify-branch.sh + # chmod u+x slack-notify-branch.sh + # BUILD_STATUS="Failed" NOTIFY_BRANCH="master" ./slack-notify-branch.sh + - if: steps.spotless.conclusion == 'success' + run: mvn -B package + + - name: Run script e2e.sh + run: .buildscript/e2e.sh \ No newline at end of file diff --git a/.github/workflows/java11.yml b/.github/workflows/java11.yml new file mode 100644 index 00000000..9b3841a0 --- /dev/null +++ b/.github/workflows/java11.yml @@ -0,0 +1,33 @@ +name: Java CI 11 + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK 11 + uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'temurin' + cache: maven + + - id: spotless + run: mvn spotless:check animal-sniffer:check test verify + # - if: failure() + # name: Test Spotless Failed + # run: | + # wget https://raw.githubusercontent.com/segmentio/circleci-notifications/master/slack-notify-branch.sh + # chmod u+x slack-notify-branch.sh + # BUILD_STATUS="Failed" NOTIFY_BRANCH="master" ./slack-notify-branch.sh + - if: steps.spotless.conclusion == 'success' + run: mvn -B package \ No newline at end of file diff --git a/.github/workflows/java17.yml b/.github/workflows/java17.yml new file mode 100644 index 00000000..fbda4492 --- /dev/null +++ b/.github/workflows/java17.yml @@ -0,0 +1,33 @@ +name: Java CI 17 + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + cache: maven + + - id: spotless + run: mvn spotless:check animal-sniffer:check test verify + # - if: failure() + # name: Test Spotless Failed + # run: | + # wget https://raw.githubusercontent.com/segmentio/circleci-notifications/master/slack-notify-branch.sh + # chmod u+x slack-notify-branch.sh + # BUILD_STATUS="Failed" NOTIFY_BRANCH="master" ./slack-notify-branch.sh + - if: steps.spotless.conclusion == 'success' + run: mvn -B package \ No newline at end of file diff --git a/.github/workflows/java8.yml b/.github/workflows/java8.yml new file mode 100644 index 00000000..59985181 --- /dev/null +++ b/.github/workflows/java8.yml @@ -0,0 +1,33 @@ +name: Java CI 8 + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK 8 + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'temurin' + cache: maven + + - id: spotless + run: mvn spotless:check animal-sniffer:check test verify + # - if: failure() + # name: Test Spotless Failed + # run: | + # wget https://raw.githubusercontent.com/segmentio/circleci-notifications/master/slack-notify-branch.sh + # chmod u+x slack-notify-branch.sh + # BUILD_STATUS="Failed" NOTIFY_BRANCH="master" ./slack-notify-branch.sh + - if: steps.spotless.conclusion == 'success' + run: mvn -B package \ No newline at end of file diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml new file mode 100644 index 00000000..3c106b30 --- /dev/null +++ b/.github/workflows/publish.yaml @@ -0,0 +1,36 @@ +name: Publish process + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK 8 + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'temurin' + cache: maven + + - id: spotless + run: mvn spotless:check animal-sniffer:check test verify + # - if: failure() + # name: Test Spotless Failed + # run: | + # wget https://raw.githubusercontent.com/segmentio/circleci-notifications/master/slack-notify-branch.sh + # chmod u+x slack-notify-branch.sh + # BUILD_STATUS="Failed" NOTIFY_BRANCH="master" ./slack-notify-branch.sh + - if: steps.spotless.conclusion == 'success' + run: mvn -B package + + - name: Run script deploy_snapshot.sh + run: .buildscript/deploy_snapshot.sh diff --git a/.github/workflows/snyk.yaml b/.github/workflows/snyk.yaml new file mode 100644 index 00000000..1ea761ec --- /dev/null +++ b/.github/workflows/snyk.yaml @@ -0,0 +1,39 @@ +name: Snyk process + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK 8 + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'temurin' + cache: maven + + - id: spotless + run: mvn spotless:check animal-sniffer:check test verify + # - if: failure() + # name: Test Spotless Failed + # run: | + # wget https://raw.githubusercontent.com/segmentio/circleci-notifications/master/slack-notify-branch.sh + # chmod u+x slack-notify-branch.sh + # BUILD_STATUS="Failed" NOTIFY_BRANCH="master" ./slack-notify-branch.sh + - if: steps.spotless.conclusion == 'success' + run: mvn -B package + + - name: Run Snyk + run: curl -sL https://raw.githubusercontent.com/segmentio/snyk_helpers/master/initialization/snyk.sh | sh + env: + SNYK_FAIL_ON: upgradable + SNYK_SEVERITY_THRESHOLD: high \ No newline at end of file From 923e6cca28c13b9e6e861ba91bf9fd9cbe43d342 Mon Sep 17 00:00:00 2001 From: Edson Amaya Date: Wed, 10 May 2023 11:01:59 -0600 Subject: [PATCH 238/272] Update library mockito-core to 5.3.1 and fix test (#411) * Update library mockito-core to 5.1.0 and fix test * Update mockito-core to 5.2.0 * Update mockito-core to 5.3.0 * Add .factorypath in .gitignore, update mockito-core to 5.3.1 --- .gitignore | 1 + .../segment/analytics/TypedInterceptorTest.java | 14 +++++++------- .../segment/analytics/TypedTransformerTest.java | 14 +++++++------- pom.xml | 10 +++++----- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index f2d6d468..ea323992 100644 --- a/.gitignore +++ b/.gitignore @@ -128,3 +128,4 @@ atlassian-ide-plugin.xml .classpath .project .settings/ +.factorypath \ No newline at end of file diff --git a/analytics/src/test/java/com/segment/analytics/TypedInterceptorTest.java b/analytics/src/test/java/com/segment/analytics/TypedInterceptorTest.java index 07470c18..44667460 100644 --- a/analytics/src/test/java/com/segment/analytics/TypedInterceptorTest.java +++ b/analytics/src/test/java/com/segment/analytics/TypedInterceptorTest.java @@ -1,7 +1,7 @@ package com.segment.analytics; +import static org.junit.Assert.assertNull; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import com.segment.analytics.messages.AliasMessage; import com.segment.analytics.messages.GroupMessage; @@ -18,26 +18,26 @@ public void messagesFanOutCorrectly() { AliasMessage alias = AliasMessage.builder("foo").userId("bar").build(); interceptor.intercept(alias); - verify(interceptor).alias(alias); + assertNull(interceptor.alias(alias)); GroupMessage group = GroupMessage.builder("foo").userId("bar").build(); interceptor.intercept(group); - verify(interceptor).group(group); + assertNull(interceptor.group(group)); IdentifyMessage identify = IdentifyMessage.builder().userId("bar").build(); interceptor.intercept(identify); - verify(interceptor).identify(identify); + assertNull(interceptor.identify(identify)); ScreenMessage screen = ScreenMessage.builder("foo").userId("bar").build(); interceptor.intercept(screen); - verify(interceptor).screen(screen); + assertNull(interceptor.screen(screen)); PageMessage page = PageMessage.builder("foo").userId("bar").build(); interceptor.intercept(page); - verify(interceptor).page(page); + assertNull(interceptor.page(page)); TrackMessage track = TrackMessage.builder("foo").userId("bar").build(); interceptor.intercept(track); - verify(interceptor).track(track); + assertNull(interceptor.track(track)); } } diff --git a/analytics/src/test/java/com/segment/analytics/TypedTransformerTest.java b/analytics/src/test/java/com/segment/analytics/TypedTransformerTest.java index 89aeaa83..d57ecba2 100644 --- a/analytics/src/test/java/com/segment/analytics/TypedTransformerTest.java +++ b/analytics/src/test/java/com/segment/analytics/TypedTransformerTest.java @@ -1,7 +1,7 @@ package com.segment.analytics; +import static org.junit.Assert.assertFalse; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import com.segment.analytics.messages.AliasMessage; import com.segment.analytics.messages.GroupMessage; @@ -18,26 +18,26 @@ public void messagesFanOutCorrectly() { AliasMessage.Builder alias = AliasMessage.builder("foo").userId("bar"); transformer.transform(alias); - verify(transformer).alias(alias); + assertFalse(transformer.alias(alias)); GroupMessage.Builder group = GroupMessage.builder("foo").userId("bar"); transformer.transform(group); - verify(transformer).group(group); + assertFalse(transformer.group(group)); IdentifyMessage.Builder identify = IdentifyMessage.builder().userId("bar"); transformer.transform(identify); - verify(transformer).identify(identify); + assertFalse(transformer.identify(identify)); ScreenMessage.Builder screen = ScreenMessage.builder("foo").userId("bar"); transformer.transform(screen); - verify(transformer).screen(screen); + assertFalse(transformer.screen(screen)); PageMessage.Builder page = PageMessage.builder("foo").userId("bar"); transformer.transform(page); - verify(transformer).page(page); + assertFalse(transformer.page(page)); TrackMessage.Builder track = TrackMessage.builder("foo").userId("bar"); transformer.transform(track); - verify(transformer).track(track); + assertFalse(transformer.track(track)); } } diff --git a/pom.xml b/pom.xml index 8cf9d80f..7c5e0150 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 1.7.20 2.27.2 2.9.0 - 1.10 + 1.10.1 3.0.1 2.9.1 @@ -45,7 +45,7 @@ 4.13.2 1.2.0 - 4.9.0 + 5.3.1 3.24.2 @@ -189,7 +189,7 @@ 1.5 - + @@ -229,7 +229,7 @@ - + @@ -276,7 +276,7 @@ html xml - + From 0331562c4324aa9f6a66e74170e62bedba599747 Mon Sep 17 00:00:00 2001 From: Edson Amaya Date: Mon, 12 Jun 2023 11:25:25 -0600 Subject: [PATCH 239/272] Downgrade to mockito-core library to use with Java 8 (#440) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7c5e0150..10a2884e 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ 4.13.2 1.2.0 - 5.3.1 + 4.11.0 3.24.2 From de66ffccd418ff1cfd33a2704d0421bf9dc1ef75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs?= Date: Wed, 21 Jun 2023 14:31:41 +0200 Subject: [PATCH 240/272] Add GitHub Action badge (#438) --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 471d16c2..3ad06ff7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -analytics-java [![CircleCI](https://circleci.com/gh/segmentio/analytics-java.svg?style=svg&circle-token=14e898d7ee1eb35ff07d2f6e0f7153a547c179fb)](https://circleci.com/gh/segmentio/analytics-java) [![codecov](https://codecov.io/gh/segmentio/analytics-java/branch/master/graph/badge.svg?token=804hPfMd0C)](https://codecov.io/gh/segmentio/analytics-java) +[![GitHub Actions](https://github.com/segmentio/analytics-java/actions/workflows/java17.yml/badge.svg)](https://github.com/segmentio/analytics-java/actions/workflows/java17.yml) [![codecov](https://codecov.io/gh/segmentio/analytics-java/branch/master/graph/badge.svg?token=804hPfMd0C)](https://codecov.io/gh/segmentio/analytics-java) + +analytics-java ============== analytics-java is a Java client for [Segment](https://segment.com) From 4e47e7692448762d19299c46bd317adfc1c8484d Mon Sep 17 00:00:00 2001 From: Louis Lepper Date: Thu, 28 Sep 2023 04:34:41 +1000 Subject: [PATCH 241/272] Allow GsonBuilder to be passed in and used through Analytics and AnalyticsClient (#446) Co-authored-by: Louis Lepper --- .../java/com/segment/analytics/Analytics.java | 32 +++++++++++++++---- .../analytics/internal/AnalyticsClient.java | 32 +++++++------------ .../analytics/AnalyticsBuilderTest.java | 29 +++++++++++++++++ .../internal/AnalyticsClientTest.java | 16 +++++++--- 4 files changed, 77 insertions(+), 32 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index faa0eabb..81af36c7 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -149,6 +149,7 @@ public static class Builder { private List callbacks; private int queueCapacity; private boolean forceTlsV1 = false; + private GsonBuilder gsonBuilder; Builder(String writeKey) { if (writeKey == null || writeKey.trim().length() == 0) { @@ -248,6 +249,20 @@ public Builder queueCapacity(int capacity) { this.queueCapacity = capacity; return this; } + + public Builder gsonBuilder(GsonBuilder gsonBuilder) { + if (gsonBuilder == null) { + throw new NullPointerException("Null gsonBuilder"); + } + + if (this.gsonBuilder != null) { + throw new IllegalStateException("gsonBuilder is already registered."); + } + + this.gsonBuilder = gsonBuilder; + return this; + } + /** Set the queueSize at which flushes should be triggered. */ @Beta public Builder flushQueueSize(int flushQueueSize) { @@ -341,11 +356,15 @@ public Builder forceTlsVersion1() { /** Create a {@link Analytics} client. */ public Analytics build() { - Gson gson = - new GsonBuilder() // - .registerTypeAdapterFactory(new AutoValueAdapterFactory()) // - .registerTypeAdapter(Date.class, new ISO8601DateAdapter()) // - .create(); + if (gsonBuilder == null) { + gsonBuilder = new GsonBuilder(); + } + + gsonBuilder + .registerTypeAdapterFactory(new AutoValueAdapterFactory()) + .registerTypeAdapter(Date.class, new ISO8601DateAdapter()); + + Gson gson = gsonBuilder.create(); if (endpoint == null) { if (uploadURL != null) { @@ -450,7 +469,8 @@ public void log(String message) { threadFactory, networkExecutor, callbacks, - writeKey); + writeKey, + gson); return new Analytics(analyticsClient, messageTransformers, messageInterceptors, log); } diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index 7c7370d7..ecb856ae 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -40,7 +40,7 @@ public class AnalyticsClient { private static final int BATCH_MAX_SIZE = 1024 * 500; private static final int MSG_MAX_SIZE = 1024 * 32; private static final Charset ENCODING = StandardCharsets.UTF_8; - private static Gson gsonInstance; + private Gson gsonInstance; private static final String instanceId = UUID.randomUUID().toString(); static { @@ -80,7 +80,8 @@ public static AnalyticsClient create( ThreadFactory threadFactory, ExecutorService networkExecutor, List callbacks, - String writeKey) { + String writeKey, + Gson gsonInstance) { return new AnalyticsClient( new LinkedBlockingQueue(queueCapacity), uploadUrl, @@ -94,7 +95,8 @@ public static AnalyticsClient create( networkExecutor, callbacks, new AtomicBoolean(false), - writeKey); + writeKey, + gsonInstance); } public AnalyticsClient( @@ -110,7 +112,8 @@ public AnalyticsClient( ExecutorService networkExecutor, List callbacks, AtomicBoolean isShutDown, - String writeKey) { + String writeKey, + Gson gsonInstance) { this.messageQueue = messageQueue; this.uploadUrl = uploadUrl; this.service = service; @@ -123,6 +126,7 @@ public AnalyticsClient( this.networkExecutor = networkExecutor; this.isShutDown = isShutDown; this.writeKey = writeKey; + this.gsonInstance = gsonInstance; this.currentQueueSizeInBytes = 0; @@ -141,24 +145,10 @@ public void run() { TimeUnit.MILLISECONDS); } - /** - * Creating GSON object everytime we check the size seems costly - * - * @return gson instance - */ - public Gson getGsonInstance() { - if (gsonInstance == null) { - gsonInstance = new Gson(); - } - return gsonInstance; - } - public int messageSizeInBytes(Message message) { - Gson gson = getGsonInstance(); - String stringifiedMessage = gson.toJson(message); + String stringifiedMessage = gsonInstance.toJson(message); - int sizeInBytes = stringifiedMessage.getBytes(ENCODING).length; - return sizeInBytes; + return stringifiedMessage.getBytes(ENCODING).length; } private Boolean isBackPressuredAfterSize(int incomingSize) { @@ -269,7 +259,7 @@ public void run() { LinkedList messages = new LinkedList<>(); AtomicInteger currentBatchSize = new AtomicInteger(); boolean batchSizeLimitReached = false; - int contextSize = getGsonInstance().toJson(CONTEXT).getBytes(ENCODING).length; + int contextSize = gsonInstance.toJson(CONTEXT).getBytes(ENCODING).length; try { while (!stop) { Message message = messageQueue.take(); diff --git a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java index dc1b12be..31596e90 100644 --- a/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java +++ b/analytics/src/test/java/com/segment/analytics/AnalyticsBuilderTest.java @@ -7,6 +7,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import com.google.gson.GsonBuilder; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; @@ -167,6 +168,34 @@ public void buildsWithValidInterceptor() { assertThat(analytics).isNotNull(); } + @Test + public void nullGsonBuilder() { + try { + builder.gsonBuilder(null); + fail("Should fail for null gsonBuilder"); + } catch (NullPointerException e) { + assertThat(e).hasMessage("Null gsonBuilder"); + } + } + + @Test + public void duplicateGsonBuilder() { + GsonBuilder gsonBuilder = new GsonBuilder(); + try { + builder.gsonBuilder(gsonBuilder).gsonBuilder(gsonBuilder); + fail("Should fail for duplicate gsonBuilder"); + } catch (IllegalStateException e) { + assertThat(e).hasMessage("gsonBuilder is already registered."); + } + } + + @Test + public void buildsWithValidGsonBuilder() { + GsonBuilder gsonBuilder = new GsonBuilder(); + Analytics analytics = builder.gsonBuilder(gsonBuilder).build(); + assertThat(analytics).isNotNull(); + } + @Test public void invalidFlushQueueSize() { try { diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index d559d737..fad36d23 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -16,6 +16,7 @@ import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.openMocks; +import com.google.gson.Gson; import com.segment.analytics.Callback; import com.segment.analytics.Log; import com.segment.analytics.TestUtils.MessageBuilderTest; @@ -105,7 +106,8 @@ AnalyticsClient newClient() { networkExecutor, Collections.singletonList(callback), isShutDown, - writeKey); + writeKey, + new Gson()); } @Test @@ -293,7 +295,8 @@ public void flushHowManyTimesNecessaryToStayWithinLimit() throws InterruptedExce networkExecutor, Collections.singletonList(callback), isShutDown, - writeKey); + writeKey, + new Gson()); Map properties = new HashMap(); @@ -868,7 +871,8 @@ public void submitBatchBelowThreshold() throws InterruptedException, IllegalArgu networkExecutor, Collections.singletonList(callback), isShutDown, - writeKey); + writeKey, + new Gson()); Map properties = new HashMap(); properties.put("property3", generateDataOfSizeSpecialChars(MAX_MSG_SIZE, true)); @@ -909,7 +913,8 @@ public void submitBatchAboveThreshold() throws InterruptedException, IllegalArgu networkExecutor, Collections.singletonList(callback), isShutDown, - writeKey); + writeKey, + new Gson()); Map properties = new HashMap(); properties.put("property3", generateDataOfSizeSpecialChars(MAX_MSG_SIZE, true)); @@ -949,7 +954,8 @@ public void submitManySmallMessagesBatchAboveThreshold() throws InterruptedExcep networkExecutor, Collections.singletonList(callback), isShutDown, - writeKey); + writeKey, + new Gson()); Map properties = new HashMap(); properties.put("property3", generateDataOfSizeSpecialChars(1024 * 8, true)); From 79c4f712fd68608f392b14be243d89b1c34aeef5 Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Wed, 27 Sep 2023 15:29:50 -0400 Subject: [PATCH 242/272] Updating changelog for release --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb34af5a..7c30f174 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# Version 3.5.0 (Sept 27, 2023) +- [New](https://github.com/segmentio/analytics-java/pull/446) Allow GsonBuilder to be passed in and used through Analytics and AnalyticsClient + # Version 3.4.0 (Feb 04, 2023) - [Chore] Dependency upgrades - [New](https://github.com/segmentio/analytics-java/pull/408) Remove writeKey from header, add writeKey on payload(batch) From 5e0b13ddf976912082e93b6f4c781f4bd0917018 Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Wed, 27 Sep 2023 15:34:18 -0400 Subject: [PATCH 243/272] [maven-release-plugin] prepare release analytics-parent-3.5.0 --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 10 +++++----- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index e4852544..26fe29c5 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.4.1-SNAPSHOT + 3.5.0 analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index e6de4dc0..81e60b3b 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.4.1-SNAPSHOT + 3.5.0 analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index d0cccc12..01d61133 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.4.1-SNAPSHOT + 3.5.0 analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index d8c44600..8cb676ad 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.4.1-SNAPSHOT + 3.5.0 analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index e642ebf8..81d5e17c 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.4.1-SNAPSHOT + 3.5.0 analytics diff --git a/pom.xml b/pom.xml index 10a2884e..8c134c30 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.4.1-SNAPSHOT + 3.5.0 pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - HEAD + analytics-parent-3.5.0 @@ -189,7 +189,7 @@ 1.5 - + @@ -229,7 +229,7 @@ - + @@ -276,7 +276,7 @@ html xml - + From 6e452c750dd7e718bf7b41f33058f02df738da26 Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Wed, 27 Sep 2023 15:35:55 -0400 Subject: [PATCH 244/272] [maven-release-plugin] prepare for next development iteration --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 26fe29c5..7a940d70 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.5.0 + 3.5.1-SNAPSHOT analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index 81e60b3b..b8534599 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.5.0 + 3.5.1-SNAPSHOT analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 01d61133..ac41f7f8 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.5.0 + 3.5.1-SNAPSHOT analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 8cb676ad..359a4ec9 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.5.0 + 3.5.1-SNAPSHOT analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index 81d5e17c..36028125 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.5.0 + 3.5.1-SNAPSHOT analytics diff --git a/pom.xml b/pom.xml index 8c134c30..f6e7fb63 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.5.0 + 3.5.1-SNAPSHOT pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - analytics-parent-3.5.0 + HEAD From fa34b2f59124adf723d13ffcccf3727ac06b862b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Nov 2023 10:07:31 -0800 Subject: [PATCH 245/272] Bump org.apache.maven.plugins:maven-surefire-plugin from 3.0.0 to 3.2.1 (#453) Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.0.0 to 3.2.1. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.0.0...surefire-3.2.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f6e7fb63..54301488 100644 --- a/pom.xml +++ b/pom.xml @@ -282,7 +282,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0 + 3.2.1 false From 92d4200f5b4413fef95b8ae16d8516d3fce74525 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 13:22:51 -0800 Subject: [PATCH 246/272] Bump actions/setup-java from 3 to 4 (#458) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/coverage.yaml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/java11.yml | 2 +- .github/workflows/java17.yml | 2 +- .github/workflows/java8.yml | 2 +- .github/workflows/publish.yaml | 2 +- .github/workflows/snyk.yaml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 00e26a59..05025cfc 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v3 - name: Set up JDK 8 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index b7dae73d..3451d0ea 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@v3 - name: Set up JDK 8 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/java11.yml b/.github/workflows/java11.yml index 9b3841a0..4514cd8f 100644 --- a/.github/workflows/java11.yml +++ b/.github/workflows/java11.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v3 - name: Set up JDK 11 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '11' distribution: 'temurin' diff --git a/.github/workflows/java17.yml b/.github/workflows/java17.yml index fbda4492..f0596695 100644 --- a/.github/workflows/java17.yml +++ b/.github/workflows/java17.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v3 - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' diff --git a/.github/workflows/java8.yml b/.github/workflows/java8.yml index 59985181..026e7129 100644 --- a/.github/workflows/java8.yml +++ b/.github/workflows/java8.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v3 - name: Set up JDK 8 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 3c106b30..acaac20a 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v3 - name: Set up JDK 8 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '8' distribution: 'temurin' diff --git a/.github/workflows/snyk.yaml b/.github/workflows/snyk.yaml index 1ea761ec..67e7e41d 100644 --- a/.github/workflows/snyk.yaml +++ b/.github/workflows/snyk.yaml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v3 - name: Set up JDK 8 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '8' distribution: 'temurin' From 520a33c2f6d653bfae514a820e41404a809ffd8b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 31 Jan 2024 09:45:45 -0800 Subject: [PATCH 247/272] Bump org.apache.maven.plugins:maven-surefire-plugin from 3.2.1 to 3.2.5 (#467) Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.2.1 to 3.2.5. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.1...surefire-3.2.5) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 54301488..a9c3e605 100644 --- a/pom.xml +++ b/pom.xml @@ -282,7 +282,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.1 + 3.2.5 false From c58231a4e62495f7229ccb06ab6ecc63bbae8422 Mon Sep 17 00:00:00 2001 From: Alan Charles <50601149+alanjcharles@users.noreply.github.com> Date: Tue, 13 Feb 2024 10:02:44 -0700 Subject: [PATCH 248/272] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 3ad06ff7..c1605961 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,10 @@ analytics-java ============== +### 🎉 Flagship 🎉 +This library is one of Segment’s most popular Flagship libraries. It is actively maintained by Segment, benefitting from new feature releases and ongoing support. + + analytics-java is a Java client for [Segment](https://segment.com)

From 6a29b4a1e45f275e1fe0a1d58ceeaad83e0007ca Mon Sep 17 00:00:00 2001 From: Phil Gebhardt Date: Wed, 14 Feb 2024 09:57:48 -0800 Subject: [PATCH 249/272] BlockingFlush: Deregister parties upon message completion (#471) As alluded to in https://github.com/segmentio/analytics-java/issues/261, parties registered when messages are enqueued must be deregistered when those messages complete, otherwise the Phaser's number of parties increases without end. As such there are certain cases where `BlockingFlush#block` will hang indefinitely, even once all messages have completed. Example: ``` 00: Phaser initialized; phase=0, parties=1, arrived=0 01: Enqueue Message 1; phase=0, parties=2, arrived=0 02: Enqueue Message 2; phase=0, parties=3, arrived=0 03: arriveAndAwaitAdvance; phase=0, parties=3, arrived=1 04: Complete Message 1; phase=0, parties=3, arrived=2 05: Complete Message 2; phase=0, parties=3, arrived=3 (advance) 06: Enqueue Message 4; phase=1, parties=4, arrived=0 07: Enqueue Message 5; phase=1, parties=5, arrived=0 08: arriveAndAwaitAdvance; phase=1, parties=5, arrived=1 09: Complete Message 4; phase=1, parties=5, arrived=2 10: Complete Message 5; phase=1, parties=5, arrived=3 (no advance) ``` if no more messages are enqueued, `08` will block forever Deregistering parties when messages complete solves this problem ``` 00: Phaser initialized; phase=0, parties=1, arrived=0 01: Enqueue Message 1; phase=0, parties=2, arrived=0 02: Enqueue Message 2; phase=0, parties=3, arrived=0 03: arriveAndAwaitAdvance; phase=0, parties=3, arrived=1 04: Complete Message 1; phase=0, parties=2, arrived=1 05: Complete Message 2; phase=0, parties=1, arrived=1 (advance) 06: Enqueue Message 4; phase=1, parties=2, arrived=0 07: Enqueue Message 5; phase=1, parties=3, arrived=0 08: arriveAndAwaitAdvance; phase=1, parties=3, arrived=1 09: Complete Message 4; phase=1, parties=2, arrived=1 10: Complete Message 5; phase=1, parties=1, arrived=1 (advance) ``` --- analytics-sample/src/main/java/sample/BlockingFlush.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/analytics-sample/src/main/java/sample/BlockingFlush.java b/analytics-sample/src/main/java/sample/BlockingFlush.java index fee534ca..9415a00c 100644 --- a/analytics-sample/src/main/java/sample/BlockingFlush.java +++ b/analytics-sample/src/main/java/sample/BlockingFlush.java @@ -55,12 +55,12 @@ public boolean transform(MessageBuilder builder) { new Callback() { @Override public void success(Message message) { - phaser.arrive(); + phaser.arriveAndDeregister(); } @Override public void failure(Message message, Throwable throwable) { - phaser.arrive(); + phaser.arriveAndDeregister(); } }); } From d3e0d86f3a71e76872be30d23e28452208f0ce70 Mon Sep 17 00:00:00 2001 From: Edson Amaya Date: Wed, 13 Mar 2024 10:45:46 -0600 Subject: [PATCH 250/272] Update CHANGELOG to release a new version (#472) --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c30f174..c2035ccb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# Verion 3.5.1 (Feb 21, 2024) +- [Chore] Dependency upgrades +- [New](https://github.com/segmentio/analytics-java/pull/471) BlockingFlush, deregister parties upon message completion + # Version 3.5.0 (Sept 27, 2023) - [New](https://github.com/segmentio/analytics-java/pull/446) Allow GsonBuilder to be passed in and used through Analytics and AnalyticsClient From ffbaca475e548443a93ddc779cd7b05fcd852884 Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Wed, 20 Mar 2024 10:58:10 -0700 Subject: [PATCH 251/272] Adding wk size to message size calculation along with a buffer (#476) * Adding wk size to message size calculation along with a buffer --- .../analytics/internal/AnalyticsClient.java | 21 ++++++++++--------- .../internal/AnalyticsClientTest.java | 12 +++-------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index ecb856ae..f7560004 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -154,7 +154,8 @@ public int messageSizeInBytes(Message message) { private Boolean isBackPressuredAfterSize(int incomingSize) { int POISON_BYTE_SIZE = messageSizeInBytes(FlushMessage.POISON); int sizeAfterAdd = this.currentQueueSizeInBytes + incomingSize + POISON_BYTE_SIZE; - return sizeAfterAdd >= Math.min(this.maximumQueueByteSize, BATCH_MAX_SIZE); + // Leave a 10% buffer since the unsynchronized enqueue could add multiple at a time + return sizeAfterAdd >= Math.min(this.maximumQueueByteSize, BATCH_MAX_SIZE) * 0.9; } public boolean offer(Message message) { @@ -176,8 +177,6 @@ public void enqueue(Message message) { // @jorgen25 check if message is below 32kb limit for individual messages, no need to check // for extra characters if (messageByteSize <= MSG_MAX_SIZE) { - // messageQueue.put(message); - if (isBackPressuredAfterSize(messageByteSize)) { this.currentQueueSizeInBytes = messageByteSize; messageQueue.put(FlushMessage.POISON); @@ -443,13 +442,13 @@ public static class BatchUtility { * "userId":"jorgen25","integrations":{"someKey":{"data":"aaaaa"}},"previousId":"foo"},{"type":"alias", * "messageId":"57b0ceb4-a1cf-4599-9fba-0a44c7041004","timestamp":"Nov 18, 2021, 2:45:07 PM", * "userId":"jorgen25","integrations":{"someKey":{"data":"aaaaa"}},"previousId":"foo"}], - * "sentAt":"Nov 18, 2021, 2:45:07 - * PM","context":{"library":{"name":"analytics-java","version":"3.1.3"}},"sequence":1} + * "sentAt":"Nov 18, 2021, 2:45:07 PM","context":{"library":{"name":"analytics-java", + * "version":"3.1.3"}},"sequence":1,"writeKey":"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"} * - *

total size of batch : 886 + *

total size of batch : 932 * *

BREAKDOWN: {"batch":[MESSAGE1,MESSAGE2,MESSAGE3,MESSAGE4],"sentAt":"MMM dd, yyyy, HH:mm:ss - * tt","context":CONTEXT,"sequence":1} + * tt","context":CONTEXT,"sequence":1,"writeKey":"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"} * *

so we need to account for: 1 -message size: 189 * 4 = 756 2 -context object size = 55 in * this sample -> 756 + 55 = 811 3 -Metadata (This has the sent data/sequence characters) + @@ -463,12 +462,14 @@ public static class BatchUtility { *

so formulae to determine the expected default size of the batch is * * @return: defaultSize = messages size + context size + metadata size + comma number + sequence - * digits + * digits + writekey + buffer * @return */ private static int getBatchDefaultSize(int contextSize, int currentMessageNumber) { - // sample data: {"batch":[],"sentAt":"MMM dd, yyyy, HH:mm:ss tt","context":,"sequence":1} - 73 - int metadataExtraCharsSize = 73; + // sample data: {"batch":[],"sentAt":"MMM dd, yyyy, HH:mm:ss tt","context":,"sequence":1, + // "writeKey":"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"} - 119 + // Don't need to squeeze everything possible into a batch, adding a buffer + int metadataExtraCharsSize = 119 + 1024; int commaNumber = currentMessageNumber - 1; return contextSize diff --git a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java index fad36d23..74f04e13 100644 --- a/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java +++ b/analytics/src/test/java/com/segment/analytics/internal/AnalyticsClientTest.java @@ -875,7 +875,7 @@ public void submitBatchBelowThreshold() throws InterruptedException, IllegalArgu new Gson()); Map properties = new HashMap(); - properties.put("property3", generateDataOfSizeSpecialChars(MAX_MSG_SIZE, true)); + properties.put("property3", generateDataOfSizeSpecialChars(((int) (MAX_MSG_SIZE * 0.9)), true)); for (int i = 0; i < 15; i++) { TrackMessage bigMessage = @@ -929,13 +929,7 @@ public void submitBatchAboveThreshold() throws InterruptedException, IllegalArgu client.shutdown(); while (!isShutDown.get()) {} - /** - * modified from expected 8 to expected 7 times, since we removed the inner loop. The inner loop - * was forcing to message list created from the queue to keep making batches even if its a 1 - * message batch until the message list is empty, that was forcing the code to make one last - * batch of 1 msg in size bumping the number of times a batch would be submitted from 7 to 8 - */ - verify(networkExecutor, times(7)).submit(any(Runnable.class)); + verify(networkExecutor, times(8)).submit(any(Runnable.class)); } @Test @@ -970,6 +964,6 @@ public void submitManySmallMessagesBatchAboveThreshold() throws InterruptedExcep client.shutdown(); while (!isShutDown.get()) {} - verify(networkExecutor, times(19)).submit(any(Runnable.class)); + verify(networkExecutor, times(21)).submit(any(Runnable.class)); } } From 4615efb8825d21071cc4571ba0766ef52f514c68 Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Wed, 20 Mar 2024 11:18:45 -0700 Subject: [PATCH 252/272] Remove old circleci snyck integration (#455) --- .github/workflows/snyk.yaml | 39 ------------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 .github/workflows/snyk.yaml diff --git a/.github/workflows/snyk.yaml b/.github/workflows/snyk.yaml deleted file mode 100644 index 67e7e41d..00000000 --- a/.github/workflows/snyk.yaml +++ /dev/null @@ -1,39 +0,0 @@ -name: Snyk process - -on: - push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - - name: Set up JDK 8 - uses: actions/setup-java@v4 - with: - java-version: '8' - distribution: 'temurin' - cache: maven - - - id: spotless - run: mvn spotless:check animal-sniffer:check test verify - # - if: failure() - # name: Test Spotless Failed - # run: | - # wget https://raw.githubusercontent.com/segmentio/circleci-notifications/master/slack-notify-branch.sh - # chmod u+x slack-notify-branch.sh - # BUILD_STATUS="Failed" NOTIFY_BRANCH="master" ./slack-notify-branch.sh - - if: steps.spotless.conclusion == 'success' - run: mvn -B package - - - name: Run Snyk - run: curl -sL https://raw.githubusercontent.com/segmentio/snyk_helpers/master/initialization/snyk.sh | sh - env: - SNYK_FAIL_ON: upgradable - SNYK_SEVERITY_THRESHOLD: high \ No newline at end of file From 19216c292765bc5387c54e0946ac6c3dbd625848 Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Wed, 20 Mar 2024 15:03:29 -0400 Subject: [PATCH 253/272] Updating changelog for release --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2035ccb..0fa7e873 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Verion 3.5.1 (Feb 21, 2024) - [Chore] Dependency upgrades - [New](https://github.com/segmentio/analytics-java/pull/471) BlockingFlush, deregister parties upon message completion +- [New](https://github.com/segmentio/analytics-java/pull/476) Added wk size to message size calc along with a buffer # Version 3.5.0 (Sept 27, 2023) - [New](https://github.com/segmentio/analytics-java/pull/446) Allow GsonBuilder to be passed in and used through Analytics and AnalyticsClient From 102e0abeafb1108efdfc7486d42705df0054e2f2 Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Wed, 20 Mar 2024 15:09:46 -0400 Subject: [PATCH 254/272] [maven-release-plugin] prepare release analytics-parent-3.5.1 --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 7a940d70..1842b3b4 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.5.1-SNAPSHOT + 3.5.1 analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index b8534599..c6c7396f 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.5.1-SNAPSHOT + 3.5.1 analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index ac41f7f8..ee647093 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.5.1-SNAPSHOT + 3.5.1 analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 359a4ec9..3d3c5d52 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.5.1-SNAPSHOT + 3.5.1 analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index 36028125..8c80856c 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.5.1-SNAPSHOT + 3.5.1 analytics diff --git a/pom.xml b/pom.xml index a9c3e605..2a9f81e1 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.5.1-SNAPSHOT + 3.5.1 pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - HEAD + analytics-parent-3.5.1 From af4a5d13e55ffd59a253adea1006f1de614791ef Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Wed, 20 Mar 2024 15:09:50 -0400 Subject: [PATCH 255/272] [maven-release-plugin] prepare for next development iteration --- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 1842b3b4..0f474c60 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.5.1 + 3.5.2-SNAPSHOT analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index c6c7396f..974b079b 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.5.1 + 3.5.2-SNAPSHOT analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index ee647093..273519df 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.5.1 + 3.5.2-SNAPSHOT analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 3d3c5d52..6e01b6ce 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.5.1 + 3.5.2-SNAPSHOT analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index 8c80856c..06995866 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.5.1 + 3.5.2-SNAPSHOT analytics diff --git a/pom.xml b/pom.xml index 2a9f81e1..0579f636 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.5.1 + 3.5.2-SNAPSHOT pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. @@ -53,7 +53,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - analytics-parent-3.5.1 + HEAD From 251e6b8974100108d7fb6b79f971eb7dee0cae4c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Apr 2024 08:38:21 -0700 Subject: [PATCH 256/272] Bump com.google.guava:guava from 31.1-jre to 33.1.0-jre (#475) Bumps [com.google.guava:guava](https://github.com/google/guava) from 31.1-jre to 33.1.0-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) --- updated-dependencies: - dependency-name: com.google.guava:guava dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0579f636..b72874ab 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ 2.9.1 4.10.0 4.10.0 - 31.1-jre + 33.1.0-jre 1.0.0 2.7.5 0.6.0.20150202 From 43e620cda4192d9a790671729de71800553fff8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 May 2024 10:07:08 -0700 Subject: [PATCH 257/272] Bump com.google.guava:guava from 33.1.0-jre to 33.2.0-jre (#480) Bumps [com.google.guava:guava](https://github.com/google/guava) from 33.1.0-jre to 33.2.0-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) --- updated-dependencies: - dependency-name: com.google.guava:guava dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b72874ab..619a9bbe 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ 2.9.1 4.10.0 4.10.0 - 33.1.0-jre + 33.2.0-jre 1.0.0 2.7.5 0.6.0.20150202 From d381d895b4df21ec70fa9b5f71a6319c8e7d69be Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Fri, 17 May 2024 14:18:05 -0700 Subject: [PATCH 258/272] Export github issues to jira --- .github/workflows/create_jira.yml | 39 +++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/create_jira.yml diff --git a/.github/workflows/create_jira.yml b/.github/workflows/create_jira.yml new file mode 100644 index 00000000..8180ac0f --- /dev/null +++ b/.github/workflows/create_jira.yml @@ -0,0 +1,39 @@ +name: Create Jira Ticket + +on: + issues: + types: + - opened + +jobs: + create_jira: + name: Create Jira Ticket + runs-on: ubuntu-latest + environment: IssueTracker + steps: + - name: Checkout + uses: actions/checkout@master + - name: Login + uses: atlassian/gajira-login@master + env: + JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} + JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} + JIRA_API_TOKEN: ${{ secrets.JIRA_TOKEN }} + JIRA_EPIC_KEY: ${{ secrets.JIRA_EPIC_KEY }} + JIRA_PROJECT: ${{ secrets.JIRA_PROJECT }} + + - name: Create + id: create + uses: atlassian/gajira-create@master + with: + project: ${{ secrets.JIRA_PROJECT }} + issuetype: Bug + summary: | + [${{ github.event.repository.name }}] (${{ github.event.issue.number }}): ${{ github.event.issue.title }} + description: | + Github Link: ${{ github.event.issue.html_url }} + ${{ github.event.issue.body }} + fields: '{"parent": {"key": "${{ secrets.JIRA_EPIC_KEY }}"}}' + + - name: Log created issue + run: echo "Issue ${{ steps.create.outputs.issue }} was created" \ No newline at end of file From a7641c5ba475a9779ceafd8126c02a15d72f1e18 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Jun 2024 10:05:46 -0700 Subject: [PATCH 259/272] Bump com.google.guava:guava from 33.2.0-jre to 33.2.1-jre (#483) Bumps [com.google.guava:guava](https://github.com/google/guava) from 33.2.0-jre to 33.2.1-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) --- updated-dependencies: - dependency-name: com.google.guava:guava dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 619a9bbe..5b34663e 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ 2.9.1 4.10.0 4.10.0 - 33.2.0-jre + 33.2.1-jre 1.0.0 2.7.5 0.6.0.20150202 From 225325768bc78004e7808044b126f34b3c0e423f Mon Sep 17 00:00:00 2001 From: Edson Amaya Date: Mon, 16 Sep 2024 14:32:44 -0600 Subject: [PATCH 260/272] Change Nonnull & Nullable annotation to jakarta.annotation (#488) --- analytics-core/pom.xml | 5 +++++ .../java/com/segment/analytics/messages/GroupMessage.java | 2 +- .../java/com/segment/analytics/messages/IdentifyMessage.java | 2 +- .../main/java/com/segment/analytics/messages/Message.java | 4 ++-- .../java/com/segment/analytics/messages/PageMessage.java | 2 +- .../java/com/segment/analytics/messages/ScreenMessage.java | 2 +- .../java/com/segment/analytics/messages/TrackMessage.java | 2 +- analytics/pom.xml | 5 +++++ .../com/segment/analytics/AnalyticsRequestInterceptor.java | 2 +- .../java/com/segment/analytics/internal/FlushMessage.java | 4 ++-- .../java/com/segment/analytics/internal/StopMessage.java | 4 ++-- 11 files changed, 22 insertions(+), 12 deletions(-) diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index 974b079b..b3ff7932 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -40,6 +40,11 @@ guava provided + + jakarta.annotation + jakarta.annotation-api + 2.1.1 + junit diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java index 55cbb04d..b51ddf0c 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/GroupMessage.java @@ -2,9 +2,9 @@ import com.google.auto.value.AutoValue; import com.segment.analytics.gson.AutoGson; +import jakarta.annotation.Nullable; import java.util.Date; import java.util.Map; -import javax.annotation.Nullable; /** * The group API call is how you associate an individual user with a group—be it a company, diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/IdentifyMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/IdentifyMessage.java index 024b2e85..dcfa0596 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/IdentifyMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/IdentifyMessage.java @@ -2,9 +2,9 @@ import com.google.auto.value.AutoValue; import com.segment.analytics.gson.AutoGson; +import jakarta.annotation.Nullable; import java.util.Date; import java.util.Map; -import javax.annotation.Nullable; /** * The identify call ties a customer and their actions to a recognizable ID and traits like their diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/Message.java b/analytics-core/src/main/java/com/segment/analytics/messages/Message.java index 4e6197ba..9fdafa2e 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/Message.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/Message.java @@ -1,9 +1,9 @@ package com.segment.analytics.messages; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; import java.util.Date; import java.util.Map; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; /** * Encapsulates properties common to all messages. Although not enforced by the compiler, either the diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java index 0c3d4a3b..2c74e32f 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/PageMessage.java @@ -2,9 +2,9 @@ import com.google.auto.value.AutoValue; import com.segment.analytics.gson.AutoGson; +import jakarta.annotation.Nullable; import java.util.Date; import java.util.Map; -import javax.annotation.Nullable; /** * The page call lets you record whenever a user sees a page of your website, along with any diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/ScreenMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/ScreenMessage.java index 4ae95091..3b4f1a7b 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/ScreenMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/ScreenMessage.java @@ -2,9 +2,9 @@ import com.google.auto.value.AutoValue; import com.segment.analytics.gson.AutoGson; +import jakarta.annotation.Nullable; import java.util.Date; import java.util.Map; -import javax.annotation.Nullable; /** * The screen call lets you record whenever a user sees a screen, along with any properties about diff --git a/analytics-core/src/main/java/com/segment/analytics/messages/TrackMessage.java b/analytics-core/src/main/java/com/segment/analytics/messages/TrackMessage.java index 6caddf5f..fde6f290 100644 --- a/analytics-core/src/main/java/com/segment/analytics/messages/TrackMessage.java +++ b/analytics-core/src/main/java/com/segment/analytics/messages/TrackMessage.java @@ -2,9 +2,9 @@ import com.google.auto.value.AutoValue; import com.segment.analytics.gson.AutoGson; +import jakarta.annotation.Nullable; import java.util.Date; import java.util.Map; -import javax.annotation.Nullable; /** * The track API call is how you record any actions your users perform, along with any properties diff --git a/analytics/pom.xml b/analytics/pom.xml index 06995866..127fd658 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -68,6 +68,11 @@ mockito-core test + + jakarta.annotation + jakarta.annotation-api + 2.1.1 + diff --git a/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java b/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java index e9b9d561..ff50fc3b 100644 --- a/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java +++ b/analytics/src/main/java/com/segment/analytics/AnalyticsRequestInterceptor.java @@ -1,7 +1,7 @@ package com.segment.analytics; +import jakarta.annotation.Nonnull; import java.io.IOException; -import javax.annotation.Nonnull; import okhttp3.Interceptor; import okhttp3.Request; diff --git a/analytics/src/main/java/com/segment/analytics/internal/FlushMessage.java b/analytics/src/main/java/com/segment/analytics/internal/FlushMessage.java index b3ee9dc2..aa3d2689 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/FlushMessage.java +++ b/analytics/src/main/java/com/segment/analytics/internal/FlushMessage.java @@ -1,10 +1,10 @@ package com.segment.analytics.internal; import com.segment.analytics.messages.Message; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; import java.util.Date; import java.util.Map; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; class FlushMessage implements Message { static final FlushMessage POISON = new FlushMessage(); diff --git a/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java b/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java index eccd278c..ad8e1352 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java +++ b/analytics/src/main/java/com/segment/analytics/internal/StopMessage.java @@ -1,10 +1,10 @@ package com.segment.analytics.internal; import com.segment.analytics.messages.Message; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; import java.util.Date; import java.util.Map; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; class StopMessage implements Message { static final StopMessage STOP = new StopMessage(); From 336bcfdb5322bab40e028d0aaba38cb29cb2df48 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Oct 2024 12:20:20 -0400 Subject: [PATCH 261/272] Bump com.google.guava:guava from 33.2.1-jre to 33.3.0-jre (#491) Bumps [com.google.guava:guava](https://github.com/google/guava) from 33.2.1-jre to 33.3.0-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) --- updated-dependencies: - dependency-name: com.google.guava:guava dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Michael Grosse Huelsewiesche --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5b34663e..653db487 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ 2.9.1 4.10.0 4.10.0 - 33.2.1-jre + 33.3.0-jre 1.0.0 2.7.5 0.6.0.20150202 From 3e255c77a748ec899c71304029778459eecca86b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 10:45:33 -0400 Subject: [PATCH 262/272] Bump com.google.guava:guava from 33.3.0-jre to 33.3.1-jre (#496) Bumps [com.google.guava:guava](https://github.com/google/guava) from 33.3.0-jre to 33.3.1-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) --- updated-dependencies: - dependency-name: com.google.guava:guava dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 653db487..9a716e1f 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ 2.9.1 4.10.0 4.10.0 - 33.3.0-jre + 33.3.1-jre 1.0.0 2.7.5 0.6.0.20150202 From 3b1b29036f42a59e1d7fd742e0a5deef2baf0c7e Mon Sep 17 00:00:00 2001 From: Neelkanth Kaushik Date: Mon, 12 May 2025 22:26:35 +0530 Subject: [PATCH 263/272] This commit will update the okhttp version to 4.12.0 in pom.xml. This update is done to fix the Github issue #503. (#505) * This commit will update the okhttp version to 4.12.0 in pom.xml. okhttp-4.12.0 uses okio-3.6.0. This update is done to fix the Github issue #503. * This commit upgrades Kotlin from 1.7.20 to 1.9.0 in pom.xml. This is done to address the CI workflow errors because okhttp-4.12.0 is pulling okio-3.6.0 which is compiled using Kotlin 1.9.0 but the our SDK's pom.xml is expecting Kotlin metadata compiled with Kotlin 1.7.20. --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9a716e1f..39ce738d 100644 --- a/pom.xml +++ b/pom.xml @@ -28,14 +28,14 @@ UTF-8 8 - 1.7.20 + 1.9.0 2.27.2 2.9.0 1.10.1 3.0.1 2.9.1 - 4.10.0 + 4.12.0 4.10.0 33.3.1-jre 1.0.0 From fca4a60a23a71d33cd9f17e59012b919007b1f75 Mon Sep 17 00:00:00 2001 From: Artem Shubovych Date: Tue, 13 May 2025 03:05:53 +1000 Subject: [PATCH 264/272] Bump retrofit to fix CVEe (#504) Co-authored-by: Michael Grosse Huelsewiesche --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 39ce738d..a324471e 100644 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ 8 1.9.0 2.27.2 - 2.9.0 + 2.11.0 1.10.1 3.0.1 From c57a583b235c9a4dcdb5d0d298dc4b4533ce3190 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 15:20:06 -0400 Subject: [PATCH 265/272] Bump com.google.guava:guava from 33.3.1-jre to 33.4.0-jre (#500) Bumps [com.google.guava:guava](https://github.com/google/guava) from 33.3.1-jre to 33.4.0-jre. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) --- updated-dependencies: - dependency-name: com.google.guava:guava dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Michael Grosse Huelsewiesche --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a324471e..8d0424e9 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ 2.9.1 4.12.0 4.10.0 - 33.3.1-jre + 33.4.0-jre 1.0.0 2.7.5 0.6.0.20150202 From 82dfde29ef78fd8c1aa4175e04d1a4a6af6dda2a Mon Sep 17 00:00:00 2001 From: Neelkanth Kaushik Date: Wed, 3 Dec 2025 05:27:57 +0530 Subject: [PATCH 266/272] Patch for Github issue #524 (#526) * Patch for Github issue #524 --- .../analytics/internal/AnalyticsClient.java | 105 ++++++++++++++++-- 1 file changed, 95 insertions(+), 10 deletions(-) diff --git a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java index f7560004..2430cd1e 100644 --- a/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java +++ b/analytics/src/main/java/com/segment/analytics/internal/AnalyticsClient.java @@ -25,7 +25,9 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; @@ -42,6 +44,8 @@ public class AnalyticsClient { private static final Charset ENCODING = StandardCharsets.UTF_8; private Gson gsonInstance; private static final String instanceId = UUID.randomUUID().toString(); + private static final int WAIT_FOR_THREAD_COMPLETE_S = 5; + private static final int TERMINATION_TIMEOUT_S = 1; static { Map library = new LinkedHashMap<>(); @@ -67,6 +71,7 @@ public class AnalyticsClient { private final ScheduledExecutorService flushScheduler; private final AtomicBoolean isShutDown; private final String writeKey; + private volatile Future looperFuture; public static AnalyticsClient create( HttpUrl uploadUrl, @@ -130,7 +135,9 @@ public AnalyticsClient( this.currentQueueSizeInBytes = 0; - if (!isShutDown.get()) looperExecutor.submit(new Looper()); + if (!isShutDown.get()) { + this.looperFuture = looperExecutor.submit(new Looper()); + } flushScheduler = Executors.newScheduledThreadPool(1, threadFactory); flushScheduler.scheduleAtFixedRate( @@ -218,6 +225,8 @@ public void shutdown() { // we can shutdown the flush scheduler without worrying flushScheduler.shutdownNow(); + // Wait for the looper to complete processing before shutting down executors + waitForLooperCompletion(); shutdownAndWait(looperExecutor, "looper"); shutdownAndWait(networkExecutor, "network"); @@ -226,19 +235,81 @@ public void shutdown() { } } + /** + * Wait for the looper to complete processing all messages before proceeding with shutdown. This + * prevents the race condition where the network executor is shut down before the looper finishes + * submitting all batches. + */ + private void waitForLooperCompletion() { + if (looperFuture != null) { + try { + // Wait for the looper to complete processing the STOP message and finish + // Use a reasonable timeout to avoid hanging indefinitely + looperFuture.get(WAIT_FOR_THREAD_COMPLETE_S, TimeUnit.SECONDS); + log.print(VERBOSE, "Looper completed successfully."); + } catch (Exception e) { + log.print(ERROR, e, "Error waiting for looper to complete."); + // Cancel the looper if it's taking too long or if there's an error + if (!looperFuture.isDone()) { + looperFuture.cancel(true); + log.print(VERBOSE, "Looper was cancelled due to timeout or error."); + } + } + } + } + public void shutdownAndWait(ExecutorService executor, String name) { + boolean isLooperExecutor = name != null && name.equalsIgnoreCase("looper"); try { executor.shutdown(); - final boolean executorTerminated = executor.awaitTermination(1, TimeUnit.SECONDS); - - log.print( - VERBOSE, - "%s executor %s.", - name, - executorTerminated ? "terminated normally" : "timed out"); + boolean terminated = executor.awaitTermination(TERMINATION_TIMEOUT_S, TimeUnit.SECONDS); + if (terminated) { + log.print(VERBOSE, "%s executor terminated normally.", name); + return; + } + if (isLooperExecutor) { // Handle looper - network should finish on its own + // not terminated within timeout -> force shutdown + log.print( + VERBOSE, + "%s did not terminate in %d seconds; requesting shutdownNow().", + name, + TERMINATION_TIMEOUT_S); + List dropped = executor.shutdownNow(); // interrupts running tasks + log.print( + VERBOSE, + "%s shutdownNow returned %d queued tasks that never started.", + name, + dropped.size()); + + // optional short wait to give interrupted tasks a chance to exit + boolean terminatedAfterForce = + executor.awaitTermination(TERMINATION_TIMEOUT_S, TimeUnit.SECONDS); + log.print( + VERBOSE, + "%s executor %s after shutdownNow().", + name, + terminatedAfterForce ? "terminated" : "still running (did not terminate)"); + + if (!terminatedAfterForce) { + // final warning — investigate tasks that ignore interrupts + log.print( + ERROR, + "%s executor still did not terminate; tasks may be ignoring interrupts.", + name); + } + } } catch (InterruptedException e) { + // Preserve interrupt status and attempt forceful shutdown log.print(ERROR, e, "Interrupted while stopping %s executor.", name); Thread.currentThread().interrupt(); + if (isLooperExecutor) { + List dropped = executor.shutdownNow(); + log.print( + VERBOSE, + "%s shutdownNow invoked after interrupt; %d tasks returned.", + name, + dropped.size()); + } } } @@ -299,8 +370,22 @@ public void run() { "Batching %s message(s) into batch %s.", batch.batch().size(), batch.sequence()); - networkExecutor.submit( - BatchUploadTask.create(AnalyticsClient.this, batch, maximumRetries)); + try { + networkExecutor.submit( + BatchUploadTask.create(AnalyticsClient.this, batch, maximumRetries)); + } catch (RejectedExecutionException e) { + log.print( + ERROR, + e, + "Failed to submit batch %s to network executor during shutdown. Batch will be lost.", + batch.sequence()); + // Notify callbacks about the failure + for (Message msg : batch.batch()) { + for (Callback callback : callbacks) { + callback.failure(msg, e); + } + } + } currentBatchSize.set(0); messages.clear(); From 4326150f0b973eea2a8bf14ca5cbc06e455bf61c Mon Sep 17 00:00:00 2001 From: Neelkanth Kaushik Date: Wed, 3 Dec 2025 05:36:09 +0530 Subject: [PATCH 267/272] Applying patch for LIBRARIES-2720 (#517) * Created ISO8601InstantAdapter.java file * Fixed CI errors * Spotless Fix * Changed version in pom.xml * Revert - Changed version in pom.xml because of failing test cases --------- Co-authored-by: Michael Grosse Huelsewiesche --- .../analytics/gson/ISO8601InstantAdapter.java | 37 +++++++++++++++++++ .../segment/analytics/gson/Iso8601Utils.java | 7 ++++ .../java/com/segment/analytics/Analytics.java | 3 ++ 3 files changed, 47 insertions(+) create mode 100644 analytics-core/src/main/java/com/segment/analytics/gson/ISO8601InstantAdapter.java diff --git a/analytics-core/src/main/java/com/segment/analytics/gson/ISO8601InstantAdapter.java b/analytics-core/src/main/java/com/segment/analytics/gson/ISO8601InstantAdapter.java new file mode 100644 index 00000000..c21638ad --- /dev/null +++ b/analytics-core/src/main/java/com/segment/analytics/gson/ISO8601InstantAdapter.java @@ -0,0 +1,37 @@ +package com.segment.analytics.gson; + +import com.google.gson.*; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.lang.reflect.Type; +import java.time.Instant; + +/** + * A {@link JsonSerializer} that formats {@link Instant} objects into iso8601 formatted strings, and + * {@link JsonDeserializer} that parses iso8601 formatted strings into {@link Instant} objects. + */ +public class ISO8601InstantAdapter extends TypeAdapter + implements JsonSerializer, JsonDeserializer { + @Override + public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(Iso8601Utils.format(src)); // ISO 8601 format + } + + @Override + public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + return Instant.parse(json.getAsString()); + } + + @Override + public void write(JsonWriter out, Instant value) throws IOException { + out.value(value == null ? null : value.toString()); + } + + @Override + public Instant read(JsonReader in) throws IOException { + String str = in.nextString(); + return str == null ? null : Instant.parse(str); + } +} diff --git a/analytics-core/src/main/java/com/segment/analytics/gson/Iso8601Utils.java b/analytics-core/src/main/java/com/segment/analytics/gson/Iso8601Utils.java index 9504a641..95ca5286 100644 --- a/analytics-core/src/main/java/com/segment/analytics/gson/Iso8601Utils.java +++ b/analytics-core/src/main/java/com/segment/analytics/gson/Iso8601Utils.java @@ -16,6 +16,7 @@ package com.segment.analytics.gson; import com.google.gson.JsonParseException; +import java.time.Instant; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; @@ -277,4 +278,10 @@ private static int indexOfNonDigit(String string, int offset) { } return string.length(); } + + /** Returns {@code date} formatted as yyyy-MM-ddThh:mm:ss.sssZ */ + static String format(Instant instant) { + // Format the instant + return String.valueOf(instant.getEpochSecond()); + } } diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index 81af36c7..9b88de8c 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -4,11 +4,13 @@ import com.google.gson.GsonBuilder; import com.segment.analytics.gson.AutoValueAdapterFactory; import com.segment.analytics.gson.ISO8601DateAdapter; +import com.segment.analytics.gson.ISO8601InstantAdapter; import com.segment.analytics.http.SegmentService; import com.segment.analytics.internal.AnalyticsClient; import com.segment.analytics.internal.AnalyticsVersion; import com.segment.analytics.messages.Message; import com.segment.analytics.messages.MessageBuilder; +import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -362,6 +364,7 @@ public Analytics build() { gsonBuilder .registerTypeAdapterFactory(new AutoValueAdapterFactory()) + .registerTypeAdapter(Instant.class, new ISO8601InstantAdapter()) .registerTypeAdapter(Date.class, new ISO8601DateAdapter()); Gson gson = gsonBuilder.create(); From b00f95156f5013f68ad29ce8a29e6c4af2519a46 Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Tue, 2 Dec 2025 19:16:46 -0500 Subject: [PATCH 268/272] Updating changelog for 3.5.2 release (#506) * Updating changelog for 3.5.2 release * [maven-release-plugin] prepare release analytics-parent-3.5.2 * [maven-release-plugin] prepare for next development iteration --- CHANGELOG.md | 5 ++++- analytics-cli/pom.xml | 2 +- analytics-core/pom.xml | 2 +- analytics-sample/pom.xml | 2 +- analytics-spring-boot-starter/pom.xml | 2 +- analytics/pom.xml | 2 +- pom.xml | 2 +- 7 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fa7e873..3bfb6679 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ -# Verion 3.5.1 (Feb 21, 2024) +# Version 3.5.2 (May 12, 2025) +- [Chore] Depenency upgrades + +# Version 3.5.1 (Feb 21, 2024) - [Chore] Dependency upgrades - [New](https://github.com/segmentio/analytics-java/pull/471) BlockingFlush, deregister parties upon message completion - [New](https://github.com/segmentio/analytics-java/pull/476) Added wk size to message size calc along with a buffer diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index 0f474c60..d4341f18 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.5.2-SNAPSHOT + 3.5.3-SNAPSHOT analytics-cli diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index b3ff7932..f3dc3d23 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.5.2-SNAPSHOT + 3.5.3-SNAPSHOT analytics-core diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 273519df..8151af27 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,7 +6,7 @@ analytics-parent com.segment.analytics.java - 3.5.2-SNAPSHOT + 3.5.3-SNAPSHOT analytics-sample diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index 6e01b6ce..d5d70478 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.5.2-SNAPSHOT + 3.5.3-SNAPSHOT analytics-spring-boot-starter diff --git a/analytics/pom.xml b/analytics/pom.xml index 127fd658..0ef7606b 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.segment.analytics.java analytics-parent - 3.5.2-SNAPSHOT + 3.5.3-SNAPSHOT analytics diff --git a/pom.xml b/pom.xml index 8d0424e9..22316d4b 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.segment.analytics.java analytics-parent - 3.5.2-SNAPSHOT + 3.5.3-SNAPSHOT pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. From abb47619e36be7b28bbc979df64ea140701c418b Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Wed, 3 Dec 2025 12:52:00 -0500 Subject: [PATCH 269/272] Updating changelog for 3.5.3 and fixing verify errors (#528) --- CHANGELOG.md | 4 ++++ .../main/java/com/segment/analytics/http/UploadResponse.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bfb6679..32676a9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# Version 3.5.3 (Dec 3, 2025) +- [New](https://github.com/segmentio/analytics-java/pull/526) Improved shutdown process +- [New](https://github.com/segmentio/analytics-java/pull/517) Support (de)serializing Instant objects to support newer java versions + # Version 3.5.2 (May 12, 2025) - [Chore] Depenency upgrades diff --git a/analytics-core/src/main/java/com/segment/analytics/http/UploadResponse.java b/analytics-core/src/main/java/com/segment/analytics/http/UploadResponse.java index e91be413..ed41a2ca 100644 --- a/analytics-core/src/main/java/com/segment/analytics/http/UploadResponse.java +++ b/analytics-core/src/main/java/com/segment/analytics/http/UploadResponse.java @@ -7,4 +7,8 @@ @AutoGson public abstract class UploadResponse { public abstract boolean success(); + + public static UploadResponse create(boolean success) { + return new AutoValue_UploadResponse(success); + } } From 1eb13a35b0ebef8278a804fff50e8ff7d117eb22 Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Mon, 12 Jan 2026 12:09:40 -0500 Subject: [PATCH 270/272] Release/3.5.4 (#530) * Updating release for new sonatype repository * Updating changelog * Update release plugin (#529) * Changing release plugin * [maven-release-plugin] prepare release analytics-parent-3.5.4 * [maven-release-plugin] prepare for next development iteration * Moving gpg signing to release deploy --- .buildscript/deploy_snapshot.sh | 2 +- .buildscript/settings.xml | 7 +- .gitignore | 4 +- CHANGELOG.md | 3 + RELEASING.md | 2 +- analytics-cli/pom.xml | 32 +- .../src/main/kotlin/cli/JavadocStub.java | 8 + analytics-core/effective-analytics-core.xml | 633 ++++++++++++++++++ analytics-core/pom.xml | 52 +- analytics-sample/pom.xml | 30 +- analytics-spring-boot-starter/pom.xml | 30 +- analytics/pom.xml | 41 +- pom.xml | 81 ++- 13 files changed, 896 insertions(+), 29 deletions(-) create mode 100644 analytics-cli/src/main/kotlin/cli/JavadocStub.java create mode 100644 analytics-core/effective-analytics-core.xml diff --git a/.buildscript/deploy_snapshot.sh b/.buildscript/deploy_snapshot.sh index e02d3c73..2d98a91b 100755 --- a/.buildscript/deploy_snapshot.sh +++ b/.buildscript/deploy_snapshot.sh @@ -23,6 +23,6 @@ elif [ "$CIRCLE_BRANCH" != "$BRANCH" ]; then echo "Skipping snapshot deployment: wrong branch. Expected '$BRANCH' but was '$CIRCLE_BRANCH'." else echo "Deploying snapshot..." - mvn clean source:jar javadoc:jar deploy --settings=".buildscript/settings.xml" -Dmaven.test.skip=true + mvn clean source:jar javadoc:jar deploy --settings=".buildscript/settings.xml" -Dmaven.test.skip=true -Dgpg.skip=true echo "Snapshot deployed!" fi diff --git a/.buildscript/settings.xml b/.buildscript/settings.xml index 97ec83d7..81d298ff 100644 --- a/.buildscript/settings.xml +++ b/.buildscript/settings.xml @@ -1,12 +1,7 @@ - sonatype-nexus-snapshots - ${env.CI_DEPLOY_USERNAME} - ${env.CI_DEPLOY_PASSWORD} - - - sonatype-nexus-staging + central ${env.CI_DEPLOY_USERNAME} ${env.CI_DEPLOY_PASSWORD} diff --git a/.gitignore b/.gitignore index ea323992..4041df6b 100644 --- a/.gitignore +++ b/.gitignore @@ -128,4 +128,6 @@ atlassian-ide-plugin.xml .classpath .project .settings/ -.factorypath \ No newline at end of file +.factorypath + +.vscode diff --git a/CHANGELOG.md b/CHANGELOG.md index 32676a9e..74b4fe12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# Version 3.5.4 (Dec 5, 2025) +- Updating release for new sonatype repository + # Version 3.5.3 (Dec 3, 2025) - [New](https://github.com/segmentio/analytics-java/pull/526) Improved shutdown process - [New](https://github.com/segmentio/analytics-java/pull/517) Support (de)serializing Instant objects to support newer java versions diff --git a/RELEASING.md b/RELEASING.md index 744ce63c..5d59be70 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -5,4 +5,4 @@ Releasing 2. Update the `CHANGELOG.md` for the impending release. 3. `mvn clean release:clean` 4. `mvn release:prepare release:perform` - 5. Visit [Sonatype Nexus](https://oss.sonatype.org/) and promote the artifact. + 4. Visit the [Maven Central Portal](https://central.sonatype.com/publishing/deployments) to review and publish the release. diff --git a/analytics-cli/pom.xml b/analytics-cli/pom.xml index d4341f18..67e1d4b9 100644 --- a/analytics-cli/pom.xml +++ b/analytics-cli/pom.xml @@ -6,16 +6,45 @@ analytics-parent com.segment.analytics.java - 3.5.3-SNAPSHOT + 3.5.5-SNAPSHOT + com.segment.analytics.java analytics-cli + 3.5.5-SNAPSHOT Analytics Java CLI + Command-line interface for Segment Analytics for Java. + https://github.com/segmentio/analytics-java + + + + The MIT License (MIT) + http://opensource.org/licenses/MIT + + + + + https://github.com/segmentio/analytics-java/ + scm:git:https://github.com/segmentio/analytics-java.git + scm:git:git@github.com:segmentio/analytics-java.git + analytics-parent-3.5.4 + + + + + segment + Segment + Segment + https://segment.com + + + org.jetbrains.kotlin kotlin-stdlib + ${kotlin.version} com.segment.analytics.java @@ -25,6 +54,7 @@ com.offbytwo docopt + ${docopt.version} diff --git a/analytics-cli/src/main/kotlin/cli/JavadocStub.java b/analytics-cli/src/main/kotlin/cli/JavadocStub.java new file mode 100644 index 00000000..403beaa7 --- /dev/null +++ b/analytics-cli/src/main/kotlin/cli/JavadocStub.java @@ -0,0 +1,8 @@ +package cli; + +/** + * Placeholder class to generate a Javadoc JAR for the CLI artifact. + */ +public final class JavadocStub { + private JavadocStub() {} +} diff --git a/analytics-core/effective-analytics-core.xml b/analytics-core/effective-analytics-core.xml new file mode 100644 index 00000000..3cb09524 --- /dev/null +++ b/analytics-core/effective-analytics-core.xml @@ -0,0 +1,633 @@ + + + + + + + + + + + + + + + 4.0.0 + + com.segment.analytics.java + analytics-parent + 3.5.4 + + com.segment.analytics.java + analytics-core + 3.5.5-SNAPSHOT + Analytics for Java (Core) + Core runtime for Segment Analytics for Java. + https://github.com/segmentio/analytics-java + + + The MIT License (MIT) + http://opensource.org/licenses/MIT + + + + + segment + Segment + Segment + https://segment.com + + + + scm:git:https://github.com/segmentio/analytics-java.git + scm:git:git@github.com:segmentio/analytics-java.git + analytics-parent-3.5.4 + https://github.com/segmentio/analytics-java/ + + + GitHub Issues + https://github.com/segmentio/analytics-java/issues + + + 3.24.2 + 1.10.1 + 1.0.0 + 1.2.0 + 0.6.0.20150202 + 3.0.1 + 2.9.1 + 33.4.0-jre + 8 + 4.13.2 + 1.9.0 + 4.10.0 + true + 4.11.0 + 4.12.0 + UTF-8 + 2.11.0 + 2.27.2 + 2.7.5 + + + + + com.squareup.retrofit2 + retrofit + 2.11.0 + + + com.squareup.retrofit2 + converter-gson + 2.9.0 + + + com.squareup.retrofit2 + retrofit-mock + 2.11.0 + + + com.google.auto.value + auto-value + 1.10.1 + provided + + + com.google.auto.value + auto-value-annotations + 1.10.1 + + + com.google.code.findbugs + findbugs + 3.0.1 + + + com.google.code.gson + gson + 2.9.1 + + + com.squareup.okhttp3 + okhttp + 4.12.0 + + + com.squareup.okhttp3 + logging-interceptor + 4.10.0 + + + com.google.guava + guava + 33.4.0-jre + + + com.segment.backo + backo + 1.0.0 + + + junit + junit + 4.13.2 + + + com.squareup.burst + burst-junit4 + 1.2.0 + + + com.squareup.burst + burst + 1.2.0 + + + org.assertj + assertj-core + 3.24.2 + + + org.mockito + mockito-core + 4.11.0 + + + com.offbytwo + docopt + 0.6.0.20150202 + + + org.jetbrains.kotlin + kotlin-stdlib + 1.9.0 + + + + + + com.squareup.retrofit2 + retrofit + 2.11.0 + compile + + + com.google.code.gson + gson + 2.9.1 + compile + + + com.google.code.findbugs + findbugs + 3.0.1 + provided + + + com.google.auto.value + auto-value + 1.10.1 + provided + + + com.google.auto.value + auto-value-annotations + 1.10.1 + compile + + + com.google.guava + guava + 33.4.0-jre + provided + + + jakarta.annotation + jakarta.annotation-api + 2.1.1 + compile + + + javax.annotation + javax.annotation-api + 1.3.2 + compile + + + junit + junit + 4.13.2 + test + + + com.squareup.burst + burst-junit4 + 1.2.0 + test + + + com.squareup.burst + burst + 1.2.0 + test + + + org.assertj + assertj-core + 3.24.2 + test + + + org.mockito + mockito-core + 4.11.0 + test + + + + + + false + + central + Central Repository + https://repo.maven.apache.org/maven2 + + + + + + never + + + false + + central + Central Repository + https://repo.maven.apache.org/maven2 + + + + /Users/michaelgh/dev/analytics-java/analytics-core/src/main/java + /Users/michaelgh/dev/analytics-java/analytics-core/src/main/scripts + /Users/michaelgh/dev/analytics-java/analytics-core/src/test/java + /Users/michaelgh/dev/analytics-java/analytics-core/target/classes + /Users/michaelgh/dev/analytics-java/analytics-core/target/test-classes + + + /Users/michaelgh/dev/analytics-java/analytics-core/src/main/resources + + + + + /Users/michaelgh/dev/analytics-java/analytics-core/src/test/resources + + + /Users/michaelgh/dev/analytics-java/analytics-core/target + analytics-core-3.5.5-SNAPSHOT + + + + maven-antrun-plugin + 1.3 + + + maven-assembly-plugin + 2.2-beta-5 + + + maven-dependency-plugin + 2.8 + + + maven-release-plugin + 2.5.3 + + + maven-compiler-plugin + 3.11.0 + + true + 8 + 8 + true + + + + com.diffplug.spotless + spotless-maven-plugin + 2.27.2 + + + + 1.5 + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.codehaus.mojo + templating-maven-plugin + [1.0-alpha-3,) + + filter-sources + filter-test-sources + + + + + true + true + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + [1.0.0,) + + enforce + + + + + + + + + + + + + + + org.sonatype.central + central-publishing-maven-plugin + 0.9.0 + true + + + injected-central-publishing + deploy + + publish + + + central + + + + + central + + + + maven-deploy-plugin + 3.0.0 + + true + + + + maven-assembly-plugin + 2.2-beta-5 + + + + com.segment.analytics.Analytics + + + + jar-with-dependencies + + + + + org.codehaus.mojo + cobertura-maven-plugin + 2.7 + + + html + xml + + + + + + maven-surefire-plugin + 3.2.5 + + + default-test + test + + test + + + false + + + + + false + + + + maven-source-plugin + 3.3.1 + + + attach-sources + + jar-no-fork + + + + + + maven-javadoc-plugin + 3.6.3 + + + attach-javadocs + + jar + + + + + + maven-gpg-plugin + 3.2.7 + + + sign-artifacts + verify + + sign + + + + + + maven-clean-plugin + 3.2.0 + + + default-clean + clean + + clean + + + + + + maven-resources-plugin + 3.3.0 + + + default-testResources + process-test-resources + + testResources + + + + default-resources + process-resources + + resources + + + + + + maven-jar-plugin + 3.3.0 + + + default-jar + package + + jar + + + + + + maven-compiler-plugin + 3.11.0 + + + default-compile + compile + + compile + + + true + 8 + 8 + true + + + + default-testCompile + test-compile + + testCompile + + + true + 8 + 8 + true + + + + + true + 8 + 8 + true + + + + maven-install-plugin + 3.1.0 + + + default-install + install + + install + + + + + + maven-site-plugin + 3.12.1 + + + default-site + site + + site + + + /Users/michaelgh/dev/analytics-java/analytics-core/target/site + + + org.apache.maven.plugins + maven-project-info-reports-plugin + + + + + + default-deploy + site-deploy + + deploy + + + /Users/michaelgh/dev/analytics-java/analytics-core/target/site + + + org.apache.maven.plugins + maven-project-info-reports-plugin + + + + + + + /Users/michaelgh/dev/analytics-java/analytics-core/target/site + + + org.apache.maven.plugins + maven-project-info-reports-plugin + + + + + + + + /Users/michaelgh/dev/analytics-java/analytics-core/target/site + + diff --git a/analytics-core/pom.xml b/analytics-core/pom.xml index f3dc3d23..e2db32c3 100644 --- a/analytics-core/pom.xml +++ b/analytics-core/pom.xml @@ -6,38 +6,72 @@ com.segment.analytics.java analytics-parent - 3.5.3-SNAPSHOT + 3.5.5-SNAPSHOT + com.segment.analytics.java analytics-core + 3.5.5-SNAPSHOT Analytics for Java (Core) + Core runtime for Segment Analytics for Java. + https://github.com/segmentio/analytics-java + + + + The MIT License (MIT) + http://opensource.org/licenses/MIT + + + + + https://github.com/segmentio/analytics-java/ + scm:git:https://github.com/segmentio/analytics-java.git + scm:git:git@github.com:segmentio/analytics-java.git + analytics-parent-3.5.4 + + + + + segment + Segment + Segment + https://segment.com + + + com.squareup.retrofit2 retrofit + ${retrofit.version} com.google.code.gson gson + ${gson.version} com.google.code.findbugs findbugs + ${findbugs.version} provided com.google.auto.value auto-value + ${auto.version} provided com.google.auto.value auto-value-annotations + ${auto.version} com.google.guava guava + ${guava.version} provided @@ -45,30 +79,46 @@ jakarta.annotation-api 2.1.1 + + javax.annotation + javax.annotation-api + 1.3.2 + + + + javax.annotation + javax.annotation-api + 1.3.2 + junit junit + ${junit.version} test com.squareup.burst burst-junit4 + ${burst.version} test com.squareup.burst burst + ${burst.version} test org.assertj assertj-core + ${assertj.version} test org.mockito mockito-core + ${mockito.version} test diff --git a/analytics-sample/pom.xml b/analytics-sample/pom.xml index 8151af27..4794d406 100644 --- a/analytics-sample/pom.xml +++ b/analytics-sample/pom.xml @@ -6,12 +6,40 @@ analytics-parent com.segment.analytics.java - 3.5.3-SNAPSHOT + 3.5.5-SNAPSHOT + com.segment.analytics.java analytics-sample + 3.5.5-SNAPSHOT Analytics Sample + Sample application demonstrating Segment Analytics for Java. + https://github.com/segmentio/analytics-java + + + + The MIT License (MIT) + http://opensource.org/licenses/MIT + + + + + https://github.com/segmentio/analytics-java/ + scm:git:https://github.com/segmentio/analytics-java.git + scm:git:git@github.com:segmentio/analytics-java.git + analytics-parent-3.5.4 + + + + + segment + Segment + Segment + https://segment.com + + + com.segment.analytics.java diff --git a/analytics-spring-boot-starter/pom.xml b/analytics-spring-boot-starter/pom.xml index d5d70478..4ebc8959 100644 --- a/analytics-spring-boot-starter/pom.xml +++ b/analytics-spring-boot-starter/pom.xml @@ -6,12 +6,40 @@ com.segment.analytics.java analytics-parent - 3.5.3-SNAPSHOT + 3.5.5-SNAPSHOT + com.segment.analytics.java analytics-spring-boot-starter + 3.5.5-SNAPSHOT Spring Boot starter for Segment Analytics for Java + Spring Boot auto-configuration for Segment Analytics for Java. + https://github.com/segmentio/analytics-java + + + + The MIT License (MIT) + http://opensource.org/licenses/MIT + + + + + https://github.com/segmentio/analytics-java/ + scm:git:https://github.com/segmentio/analytics-java.git + scm:git:git@github.com:segmentio/analytics-java.git + analytics-parent-3.5.4 + + + + + segment + Segment + Segment + https://segment.com + + + diff --git a/analytics/pom.xml b/analytics/pom.xml index 0ef7606b..05e36fbb 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,12 +6,40 @@ com.segment.analytics.java analytics-parent - 3.5.3-SNAPSHOT + 3.5.5-SNAPSHOT + com.segment.analytics.java analytics + 3.5.5-SNAPSHOT Analytics for Java + The hassle-free way to add analytics to your Java app. + https://github.com/segmentio/analytics-java + + + + The MIT License (MIT) + http://opensource.org/licenses/MIT + + + + + https://github.com/segmentio/analytics-java/ + scm:git:https://github.com/segmentio/analytics-java.git + scm:git:git@github.com:segmentio/analytics-java.git + analytics-parent-3.5.4 + + + + + segment + Segment + Segment + https://segment.com + + + com.segment.analytics.java @@ -21,51 +49,62 @@ com.squareup.okhttp3 okhttp + ${okhttp.version} com.squareup.okhttp3 logging-interceptor + ${logging.version} com.squareup.retrofit2 converter-gson + 2.9.0 com.squareup.retrofit2 retrofit-mock + ${retrofit.version} com.google.code.findbugs findbugs + ${findbugs.version} provided com.segment.backo backo + ${backo.version} junit junit + ${junit.version} test com.squareup.burst burst-junit4 + ${burst.version} test com.squareup.burst burst + ${burst.version} test org.assertj assertj-core + ${assertj.version} test org.mockito mockito-core + ${mockito.version} test diff --git a/pom.xml b/pom.xml index 22316d4b..70cfe8b4 100644 --- a/pom.xml +++ b/pom.xml @@ -3,20 +3,23 @@ 4.0.0 - - org.sonatype.oss - oss-parent - 7 - - com.segment.analytics.java analytics-parent - 3.5.3-SNAPSHOT + 3.5.5-SNAPSHOT pom Analytics for Java (Parent) The hassle-free way to add analytics to your Android app. https://github.com/segmentio/analytics-java + + + segment + Segment + Segment + https://segment.com + + + analytics-core analytics @@ -42,6 +45,9 @@ 2.7.5 0.6.0.20150202 + + true + 4.13.2 1.2.0 @@ -53,7 +59,7 @@ https://github.com/segmentio/analytics-java/ scm:git:https://github.com/segmentio/analytics-java.git scm:git:git@github.com:segmentio/analytics-java.git - HEAD + analytics-parent-3.5.4 @@ -240,16 +246,21 @@ + + org.sonatype.central + central-publishing-maven-plugin + 0.9.0 + true + + central + + org.apache.maven.plugins - maven-release-plugin - 2.5.3 + maven-deploy-plugin + 3.0.0 - true - - pom.xml - .buildscript/settings.xml - + true @@ -287,6 +298,46 @@ false + + org.apache.maven.plugins + maven-source-plugin + 3.3.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.6.3 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.2.7 + + + sign-artifacts + deploy + + sign + + + + From 3d4dd86e6ed760c61503d3808aa2cb55f21ef904 Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Wed, 18 Feb 2026 16:14:56 -0500 Subject: [PATCH 271/272] E2e cli for cross-SDK tests (#532) * Add e2e-cli module for analytics-java - Kotlin CLI using Gson for JSON parsing - Separate from existing analytics-cli to avoid disruption - Added to parent pom.xml modules * Add E2E test workflow Runs sdk-e2e-tests suite against the e2e-cli to verify SDK behavior. * Add E2E_TEST_SUITES to e2e workflow for selective test execution * Adding README.md for e2e-cli * Add E2E_TESTS_TOKEN for private sdk-e2e-tests repo checkout Per-SDK config and convenience script for the generic test runner in sdk-e2e-tests. Run ./e2e-cli/run-e2e.sh to build and test locally. Replace hardcoded env vars and direct npm test call with ./scripts/run-tests.sh which reads e2e-config.json for test configuration. This ensures CI uses the same config as local runs. Co-authored-by: Claude Opus 4.6 --- .github/workflows/e2e-tests.yml | 70 ++++++++++++ e2e-cli/README.md | 54 ++++++++++ e2e-cli/e2e-config.json | 7 ++ e2e-cli/pom.xml | 91 ++++++++++++++++ e2e-cli/run-e2e.sh | 41 +++++++ e2e-cli/src/main/kotlin/cli/Main.kt | 159 ++++++++++++++++++++++++++++ pom.xml | 1 + 7 files changed, 423 insertions(+) create mode 100644 .github/workflows/e2e-tests.yml create mode 100644 e2e-cli/README.md create mode 100644 e2e-cli/e2e-config.json create mode 100644 e2e-cli/pom.xml create mode 100755 e2e-cli/run-e2e.sh create mode 100644 e2e-cli/src/main/kotlin/cli/Main.kt diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml new file mode 100644 index 00000000..2e83d68e --- /dev/null +++ b/.github/workflows/e2e-tests.yml @@ -0,0 +1,70 @@ +# E2E Tests for analytics-java +# Copy this file to: analytics-java/.github/workflows/e2e-tests.yml +# +# This workflow: +# 1. Checks out the SDK and sdk-e2e-tests repos +# 2. Builds the SDK and e2e-cli +# 3. Runs the e2e test suite + +name: E2E Tests + +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + workflow_dispatch: # Allow manual trigger + +jobs: + e2e-tests: + runs-on: ubuntu-latest + + steps: + - name: Checkout SDK + uses: actions/checkout@v4 + with: + path: sdk + + - name: Checkout sdk-e2e-tests + uses: actions/checkout@v4 + with: + repository: segmentio/sdk-e2e-tests + token: ${{ secrets.E2E_TESTS_TOKEN }} + path: sdk-e2e-tests + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '11' + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Build Java SDK and e2e-cli + working-directory: sdk + run: mvn package -pl e2e-cli -am -DskipTests + + - name: Find e2e-cli jar + id: find-jar + working-directory: sdk + run: | + JAR_PATH=$(find e2e-cli/target -name "e2e-cli-*-jar-with-dependencies.jar" | head -1) + echo "jar_path=$JAR_PATH" >> $GITHUB_OUTPUT + + - name: Run E2E tests + working-directory: sdk-e2e-tests + run: | + ./scripts/run-tests.sh \ + --sdk-dir "${{ github.workspace }}/sdk/e2e-cli" \ + --cli "java -jar ${{ github.workspace }}/sdk/${{ steps.find-jar.outputs.jar_path }}" + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: e2e-test-results + path: sdk-e2e-tests/test-results/ + if-no-files-found: ignore diff --git a/e2e-cli/README.md b/e2e-cli/README.md new file mode 100644 index 00000000..b319749e --- /dev/null +++ b/e2e-cli/README.md @@ -0,0 +1,54 @@ +# analytics-java e2e-cli + +E2E test CLI for the [analytics-java](https://github.com/segmentio/analytics-java) SDK. Accepts a JSON input describing events and SDK configuration, sends them through the real SDK, and outputs results as JSON. + +Built with Kotlin (JVM) and packaged as a fat jar via Maven. + +## Setup + +```bash +mvn package -pl e2e-cli -am +``` + +## Usage + +```bash +java -jar e2e-cli/target/e2e-cli-*-jar-with-dependencies.jar --input '{"writeKey":"...", ...}' +``` + +## Input Format + +```jsonc +{ + "writeKey": "your-write-key", // required + "apiHost": "https://...", // optional — SDK default if omitted + "sequences": [ // required — event sequences to send + { + "delayMs": 0, + "events": [ + { "type": "track", "event": "Test", "userId": "user-1" } + ] + } + ], + "config": { // optional + "flushAt": 250, + "flushInterval": 10000, + "maxRetries": 3, + "timeout": 15 + } +} +``` + +Note: Java is a server-side SDK — there is no CDN settings fetch, so `cdnHost` does not apply. + +## Output Format + +```json +{ "success": true, "sentBatches": 1 } +``` + +On failure: + +```json +{ "success": false, "error": "description", "sentBatches": 0 } +``` diff --git a/e2e-cli/e2e-config.json b/e2e-cli/e2e-config.json new file mode 100644 index 00000000..db3d0167 --- /dev/null +++ b/e2e-cli/e2e-config.json @@ -0,0 +1,7 @@ +{ + "sdk": "java", + "test_suites": "basic", + "auto_settings": false, + "patch": null, + "env": {} +} diff --git a/e2e-cli/pom.xml b/e2e-cli/pom.xml new file mode 100644 index 00000000..b5782b8f --- /dev/null +++ b/e2e-cli/pom.xml @@ -0,0 +1,91 @@ + + + + 4.0.0 + + + analytics-parent + com.segment.analytics.java + 3.5.5-SNAPSHOT + + + com.segment.analytics.java + e2e-cli + 3.5.5-SNAPSHOT + Analytics Java E2E CLI + + E2E testing CLI for Segment Analytics for Java. + + + + org.jetbrains.kotlin + kotlin-stdlib + ${kotlin.version} + + + com.segment.analytics.java + analytics + ${project.version} + + + org.jetbrains.kotlinx + kotlinx-serialization-json + 1.4.1 + + + + + src/main/kotlin + + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${kotlin.version} + + + kotlinx-serialization + + + + + org.jetbrains.kotlin + kotlin-maven-serialization + ${kotlin.version} + + + + + compile + compile + + compile + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + jar-with-dependencies + + + + cli.MainKt + + + + + + package + + single + + + + + + + diff --git a/e2e-cli/run-e2e.sh b/e2e-cli/run-e2e.sh new file mode 100755 index 00000000..782df0e8 --- /dev/null +++ b/e2e-cli/run-e2e.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# +# Run E2E tests for analytics-java +# +# Prerequisites: Java 11+, Maven, Node.js 18+ +# +# Usage: +# ./run-e2e.sh [extra args passed to run-tests.sh] +# +# Override sdk-e2e-tests location: +# E2E_TESTS_DIR=../my-e2e-tests ./run-e2e.sh +# + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SDK_ROOT="$SCRIPT_DIR/.." +E2E_DIR="${E2E_TESTS_DIR:-$SDK_ROOT/../sdk-e2e-tests}" + +echo "=== Building analytics-java e2e-cli ===" + +# Build SDK and e2e-cli +cd "$SDK_ROOT" +mvn package -pl e2e-cli -am -DskipTests + +# Find the built jar +CLI_JAR=$(find "$SDK_ROOT/e2e-cli/target" -name "e2e-cli-*-jar-with-dependencies.jar" | head -1) +if [[ -z "$CLI_JAR" ]]; then + echo "Error: Could not find e2e-cli jar" + exit 1 +fi +echo "Found jar: $CLI_JAR" + +echo "" + +# Run tests +cd "$E2E_DIR" +./scripts/run-tests.sh \ + --sdk-dir "$SCRIPT_DIR" \ + --cli "java -jar $CLI_JAR" \ + "$@" diff --git a/e2e-cli/src/main/kotlin/cli/Main.kt b/e2e-cli/src/main/kotlin/cli/Main.kt new file mode 100644 index 00000000..6db10cbd --- /dev/null +++ b/e2e-cli/src/main/kotlin/cli/Main.kt @@ -0,0 +1,159 @@ +package cli + +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.segment.analytics.Analytics +import com.segment.analytics.Callback +import com.segment.analytics.messages.* +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit +import java.util.concurrent.atomic.AtomicBoolean + +data class CLIOutput( + val success: Boolean, + val error: String? = null, + val sentBatches: Int = 0 +) + +data class CLIConfig( + val flushAt: Int? = null, + val flushInterval: Long? = null, + val maxRetries: Int? = null, + val timeout: Int? = null +) + +data class EventSequence( + val delayMs: Long = 0, + val events: List> +) + +data class CLIInput( + val writeKey: String, + val apiHost: String, + val sequences: List, + val config: CLIConfig? = null +) + +private val gson = Gson() + +fun main(args: Array) { + var output = CLIOutput(success = false, error = "Unknown error") + + try { + // Parse --input argument + val inputIndex = args.indexOf("--input") + if (inputIndex == -1 || inputIndex + 1 >= args.size) { + throw IllegalArgumentException("Missing required --input argument") + } + + val inputJson = args[inputIndex + 1] + val input = gson.fromJson(inputJson, CLIInput::class.java) + + val flushAt = input.config?.flushAt ?: 20 + val flushIntervalMs = input.config?.flushInterval ?: 10000L + + val flushLatch = CountDownLatch(1) + val hasError = AtomicBoolean(false) + var errorMessage: String? = null + + val analytics = Analytics.builder(input.writeKey) + .endpoint(input.apiHost) + .flushQueueSize(flushAt) + .flushInterval(maxOf(flushIntervalMs, 1000L), TimeUnit.MILLISECONDS) + .callback(object : Callback { + override fun success(message: Message?) { + // Event sent successfully + } + + override fun failure(message: Message?, throwable: Throwable?) { + hasError.set(true) + errorMessage = throwable?.message + } + }) + .build() + + // Process event sequences + for (seq in input.sequences) { + if (seq.delayMs > 0) { + Thread.sleep(seq.delayMs) + } + + for (event in seq.events) { + sendEvent(analytics, event) + } + } + + // Flush and shutdown + analytics.flush() + analytics.shutdown() + + output = if (hasError.get()) { + CLIOutput(success = false, error = errorMessage, sentBatches = 0) + } else { + CLIOutput(success = true, sentBatches = 1) + } + + } catch (e: Exception) { + output = CLIOutput(success = false, error = e.message ?: e.toString()) + } + + println(gson.toJson(output)) +} + +fun sendEvent(analytics: Analytics, event: Map) { + val type = event["type"] as? String + ?: throw IllegalArgumentException("Event missing 'type' field") + + val userId = event["userId"] as? String ?: "" + val anonymousId = event["anonymousId"] as? String + val messageId = event["messageId"] as? String + @Suppress("UNCHECKED_CAST") + val traits = event["traits"] as? Map ?: emptyMap() + @Suppress("UNCHECKED_CAST") + val properties = event["properties"] as? Map ?: emptyMap() + val eventName = event["event"] as? String + val name = event["name"] as? String + val groupId = event["groupId"] as? String + val previousId = event["previousId"] as? String + + val messageBuilder: MessageBuilder<*, *> = when (type) { + "identify" -> { + IdentifyMessage.builder().apply { + traits(traits) + } + } + "track" -> { + TrackMessage.builder(eventName ?: "Unknown Event").apply { + properties(properties) + } + } + "page" -> { + PageMessage.builder(name ?: "Unknown Page").apply { + properties(properties) + } + } + "screen" -> { + ScreenMessage.builder(name ?: "Unknown Screen").apply { + properties(properties) + } + } + "alias" -> { + AliasMessage.builder(previousId ?: "") + } + "group" -> { + GroupMessage.builder(groupId ?: "").apply { + traits(traits) + } + } + else -> throw IllegalArgumentException("Unknown event type: $type") + } + + if (userId.isNotEmpty()) { + messageBuilder.userId(userId) + } + if (anonymousId != null) { + messageBuilder.anonymousId(anonymousId) + } + + analytics.enqueue(messageBuilder) +} diff --git a/pom.xml b/pom.xml index 70cfe8b4..d873d8ba 100644 --- a/pom.xml +++ b/pom.xml @@ -26,6 +26,7 @@ analytics-sample analytics-cli analytics-spring-boot-starter + e2e-cli From 8585e31a7a3e27ea9e7c3ec0ab64ffcee8d8f778 Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Thu, 26 Feb 2026 14:41:52 -0500 Subject: [PATCH 272/272] Align e2e-cli types with sdk-e2e-tests (#533) * Align e2e-cli types with sdk-e2e-tests definitions Add missing field extraction: timestamp, category, context, integrations. Wire timestamp, messageId, context, and integrations through to the Java SDK MessageBuilder for full fidelity. Co-Authored-By: Claude Opus 4.6 * Replace SimpleDateFormat with java.time.Instant for timestamp parsing Instant.parse() handles all ISO 8601 formats natively, avoids deprecated SimpleDateFormat, and throws DateTimeParseException with clear context on invalid input instead of returning null. Co-Authored-By: Claude Opus 4.6 --------- Co-authored-by: Claude Opus 4.6 --- e2e-cli/src/main/kotlin/cli/Main.kt | 30 +++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/e2e-cli/src/main/kotlin/cli/Main.kt b/e2e-cli/src/main/kotlin/cli/Main.kt index 6db10cbd..b4577615 100644 --- a/e2e-cli/src/main/kotlin/cli/Main.kt +++ b/e2e-cli/src/main/kotlin/cli/Main.kt @@ -5,6 +5,8 @@ import com.google.gson.reflect.TypeToken import com.segment.analytics.Analytics import com.segment.analytics.Callback import com.segment.analytics.messages.* +import java.time.Instant +import java.util.Date import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicBoolean @@ -107,14 +109,20 @@ fun sendEvent(analytics: Analytics, event: Map) { val userId = event["userId"] as? String ?: "" val anonymousId = event["anonymousId"] as? String val messageId = event["messageId"] as? String + val timestamp = event["timestamp"] as? String @Suppress("UNCHECKED_CAST") val traits = event["traits"] as? Map ?: emptyMap() @Suppress("UNCHECKED_CAST") val properties = event["properties"] as? Map ?: emptyMap() val eventName = event["event"] as? String val name = event["name"] as? String + val category = event["category"] as? String val groupId = event["groupId"] as? String val previousId = event["previousId"] as? String + @Suppress("UNCHECKED_CAST") + val context = event["context"] as? Map + @Suppress("UNCHECKED_CAST") + val integrations = event["integrations"] as? Map val messageBuilder: MessageBuilder<*, *> = when (type) { "identify" -> { @@ -154,6 +162,28 @@ fun sendEvent(analytics: Analytics, event: Map) { if (anonymousId != null) { messageBuilder.anonymousId(anonymousId) } + if (messageId != null) { + messageBuilder.messageId(messageId) + } + if (timestamp != null) { + messageBuilder.timestamp(parseTimestamp(timestamp)) + } + if (context != null) { + messageBuilder.context(context) + } + if (integrations != null) { + for ((key, value) in integrations) { + when (value) { + is Boolean -> messageBuilder.enableIntegration(key, value) + is Map<*, *> -> @Suppress("UNCHECKED_CAST") + messageBuilder.integrationOptions(key, value as Map) + } + } + } analytics.enqueue(messageBuilder) } + +private fun parseTimestamp(iso: String): Date { + return Date.from(Instant.parse(iso)) +}