Skip to content

Commit 490cb27

Browse files
author
Bilal Al
committed
impression toggle feature
1 parent f47aeb4 commit 490cb27

20 files changed

+341
-228
lines changed

client/src/main/java/io/split/client/CacheUpdaterService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public void updateCache(Map<SplitAndKey, LocalhostSplit> map) {
5252
String treatment = conditions.size() > 0 ? Treatments.CONTROL : localhostSplit.treatment;
5353
configurations.put(localhostSplit.treatment, localhostSplit.config);
5454

55-
split = new ParsedSplit(splitName, 0, false, treatment,conditions, LOCALHOST, 0, 100, 0, 0, configurations, new HashSet<>());
55+
split = new ParsedSplit(splitName, 0, false, treatment,conditions, LOCALHOST, 0, 100, 0, 0, configurations, new HashSet<>(), true);
5656
parsedSplits.removeIf(parsedSplit -> parsedSplit.feature().equals(splitName));
5757
parsedSplits.add(split);
5858
}

client/src/main/java/io/split/client/HttpSplitChangeFetcher.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ public SplitChange fetch(long since, FetchOptions options) {
8282
String.format("Could not retrieve splitChanges since %s; http return code %s", since, response.statusCode())
8383
);
8484
}
85-
8685
return Json.fromJson(response.body(), SplitChange.class);
8786
} catch (Exception e) {
8887
throw new IllegalStateException(String.format("Problem fetching splitChanges since %s: %s", since, e), e);

client/src/main/java/io/split/client/SplitClientImpl.java

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.split.client.api.Key;
44
import io.split.client.api.SplitResult;
5+
import io.split.client.dtos.DecoratedImpression;
56
import io.split.client.dtos.Event;
67
import io.split.client.events.EventsStorageProducer;
78
import io.split.client.impressions.Impression;
@@ -356,7 +357,8 @@ private SplitResult getTreatmentWithConfigInternal(String matchingKey, String bu
356357
String.format("sdk.%s", methodEnum.getMethod()),
357358
_config.labelsEnabled() ? result.label : null,
358359
result.changeNumber,
359-
attributes
360+
attributes,
361+
result.track
360362
);
361363
_telemetryEvaluationProducer.recordLatency(methodEnum, System.currentTimeMillis() - initTime);
362364
return new SplitResult(result.treatment, result.configurations);
@@ -435,7 +437,7 @@ private Map<String, SplitResult> getTreatmentsBySetsWithConfigInternal(String ma
435437
private Map<String, SplitResult> processEvaluatorResult(Map<String, EvaluatorImp.TreatmentLabelAndChangeNumber> evaluatorResult,
436438
MethodEnum methodEnum, String matchingKey, String bucketingKey, Map<String,
437439
Object> attributes, long initTime){
438-
List<Impression> impressions = new ArrayList<>();
440+
List<DecoratedImpression> decoratedImpressions = new ArrayList<>();
439441
Map<String, SplitResult> result = new HashMap<>();
440442
evaluatorResult.keySet().forEach(t -> {
441443
if (evaluatorResult.get(t).treatment.equals(Treatments.CONTROL) && evaluatorResult.get(t).label.
@@ -445,13 +447,16 @@ private Map<String, SplitResult> processEvaluatorResult(Map<String, EvaluatorImp
445447
result.put(t, SPLIT_RESULT_CONTROL);
446448
} else {
447449
result.put(t, new SplitResult(evaluatorResult.get(t).treatment, evaluatorResult.get(t).configurations));
448-
impressions.add(new Impression(matchingKey, bucketingKey, t, evaluatorResult.get(t).treatment, System.currentTimeMillis(),
449-
evaluatorResult.get(t).label, evaluatorResult.get(t).changeNumber, attributes));
450+
decoratedImpressions.add(
451+
new DecoratedImpression(
452+
new Impression(matchingKey, bucketingKey, t, evaluatorResult.get(t).treatment, System.currentTimeMillis(),
453+
evaluatorResult.get(t).label, evaluatorResult.get(t).changeNumber, attributes),
454+
evaluatorResult.get(t).track));
450455
}
451456
});
452457
_telemetryEvaluationProducer.recordLatency(methodEnum, System.currentTimeMillis() - initTime);
453-
if (impressions.size() > 0) {
454-
_impressionManager.track(impressions);
458+
if (decoratedImpressions.size() > 0) {
459+
_impressionManager.track(decoratedImpressions);
455460
}
456461
return result;
457462
}
@@ -501,10 +506,13 @@ private Set<String> filterSetsAreInConfig(Set<String> sets, MethodEnum methodEnu
501506
return setsToReturn;
502507
}
503508
private void recordStats(String matchingKey, String bucketingKey, String featureFlagName, long start, String result,
504-
String operation, String label, Long changeNumber, Map<String, Object> attributes) {
509+
String operation, String label, Long changeNumber, Map<String, Object> attributes, boolean track) {
505510
try {
506-
_impressionManager.track(Stream.of(new Impression(matchingKey, bucketingKey, featureFlagName, result, System.currentTimeMillis(),
507-
label, changeNumber, attributes)).collect(Collectors.toList()));
511+
_impressionManager.track(Stream.of(
512+
new DecoratedImpression(
513+
new Impression(matchingKey, bucketingKey, featureFlagName, result, System.currentTimeMillis(),
514+
label, changeNumber, attributes),
515+
track)).collect(Collectors.toList()));
508516
} catch (Throwable t) {
509517
_log.error("Exception", t);
510518
}

client/src/main/java/io/split/client/SplitFactoryImpl.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -634,9 +634,11 @@ private ImpressionsManagerImpl buildImpressionsManager(SplitClientConfig config,
634634
ImpressionListener listener = !impressionListeners.isEmpty()
635635
? new ImpressionListener.FederatedImpressionListener(impressionListeners)
636636
: null;
637+
counter = new ImpressionCounter();
638+
ProcessImpressionNone processImpressionNone = new ProcessImpressionNone(listener != null, _uniqueKeysTracker, counter);
639+
637640
switch (config.impressionsMode()) {
638641
case OPTIMIZED:
639-
counter = new ImpressionCounter();
640642
ImpressionObserver impressionObserver = new ImpressionObserver(config.getLastSeenCacheSize());
641643
processImpressionStrategy = new ProcessImpressionOptimized(listener != null, impressionObserver,
642644
counter, _telemetryStorageProducer);
@@ -646,13 +648,12 @@ private ImpressionsManagerImpl buildImpressionsManager(SplitClientConfig config,
646648
processImpressionStrategy = new ProcessImpressionDebug(listener != null, impressionObserver);
647649
break;
648650
case NONE:
649-
counter = new ImpressionCounter();
650-
processImpressionStrategy = new ProcessImpressionNone(listener != null, _uniqueKeysTracker, counter);
651+
processImpressionStrategy = processImpressionNone;
651652
break;
652653
}
653654
return ImpressionsManagerImpl.instance(config, _telemetryStorageProducer, impressionsStorageConsumer,
654655
impressionsStorageProducer,
655-
_impressionsSender, processImpressionStrategy, counter, listener);
656+
_impressionsSender, processImpressionNone, processImpressionStrategy, counter, listener);
656657
}
657658

658659
private SDKMetadata createSdkMetadata(boolean ipAddressEnabled, String splitSdkVersion) {
@@ -690,15 +691,15 @@ private void manageSdkReady(SplitClientConfig config) {
690691
}
691692

692693
private UniqueKeysTracker createUniqueKeysTracker(SplitClientConfig config) {
693-
if (config.impressionsMode().equals(ImpressionsManager.Mode.NONE)) {
694+
// if (config.impressionsMode().equals(ImpressionsManager.Mode.NONE)) {
694695
int uniqueKeysRefreshRate = config.operationMode().equals(OperationMode.STANDALONE)
695696
? config.uniqueKeysRefreshRateInMemory()
696697
: config.uniqueKeysRefreshRateRedis();
697698
return new UniqueKeysTrackerImp(_telemetrySynchronizer, uniqueKeysRefreshRate,
698699
config.filterUniqueKeysRefreshRate(),
699700
config.getThreadFactory());
700-
}
701-
return null;
701+
// }
702+
// return null;
702703
}
703704

704705
private SplitChangeFetcher createSplitChangeFetcher(SplitClientConfig splitClientConfig) {
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package io.split.client.dtos;
2+
3+
import io.split.client.impressions.Impression;
4+
5+
public class DecoratedImpression {
6+
public Impression impression;
7+
public boolean track;
8+
9+
public DecoratedImpression(Impression impression, boolean track) {
10+
this.impression = impression;
11+
this.track = track;
12+
}
13+
}
14+

client/src/main/java/io/split/client/dtos/Split.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public class Split {
1818
public int algo;
1919
public Map<String, String> configurations;
2020
public HashSet<String> sets;
21+
public Boolean trackImpression = null;
2122

2223
@Override
2324
public String toString() {

client/src/main/java/io/split/client/impressions/ImpressionsManager.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.split.client.impressions;
22

3+
import io.split.client.dtos.DecoratedImpression;
4+
35
import java.util.List;
46

57
public interface ImpressionsManager {
@@ -10,14 +12,14 @@ public enum Mode {
1012
NONE
1113
}
1214

13-
void track(List<Impression> impressions);
15+
void track(List<DecoratedImpression> decoratedImpressions);
1416
void start();
1517
void close();
1618

1719
final class NoOpImpressionsManager implements ImpressionsManager {
1820

1921
@Override
20-
public void track(List<Impression> impressions) { /* do nothing */ }
22+
public void track(List<DecoratedImpression> decoratedImpressions) { /* do nothing */ }
2123

2224
@Override
2325
public void start(){

client/src/main/java/io/split/client/impressions/ImpressionsManagerImpl.java

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
import com.google.common.annotations.VisibleForTesting;
44
import io.split.client.SplitClientConfig;
5+
import io.split.client.dtos.DecoratedImpression;
56
import io.split.client.dtos.KeyImpression;
67
import io.split.client.dtos.TestImpressions;
8+
import io.split.client.impressions.strategy.ProcessImpressionNone;
79
import io.split.client.impressions.strategy.ProcessImpressionStrategy;
810
import io.split.client.utils.SplitExecutorFactory;
911
import io.split.telemetry.domain.enums.ImpressionsDataTypeEnum;
@@ -13,10 +15,13 @@
1315

1416
import java.io.Closeable;
1517
import java.net.URISyntaxException;
18+
import java.util.ArrayList;
1619
import java.util.List;
20+
import java.util.Objects;
1721
import java.util.concurrent.ScheduledExecutorService;
1822
import java.util.concurrent.TimeUnit;
1923
import java.util.stream.Collectors;
24+
import java.util.stream.Stream;
2025

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

@@ -40,37 +45,42 @@ public class ImpressionsManagerImpl implements ImpressionsManager, Closeable {
4045
private TelemetryRuntimeProducer _telemetryRuntimeProducer;
4146
private ImpressionCounter _counter;
4247
private ProcessImpressionStrategy _processImpressionStrategy;
48+
private ProcessImpressionNone _processImpressionNone;
49+
4350
private final int _impressionsRefreshRate;
4451

4552
public static ImpressionsManagerImpl instance(SplitClientConfig config,
4653
TelemetryRuntimeProducer telemetryRuntimeProducer,
4754
ImpressionsStorageConsumer impressionsStorageConsumer,
4855
ImpressionsStorageProducer impressionsStorageProducer,
4956
ImpressionsSender impressionsSender,
57+
ProcessImpressionNone processImpressionNone,
5058
ProcessImpressionStrategy processImpressionStrategy,
5159
ImpressionCounter counter,
5260
ImpressionListener listener) throws URISyntaxException {
5361
return new ImpressionsManagerImpl(config, impressionsSender, telemetryRuntimeProducer, impressionsStorageConsumer,
54-
impressionsStorageProducer, processImpressionStrategy, counter, listener);
62+
impressionsStorageProducer, processImpressionNone, processImpressionStrategy, counter, listener);
5563
}
5664

5765
public static ImpressionsManagerImpl instanceForTest(SplitClientConfig config,
5866
ImpressionsSender impressionsSender,
5967
TelemetryRuntimeProducer telemetryRuntimeProducer,
6068
ImpressionsStorageConsumer impressionsStorageConsumer,
6169
ImpressionsStorageProducer impressionsStorageProducer,
70+
ProcessImpressionNone processImpressionNone,
6271
ProcessImpressionStrategy processImpressionStrategy,
6372
ImpressionCounter counter,
6473
ImpressionListener listener) {
6574
return new ImpressionsManagerImpl(config, impressionsSender, telemetryRuntimeProducer, impressionsStorageConsumer,
66-
impressionsStorageProducer, processImpressionStrategy, counter, listener);
75+
impressionsStorageProducer, processImpressionNone, processImpressionStrategy, counter, listener);
6776
}
6877

6978
private ImpressionsManagerImpl(SplitClientConfig config,
7079
ImpressionsSender impressionsSender,
7180
TelemetryRuntimeProducer telemetryRuntimeProducer,
7281
ImpressionsStorageConsumer impressionsStorageConsumer,
7382
ImpressionsStorageProducer impressionsStorageProducer,
83+
ProcessImpressionNone processImpressionNone,
7484
ProcessImpressionStrategy processImpressionStrategy,
7585
ImpressionCounter impressionCounter,
7686
ImpressionListener impressionListener) {
@@ -81,6 +91,7 @@ private ImpressionsManagerImpl(SplitClientConfig config,
8191
_impressionsStorageConsumer = checkNotNull(impressionsStorageConsumer);
8292
_impressionsStorageProducer = checkNotNull(impressionsStorageProducer);
8393
_telemetryRuntimeProducer = checkNotNull(telemetryRuntimeProducer);
94+
_processImpressionNone = checkNotNull(processImpressionNone);
8495
_processImpressionStrategy = checkNotNull(processImpressionStrategy);
8596
_impressionsSender = impressionsSender;
8697
_counter = impressionCounter;
@@ -110,15 +121,29 @@ public void start(){
110121
}
111122

112123
@Override
113-
public void track(List<Impression> impressions) {
114-
if (null == impressions) {
124+
public void track(List<DecoratedImpression> decoratedImpressions) {
125+
if (null == decoratedImpressions) {
115126
return;
116127
}
117-
118-
ImpressionsResult impressionsResult = _processImpressionStrategy.process(impressions);
119-
List<Impression> impressionsForLogs = impressionsResult.getImpressionsToQueue();
120-
List<Impression> impressionsToListener = impressionsResult.getImpressionsToListener();
121-
128+
List<Impression> impressionsForLogs = new ArrayList<>();
129+
List<Impression> impressionsToListener = new ArrayList<>();
130+
131+
for (int i = 0; i < decoratedImpressions.size(); i++) {
132+
ImpressionsResult impressionsResult;
133+
if (decoratedImpressions.get(i).track) {
134+
impressionsResult = _processImpressionStrategy.process(Stream.of(
135+
decoratedImpressions.get(i).impression).collect(Collectors.toList()));
136+
} else {
137+
impressionsResult = _processImpressionNone.process(Stream.of(
138+
decoratedImpressions.get(i).impression).collect(Collectors.toList()));
139+
}
140+
if (!Objects.isNull(impressionsResult.getImpressionsToQueue())) {
141+
_log.info("Adding impression to queue");
142+
impressionsForLogs.addAll(impressionsResult.getImpressionsToQueue());
143+
}
144+
if (!Objects.isNull(impressionsResult.getImpressionsToListener()))
145+
impressionsToListener.addAll(impressionsResult.getImpressionsToListener());
146+
}
122147
int totalImpressions = impressionsForLogs.size();
123148
long queued = _impressionsStorageProducer.put(impressionsForLogs.stream().map(KeyImpression::fromImpression).collect(Collectors.toList()));
124149
if (queued < totalImpressions) {

0 commit comments

Comments
 (0)