Skip to content

Commit cbe85de

Browse files
authored
feat(ats): add support for android ODP events (#502)
Add support for Android-SDK ODP integration, which may not be implemented in the Android-SDK. 1. ODPManager.Builder.withExtraCommonData(commonData) - clients (android-sdk) will pass common data (client os, device type,...) which should be added into all ODPEvents. 2. ODPManager.Builder.withExtraCommonIdentifiers(commonIdentifiers) - clients (android-sdk) will pass common identifiers (vuid,...) which should be added into all ODPEvents.
1 parent ac27ae7 commit cbe85de

File tree

8 files changed

+290
-13
lines changed

8 files changed

+290
-13
lines changed

core-api/src/main/java/com/optimizely/ab/OptimizelyUserContext.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717
package com.optimizely.ab;
1818

19+
import com.optimizely.ab.config.ProjectConfig;
1920
import com.optimizely.ab.odp.ODPManager;
2021
import com.optimizely.ab.odp.ODPSegmentCallback;
2122
import com.optimizely.ab.odp.ODPSegmentOption;
@@ -313,6 +314,8 @@ public void setQualifiedSegments(List<String> qualifiedSegments) {
313314
* Fetch all qualified segments for the user context.
314315
* <p>
315316
* The segments fetched will be saved and can be accessed at any time by calling {@link #getQualifiedSegments()}.
317+
*
318+
* @return a boolean value for fetch success or failure.
316319
*/
317320
public Boolean fetchQualifiedSegments() {
318321
return fetchQualifiedSegments(Collections.emptyList());
@@ -324,6 +327,7 @@ public Boolean fetchQualifiedSegments() {
324327
* The segments fetched will be saved and can be accessed at any time by calling {@link #getQualifiedSegments()}.
325328
*
326329
* @param segmentOptions A set of options for fetching qualified segments.
330+
* @return a boolean value for fetch success or failure.
327331
*/
328332
public Boolean fetchQualifiedSegments(@Nonnull List<ODPSegmentOption> segmentOptions) {
329333
List<String> segments = optimizely.fetchQualifiedSegments(userId, segmentOptions);

core-api/src/main/java/com/optimizely/ab/odp/ODPEvent.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2022, Optimizely Inc. and contributors
2+
* Copyright 2022-2023, Optimizely Inc. and contributors
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@ public class ODPEvent {
2626

2727
private String type;
2828
private String action;
29-
private Map<String, String > identifiers;
29+
private Map<String, String> identifiers;
3030
private Map<String, Object> data;
3131

3232
public ODPEvent(@Nullable String type, @Nonnull String action, @Nullable Map<String, String> identifiers, @Nullable Map<String, Object> data) {

core-api/src/main/java/com/optimizely/ab/odp/ODPEventManager.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717
package com.optimizely.ab.odp;
1818

19+
import com.optimizely.ab.annotations.VisibleForTesting;
1920
import com.optimizely.ab.event.internal.BuildVersionInfo;
2021
import com.optimizely.ab.event.internal.ClientEngineInfo;
2122
import com.optimizely.ab.odp.serializer.ODPJsonSerializerFactory;
@@ -38,6 +39,8 @@ public class ODPEventManager {
3839
private final int queueSize;
3940
private final int batchSize;
4041
private final int flushInterval;
42+
@Nonnull private Map<String, Object> userCommonData = Collections.emptyMap();
43+
@Nonnull private Map<String, String> userCommonIdentifiers = Collections.emptyMap();
4144

4245
private Boolean isRunning = false;
4346

@@ -63,6 +66,16 @@ public ODPEventManager(@Nonnull ODPApiManager apiManager, @Nullable Integer queu
6366
this.batchSize = (flushInterval != null && flushInterval == 0) ? 1 : DEFAULT_BATCH_SIZE;
6467
}
6568

69+
// these user-provided common data are included in all ODP events in addition to the SDK-generated common data.
70+
public void setUserCommonData(@Nullable Map<String, Object> commonData) {
71+
if (commonData != null) this.userCommonData = commonData;
72+
}
73+
74+
// these user-provided common identifiers are included in all ODP events in addition to the SDK-generated identifiers.
75+
public void setUserCommonIdentifiers(@Nullable Map<String, String> commonIdentifiers) {
76+
if (commonIdentifiers != null) this.userCommonIdentifiers = commonIdentifiers;
77+
}
78+
6679
public void start() {
6780
if (eventDispatcherThread == null) {
6881
eventDispatcherThread = new EventDispatcherThread();
@@ -107,19 +120,35 @@ public void sendEvent(ODPEvent event) {
107120
return;
108121
}
109122
event.setData(augmentCommonData(event.getData()));
123+
event.setIdentifiers(augmentCommonIdentifiers(event.getIdentifiers()));
110124
processEvent(event);
111125
}
112126

113-
private Map<String, Object> augmentCommonData(Map<String, Object> sourceData) {
127+
@VisibleForTesting
128+
Map<String, Object> augmentCommonData(Map<String, Object> sourceData) {
129+
// priority: sourceData > userCommonData > sdkCommonData
130+
114131
Map<String, Object> data = new HashMap<>();
115132
data.put("idempotence_id", UUID.randomUUID().toString());
116133
data.put("data_source_type", "sdk");
117134
data.put("data_source", ClientEngineInfo.getClientEngine().getClientEngineValue());
118135
data.put("data_source_version", BuildVersionInfo.getClientVersion());
136+
137+
data.putAll(userCommonData);
119138
data.putAll(sourceData);
120139
return data;
121140
}
122141

142+
@VisibleForTesting
143+
Map<String, String> augmentCommonIdentifiers(Map<String, String> sourceIdentifiers) {
144+
// priority: sourceIdentifiers > userCommonIdentifiers
145+
146+
Map<String, String> identifiers = new HashMap<>();
147+
identifiers.putAll(userCommonIdentifiers);
148+
identifiers.putAll(sourceIdentifiers);
149+
return identifiers;
150+
}
151+
123152
private void processEvent(ODPEvent event) {
124153
if (!isRunning) {
125154
logger.warn("Failed to Process ODP Event. ODPEventManager is not running");

core-api/src/main/java/com/optimizely/ab/odp/ODPManager.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
import org.slf4j.LoggerFactory;
2222

2323
import javax.annotation.Nonnull;
24+
import java.util.Collections;
2425
import java.util.List;
26+
import java.util.Map;
2527
import java.util.Set;
2628

2729
public class ODPManager implements AutoCloseable {
@@ -77,6 +79,8 @@ public static class Builder {
7779
private Integer cacheSize;
7880
private Integer cacheTimeoutSeconds;
7981
private Cache<List<String>> cacheImpl;
82+
private Map<String, Object> userCommonData;
83+
private Map<String, String> userCommonIdentifiers;
8084

8185
/**
8286
* Provide a custom {@link ODPManager} instance which makes http calls to fetch segments and send events.
@@ -156,6 +160,32 @@ public Builder withSegmentCache(Cache<List<String>> cacheImpl) {
156160
return this;
157161
}
158162

163+
/**
164+
* Provide an optional group of user data that should be included in all ODP events.
165+
*
166+
* Note that this is in addition to the default data that is automatically included in all ODP events by this SDK (sdk-name, sdk-version, etc).
167+
*
168+
* @param commonData A key-value map of common user data.
169+
* @return ODPManager builder
170+
*/
171+
public Builder withUserCommonData(@Nonnull Map<String, Object> commonData) {
172+
this.userCommonData = commonData;
173+
return this;
174+
}
175+
176+
/**
177+
* Provide an optional group of identifiers that should be included in all ODP events.
178+
*
179+
* Note that this is in addition to the identifiers that is automatically included in all ODP events by this SDK.
180+
*
181+
* @param commonIdentifiers A key-value map of common identifiers.
182+
* @return ODPManager builder
183+
*/
184+
public Builder withUserCommonIdentifiers(@Nonnull Map<String, String> commonIdentifiers) {
185+
this.userCommonIdentifiers = commonIdentifiers;
186+
return this;
187+
}
188+
159189
public ODPManager build() {
160190
if ((segmentManager == null || eventManager == null) && apiManager == null) {
161191
logger.warn("ApiManager instance is needed when using default EventManager or SegmentManager");
@@ -182,6 +212,8 @@ public ODPManager build() {
182212
if (eventManager == null) {
183213
eventManager = new ODPEventManager(apiManager);
184214
}
215+
eventManager.setUserCommonData(userCommonData);
216+
eventManager.setUserCommonIdentifiers(userCommonIdentifiers);
185217

186218
return new ODPManager(segmentManager, eventManager);
187219
}

core-api/src/main/java/com/optimizely/ab/optimizelyconfig/OptimizelyFeature.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/****************************************************************************
2-
* Copyright 2020-2021, Optimizely, Inc. and contributors *
2+
* Copyright 2020-2021, 2023, Optimizely, Inc. and contributors *
33
* *
44
* Licensed under the Apache License, Version 2.0 (the "License"); *
55
* you may not use this file except in compliance with the License. *
@@ -63,6 +63,8 @@ public String getKey() {
6363

6464
/**
6565
* @deprecated use {@link #getExperimentRules()} and {@link #getDeliveryRules()} instead
66+
*
67+
* @return a map of ExperimentKey to OptimizelyExperiment
6668
*/
6769
@Deprecated
6870
public Map<String, OptimizelyExperiment> getExperimentsMap() {

core-api/src/test/java/com/optimizely/ab/OptimizelyBuilderTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import com.optimizely.ab.event.EventHandler;
2424
import com.optimizely.ab.event.LogEvent;
2525
import com.optimizely.ab.event.internal.BuildVersionInfo;
26+
import com.optimizely.ab.event.internal.ClientEngineInfo;
27+
import com.optimizely.ab.event.internal.payload.Event;
2628
import com.optimizely.ab.event.internal.payload.EventBatch;
2729
import com.optimizely.ab.odp.ODPEventManager;
2830
import com.optimizely.ab.odp.ODPManager;
@@ -241,6 +243,10 @@ public void withClientInfo() throws Exception {
241243
verify(eventHandler, timeout(5000)).dispatchEvent(argument.capture());
242244
assertEquals(argument.getValue().getEventBatch().getClientName(), "android-sdk");
243245
assertEquals(argument.getValue().getEventBatch().getClientVersion(), "1.2.3");
246+
247+
// restore the default values for other tests
248+
ClientEngineInfo.setClientEngine(ClientEngineInfo.DEFAULT);
249+
BuildVersionInfo.setClientVersion(BuildVersionInfo.VERSION);
244250
}
245251

246252
@Test

0 commit comments

Comments
 (0)