Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@
<artifactId>tracker</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.split.client</groupId>
<artifactId>impressions</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.split.client</groupId>
<artifactId>targeting-engine</artifactId>
Expand Down
17 changes: 14 additions & 3 deletions client/src/main/java/io/split/client/SplitFactoryImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@
import io.split.client.impressions.ImpressionListener;
import io.split.client.impressions.ImpressionObserver;
import io.split.client.impressions.ImpressionsManager;
import io.split.client.impressions.ImpressionsManagerConfig;
import io.split.client.impressions.ImpressionsManagerImpl;
import io.split.client.impressions.ImpressionsTelemetryRecorder;
import io.split.client.impressions.ImpressionsSender;
import io.split.client.impressions.TelemetryRuntimeImpressionsRecorder;
import io.split.client.impressions.TelemetryUniqueKeysSender;
import io.split.client.impressions.ImpressionsStorage;
import io.split.client.impressions.ImpressionsStorageConsumer;
import io.split.client.impressions.ImpressionsStorageProducer;
Expand Down Expand Up @@ -137,7 +141,7 @@
import io.split.client.utils.SplitExecutorFactory;
import static io.split.client.utils.SplitExecutorFactory.buildExecutorService;

public class SplitFactoryImpl implements SplitFactory {

Check warning on line 144 in client/src/main/java/io/split/client/SplitFactoryImpl.java

View check run for this annotation

SonarQube Pull Requests / SonarQube Code Analysis

Split this “Monster Class” into smaller and more specialized ones to reduce its dependencies on other classes from 32 to the maximum authorized 20 or less.

[S6539] Classes should not depend on an excessive number of classes (aka Monster Class) See more on https://sonar.harness.io/project/issues?id=io.split.client%3Ajava-client-parent&pullRequest=625&issues=ee59d0bf-4013-4b6f-b020-fd7900daf6cc&open=ee59d0bf-4013-4b6f-b020-fd7900daf6cc
private static final org.slf4j.Logger _log = LoggerFactory.getLogger(SplitFactoryImpl.class);
private static final String LEGACY_LOG_MESSAGE = "The sdk initialize in localhost mode using Legacy file. The splitFile or "
+
Expand Down Expand Up @@ -752,11 +756,12 @@
: null;
ProcessImpressionNone processImpressionNone = new ProcessImpressionNone(listener != null, _uniqueKeysTracker, counter);

ImpressionsTelemetryRecorder telemetryRecorder = new TelemetryRuntimeImpressionsRecorder(_telemetryStorageProducer);
switch (config.impressionsMode()) {
case OPTIMIZED:
ImpressionObserver impressionObserver = new ImpressionObserver(config.getLastSeenCacheSize());
processImpressionStrategy = new ProcessImpressionOptimized(listener != null, impressionObserver,
counter, _telemetryStorageProducer);
counter, telemetryRecorder);
break;
case DEBUG:
impressionObserver = new ImpressionObserver(config.getLastSeenCacheSize());
Expand All @@ -766,7 +771,13 @@
processImpressionStrategy = processImpressionNone;
break;
}
return ImpressionsManagerImpl.instance(config, _telemetryStorageProducer, impressionsStorageConsumer,
ImpressionsManagerConfig impressionsManagerConfig = ImpressionsManagerConfig.builder()
.mode(config.impressionsMode())
.impressionsRefreshRateSeconds(config.impressionsRefreshRate())
.threadFactory(config.getThreadFactory())
.debugEnabled(config.debugEnabled())
.build();
return ImpressionsManagerImpl.instance(impressionsManagerConfig, telemetryRecorder, impressionsStorageConsumer,
impressionsStorageProducer,
_impressionsSender, processImpressionNone, processImpressionStrategy, counter, listener);
}
Expand Down Expand Up @@ -809,7 +820,7 @@
int uniqueKeysRefreshRate = config.operationMode().equals(OperationMode.STANDALONE)
? config.uniqueKeysRefreshRateInMemory()
: config.uniqueKeysRefreshRateRedis();
return new UniqueKeysTrackerImp(_telemetrySynchronizer, uniqueKeysRefreshRate,
return new UniqueKeysTrackerImp(new TelemetryUniqueKeysSender(_telemetrySynchronizer), uniqueKeysRefreshRate,
config.filterUniqueKeysRefreshRate(),
config.getThreadFactory());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.split.client.impressions;

import io.split.telemetry.domain.enums.ImpressionsDataTypeEnum;
import io.split.telemetry.storage.TelemetryRuntimeProducer;

public class TelemetryRuntimeImpressionsRecorder implements ImpressionsTelemetryRecorder {

private final TelemetryRuntimeProducer _telemetryRuntimeProducer;

Check warning on line 8 in client/src/main/java/io/split/client/impressions/TelemetryRuntimeImpressionsRecorder.java

View check run for this annotation

SonarQube Pull Requests / SonarQube Code Analysis

Rename this field "_telemetryRuntimeProducer" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

[S116] Field names should comply with a naming convention See more on https://sonar.harness.io/project/issues?id=io.split.client%3Ajava-client-parent&pullRequest=625&issues=51606e78-8c00-4b2f-bd6f-f0603e8f5687&open=51606e78-8c00-4b2f-bd6f-f0603e8f5687

public TelemetryRuntimeImpressionsRecorder(TelemetryRuntimeProducer telemetryRuntimeProducer) {
_telemetryRuntimeProducer = telemetryRuntimeProducer;
}

@Override
public void recordImpressionsDropped(long count) {
_telemetryRuntimeProducer.recordImpressionStats(ImpressionsDataTypeEnum.IMPRESSIONS_DROPPED, count);
}

@Override
public void recordImpressionsQueued(long count) {
_telemetryRuntimeProducer.recordImpressionStats(ImpressionsDataTypeEnum.IMPRESSIONS_QUEUED, count);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.split.client.impressions;

import io.split.client.dtos.UniqueKeys;
import io.split.telemetry.synchronizer.TelemetrySynchronizer;

public class TelemetryUniqueKeysSender implements UniqueKeysSender {

private final TelemetrySynchronizer _telemetrySynchronizer;

Check warning on line 8 in client/src/main/java/io/split/client/impressions/TelemetryUniqueKeysSender.java

View check run for this annotation

SonarQube Pull Requests / SonarQube Code Analysis

Rename this field "_telemetrySynchronizer" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

[S116] Field names should comply with a naming convention See more on https://sonar.harness.io/project/issues?id=io.split.client%3Ajava-client-parent&pullRequest=625&issues=7311ef74-c4dc-4af6-bb67-7c90679401a3&open=7311ef74-c4dc-4af6-bb67-7c90679401a3

public TelemetryUniqueKeysSender(TelemetrySynchronizer telemetrySynchronizer) {
_telemetrySynchronizer = telemetrySynchronizer;
}

@Override
public void send(UniqueKeys uniqueKeys) {
_telemetrySynchronizer.synchronizeUniqueKeys(uniqueKeys);
}
}
65 changes: 65 additions & 0 deletions impressions/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>io.split.client</groupId>
<artifactId>java-client-parent</artifactId>
<version>4.18.3</version>
</parent>

<artifactId>impressions</artifactId>
<packaging>jar</packaging>
<name>Impressions</name>
<description>Impression tracking core: dedup strategies, bloom-filter unique-key tracking, counter aggregation</description>

<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.13.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.0.1-jre</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.split.client.impressions;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -9,6 +8,7 @@
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
* A wrapper around an ImpressionListener provided by the customer. The purpose
Expand All @@ -25,10 +25,12 @@ public class AsynchronousImpressionListener implements ImpressionListener {
private final ExecutorService _executor;

public static AsynchronousImpressionListener build(ImpressionListener delegate, int capacity) {
ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setDaemon(true)
.setNameFormat("impression-listener-wrapper-%d")
.build();
AtomicInteger counter = new AtomicInteger(0);
ThreadFactory threadFactory = r -> {
Thread t = new Thread(r, "impression-listener-wrapper-" + counter.getAndIncrement());
t.setDaemon(true);
return t;
};

ExecutorService executor = new ThreadPoolExecutor(2, 2, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(capacity), threadFactory);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import static com.google.common.base.Preconditions.checkNotNull;

public class ImpressionCounter {

public static class Key {
private final String _featureName;
private final long _timeFrame;

public Key(String featureFlagName, long timeframe) {
_featureName = checkNotNull(featureFlagName);
_featureName = Objects.requireNonNull(featureFlagName);
_timeFrame = timeframe;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package io.split.client.impressions;

import java.util.concurrent.ThreadFactory;

public final class ImpressionsManagerConfig {

private final ImpressionsManager.Mode _mode;

Check warning on line 7 in impressions/src/main/java/io/split/client/impressions/ImpressionsManagerConfig.java

View check run for this annotation

SonarQube Pull Requests / SonarQube Code Analysis

Rename this field "_mode" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

[S116] Field names should comply with a naming convention See more on https://sonar.harness.io/project/issues?id=io.split.client%3Ajava-client-parent&pullRequest=625&issues=e5e194a4-dc71-4511-9929-22ff29101ca4&open=e5e194a4-dc71-4511-9929-22ff29101ca4
private final int _impressionsRefreshRateSeconds;

Check warning on line 8 in impressions/src/main/java/io/split/client/impressions/ImpressionsManagerConfig.java

View check run for this annotation

SonarQube Pull Requests / SonarQube Code Analysis

Rename this field "_impressionsRefreshRateSeconds" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

[S116] Field names should comply with a naming convention See more on https://sonar.harness.io/project/issues?id=io.split.client%3Ajava-client-parent&pullRequest=625&issues=279a3fbe-4aa5-4d74-9594-70660d6c0dd2&open=279a3fbe-4aa5-4d74-9594-70660d6c0dd2
private final ThreadFactory _threadFactory;

Check warning on line 9 in impressions/src/main/java/io/split/client/impressions/ImpressionsManagerConfig.java

View check run for this annotation

SonarQube Pull Requests / SonarQube Code Analysis

Rename this field "_threadFactory" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

[S116] Field names should comply with a naming convention See more on https://sonar.harness.io/project/issues?id=io.split.client%3Ajava-client-parent&pullRequest=625&issues=f1727cf1-869a-425f-b4a9-1fb8dff4fb53&open=f1727cf1-869a-425f-b4a9-1fb8dff4fb53
private final boolean _debugEnabled;

Check warning on line 10 in impressions/src/main/java/io/split/client/impressions/ImpressionsManagerConfig.java

View check run for this annotation

SonarQube Pull Requests / SonarQube Code Analysis

Rename this field "_debugEnabled" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

[S116] Field names should comply with a naming convention See more on https://sonar.harness.io/project/issues?id=io.split.client%3Ajava-client-parent&pullRequest=625&issues=fbd2f7ad-4105-4a43-9d0e-93fb5450812d&open=fbd2f7ad-4105-4a43-9d0e-93fb5450812d

private ImpressionsManagerConfig(Builder builder) {
_mode = builder._mode;
_impressionsRefreshRateSeconds = builder._impressionsRefreshRateSeconds;
_threadFactory = builder._threadFactory;
_debugEnabled = builder._debugEnabled;
}

public ImpressionsManager.Mode mode() { return _mode; }
public int impressionsRefreshRateSeconds() { return _impressionsRefreshRateSeconds; }
public ThreadFactory threadFactory() { return _threadFactory; }
public boolean debugEnabled() { return _debugEnabled; }

public static Builder builder() { return new Builder(); }

public static final class Builder {
private ImpressionsManager.Mode _mode = ImpressionsManager.Mode.OPTIMIZED;

Check warning on line 27 in impressions/src/main/java/io/split/client/impressions/ImpressionsManagerConfig.java

View check run for this annotation

SonarQube Pull Requests / SonarQube Code Analysis

Rename this field "_mode" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

[S116] Field names should comply with a naming convention See more on https://sonar.harness.io/project/issues?id=io.split.client%3Ajava-client-parent&pullRequest=625&issues=f64e8a74-982f-4c50-bee0-e14444a416f9&open=f64e8a74-982f-4c50-bee0-e14444a416f9
private int _impressionsRefreshRateSeconds = 60;

Check warning on line 28 in impressions/src/main/java/io/split/client/impressions/ImpressionsManagerConfig.java

View check run for this annotation

SonarQube Pull Requests / SonarQube Code Analysis

Rename this field "_impressionsRefreshRateSeconds" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

[S116] Field names should comply with a naming convention See more on https://sonar.harness.io/project/issues?id=io.split.client%3Ajava-client-parent&pullRequest=625&issues=3a89b0dd-2470-4f03-bc81-047c765cb384&open=3a89b0dd-2470-4f03-bc81-047c765cb384
private ThreadFactory _threadFactory = null;

Check warning on line 29 in impressions/src/main/java/io/split/client/impressions/ImpressionsManagerConfig.java

View check run for this annotation

SonarQube Pull Requests / SonarQube Code Analysis

Rename this field "_threadFactory" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

[S116] Field names should comply with a naming convention See more on https://sonar.harness.io/project/issues?id=io.split.client%3Ajava-client-parent&pullRequest=625&issues=492df1e9-c5f1-4e9f-8491-13de9aa18251&open=492df1e9-c5f1-4e9f-8491-13de9aa18251
private boolean _debugEnabled = false;

public Builder mode(ImpressionsManager.Mode mode) { _mode = mode; return this; }
public Builder impressionsRefreshRateSeconds(int rate) { _impressionsRefreshRateSeconds = rate; return this; }
public Builder threadFactory(ThreadFactory tf) { _threadFactory = tf; return this; }
public Builder debugEnabled(boolean debug) { _debugEnabled = debug; return this; }

public ImpressionsManagerConfig build() { return new ImpressionsManagerConfig(this); }
}
}
Loading
Loading