Skip to content

Commit 9dfbcec

Browse files
[FSSDK-11985] feat: add android logger support (#90)
* chore: add new classes for logging - Add FlutterLogbackAppender.java for logging events in the Flutter app - Integrate OptimizelyFlutterSdkPlugin with FlutterLogbackAppender - Update Constants.swift, SwiftOptimizelyFlutterSdkPlugin.swift, and related classes * refactor: update log level conversion logic - Adjust method to correctly convert log level strings to integers - Refactor switch statement for better readability and maintainability * refactor: optimize log level conversion - Remove unnecessary default log level value initialization - Refactor switch statement to directly return log levels for each case - Simplify comparison for warning log levels to include both "WARN" and "WARNING" * style: update logback configuration and log levels - Comment out configuration block in logback.xml - Modify log level 'WARNING' to 'WARN' in FlutterLogbackAppender.java * fix: ensure debugging logs are only printed in debug mode - Add check for kDebugMode to control printing of logs * chore: update logback.xml - Comment out old logback configuration - Add note explaining the use of FlutterLogbackAppender for logging
1 parent 00fd215 commit 9dfbcec

File tree

9 files changed

+103
-41
lines changed

9 files changed

+103
-41
lines changed
Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1 @@
1-
<configuration
2-
xmlns="https://tony19.github.io/logback-android/xml"
3-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4-
xsi:schemaLocation="https://tony19.github.io/logback-android/xml https://cdn.jsdelivr.net/gh/tony19/logback-android/logback.xsd"
5-
>
6-
<appender name="logcat" class="ch.qos.logback.classic.android.LogcatAppender">
7-
<tagEncoder>
8-
<pattern>Optimizely</pattern>
9-
</tagEncoder>
10-
<encoder>
11-
<pattern>%msg</pattern>
12-
</encoder>
13-
</appender>
14-
15-
<root level="DEBUG">
16-
<appender-ref ref="logcat" />
17-
</root>
18-
</configuration>
1+
<!-- We do not use this since all logging is handled programmatically via FlutterLogbackAppender and forwarded to the Dart logger. -->
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.optimizely.optimizely_flutter_sdk;
2+
import com.optimizely.optimizely_flutter_sdk.helper_classes.Constants;
3+
4+
import android.os.Handler;
5+
import android.os.Looper;
6+
7+
import java.util.HashMap;
8+
import java.util.Map;
9+
10+
import ch.qos.logback.classic.spi.ILoggingEvent;
11+
import ch.qos.logback.core.AppenderBase;
12+
import io.flutter.plugin.common.MethodChannel;
13+
14+
public class FlutterLogbackAppender extends AppenderBase<ILoggingEvent> {
15+
16+
public static final String CHANNEL_NAME = "optimizely_flutter_sdk_logger";
17+
public static MethodChannel channel;
18+
private static final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
19+
20+
public static void setChannel(MethodChannel channel) {
21+
FlutterLogbackAppender.channel = channel;
22+
}
23+
24+
@Override
25+
protected void append(ILoggingEvent event) {
26+
if (channel == null) {
27+
return;
28+
}
29+
30+
String message = event.getFormattedMessage();
31+
String level = event.getLevel().toString();
32+
int logLevel = convertLogLevel(level);
33+
Map<String, Object> logData = new HashMap<>();
34+
logData.put("level", logLevel);
35+
logData.put("message", message);
36+
37+
mainThreadHandler.post(() -> {
38+
if (channel != null) {
39+
channel.invokeMethod("log", logData);
40+
}
41+
});
42+
}
43+
44+
int convertLogLevel(String logLevel) {
45+
if (logLevel == null || logLevel.isEmpty()) {
46+
return 3;
47+
}
48+
49+
switch (logLevel.toUpperCase()) {
50+
case "ERROR":
51+
return 1;
52+
case "WARN":
53+
return 2;
54+
case "INFO":
55+
return 3;
56+
case "DEBUG":
57+
return 4;
58+
default:
59+
return 3;
60+
}
61+
}
62+
}

android/src/main/java/com/optimizely/optimizely_flutter_sdk/OptimizelyFlutterSdkPlugin.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,19 @@
3232

3333
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
3434

35+
import org.slf4j.LoggerFactory;
36+
37+
import ch.qos.logback.classic.Logger;
38+
import ch.qos.logback.classic.LoggerContext;
39+
import ch.qos.logback.classic.spi.ILoggingEvent;
40+
import ch.qos.logback.core.Appender;
41+
42+
3543
/** OptimizelyFlutterSdkPlugin */
3644
public class OptimizelyFlutterSdkPlugin extends OptimizelyFlutterClient implements FlutterPlugin, ActivityAware, MethodCallHandler {
3745

3846
public static MethodChannel channel;
47+
private Appender<ILoggingEvent> flutterLogbackAppender;
3948

4049
@Override
4150
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
@@ -157,11 +166,32 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
157166
channel = new MethodChannel(binding.getBinaryMessenger(), "optimizely_flutter_sdk");
158167
channel.setMethodCallHandler(this);
159168
context = binding.getApplicationContext();
169+
170+
MethodChannel loggerChannel = new MethodChannel(binding.getBinaryMessenger(), FlutterLogbackAppender.CHANNEL_NAME);
171+
FlutterLogbackAppender.setChannel(loggerChannel);
172+
173+
// Add appender to logback
174+
flutterLogbackAppender = new FlutterLogbackAppender();
175+
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
176+
flutterLogbackAppender.setContext(lc);
177+
flutterLogbackAppender.start();
178+
Logger rootLogger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
179+
rootLogger.setLevel(ch.qos.logback.classic.Level.ALL);
180+
rootLogger.addAppender(flutterLogbackAppender);
160181
}
161182

162183
@Override
163184
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
164185
channel.setMethodCallHandler(null);
186+
// Stop and detach the appender
187+
if (flutterLogbackAppender != null) {
188+
Logger rootLogger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
189+
rootLogger.detachAppender(flutterLogbackAppender);
190+
flutterLogbackAppender.stop();
191+
flutterLogbackAppender = null;
192+
}
193+
// Clean up the channel
194+
FlutterLogbackAppender.setChannel(null);
165195
}
166196

