From 70afc4f5097639f7e26fea7632d7d0e527fba4e1 Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Tue, 13 Jun 2023 16:05:17 -0700 Subject: [PATCH 1/8] add log-level configurable --- android/build.gradle | 4 +- .../OptimizelyFlutterClient.java | 4 ++ .../helper_classes/ArgumentsParser.java | 4 ++ .../helper_classes/Constants.java | 8 +++ .../helper_classes/Utils.java | 26 ++++++++ example/android/app/build.gradle | 4 +- example/ios/Podfile | 2 +- example/lib/main.dart | 1 + .../macos/Runner.xcodeproj/project.pbxproj | 62 ++++++++++++++++++- .../contents.xcworkspacedata | 3 + ios/Classes/HelperClasses/Constants.swift | 1 + ios/Classes/HelperClasses/Utils.swift | 13 ++++ .../SwiftOptimizelyFlutterSdkPlugin.swift | 21 ++++++- lib/optimizely_flutter_sdk.dart | 8 +++ lib/src/data_objects/log_levels.dart | 7 +++ lib/src/optimizely_client_wrapper.dart | 4 ++ lib/src/utils/constants.dart | 1 + 17 files changed, 166 insertions(+), 7 deletions(-) create mode 100644 lib/src/data_objects/log_levels.dart diff --git a/android/build.gradle b/android/build.gradle index df5b447..0807b43 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -75,7 +75,9 @@ android { dependencies { implementation 'androidx.multidex:multidex:2.0.0' implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' - implementation group: 'org.slf4j', name: 'slf4j-android', version: '1.7.25' + //implementation group: 'org.slf4j', name: 'slf4j-android', version: '1.7.25' + //implementation 'org.slf4j:slf4j-api:2.0.7' + implementation 'com.github.tony19:logback-android:3.0.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.10" implementation "com.optimizely.ab:android-sdk:4.0.0-beta2" implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8' diff --git a/android/src/main/java/com/optimizely/optimizely_flutter_sdk/OptimizelyFlutterClient.java b/android/src/main/java/com/optimizely/optimizely_flutter_sdk/OptimizelyFlutterClient.java index 8d0ca28..6ece8d4 100644 --- a/android/src/main/java/com/optimizely/optimizely_flutter_sdk/OptimizelyFlutterClient.java +++ b/android/src/main/java/com/optimizely/optimizely_flutter_sdk/OptimizelyFlutterClient.java @@ -97,6 +97,10 @@ protected void initializeOptimizely(@NonNull ArgumentsParser argumentsParser, @N maxQueueSize = argumentsParser.getEventMaxQueueSize(); } + if (argumentsParser.getDefaultLogLevel() != null) { + Utils.setDefaultLogLevel(argumentsParser.getDefaultLogLevel()); + } + DefaultEventHandler eventHandler = DefaultEventHandler.getInstance(context); eventHandler.setDispatchInterval(-1L); NotificationCenter notificationCenter = new NotificationCenter(); diff --git a/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/ArgumentsParser.java b/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/ArgumentsParser.java index 605b0aa..88087c7 100644 --- a/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/ArgumentsParser.java +++ b/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/ArgumentsParser.java @@ -72,6 +72,10 @@ public List getDecideOptions() { return Utils.getDecideOptions((List) arguments.get(Constants.RequestParameterKey.DECIDE_OPTIONS)); } + public String getDefaultLogLevel() { + return (String) arguments.get(Constants.RequestParameterKey.DEFAULT_LOG_LEVEL); + } + public String getFlagKey() { return (String) arguments.get(Constants.RequestParameterKey.FLAG_KEY); } diff --git a/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Constants.java b/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Constants.java index 2f200db..453b1d6 100644 --- a/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Constants.java +++ b/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Constants.java @@ -67,6 +67,7 @@ public static class RequestParameterKey { public static final String ATTRIBUTES = "attributes"; public static final String DECIDE_KEYS = "keys"; public static final String DECIDE_OPTIONS = "optimizelyDecideOption"; + public static final String DEFAULT_LOG_LEVEL = "defaultLogLevel"; public static final String EVENT_BATCH_SIZE = "eventBatchSize"; public static final String EVENT_TIME_INTERVAL = "eventTimeInterval"; public static final String EVENT_MAX_QUEUE_SIZE = "eventMaxQueueSize"; @@ -153,4 +154,11 @@ public static class SegmentOption { public static final String IGNORE_CACHE = "ignoreCache"; public static final String RESET_CACHE = "resetCache"; } + + public static class LogLevel { + public static final String ERROR = "error"; + public static final String WARNING = "warning"; + public static final String INFO = "info"; + public static final String DEBUG = "debug"; + } } diff --git a/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java b/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java index 76ec8c8..29cfcc9 100644 --- a/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java +++ b/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java @@ -31,6 +31,9 @@ import com.optimizely.ab.notification.UpdateConfigNotification; import com.optimizely.ab.odp.ODPSegmentOption; import com.optimizely.ab.optimizelydecision.OptimizelyDecideOption; +import org.slf4j.LoggerFactory; +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; public class Utils { @@ -104,4 +107,27 @@ public static Class getNotificationListenerType(String notificationType) { } return listenerClass; } + + public static Level mapLogLevel(String logLevel) { + Level level = Level.INFO; + + if (logLevel == null || logLevel.isEmpty()) { + return level; + } + + switch (logLevel) { + case Constants.LogLevel.ERROR: level = Level.ERROR; break; + case Constants.LogLevel.WARNING: level = Level.WARN; break; + case Constants.LogLevel.INFO: level = Level.INFO; break; + case Constants.LogLevel.DEBUG: level = Level.DEBUG; break; + default: {} + } + return level; + } + + public static void setDefaultLogLevel(String logLevel) { + Logger rootLogger = (Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME); + rootLogger.setLevel(Utils.mapLogLevel(logLevel)); + } + } diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index ceec9a6..89fc349 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion flutter.compileSdkVersion + compileSdkVersion 32 ndkVersion flutter.ndkVersion compileOptions { @@ -40,7 +40,7 @@ android { // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. minSdkVersion 21 - targetSdkVersion flutter.targetSdkVersion + targetSdkVersion 32 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/example/ios/Podfile b/example/ios/Podfile index 9411102..313ea4a 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '10.0' +platform :ios, '11.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/example/lib/main.dart b/example/lib/main.dart index a717223..e7db8fa 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -32,6 +32,7 @@ class _MyAppState extends State { datafilePeriodicDownloadInterval: 10 * 60, eventOptions: const EventOptions( batchSize: 1, timeInterval: 60, maxQueueSize: 10000), + defaultLogLevel: OptimizelyLogLevel.debug, defaultDecideOptions: defaultOptions); var response = await flutterSDK.initializeClient(); diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj index 154f82d..9f89128 100644 --- a/example/macos/Runner.xcodeproj/project.pbxproj +++ b/example/macos/Runner.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 90B9B075FD9D5B075E83BE96 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A8DB69DD1CEB9DE6D5A4070 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -52,9 +53,10 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 019D04A8C81D7599D2E638FA /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* optimizely_flutter_sdk_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "optimizely_flutter_sdk_example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* optimizely_flutter_sdk_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = optimizely_flutter_sdk_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -66,7 +68,10 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 5A8DB69DD1CEB9DE6D5A4070 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 7EEA78DE428A25C4C9195EC6 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 8D05B77804EBF39FD6D6D079 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ @@ -75,6 +80,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 90B9B075FD9D5B075E83BE96 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -99,6 +105,7 @@ 33CEB47122A05771004F2AC0 /* Flutter */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, + F74646C1D5F338EF32BE10E1 /* Pods */, ); sourceTree = ""; }; @@ -148,10 +155,22 @@ D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + 5A8DB69DD1CEB9DE6D5A4070 /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; }; + F74646C1D5F338EF32BE10E1 /* Pods */ = { + isa = PBXGroup; + children = ( + 7EEA78DE428A25C4C9195EC6 /* Pods-Runner.debug.xcconfig */, + 8D05B77804EBF39FD6D6D079 /* Pods-Runner.release.xcconfig */, + 019D04A8C81D7599D2E638FA /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -159,11 +178,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 834CC0346DE4E8E368DFDFD4 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + F96AA93D7120056FD027BD50 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -270,6 +291,45 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; + 834CC0346DE4E8E368DFDFD4 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + F96AA93D7120056FD027BD50 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/example/macos/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/example/macos/Runner.xcworkspace/contents.xcworkspacedata +++ b/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/ios/Classes/HelperClasses/Constants.swift b/ios/Classes/HelperClasses/Constants.swift index c674389..e5be618 100644 --- a/ios/Classes/HelperClasses/Constants.swift +++ b/ios/Classes/HelperClasses/Constants.swift @@ -90,6 +90,7 @@ struct RequestParameterKey { static let eventTags = "eventTags" static let reasons = "reasons" static let decideOptions = "optimizelyDecideOption" + static let defaultLogLevel = "defaultLogLevel" static let eventBatchSize = "eventBatchSize" static let eventTimeInterval = "eventTimeInterval" static let eventMaxQueueSize = "eventMaxQueueSize" diff --git a/ios/Classes/HelperClasses/Utils.swift b/ios/Classes/HelperClasses/Utils.swift index 82f858a..6cac144 100644 --- a/ios/Classes/HelperClasses/Utils.swift +++ b/ios/Classes/HelperClasses/Utils.swift @@ -202,4 +202,17 @@ public class Utils: NSObject { return nil } } + + static func getDefaultLogLevel(_ logLevel: String) -> OptimizelyLogLevel { + var defaultLogLevel: OptimizelyLogLevel + switch logLevel { + case "error": defaultLogLevel = OptimizelyLogLevel.error + case "warning": defaultLogLevel = OptimizelyLogLevel.warning + case "info": defaultLogLevel = OptimizelyLogLevel.info + case "debug": defaultLogLevel = OptimizelyLogLevel.debug + default: defaultLogLevel = OptimizelyLogLevel.info + } + return defaultLogLevel; + } + } diff --git a/ios/Classes/SwiftOptimizelyFlutterSdkPlugin.swift b/ios/Classes/SwiftOptimizelyFlutterSdkPlugin.swift index cdc1549..42d363f 100644 --- a/ios/Classes/SwiftOptimizelyFlutterSdkPlugin.swift +++ b/ios/Classes/SwiftOptimizelyFlutterSdkPlugin.swift @@ -81,6 +81,10 @@ public class SwiftOptimizelyFlutterSdkPlugin: NSObject, FlutterPlugin { /// Initializes optimizely client with the provided sdkKey func initialize(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + + print("[iOS][flutter] initialize") + + guard let (parameters, sdkKey) = getParametersAndSdkKey(arguments: call.arguments, result: result) else { return } @@ -106,7 +110,13 @@ public class SwiftOptimizelyFlutterSdkPlugin: NSObject, FlutterPlugin { decideOptions = options } let defaultDecideOptions = Utils.getDecideOptions(options: decideOptions) - + + var defaultLogLevel = OptimizelyLogLevel.info + if let logLevel = parameters[RequestParameterKey.defaultLogLevel] as? String { + defaultLogLevel = Utils.getDefaultLogLevel(logLevel) + } + print("[iOS][flutter] \(parameters[RequestParameterKey.defaultLogLevel]) -> \(defaultLogLevel)") + // SDK Settings Default Values var segmentsCacheSize: Int = 100 var segmentsCacheTimeoutInSecs: Int = 600 @@ -152,7 +162,14 @@ public class SwiftOptimizelyFlutterSdkPlugin: NSObject, FlutterPlugin { optimizelyClientsTracker.removeValue(forKey: sdkKey) // Creating new instance - let optimizelyInstance = OptimizelyClient(sdkKey:sdkKey, eventDispatcher: eventDispatcher, datafileHandler: datafileHandler, periodicDownloadInterval: datafilePeriodicDownloadInterval, defaultDecideOptions: defaultDecideOptions, settings: optimizelySdkSettings) + let optimizelyInstance = OptimizelyClient( + sdkKey:sdkKey, + eventDispatcher: eventDispatcher, + datafileHandler: datafileHandler, + periodicDownloadInterval: datafilePeriodicDownloadInterval, + /// defaultLogLevel: defaultLogLevel, + defaultDecideOptions: defaultDecideOptions, + settings: optimizelySdkSettings) optimizelyInstance.start{ [weak self] res in switch res { diff --git a/lib/optimizely_flutter_sdk.dart b/lib/optimizely_flutter_sdk.dart index 775130f..80414fb 100644 --- a/lib/optimizely_flutter_sdk.dart +++ b/lib/optimizely_flutter_sdk.dart @@ -28,6 +28,8 @@ import 'package:optimizely_flutter_sdk/src/data_objects/optimizely_config_respon import 'package:optimizely_flutter_sdk/src/optimizely_client_wrapper.dart'; import 'package:optimizely_flutter_sdk/src/user_context/optimizely_user_context.dart'; +import 'src/data_objects/log_levels.dart'; + export 'package:optimizely_flutter_sdk/src/optimizely_client_wrapper.dart' show ClientPlatform, ListenerType; export 'package:optimizely_flutter_sdk/src/user_context/optimizely_forced_decision.dart' @@ -50,6 +52,8 @@ export 'package:optimizely_flutter_sdk/src/data_objects/sdk_settings.dart' show SDKSettings; export 'package:optimizely_flutter_sdk/src/data_objects/datafile_options.dart' show DatafileHostOptions; +export 'package:optimizely_flutter_sdk/src/data_objects/log_levels.dart' + show OptimizelyLogLevel; /// The main client class for the Optimizely Flutter SDK. /// @@ -63,6 +67,7 @@ class OptimizelyFlutterSdk { final int _datafilePeriodicDownloadInterval; final Map _datafileHostOptions; final Set _defaultDecideOptions; + final OptimizelyLogLevel _defaultLogLevel; final SDKSettings _sdkSettings; OptimizelyFlutterSdk(this._sdkKey, {EventOptions eventOptions = const EventOptions(), @@ -70,11 +75,13 @@ class OptimizelyFlutterSdk { 10 * 60, // Default time interval in seconds Map datafileHostOptions = const {}, Set defaultDecideOptions = const {}, + OptimizelyLogLevel defaultLogLevel = OptimizelyLogLevel.info, SDKSettings sdkSettings = const SDKSettings()}) : _eventOptions = eventOptions, _datafilePeriodicDownloadInterval = datafilePeriodicDownloadInterval, _datafileHostOptions = datafileHostOptions, _defaultDecideOptions = defaultDecideOptions, + _defaultLogLevel = defaultLogLevel, _sdkSettings = sdkSettings; /// Starts Optimizely SDK (Synchronous) with provided sdkKey. @@ -85,6 +92,7 @@ class OptimizelyFlutterSdk { _datafilePeriodicDownloadInterval, _datafileHostOptions, _defaultDecideOptions, + _defaultLogLevel, _sdkSettings); } diff --git a/lib/src/data_objects/log_levels.dart b/lib/src/data_objects/log_levels.dart new file mode 100644 index 0000000..517acb7 --- /dev/null +++ b/lib/src/data_objects/log_levels.dart @@ -0,0 +1,7 @@ +/// Log levels for the SDK. +enum OptimizelyLogLevel { + error, + warning, + info, + debug +} diff --git a/lib/src/optimizely_client_wrapper.dart b/lib/src/optimizely_client_wrapper.dart index e26b74f..c28dde6 100644 --- a/lib/src/optimizely_client_wrapper.dart +++ b/lib/src/optimizely_client_wrapper.dart @@ -27,6 +27,8 @@ import 'package:optimizely_flutter_sdk/src/data_objects/optimizely_config_respon import 'package:optimizely_flutter_sdk/src/utils/constants.dart'; import 'package:optimizely_flutter_sdk/src/utils/utils.dart'; +import 'data_objects/log_levels.dart'; + enum ListenerType { activate, track, decision, logEvent, projectConfigUpdate } enum ClientPlatform { iOS, android } @@ -61,6 +63,7 @@ class OptimizelyClientWrapper { int datafilePeriodicDownloadInterval, Map datafileHostOptions, Set defaultDecideOptions, + OptimizelyLogLevel defaultLogLevel, SDKSettings sdkSettings) async { _channel.setMethodCallHandler(methodCallHandler); final convertedOptions = Utils.convertDecideOptions(defaultDecideOptions); @@ -69,6 +72,7 @@ class OptimizelyClientWrapper { Constants.datafilePeriodicDownloadInterval: datafilePeriodicDownloadInterval, Constants.optimizelyDecideOption: convertedOptions, + Constants.defaultLogLevel: defaultLogLevel.toString(), Constants.eventBatchSize: eventOptions.batchSize, Constants.eventTimeInterval: eventOptions.timeInterval, Constants.eventMaxQueueSize: eventOptions.maxQueueSize, diff --git a/lib/src/utils/constants.dart b/lib/src/utils/constants.dart index f6a61d5..d5bc3ff 100644 --- a/lib/src/utils/constants.dart +++ b/lib/src/utils/constants.dart @@ -83,6 +83,7 @@ class Constants { static const String optimizelyDecideOption = "optimizelyDecideOption"; static const String optimizelySegmentOption = "optimizelySegmentOption"; static const String optimizelySdkSettings = "optimizelySdkSettings"; + static const String defaultLogLevel = "defaultLogLevel"; static const String payload = "payload"; static const String value = "value"; static const String type = "type"; From e8b7e09405acac835e88e6ace6031d4868618de3 Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Tue, 13 Jun 2023 16:56:46 -0700 Subject: [PATCH 2/8] add logback config file --- android/build.gradle | 2 +- android/src/main/assets/logback.xml | 18 ++++++++++++++++++ .../SwiftOptimizelyFlutterSdkPlugin.swift | 7 +------ lib/src/optimizely_client_wrapper.dart | 2 +- 4 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 android/src/main/assets/logback.xml diff --git a/android/build.gradle b/android/build.gradle index 0807b43..6d53533 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -76,7 +76,7 @@ dependencies { implementation 'androidx.multidex:multidex:2.0.0' implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' //implementation group: 'org.slf4j', name: 'slf4j-android', version: '1.7.25' - //implementation 'org.slf4j:slf4j-api:2.0.7' + implementation 'org.slf4j:slf4j-api:2.0.7' implementation 'com.github.tony19:logback-android:3.0.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.10" implementation "com.optimizely.ab:android-sdk:4.0.0-beta2" diff --git a/android/src/main/assets/logback.xml b/android/src/main/assets/logback.xml new file mode 100644 index 0000000..8e6e0d6 --- /dev/null +++ b/android/src/main/assets/logback.xml @@ -0,0 +1,18 @@ + + + + Optimizely + + + %msg + + + + + + + diff --git a/ios/Classes/SwiftOptimizelyFlutterSdkPlugin.swift b/ios/Classes/SwiftOptimizelyFlutterSdkPlugin.swift index 42d363f..287b056 100644 --- a/ios/Classes/SwiftOptimizelyFlutterSdkPlugin.swift +++ b/ios/Classes/SwiftOptimizelyFlutterSdkPlugin.swift @@ -81,10 +81,6 @@ public class SwiftOptimizelyFlutterSdkPlugin: NSObject, FlutterPlugin { /// Initializes optimizely client with the provided sdkKey func initialize(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - - print("[iOS][flutter] initialize") - - guard let (parameters, sdkKey) = getParametersAndSdkKey(arguments: call.arguments, result: result) else { return } @@ -115,7 +111,6 @@ public class SwiftOptimizelyFlutterSdkPlugin: NSObject, FlutterPlugin { if let logLevel = parameters[RequestParameterKey.defaultLogLevel] as? String { defaultLogLevel = Utils.getDefaultLogLevel(logLevel) } - print("[iOS][flutter] \(parameters[RequestParameterKey.defaultLogLevel]) -> \(defaultLogLevel)") // SDK Settings Default Values var segmentsCacheSize: Int = 100 @@ -167,7 +162,7 @@ public class SwiftOptimizelyFlutterSdkPlugin: NSObject, FlutterPlugin { eventDispatcher: eventDispatcher, datafileHandler: datafileHandler, periodicDownloadInterval: datafilePeriodicDownloadInterval, - /// defaultLogLevel: defaultLogLevel, + defaultLogLevel: defaultLogLevel, defaultDecideOptions: defaultDecideOptions, settings: optimizelySdkSettings) diff --git a/lib/src/optimizely_client_wrapper.dart b/lib/src/optimizely_client_wrapper.dart index c28dde6..a65be80 100644 --- a/lib/src/optimizely_client_wrapper.dart +++ b/lib/src/optimizely_client_wrapper.dart @@ -72,7 +72,7 @@ class OptimizelyClientWrapper { Constants.datafilePeriodicDownloadInterval: datafilePeriodicDownloadInterval, Constants.optimizelyDecideOption: convertedOptions, - Constants.defaultLogLevel: defaultLogLevel.toString(), + Constants.defaultLogLevel: defaultLogLevel.toString().split('.').last, // "error", "warning", "info", "debug" Constants.eventBatchSize: eventOptions.batchSize, Constants.eventTimeInterval: eventOptions.timeInterval, Constants.eventMaxQueueSize: eventOptions.maxQueueSize, From e1cbc79580713ffd62fc72178f66a3a8ca406d16 Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Tue, 13 Jun 2023 17:20:16 -0700 Subject: [PATCH 3/8] clean up --- android/build.gradle | 7 +++++-- .../OptimizelyFlutterClient.java | 4 +--- .../helper_classes/Utils.java | 15 ++++++++++----- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 6d53533..c9d2ab5 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -75,9 +75,12 @@ android { dependencies { implementation 'androidx.multidex:multidex:2.0.0' implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' - //implementation group: 'org.slf4j', name: 'slf4j-android', version: '1.7.25' - implementation 'org.slf4j:slf4j-api:2.0.7' + + //"logback-android" required for programmatic control of glbal sl4j log level + // [ref] https://github.com/tony19/logback-android implementation 'com.github.tony19:logback-android:3.0.0' + 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.fasterxml.jackson.core:jackson-databind:2.9.8' diff --git a/android/src/main/java/com/optimizely/optimizely_flutter_sdk/OptimizelyFlutterClient.java b/android/src/main/java/com/optimizely/optimizely_flutter_sdk/OptimizelyFlutterClient.java index 6ece8d4..82e3384 100644 --- a/android/src/main/java/com/optimizely/optimizely_flutter_sdk/OptimizelyFlutterClient.java +++ b/android/src/main/java/com/optimizely/optimizely_flutter_sdk/OptimizelyFlutterClient.java @@ -97,9 +97,7 @@ protected void initializeOptimizely(@NonNull ArgumentsParser argumentsParser, @N maxQueueSize = argumentsParser.getEventMaxQueueSize(); } - if (argumentsParser.getDefaultLogLevel() != null) { - Utils.setDefaultLogLevel(argumentsParser.getDefaultLogLevel()); - } + Utils.setDefaultLogLevel(argumentsParser.getDefaultLogLevel()); DefaultEventHandler eventHandler = DefaultEventHandler.getInstance(context); eventHandler.setDispatchInterval(-1L); diff --git a/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java b/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java index 29cfcc9..c8d0e3c 100644 --- a/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java +++ b/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java @@ -108,6 +108,16 @@ public static Class getNotificationListenerType(String notificationType) { return listenerClass; } + // SLF4J log level control: + // - logback logger (ch.qos.logback) is the only option that supports global log level control programmatically (not only via configuration file) + // - "logback-android" logger (com.github.tony19:logback-android) is integrated in build.gradle. + + public static void setDefaultLogLevel(String logLevel) { + Level defaultLogLevel = Utils.mapLogLevel(logLevel); + Logger rootLogger = (Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME); + rootLogger.setLevel(defaultLogLevel); + } + public static Level mapLogLevel(String logLevel) { Level level = Level.INFO; @@ -125,9 +135,4 @@ public static Level mapLogLevel(String logLevel) { return level; } - public static void setDefaultLogLevel(String logLevel) { - Logger rootLogger = (Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME); - rootLogger.setLevel(Utils.mapLogLevel(logLevel)); - } - } From adf6446bde98e994a3b531f410bc1946bc49dc33 Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Tue, 13 Jun 2023 17:22:13 -0700 Subject: [PATCH 4/8] clean up --- android/build.gradle | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index c9d2ab5..33b58e3 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -76,11 +76,12 @@ dependencies { implementation 'androidx.multidex:multidex:2.0.0' implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' - //"logback-android" required for programmatic control of glbal sl4j log level - // [ref] https://github.com/tony19/logback-android + //"logback-android" required for programmatic control of glbal sl4j log level. + // - default log configuration in /assets/logback.xml + // - [ref] https://github.com/tony19/logback-android implementation 'com.github.tony19:logback-android:3.0.0' 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.fasterxml.jackson.core:jackson-databind:2.9.8' From 0a29aaf0a67a2a56bda200bd6181af02a317940f Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Tue, 13 Jun 2023 17:34:16 -0700 Subject: [PATCH 5/8] clean up --- lib/optimizely_flutter_sdk.dart | 5 ++--- lib/src/data_objects/log_level.dart | 22 ++++++++++++++++++++++ lib/src/data_objects/log_levels.dart | 7 ------- lib/src/optimizely_client_wrapper.dart | 2 +- 4 files changed, 25 insertions(+), 11 deletions(-) create mode 100644 lib/src/data_objects/log_level.dart delete mode 100644 lib/src/data_objects/log_levels.dart diff --git a/lib/optimizely_flutter_sdk.dart b/lib/optimizely_flutter_sdk.dart index 80414fb..51dc9af 100644 --- a/lib/optimizely_flutter_sdk.dart +++ b/lib/optimizely_flutter_sdk.dart @@ -27,8 +27,7 @@ import 'package:optimizely_flutter_sdk/src/data_objects/get_variation_response.d import 'package:optimizely_flutter_sdk/src/data_objects/optimizely_config_response.dart'; import 'package:optimizely_flutter_sdk/src/optimizely_client_wrapper.dart'; import 'package:optimizely_flutter_sdk/src/user_context/optimizely_user_context.dart'; - -import 'src/data_objects/log_levels.dart'; +import 'package:optimizely_flutter_sdk/src/data_objects/log_level.dart'; export 'package:optimizely_flutter_sdk/src/optimizely_client_wrapper.dart' show ClientPlatform, ListenerType; @@ -52,7 +51,7 @@ export 'package:optimizely_flutter_sdk/src/data_objects/sdk_settings.dart' show SDKSettings; export 'package:optimizely_flutter_sdk/src/data_objects/datafile_options.dart' show DatafileHostOptions; -export 'package:optimizely_flutter_sdk/src/data_objects/log_levels.dart' +export 'package:optimizely_flutter_sdk/src/data_objects/log_level.dart' show OptimizelyLogLevel; /// The main client class for the Optimizely Flutter SDK. diff --git a/lib/src/data_objects/log_level.dart b/lib/src/data_objects/log_level.dart new file mode 100644 index 0000000..c2eacd3 --- /dev/null +++ b/lib/src/data_objects/log_level.dart @@ -0,0 +1,22 @@ +/// ************************************************************************** +/// Copyright 2023, Optimizely, Inc. and contributors * +/// * +/// Licensed under the Apache License, Version 2.0 (the "License"); * +/// you may not use this file except in compliance with the License. * +/// You may obtain a copy of the License at * +/// * +/// http://www.apache.org/licenses/LICENSE-2.0 * +/// * +/// Unless required by applicable law or agreed to in writing, software * +/// distributed under the License is distributed on an "AS IS" BASIS, * +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * +/// See the License for the specific language governing permissions and * +/// limitations under the License. * +///**************************************************************************/ + +enum OptimizelyLogLevel { + error, + warning, + info, + debug +} diff --git a/lib/src/data_objects/log_levels.dart b/lib/src/data_objects/log_levels.dart deleted file mode 100644 index 517acb7..0000000 --- a/lib/src/data_objects/log_levels.dart +++ /dev/null @@ -1,7 +0,0 @@ -/// Log levels for the SDK. -enum OptimizelyLogLevel { - error, - warning, - info, - debug -} diff --git a/lib/src/optimizely_client_wrapper.dart b/lib/src/optimizely_client_wrapper.dart index a65be80..9312b56 100644 --- a/lib/src/optimizely_client_wrapper.dart +++ b/lib/src/optimizely_client_wrapper.dart @@ -27,7 +27,7 @@ import 'package:optimizely_flutter_sdk/src/data_objects/optimizely_config_respon import 'package:optimizely_flutter_sdk/src/utils/constants.dart'; import 'package:optimizely_flutter_sdk/src/utils/utils.dart'; -import 'data_objects/log_levels.dart'; +import 'data_objects/log_level.dart'; enum ListenerType { activate, track, decision, logEvent, projectConfigUpdate } From cfd52f5c9bcf0bbaaac9f78caf0e276e3fc6fc26 Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Wed, 14 Jun 2023 12:04:42 -0700 Subject: [PATCH 6/8] add log level tests --- .../helper_classes/Utils.java | 3 +- lib/src/optimizely_client_wrapper.dart | 3 +- lib/src/utils/utils.dart | 7 +++++ test/optimizely_flutter_sdk_test.dart | 31 +++++++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java b/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java index c8d0e3c..93cc712 100644 --- a/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java +++ b/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java @@ -109,8 +109,9 @@ public static Class getNotificationListenerType(String notificationType) { } // SLF4J log level control: - // - logback logger (ch.qos.logback) is the only option that supports global log level control programmatically (not only via configuration file) + // - logback logger (ch.qos.logback) is the only option available that supports global log level control programmatically (not only via configuration file) // - "logback-android" logger (com.github.tony19:logback-android) is integrated in build.gradle. + // - log-level control is not integrated into the native android-sdk core since this solution depends on logback logger. public static void setDefaultLogLevel(String logLevel) { Level defaultLogLevel = Utils.mapLogLevel(logLevel); diff --git a/lib/src/optimizely_client_wrapper.dart b/lib/src/optimizely_client_wrapper.dart index 9312b56..bb2c4c0 100644 --- a/lib/src/optimizely_client_wrapper.dart +++ b/lib/src/optimizely_client_wrapper.dart @@ -67,12 +67,13 @@ class OptimizelyClientWrapper { SDKSettings sdkSettings) async { _channel.setMethodCallHandler(methodCallHandler); final convertedOptions = Utils.convertDecideOptions(defaultDecideOptions); + final convertedLogLevel = Utils.convertLogLevel(defaultLogLevel); Map requestDict = { Constants.sdkKey: sdkKey, Constants.datafilePeriodicDownloadInterval: datafilePeriodicDownloadInterval, Constants.optimizelyDecideOption: convertedOptions, - Constants.defaultLogLevel: defaultLogLevel.toString().split('.').last, // "error", "warning", "info", "debug" + Constants.defaultLogLevel: convertedLogLevel, Constants.eventBatchSize: eventOptions.batchSize, Constants.eventTimeInterval: eventOptions.timeInterval, Constants.eventMaxQueueSize: eventOptions.maxQueueSize, diff --git a/lib/src/utils/utils.dart b/lib/src/utils/utils.dart index da36841..782178e 100644 --- a/lib/src/utils/utils.dart +++ b/lib/src/utils/utils.dart @@ -18,6 +18,7 @@ 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'; class Utils { static Map decideOptions = { @@ -94,4 +95,10 @@ class Utils { Set options) { return options.map((option) => Utils.segmentOptions[option]!).toList(); } + + static String convertLogLevel(OptimizelyLogLevel logLevel) { + // OptimizelyLogLevel.error -> "error" + // OptimizelyLogLevel.debug -> "debug" + return logLevel.toString().split('.').last; + } } diff --git a/test/optimizely_flutter_sdk_test.dart b/test/optimizely_flutter_sdk_test.dart index fa81adb..1cf6a9d 100644 --- a/test/optimizely_flutter_sdk_test.dart +++ b/test/optimizely_flutter_sdk_test.dart @@ -56,6 +56,7 @@ void main() { DatafileHostOptions datafileHostOptions = const DatafileHostOptions("", ""); SDKSettings sdkSettings = const SDKSettings(); int datafilePeriodicDownloadInterval = 0; + String defaultLogLevel = "error"; const MethodChannel channel = MethodChannel("optimizely_flutter_sdk"); dynamic mockOptimizelyConfig; @@ -83,6 +84,9 @@ void main() { case Constants.initializeMethod: expect(methodCall.arguments[Constants.sdkKey], isNotEmpty); expect(methodCall.arguments[Constants.userContextId], isNull); + + defaultLogLevel = methodCall.arguments[Constants.defaultLogLevel]; + // To Check if eventOptions were received eventOptions = EventOptions( batchSize: methodCall.arguments[Constants.eventBatchSize], @@ -542,6 +546,33 @@ void main() { }); }); + group("log level", () { + test("with no defaultLogLevel, log level should be info level", () async { + var sdk = OptimizelyFlutterSdk(testSDKKey); + + var response = await sdk.initializeClient(); + + expect(response.success, isTrue); + expect(defaultLogLevel, equals("info")); + }); + + test("with a valid defaultLogLevel parameter", () async { + var sdk = OptimizelyFlutterSdk(testSDKKey, defaultLogLevel: OptimizelyLogLevel.debug); + + var response = await sdk.initializeClient(); + + expect(response.success, isTrue); + expect(defaultLogLevel, equals("debug")); + }); + + test("should convert OptimizelyLogLevel to string", () async { + expect(Utils.convertLogLevel(OptimizelyLogLevel.error), "error"); + expect(Utils.convertLogLevel(OptimizelyLogLevel.warning), "warning"); + expect(Utils.convertLogLevel(OptimizelyLogLevel.info), "info"); + expect(Utils.convertLogLevel(OptimizelyLogLevel.debug), "debug"); + }); + }); + group("close()", () { test("should succeed", () async { var sdk = OptimizelyFlutterSdk(testSDKKey); From 9f8998c17212471f86f8ba28d13c4c126909fc4c Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Wed, 14 Jun 2023 13:41:12 -0700 Subject: [PATCH 7/8] clean up --- android/build.gradle | 2 +- .../optimizely_flutter_sdk/helper_classes/Utils.java | 5 +++-- test/optimizely_flutter_sdk_test.dart | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 33b58e3..a96df3b 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -76,7 +76,7 @@ dependencies { implementation 'androidx.multidex:multidex:2.0.0' implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' - //"logback-android" required for programmatic control of glbal sl4j log level. + //"logback-android" required for programmatic control of global sl4j log level. // - default log configuration in /assets/logback.xml // - [ref] https://github.com/tony19/logback-android implementation 'com.github.tony19:logback-android:3.0.0' diff --git a/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java b/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java index 93cc712..a4353b5 100644 --- a/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java +++ b/android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Utils.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import androidx.annotation.Nullable; import static com.optimizely.ab.notification.DecisionNotification.FeatureVariableDecisionNotificationBuilder.SOURCE_INFO; @@ -113,13 +114,13 @@ public static Class getNotificationListenerType(String notificationType) { // - "logback-android" logger (com.github.tony19:logback-android) is integrated in build.gradle. // - log-level control is not integrated into the native android-sdk core since this solution depends on logback logger. - public static void setDefaultLogLevel(String logLevel) { + public static void setDefaultLogLevel(@Nullable String logLevel) { Level defaultLogLevel = Utils.mapLogLevel(logLevel); Logger rootLogger = (Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME); rootLogger.setLevel(defaultLogLevel); } - public static Level mapLogLevel(String logLevel) { + public static Level mapLogLevel(@Nullable String logLevel) { Level level = Level.INFO; if (logLevel == null || logLevel.isEmpty()) { diff --git a/test/optimizely_flutter_sdk_test.dart b/test/optimizely_flutter_sdk_test.dart index 1cf6a9d..debf769 100644 --- a/test/optimizely_flutter_sdk_test.dart +++ b/test/optimizely_flutter_sdk_test.dart @@ -546,7 +546,7 @@ void main() { }); }); - group("log level", () { + group("log level configuration", () { test("with no defaultLogLevel, log level should be info level", () async { var sdk = OptimizelyFlutterSdk(testSDKKey); From c6b8b21e85e99739420edb9bf652d528ba7ca64f Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Wed, 14 Jun 2023 13:52:54 -0700 Subject: [PATCH 8/8] upgrade jackson json lib --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index a96df3b..03427ea 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -84,7 +84,7 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.10" implementation "com.optimizely.ab:android-sdk:4.0.0-beta2" - implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4' implementation ('com.google.guava:guava:19.0') { exclude group:'com.google.guava', module:'listenablefuture' }