Skip to content

[FSSDK-9358] chore: add flutter specific client name support to track event #72

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jan 26, 2024
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
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ dependencies {
implementation 'org.slf4j:slf4j-api:2.0.7'

implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.10"
implementation "com.optimizely.ab:android-sdk:4.0.0-beta2"
implementation "com.optimizely.ab:android-sdk:4.0.0"
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4'
implementation ('com.google.guava:guava:19.0') {
exclude group:'com.google.guava', module:'listenablefuture'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ public class OptimizelyFlutterClient {

protected void initializeOptimizely(@NonNull ArgumentsParser argumentsParser, @NonNull Result result) {
String sdkKey = argumentsParser.getSdkKey();
String sdkName = Utils.sdkName;
String sdkVersion = argumentsParser.getSdkVersion();
if (sdkKey == null) {
result.success(createResponse(ErrorMessage.INVALID_PARAMS));
return;
Expand Down Expand Up @@ -172,7 +174,8 @@ protected void initializeOptimizely(@NonNull ArgumentsParser argumentsParser, @N
.withODPSegmentCacheTimeout(segmentsCacheTimeoutInSecs, TimeUnit.SECONDS)
.withTimeoutForODPSegmentFetch(timeoutForSegmentFetchInSecs)
.withTimeoutForODPEventDispatch(timeoutForOdpEventInSecs)
.withSDKKey(sdkKey);
.withSDKKey(sdkKey)
.withClientInfo(sdkName, sdkVersion);
if (disableOdp) {
optimizelyManagerBuilder.withODPDisabled();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ public ArgumentsParser(Map<String, ?> arguments) {
public String getSdkKey() {
return (String) arguments.get(Constants.RequestParameterKey.SDK_KEY);
}

public String getSdkVersion() {
return (String) arguments.get(Constants.RequestParameterKey.SDK_VERSION);
}

public Integer getNotificationID() {
return (Integer) arguments.get(Constants.RequestParameterKey.NOTIFICATION_ID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public static class NotificationType {

public static class RequestParameterKey {
public static final String SDK_KEY = "sdkKey";
public static final String SDK_VERSION = "sdkVersion";
public static final String USER_ID = "userId";
public static final String USER_CONTEXT_ID = "userContextId";
public static final String NOTIFICATION_ID = "id";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
import ch.qos.logback.classic.Logger;

public class Utils {

public static String sdkName = "flutter/android-sdk";

public static String getRandomUUID() {
return UUID.randomUUID().toString();
}
Expand Down
2 changes: 1 addition & 1 deletion example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ buildscript {
}
}
ext {
android_sdk_version = "4.0.0-beta3"
android_sdk_version = "4.0.0"
}
allprojects {
repositories {
Expand Down
1 change: 1 addition & 0 deletions ios/Classes/HelperClasses/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ struct RequestParameterKey {
static let timeoutForSegmentFetchInSecs = "timeoutForSegmentFetchInSecs"
static let timeoutForOdpEventInSecs = "timeoutForOdpEventInSecs"
static let disableOdp = "disableOdp"
static let sdkVersion = "sdkVersion";
}

struct ResponseKey {
Expand Down
2 changes: 1 addition & 1 deletion ios/Classes/HelperClasses/Utils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import Foundation
import Optimizely

public class Utils: NSObject {

static var sdkName = "flutter/swift-sdk"
/// Converts and returns dart map to native map
static func getTypedMap(arguments: Any?) -> [String: Any]? {
guard let args = arguments as? Dictionary<String, Any?> else {
Expand Down
5 changes: 4 additions & 1 deletion ios/Classes/SwiftOptimizelyFlutterSdkPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ public class SwiftOptimizelyFlutterSdkPlugin: NSObject, FlutterPlugin {
var timeoutForSegmentFetchInSecs: Int = 10
var timeoutForOdpEventInSecs: Int = 10
var disableOdp: Bool = false
var sdkVersion = parameters[RequestParameterKey.sdkVersion] as? String
var sdkName = Utils.sdkName

if let sdkSettings = parameters[RequestParameterKey.optimizelySdkSettings] as? Dictionary<String, Any?> {
if let cacheSize = sdkSettings[RequestParameterKey.segmentsCacheSize] as? Int {
segmentsCacheSize = cacheSize
Expand All @@ -135,7 +138,7 @@ public class SwiftOptimizelyFlutterSdkPlugin: NSObject, FlutterPlugin {
disableOdp = isOdpDisabled
}
}
let optimizelySdkSettings = OptimizelySdkSettings(segmentsCacheSize: segmentsCacheSize, segmentsCacheTimeoutInSecs: segmentsCacheTimeoutInSecs, timeoutForSegmentFetchInSecs: timeoutForSegmentFetchInSecs, timeoutForOdpEventInSecs: timeoutForOdpEventInSecs, disableOdp: disableOdp)
let optimizelySdkSettings = OptimizelySdkSettings(segmentsCacheSize: segmentsCacheSize, segmentsCacheTimeoutInSecs: segmentsCacheTimeoutInSecs, timeoutForSegmentFetchInSecs: timeoutForSegmentFetchInSecs, timeoutForOdpEventInSecs: timeoutForOdpEventInSecs, disableOdp: disableOdp, sdkName: sdkName, sdkVersion: sdkVersion)

// Datafile Download Interval
var datafilePeriodicDownloadInterval = 10 * 60 // seconds
Expand Down
2 changes: 1 addition & 1 deletion ios/optimizely_flutter_sdk.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Pod::Spec.new do |s|
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.dependency 'Flutter'
s.dependency 'OptimizelySwiftSDK', '4.0.0-beta'
s.dependency 'OptimizelySwiftSDK', '4.0.0'
s.platform = :ios, '10.0'
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
Expand Down
7 changes: 7 additions & 0 deletions lib/package_info.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Purpose: Package information for the Optimizely Flutter SDK
// Note: This info should be synced with pubspec.yaml

class PackageInfo {
static const String name = 'optimizely_flutter_sdk';
static const String version = '2.0.0-beta';
}
4 changes: 4 additions & 0 deletions lib/src/optimizely_client_wrapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:optimizely_flutter_sdk/optimizely_flutter_sdk.dart';
import 'package:optimizely_flutter_sdk/package_info.dart';
import 'package:optimizely_flutter_sdk/src/data_objects/activate_listener_response.dart';
import 'package:optimizely_flutter_sdk/src/data_objects/activate_response.dart';
import 'package:optimizely_flutter_sdk/src/data_objects/base_response.dart';
Expand Down Expand Up @@ -66,8 +67,11 @@ class OptimizelyClientWrapper {
_channel.setMethodCallHandler(methodCallHandler);
final convertedOptions = Utils.convertDecideOptions(defaultDecideOptions);
final convertedLogLevel = Utils.convertLogLevel(defaultLogLevel);
final sdkVersion = PackageInfo.version;

Map<String, dynamic> requestDict = {
Constants.sdkKey: sdkKey,
Constants.sdkVersion: sdkVersion,
Constants.datafilePeriodicDownloadInterval:
datafilePeriodicDownloadInterval,
Constants.optimizelyDecideOption: convertedOptions,
Expand Down
1 change: 1 addition & 0 deletions lib/src/utils/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class Constants {
// Request parameter keys
static const String id = "id";
static const String sdkKey = "sdkKey";
static const String sdkVersion = "sdkVersion";
static const String userContextId = "userContextId";
static const String userContext = "userContext";
static const String experiment = "experiment";
Expand Down
2 changes: 1 addition & 1 deletion lib/src/utils/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
///**************************************************************************/

import 'dart:io' show Platform;

import 'package:optimizely_flutter_sdk/src/user_context/optimizely_user_context.dart';
import 'package:optimizely_flutter_sdk/src/utils/constants.dart';
import 'package:optimizely_flutter_sdk/src/data_objects/log_level.dart';
Expand Down Expand Up @@ -101,4 +100,5 @@ class Utils {
// OptimizelyLogLevel.debug -> "debug"
return logLevel.toString().split('.').last;
}

}
76 changes: 74 additions & 2 deletions test/optimizely_flutter_sdk_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import 'package:optimizely_flutter_sdk/src/utils/constants.dart';
import 'package:optimizely_flutter_sdk/src/utils/utils.dart';
import 'dart:io';
import 'dart:convert';

import 'test_utils.dart';

void main() {
Expand Down Expand Up @@ -557,7 +556,8 @@ void main() {
});

test("with a valid defaultLogLevel parameter", () async {
var sdk = OptimizelyFlutterSdk(testSDKKey, defaultLogLevel: OptimizelyLogLevel.debug);
var sdk = OptimizelyFlutterSdk(testSDKKey,
defaultLogLevel: OptimizelyLogLevel.debug);

var response = await sdk.initializeClient();

Expand Down Expand Up @@ -1553,4 +1553,76 @@ void main() {
});
});
});

group("Test client_name and client_version event parsing", () {
test("Test track event with swift sdk name and version", () async {
var sdk = OptimizelyFlutterSdk(testSDKKey);

TrackListenerResponse? response;

await sdk.addTrackNotificationListener((msg) {
response = msg;
});
var callHandler = OptimizelyClientWrapper.methodCallHandler;
tester?.setMockMethodCallHandler(channel, callHandler);
TestUtils.sendTestTrackClientNameAndVersion(
callHandler, 0, testSDKKey, "flutter/swift-sdk", "2.0.0");

expect(response == null, false);

expect(response!.eventTags!["client_name"], "flutter/swift-sdk");

});

test("Test track event with android sdk name and version", () async {
var sdk = OptimizelyFlutterSdk(testSDKKey);

var responses = [];

await sdk.addTrackNotificationListener((msg) {
responses.add(msg);
});

var callHandler = OptimizelyClientWrapper.methodCallHandler;
tester?.setMockMethodCallHandler(channel, callHandler);

TestUtils.sendTestTrackClientNameAndVersion(
callHandler, 0, testSDKKey, "flutter/swift-sdk", "2.0.0");
TestUtils.sendTestTrackClientNameAndVersion(
callHandler, 0, testSDKKey, "flutter/android-sdk", "2.0.0-beta");

expect(responses.length == 2, true);

expect(responses[0]!.eventTags!["client_name"], "flutter/swift-sdk");
expect(responses[0]!.eventTags!["client_version"], "2.0.0");
expect(responses[1]!.eventTags!["client_name"], "flutter/android-sdk");
expect(responses[1]!.eventTags!["client_version"], "2.0.0-beta");

});

test("Test log event with client sdk name and version", () async {
var sdk = OptimizelyFlutterSdk(testSDKKey);

var responses = [];

await sdk.addLogEventNotificationListener((msg) {
responses.add(msg);
});
var callHandler = OptimizelyClientWrapper.methodCallHandler;
tester?.setMockMethodCallHandler(channel, callHandler);
TestUtils.sendTestClientNameAndVersionLogEventNotification(
callHandler, 0, testSDKKey, "flutter/android-sdk", "2.0.0-beta");

TestUtils.sendTestClientNameAndVersionLogEventNotification(
callHandler, 0, testSDKKey, "flutter/swift-sdk", "2.0.0");

expect(responses.length == 2, true);

expect(responses[0]!.params!["client_name"], "flutter/android-sdk");
expect(responses[0]!.params!["client_version"], "2.0.0-beta");
expect(responses[1]!.params!["client_name"], "flutter/swift-sdk");
expect(responses[1]!.params!["client_version"], "2.0.0");
});

});
}
35 changes: 35 additions & 0 deletions test/test_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,23 @@ class TestUtils {
}));
}

static sendTestClientNameAndVersionLogEventNotification(
Function(MethodCall message) handler, int id, String sdkKey, String clientName, String sdkVersion) {
var payload = {
Constants.url: "$id",
Constants.params: {
"test": id,
"client_name": clientName,
"client_version": sdkVersion
}
};
handler(MethodCall(Constants.logEventCallbackListener, {
Constants.id: id,
Constants.sdkKey: sdkKey,
Constants.payload: payload
}));
}

static sendTestTrackNotifications(
Function(MethodCall message) handler, int id, String sdkKey) {
var payload = {
Expand All @@ -121,6 +138,24 @@ class TestUtils {
}));
}

static sendTestTrackClientNameAndVersion(Function(MethodCall message) handler, int id, String sdkKey, String clientName, String sdkVersion) {
var payload = {
Constants.eventKey: "$id",
Constants.userId: "test",
Constants.attributes: {"test": id},
Constants.eventTags: {
"testTag": id,
"client_name": clientName,
"client_version": sdkVersion
}
};
handler(MethodCall(Constants.trackCallBackListener, {
Constants.id: id,
Constants.sdkKey: sdkKey,
Constants.payload: payload
}));
}

static sendTestUpdateConfigNotifications(
Function(MethodCall message) handler, int id, String sdkKey) {
handler(MethodCall(Constants.configUpdateCallBackListener, {
Expand Down