Skip to content

Commit 52f5f6d

Browse files
authored
[FSSDK-9432] fix: fix to support arbitrary client names to be included in logx and odp events. (#459)
support configurable sdk name and version
1 parent 9b5fe75 commit 52f5f6d

File tree

10 files changed

+140
-45
lines changed

10 files changed

+140
-45
lines changed

android-sdk/src/androidTest/java/com/optimizely/ab/android/sdk/ODPIntegrationUpdateConfigTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,9 @@ public void setup() throws Exception {
117117
notificationCenter,
118118
null,
119119
odpManager,
120-
"test-vuid");
120+
"test-vuid",
121+
null,
122+
null);
121123
}
122124

123125
@Test

android-sdk/src/androidTest/java/com/optimizely/ab/android/sdk/OptimizelyClientEngineTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,20 @@
3535
@RunWith(AndroidJUnit4.class)
3636
public class OptimizelyClientEngineTest {
3737
@Test
38-
public void testGetClientEngineFromContextAndroidTV() {
38+
public void testGetClientEngineNameFromContextAndroidTV() {
3939
Context context = mock(Context.class);
4040
UiModeManager uiModeManager = mock(UiModeManager.class);
4141
when(context.getSystemService(Context.UI_MODE_SERVICE)).thenReturn(uiModeManager);
4242
when(uiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_TELEVISION);
43-
assertEquals(EventBatch.ClientEngine.ANDROID_TV_SDK, OptimizelyClientEngine.getClientEngineFromContext(context));
43+
assertEquals("android-tv-sdk", OptimizelyClientEngine.getClientEngineNameFromContext(context));
4444
}
4545

4646
@Test
47-
public void testGetClientEngineFromContextAndroid() {
47+
public void testGetClientEngineNameFromContextAndroid() {
4848
Context context = mock(Context.class);
4949
UiModeManager uiModeManager = mock(UiModeManager.class);
5050
when(context.getSystemService(Context.UI_MODE_SERVICE)).thenReturn(uiModeManager);
5151
when(uiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_NORMAL);
52-
assertEquals(EventBatch.ClientEngine.ANDROID_SDK, OptimizelyClientEngine.getClientEngineFromContext(context));
52+
assertEquals("android-sdk", OptimizelyClientEngine.getClientEngineNameFromContext(context));
5353
}
5454
}

android-sdk/src/androidTest/java/com/optimizely/ab/android/sdk/OptimizelyManagerEventHandlerTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,25 @@ public void eventClientNameAndVersion() throws Exception {
6565
assertEquals(argument.getValue().getEventBatch().getClientVersion(), BuildConfig.CLIENT_VERSION);
6666
}
6767

68+
@Test
69+
public void eventClientWithCustomNameAndVersion() throws Exception {
70+
EventHandler mockEventHandler = mock(EventHandler.class);
71+
72+
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
73+
OptimizelyManager optimizelyManager = OptimizelyManager.builder()
74+
.withSDKKey("any-sdk-key")
75+
.withEventDispatchInterval(0, TimeUnit.SECONDS)
76+
.withEventHandler(mockEventHandler)
77+
.withClientInfo("test-sdk", "test-version")
78+
.build(context);
79+
80+
OptimizelyClient optimizelyClient = optimizelyManager.initialize(context, minDatafileWithEvent);
81+
optimizelyClient.track("test_event", "tester");
82+
83+
ArgumentCaptor<LogEvent> argument = ArgumentCaptor.forClass(LogEvent.class);
84+
verify(mockEventHandler, timeout(5000)).dispatchEvent(argument.capture());
85+
assertEquals(argument.getValue().getEventBatch().getClientName(), "test-sdk");
86+
assertEquals(argument.getValue().getEventBatch().getClientVersion(), "test-version");
87+
}
88+
6889
}

android-sdk/src/androidTest/java/com/optimizely/ab/android/sdk/OptimizelyManagerTest.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ public void initializeSyncWithEnvironment() {
163163
EventHandler eventHandler = mock(DefaultEventHandler.class);
164164
EventProcessor eventProcessor = mock(EventProcessor.class);
165165
OptimizelyManager optimizelyManager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, 3600L, datafileHandler, null, 3600L,
166-
eventHandler, eventProcessor, null, null, null, null, null);
166+
eventHandler, eventProcessor, null, null, null, null, null, null, null);
167167
/*
168168
* Scenario#1: when datafile is not Empty
169169
* Scenario#2: when datafile is Empty
@@ -222,7 +222,7 @@ public void initializeAsyncWithEnvironment() {
222222
EventHandler eventHandler = mock(DefaultEventHandler.class);
223223
EventProcessor eventProcessor = mock(EventProcessor.class);
224224
final OptimizelyManager optimizelyManager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, 3600L, datafileHandler, null, 3600L,
225-
eventHandler, eventProcessor, null, null, null, null, null);
225+
eventHandler, eventProcessor, null, null, null, null, null, null, null);
226226

227227
/*
228228
* Scenario#1: when datafile is not Empty
@@ -494,7 +494,7 @@ public void initializeSyncWithUpdateOnNewDatafileDisabled() {
494494
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
495495

496496
OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
497-
null, null, null, null, null, null, null);
497+
null, null, null, null, null, null, null, null, null);
498498

499499
doAnswer(
500500
new Answer<Object>() {
@@ -527,7 +527,7 @@ public void initializeSyncWithUpdateOnNewDatafileEnabled() {
527527
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
528528

529529
OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
530-
null, null, null, null, null, null, null);
530+
null, null, null, null, null, null, null, null, null);
531531

532532
doAnswer(
533533
new Answer<Object>() {
@@ -560,7 +560,7 @@ public void initializeSyncWithDownloadToCacheDisabled() {
560560
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
561561

562562
OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
563-
null, null, null, null, null, null, null);
563+
null, null, null, null, null, null, null, null, null);
564564

565565
doAnswer(
566566
new Answer<Object>() {
@@ -593,7 +593,7 @@ public void initializeSyncWithUpdateOnNewDatafileDisabledWithPeriodicPollingEnab
593593
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
594594

595595
OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
596-
null, null, null, null, null, null, null);
596+
null, null, null, null, null, null, null, null, null);
597597

598598
doAnswer(
599599
(Answer<Object>) invocation -> {
@@ -625,7 +625,7 @@ public void initializeSyncWithUpdateOnNewDatafileEnabledWithPeriodicPollingEnabl
625625
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
626626

627627
OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
628-
null, null, null, null, null, null, null);
628+
null, null, null, null, null, null, null, null, null);
629629

630630
doAnswer(
631631
new Answer<Object>() {
@@ -658,7 +658,7 @@ public void initializeSyncWithUpdateOnNewDatafileDisabledWithPeriodicPollingDisa
658658
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
659659

660660
OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
661-
null, null, null, null, null, null, null);
661+
null, null, null, null, null, null, null, null, null);
662662

663663
doAnswer(
664664
new Answer<Object>() {
@@ -692,7 +692,7 @@ public void initializeSyncWithUpdateOnNewDatafileEnabledWithPeriodicPollingDisab
692692
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
693693

694694
OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
695-
null, null, null, null, null, null, null);
695+
null, null, null, null, null, null, null, null, null);
696696

697697
doAnswer(
698698
new Answer<Object>() {
@@ -725,7 +725,7 @@ public void initializeSyncWithResourceDatafileNoCache() {
725725
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
726726

727727
OptimizelyManager manager = spy(new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
728-
null, null, null, null, null, null, null));
728+
null, null, null, null, null, null, null, null, null));
729729

730730
datafileHandler.removeSavedDatafile(context, manager.getDatafileConfig());
731731
OptimizelyClient client = manager.initialize(context, R.raw.datafile, downloadToCache, updateConfigOnNewDatafile);
@@ -742,7 +742,7 @@ public void initializeSyncWithResourceDatafileNoCacheWithDefaultParams() {
742742
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
743743

744744
OptimizelyManager manager = spy(new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
745-
null, null, null, null, null, null, null));
745+
null, null, null, null, null, null, null, null, null));
746746

747747
datafileHandler.removeSavedDatafile(context, manager.getDatafileConfig());
748748
OptimizelyClient client = manager.initialize(context, R.raw.datafile);

android-sdk/src/main/java/com/optimizely/ab/android/sdk/OptimizelyClientEngine.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,30 @@
2828
*/
2929
public class OptimizelyClientEngine {
3030

31+
/**
32+
* Get client engine name for current UI mode type
33+
*
34+
* @param context any valid Android {@link Context}
35+
* @return client engine name ("android-sdk" or "android-tv-sdk")
36+
*/
37+
public static String getClientEngineNameFromContext(@NonNull Context context) {
38+
UiModeManager uiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE);
39+
40+
if (uiModeManager != null && uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
41+
return "android-tv-sdk";
42+
}
43+
44+
return "android-sdk";
45+
}
46+
3147
/**
3248
* Get client engine value for current UI mode type
3349
*
3450
* @param context any valid Android {@link Context}
3551
* @return String value of client engine
52+
* @deprecated Consider using {@link #getClientEngineNameFromContext(Context, Integer, OptimizelyStartListener)}
3653
*/
54+
@Deprecated
3755
public static EventBatch.ClientEngine getClientEngineFromContext(@NonNull Context context) {
3856
UiModeManager uiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE);
3957

