Skip to content

Commit

Permalink
[FSSDK-9432] fix: fix to support arbitrary client names to be include…
Browse files Browse the repository at this point in the history
…d in logx and odp events. (#459)

support configurable sdk name and version
  • Loading branch information
jaeopt authored Aug 31, 2023
1 parent 9b5fe75 commit 52f5f6d
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ public void setup() throws Exception {
notificationCenter,
null,
odpManager,
"test-vuid");
"test-vuid",
null,
null);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,20 @@
@RunWith(AndroidJUnit4.class)
public class OptimizelyClientEngineTest {
@Test
public void testGetClientEngineFromContextAndroidTV() {
public void testGetClientEngineNameFromContextAndroidTV() {
Context context = mock(Context.class);
UiModeManager uiModeManager = mock(UiModeManager.class);
when(context.getSystemService(Context.UI_MODE_SERVICE)).thenReturn(uiModeManager);
when(uiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_TELEVISION);
assertEquals(EventBatch.ClientEngine.ANDROID_TV_SDK, OptimizelyClientEngine.getClientEngineFromContext(context));
assertEquals("android-tv-sdk", OptimizelyClientEngine.getClientEngineNameFromContext(context));
}

@Test
public void testGetClientEngineFromContextAndroid() {
public void testGetClientEngineNameFromContextAndroid() {
Context context = mock(Context.class);
UiModeManager uiModeManager = mock(UiModeManager.class);
when(context.getSystemService(Context.UI_MODE_SERVICE)).thenReturn(uiModeManager);
when(uiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_NORMAL);
assertEquals(EventBatch.ClientEngine.ANDROID_SDK, OptimizelyClientEngine.getClientEngineFromContext(context));
assertEquals("android-sdk", OptimizelyClientEngine.getClientEngineNameFromContext(context));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,25 @@ public void eventClientNameAndVersion() throws Exception {
assertEquals(argument.getValue().getEventBatch().getClientVersion(), BuildConfig.CLIENT_VERSION);
}

@Test
public void eventClientWithCustomNameAndVersion() throws Exception {
EventHandler mockEventHandler = mock(EventHandler.class);

Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
OptimizelyManager optimizelyManager = OptimizelyManager.builder()
.withSDKKey("any-sdk-key")
.withEventDispatchInterval(0, TimeUnit.SECONDS)
.withEventHandler(mockEventHandler)
.withClientInfo("test-sdk", "test-version")
.build(context);

OptimizelyClient optimizelyClient = optimizelyManager.initialize(context, minDatafileWithEvent);
optimizelyClient.track("test_event", "tester");

ArgumentCaptor<LogEvent> argument = ArgumentCaptor.forClass(LogEvent.class);
verify(mockEventHandler, timeout(5000)).dispatchEvent(argument.capture());
assertEquals(argument.getValue().getEventBatch().getClientName(), "test-sdk");
assertEquals(argument.getValue().getEventBatch().getClientVersion(), "test-version");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public void initializeSyncWithEnvironment() {
EventHandler eventHandler = mock(DefaultEventHandler.class);
EventProcessor eventProcessor = mock(EventProcessor.class);
OptimizelyManager optimizelyManager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, 3600L, datafileHandler, null, 3600L,
eventHandler, eventProcessor, null, null, null, null, null);
eventHandler, eventProcessor, null, null, null, null, null, null, null);
/*
* Scenario#1: when datafile is not Empty
* Scenario#2: when datafile is Empty
Expand Down Expand Up @@ -222,7 +222,7 @@ public void initializeAsyncWithEnvironment() {
EventHandler eventHandler = mock(DefaultEventHandler.class);
EventProcessor eventProcessor = mock(EventProcessor.class);
final OptimizelyManager optimizelyManager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, 3600L, datafileHandler, null, 3600L,
eventHandler, eventProcessor, null, null, null, null, null);
eventHandler, eventProcessor, null, null, null, null, null, null, null);

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

OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, null);

doAnswer(
new Answer<Object>() {
Expand Down Expand Up @@ -527,7 +527,7 @@ public void initializeSyncWithUpdateOnNewDatafileEnabled() {
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, null);

doAnswer(
new Answer<Object>() {
Expand Down Expand Up @@ -560,7 +560,7 @@ public void initializeSyncWithDownloadToCacheDisabled() {
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, null);

doAnswer(
new Answer<Object>() {
Expand Down Expand Up @@ -593,7 +593,7 @@ public void initializeSyncWithUpdateOnNewDatafileDisabledWithPeriodicPollingEnab
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, null);

doAnswer(
(Answer<Object>) invocation -> {
Expand Down Expand Up @@ -625,7 +625,7 @@ public void initializeSyncWithUpdateOnNewDatafileEnabledWithPeriodicPollingEnabl
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, null);

doAnswer(
new Answer<Object>() {
Expand Down Expand Up @@ -658,7 +658,7 @@ public void initializeSyncWithUpdateOnNewDatafileDisabledWithPeriodicPollingDisa
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, null);

doAnswer(
new Answer<Object>() {
Expand Down Expand Up @@ -692,7 +692,7 @@ public void initializeSyncWithUpdateOnNewDatafileEnabledWithPeriodicPollingDisab
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

OptimizelyManager manager = new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, null);

doAnswer(
new Answer<Object>() {
Expand Down Expand Up @@ -725,7 +725,7 @@ public void initializeSyncWithResourceDatafileNoCache() {
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

OptimizelyManager manager = spy(new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null));
null, null, null, null, null, null, null, null, null));

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

OptimizelyManager manager = spy(new OptimizelyManager(testProjectId, testSdkKey, null, logger, pollingInterval, datafileHandler, null, 0,
null, null, null, null, null, null, null));
null, null, null, null, null, null, null, null, null));

datafileHandler.removeSavedDatafile(context, manager.getDatafileConfig());
OptimizelyClient client = manager.initialize(context, R.raw.datafile);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,30 @@
*/
public class OptimizelyClientEngine {

/**
* Get client engine name for current UI mode type
*
* @param context any valid Android {@link Context}
* @return client engine name ("android-sdk" or "android-tv-sdk")
*/
public static String getClientEngineNameFromContext(@NonNull Context context) {
UiModeManager uiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE);

if (uiModeManager != null && uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
return "android-tv-sdk";
}

return "android-sdk";
}

/**
* Get client engine value for current UI mode type
*
* @param context any valid Android {@link Context}
* @return String value of client engine
* @deprecated Consider using {@link #getClientEngineNameFromContext(Context, Integer, OptimizelyStartListener)}
*/
@Deprecated
public static EventBatch.ClientEngine getClientEngineFromContext(@NonNull Context context) {
UiModeManager uiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ public class OptimizelyManager {
@Nullable private OptimizelyStartListener optimizelyStartListener;

@Nullable private final List<OptimizelyDecideOption> defaultDecideOptions;
private String sdkVersion = null;
private String customSdkName = null;
private String customSdkVersion = null;

OptimizelyManager(@Nullable String projectId,
@Nullable String sdkKey,
Expand All @@ -115,7 +116,9 @@ public class OptimizelyManager {
@NonNull NotificationCenter notificationCenter,
@Nullable List<OptimizelyDecideOption> defaultDecideOptions,
@Nullable ODPManager odpManager,
@Nullable String vuid) {
@Nullable String vuid,
@Nullable String clientEngineName,
@Nullable String clientVersion) {

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

try {
sdkVersion = BuildConfig.CLIENT_VERSION;
logger.info("SDK Version: {}", sdkVersion);
} catch (Exception e) {
logger.warn("Error getting BuildConfig version");
}
this.customSdkName = clientEngineName;
this.customSdkVersion = clientVersion;
}

@VisibleForTesting
Expand Down Expand Up @@ -514,6 +513,29 @@ public DatafileHandler getDatafileHandler() {
return datafileHandler;
}

@NonNull
public String getSdkName(Context context) {
String sdkName = customSdkName;
if (sdkName == null) {
sdkName = OptimizelyClientEngine.getClientEngineNameFromContext(context);
}
return sdkName;
}

@NonNull
public String getSdkVersion() {
String sdkVersion = customSdkVersion;
if (sdkVersion == null) {
try {
sdkVersion = BuildConfig.CLIENT_VERSION;
} catch (Exception e) {
logger.warn("Error getting BuildConfig version");
sdkVersion = "UNKNOWN";
}
}
return sdkVersion;
}

private boolean datafileDownloadEnabled() {
return datafileDownloadInterval > 0;
}
Expand Down Expand Up @@ -577,7 +599,8 @@ public void onStartComplete(UserProfileService userProfileService) {
private OptimizelyClient buildOptimizely(@NonNull Context context, @NonNull String datafile) throws ConfigParseException {
EventHandler eventHandler = getEventHandler(context);

EventBatch.ClientEngine clientEngine = OptimizelyClientEngine.getClientEngineFromContext(context);
String sdkName = getSdkName(context);
String sdkVersion = getSdkVersion();

Optimizely.Builder builder = Optimizely.builder();

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

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

if (errorHandler != null) {
builder.withErrorHandler(errorHandler);
Expand Down Expand Up @@ -747,6 +771,9 @@ public static class Builder {
private boolean odpEnabled = true;
private String vuid = null;

private String customSdkName = null;
private String customSdkVersion = null;

@Deprecated
/**
* @deprecated use {@link #Builder()} instead and pass in an SDK Key with {@link #withSDKKey(String)}
Expand Down Expand Up @@ -991,6 +1018,18 @@ public Builder withVuid(String vuid) {
return this;
}

/**
* Override the SDK name and version (for client SDKs like flutter-sdk wrapping the core android-sdk) to be included in events.
*
* @param clientEngineName the client engine name ("flutter/android-sdk", etc.).
* @param clientVersion the client SDK version.
* @return this {@link Builder} instance
*/
public Builder withClientInfo(@Nullable String clientEngineName, @Nullable String clientVersion) {
this.customSdkName = clientEngineName;
this.customSdkVersion = clientVersion;
return this;
}
/**
* Get a new {@link Builder} instance to create {@link OptimizelyManager} with.
* @param context the application context used to create default service if not provided.
Expand Down Expand Up @@ -1103,7 +1142,10 @@ public OptimizelyManager build(Context context) {
notificationCenter,
defaultDecideOptions,
odpManager,
vuid);
vuid,
customSdkName,
customSdkVersion
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -216,18 +216,14 @@ public void testBuildWithDatafileDownloadInterval_workerCancelledWhenIntervalIsN
}

@Test
public void testBuildWithDatafileDownloadInterval_workerCancelledWhenNoIntervalProvided() throws Exception {
public void testBuildWithCustomSdkNameAndVersion() throws Exception {
OptimizelyManager manager = OptimizelyManager.builder()
.withSDKKey(testSdkKey)
.withDatafileHandler(mockDatafileHandler)
.withVuid("any-to-avoid-generate")
.build(mockContext);
OptimizelyManager spyManager = spy(manager);
when(spyManager.isAndroidVersionSupported()).thenReturn(true);
spyManager.initialize(mockContext, "");

verify(mockDatafileHandler).stopBackgroundUpdates(any(), any());
verify(mockDatafileHandler, never()).startBackgroundUpdates(any(), any(), any(), any());
.withSDKKey(testSdkKey)
.withClientInfo("test-sdk", "test-version")
.withVuid("any-to-avoid-generate")
.build(mockContext);
assertEquals(manager.getSdkName(mockContext), "test-sdk");
assertEquals(manager.getSdkVersion(), "test-version");
}

@Test
Expand All @@ -254,7 +250,9 @@ public void testBuildWithDefaultODP_defaultEnabled() throws Exception {
any(NotificationCenter.class),
any(), // nullable (DefaultDecideOptions)
any(ODPManager.class),
eq("test-vuid"));
eq("test-vuid"),
any(),
any());
}

@Test
Expand Down Expand Up @@ -282,7 +280,9 @@ public void testBuildWithDefaultODP_disabled() throws Exception {
any(NotificationCenter.class),
any(), // nullable (DefaultDecideOptions)
isNull(),
eq("test-vuid"));
eq("test-vuid"),
any(),
any());
}

@Test
Expand Down
Loading

0 comments on commit 52f5f6d

Please sign in to comment.