167197
@Override

ios/Classes/HelperClasses/Constants.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ struct RequestParameterKey {
9191
static let reasons = "reasons"
9292
static let decideOptions = "optimizelyDecideOption"
9393
static let defaultLogLevel = "defaultLogLevel"
94-
static let useCustomLogger = "useCustomLogger"
9594
static let eventBatchSize = "eventBatchSize"
9695
static let eventTimeInterval = "eventTimeInterval"
9796
static let eventMaxQueueSize = "eventMaxQueueSize"

ios/Classes/SwiftOptimizelyFlutterSdkPlugin.swift

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -172,15 +172,10 @@ public class SwiftOptimizelyFlutterSdkPlugin: NSObject, FlutterPlugin {
172172
notificationIdsTracker.removeValue(forKey: sdkKey)
173173
optimizelyClientsTracker.removeValue(forKey: sdkKey)
174174

175-
// Check if custom logger is requested
176-
var logger: OPTLogger?
177-
if let useCustomLogger = parameters[RequestParameterKey.useCustomLogger] as? Bool, useCustomLogger {
178-
// OptimizelyFlutterLogger bridges iOS logs to Flutter via Method Channel
179-
// When useCustomLogger = true:
180-
// iOS SDK log → OptimizelyFlutterLogger → Flutter Method Channel → Flutter console
181-
logger = OptimizelyFlutterLogger()
182-
}
183-
175+
// OptimizelyFlutterLogger bridges iOS logs to Flutter via Method Channel
176+
// iOS SDK log → OptimizelyFlutterLogger → Flutter Method Channel → Flutter console
177+
var logger: OPTLogger = OptimizelyFlutterLogger()
178+
184179
// Creating new instance
185180
let optimizelyInstance = OptimizelyClient(
186181
sdkKey:sdkKey,

lib/optimizely_flutter_sdk.dart

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,6 @@ class OptimizelyFlutterSdk {
7373
final OptimizelyLogLevel _defaultLogLevel;
7474
final SDKSettings _sdkSettings;
7575
static OptimizelyLogger? _customLogger;
76-
/// Set a custom logger for the SDK
77-
static void setLogger(OptimizelyLogger logger) {
78-
_customLogger = logger;
79-
LoggerBridge.initialize(logger);
80-
}
8176
/// Get the current logger
8277
static OptimizelyLogger? get logger {
8378
return _customLogger;
@@ -97,11 +92,8 @@ class OptimizelyFlutterSdk {
9792
_defaultLogLevel = defaultLogLevel,
9893
_sdkSettings = sdkSettings {
9994
// Set the logger if provided
100-
if (logger != null) {
101-
setLogger(logger);
102-
} else {
103-
logWarning("Logger not provided.");
104-
}
95+
_customLogger = logger ?? DefaultOptimizelyLogger();
96+
LoggerBridge.initialize(_customLogger);
10597
}
10698

10799
/// Starts Optimizely SDK (Synchronous) with provided sdkKey.

lib/src/logger/flutter_logger.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:flutter/foundation.dart';
12
import 'package:optimizely_flutter_sdk/src/data_objects/log_level.dart';
23

34
abstract class OptimizelyLogger {
@@ -8,7 +9,9 @@ abstract class OptimizelyLogger {
89
class DefaultOptimizelyLogger implements OptimizelyLogger {
910
@override
1011
void log(OptimizelyLogLevel level, String message) {
11-
print('[OPTIMIZELY] [${level.name.toUpperCase()}]: $message');
12+
if (kDebugMode) {
13+
print('[OPTIMIZELY] [${level.name.toUpperCase()}]: $message');
14+
}
1215
}
1316
}
1417

lib/src/optimizely_client_wrapper.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ class OptimizelyClientWrapper {
8080
Constants.eventBatchSize: eventOptions.batchSize,
8181
Constants.eventTimeInterval: eventOptions.timeInterval,
8282
Constants.eventMaxQueueSize: eventOptions.maxQueueSize,
83-
Constants.useCustomLogger: logger != null,
8483
};
8584

8685
// Odp Request params

lib/src/utils/constants.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ class Constants {
8686
static const String optimizelyDecideOption = "optimizelyDecideOption";
8787
static const String optimizelySegmentOption = "optimizelySegmentOption";
8888
static const String optimizelySdkSettings = "optimizelySdkSettings";
89-
static const String useCustomLogger = 'useCustomLogger';
9089
static const String defaultLogLevel = "defaultLogLevel";
9190
static const String payload = "payload";
9291
static const String value = "value";

0 commit comments

Comments
 (0)