android-sdk/src/main/java/com/optimizely/ab/android/sdk/OptimizelyManager.java

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ public class OptimizelyManager {
9999
@Nullable private OptimizelyStartListener optimizelyStartListener;
100100

101101
@Nullable private final List<OptimizelyDecideOption> defaultDecideOptions;
102-
private String sdkVersion = null;
102+
private String customSdkName = null;
103+
private String customSdkVersion = null;
103104

104105
OptimizelyManager(@Nullable String projectId,
105106
@Nullable String sdkKey,
@@ -115,7 +116,9 @@ public class OptimizelyManager {
115116
@NonNull NotificationCenter notificationCenter,
116117
@Nullable List<OptimizelyDecideOption> defaultDecideOptions,
117118
@Nullable ODPManager odpManager,
118-
@Nullable String vuid) {
119+
@Nullable String vuid,
120+
@Nullable String clientEngineName,
121+
@Nullable String clientVersion) {
119122

120123
if (projectId == null && sdkKey == null) {
121124
logger.error("projectId and sdkKey are both null!");
@@ -141,12 +144,8 @@ public class OptimizelyManager {
141144
this.notificationCenter = notificationCenter;
142145
this.defaultDecideOptions = defaultDecideOptions;
143146

144-
try {
145-
sdkVersion = BuildConfig.CLIENT_VERSION;
146-
logger.info("SDK Version: {}", sdkVersion);
147-
} catch (Exception e) {
148-
logger.warn("Error getting BuildConfig version");
149-
}
147+
this.customSdkName = clientEngineName;
148+
this.customSdkVersion = clientVersion;
150149
}
151150

152151
@VisibleForTesting
@@ -514,6 +513,29 @@ public DatafileHandler getDatafileHandler() {
514513
return datafileHandler;
515514
}
516515

516+
@NonNull
517+
public String getSdkName(Context context) {
518+
String sdkName = customSdkName;
519+
if (sdkName == null) {
520+
sdkName = OptimizelyClientEngine.getClientEngineNameFromContext(context);
521+
}
522+
return sdkName;
523+
}
524+
525+
@NonNull
526+
public String getSdkVersion() {
527+
String sdkVersion = customSdkVersion;
528+
if (sdkVersion == null) {
529+
try {
530+
sdkVersion = BuildConfig.CLIENT_VERSION;
531+
} catch (Exception e) {
532+
logger.warn("Error getting BuildConfig version");
533+
sdkVersion = "UNKNOWN";
534+
}
535+
}
536+
return sdkVersion;
537+
}
538+
517539
private boolean datafileDownloadEnabled() {
518540
return datafileDownloadInterval > 0;
519541
}
@@ -577,7 +599,8 @@ public void onStartComplete(UserProfileService userProfileService) {
577599
private OptimizelyClient buildOptimizely(@NonNull Context context, @NonNull String datafile) throws ConfigParseException {
578600
EventHandler eventHandler = getEventHandler(context);
579601

580-
EventBatch.ClientEngine clientEngine = OptimizelyClientEngine.getClientEngineFromContext(context);
602+
String sdkName = getSdkName(context);
603+
String sdkVersion = getSdkVersion();
581604

582605
Optimizely.Builder builder = Optimizely.builder();
583606

@@ -594,7 +617,8 @@ private OptimizelyClient buildOptimizely(@NonNull Context context, @NonNull Stri
594617
}
595618

596619
// override client sdk name/version to be included in events
597-
builder.withClientInfo(clientEngine, sdkVersion);
620+
builder.withClientInfo(sdkName, sdkVersion);
621+
logger.info("SDK name: {} and version: {}", sdkName, sdkVersion);
598622

599623
if (errorHandler != null) {
600624
builder.withErrorHandler(errorHandler);
@@ -747,6 +771,9 @@ public static class Builder {
747771
private boolean odpEnabled = true;
748772
private String vuid = null;
749773

774+
private String customSdkName = null;
775+
private String customSdkVersion = null;
776+
750777
@Deprecated
751778
/**
752779
* @deprecated use {@link #Builder()} instead and pass in an SDK Key with {@link #withSDKKey(String)}
@@ -991,6 +1018,18 @@ public Builder withVuid(String vuid) {
9911018
return this;
9921019
}
9931020

1021+
/**
1022+
* Override the SDK name and version (for client SDKs like flutter-sdk wrapping the core android-sdk) to be included in events.
1023+
*
1024+
* @param clientEngineName the client engine name ("flutter/android-sdk", etc.).
1025+
* @param clientVersion the client SDK version.
1026+
* @return this {@link Builder} instance
1027+
*/
1028+
public Builder withClientInfo(@Nullable String clientEngineName, @Nullable String clientVersion) {
1029+
this.customSdkName = clientEngineName;
1030+
this.customSdkVersion = clientVersion;
1031+
return this;
1032+
}
9941033
/**
9951034
* Get a new {@link Builder} instance to create {@link OptimizelyManager} with.
9961035
* @param context the application context used to create default service if not provided.
@@ -1103,7 +1142,10 @@ public OptimizelyManager build(Context context) {
11031142
notificationCenter,
11041143
defaultDecideOptions,
11051144
odpManager,
1106-
vuid);
1145+
vuid,
1146+
customSdkName,
1147+
customSdkVersion
1148+
);
11071149
}
11081150
}
11091151
}

android-sdk/src/test/java/com/optimizely/ab/android/sdk/OptimizelyManagerBuilderTest.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -216,18 +216,14 @@ public void testBuildWithDatafileDownloadInterval_workerCancelledWhenIntervalIsN
216216
}
217217

218218
@Test
219-
public void testBuildWithDatafileDownloadInterval_workerCancelledWhenNoIntervalProvided() throws Exception {
219+
public void testBuildWithCustomSdkNameAndVersion() throws Exception {
220220
OptimizelyManager manager = OptimizelyManager.builder()
221-
.withSDKKey(testSdkKey)
222-
.withDatafileHandler(mockDatafileHandler)
223-
.withVuid("any-to-avoid-generate")
224-
.build(mockContext);
225-
OptimizelyManager spyManager = spy(manager);
226-
when(spyManager.isAndroidVersionSupported()).thenReturn(true);
227-
spyManager.initialize(mockContext, "");
228-
229-
verify(mockDatafileHandler).stopBackgroundUpdates(any(), any());
230-
verify(mockDatafileHandler, never()).startBackgroundUpdates(any(), any(), any(), any());
221+
.withSDKKey(testSdkKey)
222+
.withClientInfo("test-sdk", "test-version")
223+
.withVuid("any-to-avoid-generate")
224+
.build(mockContext);
225+
assertEquals(manager.getSdkName(mockContext), "test-sdk");
226+
assertEquals(manager.getSdkVersion(), "test-version");
231227
}
232228

233229
@Test
@@ -254,7 +250,9 @@ public void testBuildWithDefaultODP_defaultEnabled() throws Exception {
254250
any(NotificationCenter.class),
255251
any(), // nullable (DefaultDecideOptions)
256252
any(ODPManager.class),
257-
eq("test-vuid"));
253+
eq("test-vuid"),
254+
any(),
255+
any());
258256
}
259257

260258
@Test
@@ -282,7 +280,9 @@ public void testBuildWithDefaultODP_disabled() throws Exception {
282280
any(NotificationCenter.class),
283281
any(), // nullable (DefaultDecideOptions)
284282
isNull(),
285-
eq("test-vuid"));
283+
eq("test-vuid"),
284+
any(),
285+
any());
286286
}
287287

288288
@Test

0 commit comments

Comments
 (0)