@luciq/react-native 19.3.0-40271-SNAPSHOT → 19.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [19.4.0](https://github.com/luciqai/luciq-reactnative-sdk/compare/v19.4.0...19.3.0)
4
+
5
+ ### Added
6
+
7
+ - **WebView Monitoring**: Added comprehensive WebView monitoring to capture performance metrics, user interactions, and network requests from WebView components.
8
+ - `Luciq.setWebViewMonitoringEnabled(boolean)` - Enable/disable master WebView monitoring
9
+ - `Luciq.setWebViewUserInteractionsTrackingEnabled(boolean)` - Enable/disable user interaction tracking in WebViews
10
+ - `Luciq.setWebViewNetworkTrackingEnabled(boolean`) - Enable/disable network logging from WebViews
11
+
12
+ ### Changed
13
+
14
+ - Bump Luciq iOS SDK to v19.5.1 ([#42](https://github.com/luciqai/luciq-reactnative-sdk/pull/42)). [See release notes](https://github.com/luciqai/Luciq-iOS-sdk/releases/tag/19.5.1).
15
+
16
+ - Bump Luciq Android SDK to v19.4.0 ([#42](https://github.com/luciqai/luciq-reactnative-sdk/pull/42)). [See release notes](https://github.com/luciqai/Luciq-Android-sdk/releases/tag/v19.4.0).
17
+
3
18
  ## [19.3.0](https://github.com/luciqai/luciq-reactnative-sdk/compare/v19.3.0...19.2.1)
4
19
 
5
20
  ### Added
@@ -1,5 +1,5 @@
1
1
  project.ext.luciq = [
2
- version: '19.3.0'
2
+ version: '19.4.0'
3
3
  ]
4
4
 
5
5
  dependencies {
@@ -30,8 +30,6 @@ import ai.luciq.reactlibrary.utils.MainThreadHandler;
30
30
 
31
31
  public class RNLuciqAPMModule extends EventEmitterModule {
32
32
 
33
- private static final String NET_TAG = "LCQ-RN-NET";
34
-
35
33
  public RNLuciqAPMModule(ReactApplicationContext reactApplicationContext) {
36
34
  super(reactApplicationContext);
37
35
  }
@@ -330,7 +328,6 @@ public class RNLuciqAPMModule extends EventEmitterModule {
330
328
  @Nullable final String gqLCQueryName,
331
329
  @Nullable final String serverErrorMessage
332
330
  ) {
333
- Log.d(NET_TAG, "[networkLogAndroid-APM] Received from JS: " + requestMethod + " " + requestUrl + ", status=" + (int) statusCode + ", duration=" + (long) requestDuration + "ms, startTime=" + (long) requestStartTime + ", error=" + errorDomain + ", gqlQuery=" + gqLCQueryName);
334
331
  try {
335
332
  APMNetworkLogger networkLogger = new APMNetworkLogger();
336
333
 
@@ -352,10 +349,8 @@ public class RNLuciqAPMModule extends EventEmitterModule {
352
349
  }
353
350
 
354
351
  } catch (Exception e) {
355
- Log.e(NET_TAG, "[networkLogAndroid-APM] Error parsing W3C attributes for " + requestMethod + " " + requestUrl, e);
356
352
  e.printStackTrace();
357
353
  }
358
- Log.d(NET_TAG, "[networkLogAndroid-APM] W3C attrs — isW3cHeaderFound=" + isW3cHeaderFound + ", partialId=" + partialId + ", networkStartTimeInSeconds=" + networkStartTimeInSeconds + ", generatedHeader=" + (w3cAttributes != null && !w3cAttributes.isNull("w3cGeneratedHeader") ? w3cAttributes.getString("w3cGeneratedHeader") : "null") + ", caughtHeader=" + (w3cAttributes != null && !w3cAttributes.isNull("w3cCaughtHeader") ? w3cAttributes.getString("w3cCaughtHeader") : "null"));
359
354
  APMCPNetworkLog.W3CExternalTraceAttributes w3cExternalTraceAttributes =
360
355
  new APMCPNetworkLog.W3CExternalTraceAttributes(
361
356
  isW3cHeaderFound,
@@ -387,17 +382,13 @@ public class RNLuciqAPMModule extends EventEmitterModule {
387
382
  serverErrorMessage,
388
383
  w3cExternalTraceAttributes
389
384
  );
390
- Log.d(NET_TAG, "[networkLogAndroid-APM] Successfully invoked APMNetworkLogger.log via reflection: " + requestMethod + " " + requestUrl);
391
385
  } else {
392
- Log.e(NET_TAG, "[networkLogAndroid-APM] APMNetworkLogger.log method NOT found by reflection — network log will be lost: " + requestMethod + " " + requestUrl);
393
386
  Log.e("IB-CP-Bridge", "APMNetworkLogger.log was not found by reflection");
394
387
  }
395
388
  } catch (Throwable e) {
396
- Log.e(NET_TAG, "[networkLogAndroid-APM] Exception invoking APMNetworkLogger.log: " + e.getMessage() + " for " + requestMethod + " " + requestUrl, e);
397
389
  e.printStackTrace();
398
390
  }
399
391
  } catch (Throwable e) {
400
- Log.e(NET_TAG, "[networkLogAndroid-APM] Top-level exception: " + e.getMessage() + " for " + requestMethod + " " + requestUrl, e);
401
392
  e.printStackTrace();
402
393
  }
403
394
  }
@@ -32,8 +32,6 @@ import java.util.concurrent.ConcurrentHashMap;
32
32
 
33
33
  public class RNLuciqNetworkLoggerModule extends EventEmitterModule {
34
34
 
35
- private static final String NET_TAG = "LCQ-RN-NET";
36
-
37
35
  public final ConcurrentHashMap<String, OnCompleteCallback<NetworkLogSnapshot>> callbackMap = new ConcurrentHashMap<String, OnCompleteCallback<NetworkLogSnapshot>>();
38
36
 
39
37
  public RNLuciqNetworkLoggerModule(ReactApplicationContext reactContext) {
@@ -59,9 +57,7 @@ public class RNLuciqNetworkLoggerModule extends EventEmitterModule {
59
57
  }
60
58
 
61
59
  private boolean getFlagValue(String key) {
62
- boolean value = InternalAPM._isFeatureEnabledCP(key, "");
63
- Log.d(NET_TAG, "[getFlagValue] key=" + key + ", value=" + value);
64
- return value;
60
+ return InternalAPM._isFeatureEnabledCP(key, "");
65
61
  }
66
62
 
67
63
  private WritableMap convertFromMapToWritableMap(Map<String, Object> map) {
@@ -90,18 +86,14 @@ public class RNLuciqNetworkLoggerModule extends EventEmitterModule {
90
86
  */
91
87
  @ReactMethod
92
88
  public void isNativeInterceptionEnabled(Promise promise) {
93
- Log.d(NET_TAG, "[isNativeInterceptionEnabled] Querying CP_NATIVE_INTERCEPTION_ENABLED flag");
94
89
  MainThreadHandler.runOnMainThread(new Runnable() {
95
90
  @Override
96
91
  public void run() {
97
92
  try {
98
- boolean enabled = getFlagValue(CP_NATIVE_INTERCEPTION_ENABLED);
99
- Log.d(NET_TAG, "[isNativeInterceptionEnabled] Result=" + enabled);
100
- promise.resolve(enabled);
93
+ promise.resolve(getFlagValue(CP_NATIVE_INTERCEPTION_ENABLED));
101
94
  } catch (Exception e) {
102
- Log.e(NET_TAG, "[isNativeInterceptionEnabled] Error — falling back to false (JS interceptor)", e);
103
95
  e.printStackTrace();
104
- promise.resolve(false);
96
+ promise.resolve(false); // Will rollback to JS interceptor
105
97
  }
106
98
 
107
99
  }
@@ -115,18 +107,14 @@ public class RNLuciqNetworkLoggerModule extends EventEmitterModule {
115
107
  */
116
108
  @ReactMethod
117
109
  public void hasAPMNetworkPlugin(Promise promise) {
118
- Log.d(NET_TAG, "[hasAPMNetworkPlugin] Querying APM_NETWORK_PLUGIN_INSTALLED flag");
119
110
  MainThreadHandler.runOnMainThread(new Runnable() {
120
111
  @Override
121
112
  public void run() {
122
113
  try {
123
- boolean hasPlugin = getFlagValue(APM_NETWORK_PLUGIN_INSTALLED);
124
- Log.d(NET_TAG, "[hasAPMNetworkPlugin] Result=" + hasPlugin);
125
- promise.resolve(hasPlugin);
114
+ promise.resolve(getFlagValue(APM_NETWORK_PLUGIN_INSTALLED));
126
115
  } catch (Exception e) {
127
- Log.e(NET_TAG, "[hasAPMNetworkPlugin] Error — falling back to false", e);
128
116
  e.printStackTrace();
129
- promise.resolve(false);
117
+ promise.resolve(false); // Will rollback to JS interceptor
130
118
  }
131
119
 
132
120
  }
@@ -136,14 +124,12 @@ public class RNLuciqNetworkLoggerModule extends EventEmitterModule {
136
124
 
137
125
  @ReactMethod
138
126
  public void registerNetworkLogsListener() {
139
- Log.d(NET_TAG, "[registerNetworkLogsListener] Registering network log sanitizer");
140
127
  MainThreadHandler.runOnMainThread(new Runnable() {
141
128
  @Override
142
129
  public void run() {
143
130
  InternalAPM._registerNetworkLogSanitizer((networkLogSnapshot, onCompleteCallback) -> {
144
131
  final String id = String.valueOf(onCompleteCallback.hashCode());
145
132
  callbackMap.put(id, onCompleteCallback);
146
- Log.d(NET_TAG, "[NetworkLogSanitizer] Received snapshot — id=" + id + ", url=" + networkLogSnapshot.getUrl() + ", responseCode=" + networkLogSnapshot.getResponseCode() + ", callbackMapSize=" + callbackMap.size());
147
133
 
148
134
  WritableMap networkSnapshotParams = Arguments.createMap();
149
135
  networkSnapshotParams.putString("id", id);
@@ -161,7 +147,6 @@ public class RNLuciqNetworkLoggerModule extends EventEmitterModule {
161
147
  }
162
148
 
163
149
  sendEvent(Constants.LCQ_NETWORK_LOGGER_HANDLER, networkSnapshotParams);
164
- Log.d(NET_TAG, "[NetworkLogSanitizer] Sent event to JS: " + Constants.LCQ_NETWORK_LOGGER_HANDLER + " for " + networkLogSnapshot.getUrl());
165
150
  });
166
151
  }
167
152
  });
@@ -169,12 +154,10 @@ public class RNLuciqNetworkLoggerModule extends EventEmitterModule {
169
154
 
170
155
  @ReactMethod
171
156
  public void resetNetworkLogsListener() {
172
- Log.d(NET_TAG, "[resetNetworkLogsListener] Clearing network log sanitizer, callbackMapSize=" + callbackMap.size());
173
157
  MainThreadHandler.runOnMainThread(new Runnable() {
174
158
  @Override
175
159
  public void run() {
176
160
  InternalAPM._registerNetworkLogSanitizer(null);
177
- Log.d(NET_TAG, "[resetNetworkLogsListener] Sanitizer cleared");
178
161
  }
179
162
  });
180
163
  }
@@ -189,28 +172,23 @@ public class RNLuciqNetworkLoggerModule extends EventEmitterModule {
189
172
  ReadableMap requestHeaders,
190
173
  ReadableMap responseHeaders
191
174
  ) {
192
- Log.d(NET_TAG, "[updateNetworkLogSnapshot] callbackID=" + callbackID + ", url=" + url + ", responseCode=" + responseCode + ", callbackMapSize=" + callbackMap.size());
193
175
  try {
176
+ // Convert ReadableMap to a Java Map for easier handling
194
177
  Map<String, Object> requestHeadersMap = convertReadableMapToMap(requestHeaders);
195
178
  Map<String, Object> responseHeadersMap = convertReadableMapToMap(responseHeaders);
196
179
 
197
180
  NetworkLogSnapshot modifiedSnapshot = null;
198
181
  if (!url.isEmpty()) {
199
182
  modifiedSnapshot = new NetworkLogSnapshot(url, requestHeadersMap, requestBody, responseHeadersMap, responseBody, responseCode);
200
- } else {
201
- Log.d(NET_TAG, "[updateNetworkLogSnapshot] Empty URL — snapshot will be null (request filtered/removed)");
202
183
  }
203
184
 
204
185
  final OnCompleteCallback<NetworkLogSnapshot> callback = callbackMap.get(callbackID);
205
186
  if (callback != null) {
206
187
  callback.onComplete(modifiedSnapshot);
207
188
  callbackMap.remove(callbackID);
208
- Log.d(NET_TAG, "[updateNetworkLogSnapshot] Callback invoked and removed for " + callbackID + ", remaining=" + callbackMap.size());
209
- } else {
210
- Log.e(NET_TAG, "[updateNetworkLogSnapshot] No callback found for callbackID=" + callbackID + " — possible leak or duplicate call, mapKeys=" + callbackMap.keySet());
211
189
  }
212
190
  } catch (Exception e) {
213
- Log.e(NET_TAG, "[updateNetworkLogSnapshot] Exception processing snapshot: " + e.getMessage() + " for callbackID=" + callbackID, e);
191
+ // Reject the promise to indicate an error occurred
214
192
  Log.e("IB-CP-Bridge", "LuciqNetworkLogger.updateNetworkLogSnapshot failed to parse the network snapshot object.");
215
193
  }
216
194
  }
@@ -86,7 +86,6 @@ import javax.annotation.Nullable;
86
86
  public class RNLuciqReactnativeModule extends EventEmitterModule {
87
87
 
88
88
  private static final String TAG = "Luciq-RN-Core";
89
- private static final String NET_TAG = "LCQ-RN-NET";
90
89
 
91
90
  private LuciqCustomTextPlaceHolder placeHolders;
92
91
  private static Report currentReport;
@@ -164,7 +163,6 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
164
163
 
165
164
 
166
165
  ) {
167
- Log.d(NET_TAG, "[init] Called — logLevel=" + logLevel + ", useNativeNetworkInterception=" + useNativeNetworkInterception + ", codePushVersion=" + codePushVersion + ", appVariant=" + appVariant);
168
166
  MainThreadHandler.runOnMainThread(new Runnable() {
169
167
  @Override
170
168
  public void run() {
@@ -206,7 +204,6 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
206
204
  }
207
205
 
208
206
  builder.build();
209
- Log.d(NET_TAG, "[init] SDK build complete");
210
207
  }
211
208
  });
212
209
  }
@@ -972,7 +969,6 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
972
969
  final String requestHeaders,
973
970
  final String responseHeaders,
974
971
  final double duration) {
975
- Log.d(NET_TAG, "[networkLogAndroid-Core] Received from JS: " + method + " " + url + ", status=" + (int) responseCode + ", duration=" + (long) duration + "ms, reqBodyLen=" + (requestBody != null ? requestBody.length() : 0) + ", resBodyLen=" + (responseBody != null ? responseBody.length() : 0));
976
972
  try {
977
973
  final String date = String.valueOf(System.currentTimeMillis());
978
974
 
@@ -989,14 +985,11 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
989
985
  networkLog.setRequestHeaders(requestHeaders);
990
986
  networkLog.setResponseHeaders(responseHeaders);
991
987
  } catch (OutOfMemoryError | Exception exception) {
992
- Log.e(NET_TAG, "[networkLogAndroid-Core] OOM/Error setting log contents: " + exception.getMessage() + " for " + method + " " + url);
993
988
  Log.d(TAG, "Error: " + exception.getMessage() + "while trying to set network log contents (request body, response body, request headers, and response headers).");
994
989
  }
995
990
 
996
991
  networkLog.insert();
997
- Log.d(NET_TAG, "[networkLogAndroid-Core] Successfully inserted NetworkLog: " + method + " " + url);
998
992
  } catch (OutOfMemoryError | Exception exception) {
999
- Log.e(NET_TAG, "[networkLogAndroid-Core] OOM/Error inserting network log: " + exception.getMessage() + " for " + method + " " + url);
1000
993
  Log.d(TAG, "Error: " + exception.getMessage() + "while trying to insert a network log");
1001
994
  }
1002
995
  }
@@ -1177,7 +1170,7 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
1177
1170
  */
1178
1171
  @ReactMethod
1179
1172
  public void registerFeatureFlagsChangeListener() {
1180
- Log.d(NET_TAG, "[registerFeatureFlagsChangeListener] Registering native feature flags listener");
1173
+
1181
1174
  MainThreadHandler.runOnMainThread(new Runnable() {
1182
1175
  @Override
1183
1176
  public void run() {
@@ -1185,7 +1178,6 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
1185
1178
  InternalCore.INSTANCE._setFeaturesStateListener(new FeaturesStateListener() {
1186
1179
  @Override
1187
1180
  public void invoke(@NonNull CoreFeaturesState featuresState) {
1188
- Log.d(NET_TAG, "[FeatureFlagsListener] Received update — W3CTraceID=" + featuresState.isW3CExternalTraceIdEnabled() + ", generatedHeader=" + featuresState.isAttachingGeneratedHeaderEnabled() + ", caughtHeader=" + featuresState.isAttachingCapturedHeaderEnabled() + ", networkBodyLimit=" + featuresState.getNetworkLogCharLimit());
1189
1181
  WritableMap params = Arguments.createMap();
1190
1182
  params.putBoolean("isW3ExternalTraceIDEnabled", featuresState.isW3CExternalTraceIdEnabled());
1191
1183
  params.putBoolean("isW3ExternalGeneratedHeaderEnabled", featuresState.isAttachingGeneratedHeaderEnabled());
@@ -1193,11 +1185,9 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
1193
1185
  params.putInt("networkBodyLimit",featuresState.getNetworkLogCharLimit());
1194
1186
 
1195
1187
  sendEvent(Constants.LCQ_ON_FEATURE_FLAGS_UPDATE_RECEIVED_CALLBACK, params);
1196
- Log.d(NET_TAG, "[FeatureFlagsListener] Sent event to JS: " + Constants.LCQ_ON_FEATURE_FLAGS_UPDATE_RECEIVED_CALLBACK);
1197
1188
  }
1198
1189
  });
1199
1190
  } catch (Exception e) {
1200
- Log.e(NET_TAG, "[registerFeatureFlagsChangeListener] Failed to register listener", e);
1201
1191
  e.printStackTrace();
1202
1192
  }
1203
1193
 
@@ -1212,16 +1202,13 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
1212
1202
  */
1213
1203
  @ReactMethod
1214
1204
  public void isW3ExternalTraceIDEnabled(Promise promise) {
1215
- Log.d(NET_TAG, "[isW3ExternalTraceIDEnabled] Querying native flag");
1205
+
1216
1206
  MainThreadHandler.runOnMainThread(new Runnable() {
1217
1207
  @Override
1218
1208
  public void run() {
1219
1209
  try {
1220
- boolean enabled = InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_EXTERNAL_TRACE_ID);
1221
- Log.d(NET_TAG, "[isW3ExternalTraceIDEnabled] Result=" + enabled);
1222
- promise.resolve(enabled);
1210
+ promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_EXTERNAL_TRACE_ID));
1223
1211
  } catch (Exception e) {
1224
- Log.e(NET_TAG, "[isW3ExternalTraceIDEnabled] Error querying flag", e);
1225
1212
  e.printStackTrace();
1226
1213
  promise.resolve(false);
1227
1214
  }
@@ -1237,16 +1224,13 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
1237
1224
  */
1238
1225
  @ReactMethod
1239
1226
  public void isW3ExternalGeneratedHeaderEnabled(Promise promise) {
1240
- Log.d(NET_TAG, "[isW3ExternalGeneratedHeaderEnabled] Querying native flag");
1227
+
1241
1228
  MainThreadHandler.runOnMainThread(new Runnable() {
1242
1229
  @Override
1243
1230
  public void run() {
1244
1231
  try {
1245
- boolean enabled = InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_GENERATED_HEADER);
1246
- Log.d(NET_TAG, "[isW3ExternalGeneratedHeaderEnabled] Result=" + enabled);
1247
- promise.resolve(enabled);
1232
+ promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_GENERATED_HEADER));
1248
1233
  } catch (Exception e) {
1249
- Log.e(NET_TAG, "[isW3ExternalGeneratedHeaderEnabled] Error querying flag", e);
1250
1234
  e.printStackTrace();
1251
1235
  promise.resolve(false);
1252
1236
  }
@@ -1261,16 +1245,13 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
1261
1245
  */
1262
1246
  @ReactMethod
1263
1247
  public void isW3CaughtHeaderEnabled(Promise promise) {
1264
- Log.d(NET_TAG, "[isW3CaughtHeaderEnabled] Querying native flag");
1248
+
1265
1249
  MainThreadHandler.runOnMainThread(new Runnable() {
1266
1250
  @Override
1267
1251
  public void run() {
1268
1252
  try {
1269
- boolean enabled = InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_CAPTURED_HEADER);
1270
- Log.d(NET_TAG, "[isW3CaughtHeaderEnabled] Result=" + enabled);
1271
- promise.resolve(enabled);
1253
+ promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_CAPTURED_HEADER));
1272
1254
  } catch (Exception e) {
1273
- Log.e(NET_TAG, "[isW3CaughtHeaderEnabled] Error querying flag", e);
1274
1255
  e.printStackTrace();
1275
1256
  promise.resolve(false);
1276
1257
  }
@@ -1364,16 +1345,13 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
1364
1345
  */
1365
1346
  @ReactMethod
1366
1347
  public void getNetworkBodyMaxSize(Promise promise) {
1367
- Log.d(NET_TAG, "[getNetworkBodyMaxSize] Querying network body size limit");
1348
+
1368
1349
  MainThreadHandler.runOnMainThread(new Runnable() {
1369
1350
  @Override
1370
1351
  public void run() {
1371
1352
  try {
1372
- Object limit = InternalCore.INSTANCE.get_networkLogCharLimit();
1373
- Log.d(NET_TAG, "[getNetworkBodyMaxSize] Result=" + limit);
1374
- promise.resolve(limit);
1353
+ promise.resolve(InternalCore.INSTANCE.get_networkLogCharLimit());
1375
1354
  } catch (Exception e) {
1376
- Log.e(NET_TAG, "[getNetworkBodyMaxSize] Error querying limit", e);
1377
1355
  e.printStackTrace();
1378
1356
  promise.resolve(false);
1379
1357
  }
@@ -1395,6 +1373,49 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
1395
1373
  e.printStackTrace();
1396
1374
  }
1397
1375
  }
1376
+
1377
+ /**
1378
+ * Enables or disables WebView monitoring.
1379
+ *
1380
+ * @param isEnabled A boolean to enable/disable WebView monitoring.
1381
+ */
1382
+ @ReactMethod
1383
+ public void setWebViewMonitoringEnabled(final boolean isEnabled) {
1384
+ try {
1385
+ Luciq.setWebViewMonitoringEnabled(isEnabled);
1386
+ } catch (Exception e) {
1387
+ e.printStackTrace();
1388
+ }
1389
+ }
1390
+
1391
+ /**
1392
+ * Enables or disables WebView network tracking.
1393
+ *
1394
+ * @param isEnabled A boolean to enable/disable WebView network tracking.
1395
+ */
1396
+ @ReactMethod
1397
+ public void setWebViewNetworkTrackingEnabled(final boolean isEnabled) {
1398
+ try {
1399
+ Luciq.setWebViewNetworkTrackingEnabled(isEnabled);
1400
+ } catch (Exception e) {
1401
+ e.printStackTrace();
1402
+ }
1403
+ }
1404
+
1405
+ /**
1406
+ * Enables or disables WebView user interactions tracking.
1407
+ *
1408
+ * @param isEnabled A boolean to enable/disable WebView user interactions tracking.
1409
+ */
1410
+ @ReactMethod
1411
+ public void setWebViewUserInteractionsTrackingEnabled(final boolean isEnabled) {
1412
+ try {
1413
+ Luciq.setWebViewUserInteractionsTrackingEnabled(isEnabled);
1414
+ } catch (Exception e) {
1415
+ e.printStackTrace();
1416
+ }
1417
+ }
1418
+
1398
1419
  /**
1399
1420
  * Sets the theme for Luciq using a configuration object.
1400
1421
  *
@@ -20,6 +20,8 @@ public class RNLuciqReactnativePackage implements ReactPackage {
20
20
  @NonNull
21
21
  @Override
22
22
  public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
23
+ RNLuciq.getInstance().setCurrentPlatform();
24
+
23
25
  List<NativeModule> modules = new ArrayList<>();
24
26
  modules.add(new RNLuciqReactnativeModule(reactContext));
25
27
  modules.add(new RNLuciqBugReportingModule(reactContext));
@@ -1,7 +1,5 @@
1
1
  package ai.luciq.reactlibrary.utils;
2
2
 
3
- import android.util.Log;
4
-
5
3
  import androidx.annotation.Nullable;
6
4
  import androidx.annotation.VisibleForTesting;
7
5
 
@@ -12,7 +10,6 @@ import com.facebook.react.bridge.WritableMap;
12
10
  import com.facebook.react.modules.core.DeviceEventManagerModule;
13
11
 
14
12
  public abstract class EventEmitterModule extends ReactContextBaseJavaModule {
15
- private static final String NET_TAG = "LCQ-RN-NET";
16
13
  private int listenerCount = 0;
17
14
 
18
15
  public EventEmitterModule(ReactApplicationContext context) {
@@ -25,18 +22,14 @@ public abstract class EventEmitterModule extends ReactContextBaseJavaModule {
25
22
  getReactApplicationContext()
26
23
  .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
27
24
  .emit(event, params);
28
- } else {
29
- Log.w(NET_TAG, "[EventEmitter] Event DROPPED (no JS listeners): event=" + event + ", module=" + getName() + ", listenerCount=0");
30
25
  }
31
26
  }
32
27
 
33
28
  protected void addListener(String ignoredEvent) {
34
29
  listenerCount++;
35
- Log.d(NET_TAG, "[EventEmitter] addListener — module=" + getName() + ", event=" + ignoredEvent + ", listenerCount=" + listenerCount);
36
30
  }
37
31
 
38
32
  protected void removeListeners(Integer count) {
39
33
  listenerCount -= count;
40
- Log.d(NET_TAG, "[EventEmitter] removeListeners — module=" + getName() + ", removed=" + count + ", listenerCount=" + listenerCount);
41
34
  }
42
35
  }
@@ -6,14 +6,7 @@ import com.facebook.react.bridge.ReadableArray;
6
6
  import com.facebook.react.bridge.ReadableMap;
7
7
  import com.facebook.react.bridge.ReadableMapKeySetIterator;
8
8
  import com.facebook.react.bridge.ReadableType;
9
- import com.facebook.react.bridge.WritableArray;
10
- import com.facebook.react.bridge.WritableNativeArray;
11
9
  import ai.luciq.library.model.Report;
12
- import ai.luciq.library.model.a;
13
-
14
- import org.json.JSONException;
15
-
16
- import java.util.ArrayList;
17
10
 
18
11
 
19
12
  /**
@@ -26,6 +26,21 @@ export declare const init: (config: LuciqConfig) => void;
26
26
  * @param appVariant the current App variant name
27
27
  */
28
28
  export declare const setAppVariant: (appVariant: string) => void;
29
+ /**
30
+ * Enables or disables WebView monitoring.
31
+ * @param isEnabled A boolean to enable/disable WebView monitoring.
32
+ */
33
+ export declare const setWebViewMonitoringEnabled: (isEnabled: boolean) => void;
34
+ /**
35
+ * Enables or disables WebView network tracking.
36
+ * @param isEnabled A boolean to enable/disable WebView network tracking.
37
+ */
38
+ export declare const setWebViewNetworkTrackingEnabled: (isEnabled: boolean) => void;
39
+ /**
40
+ * Enables or disables WebView user interactions tracking.
41
+ * @param isEnabled A boolean to enable/disable WebView user interactions tracking.
42
+ */
43
+ export declare const setWebViewUserInteractionsTrackingEnabled: (isEnabled: boolean) => void;
29
44
  /**
30
45
  * Sets the Code Push version to be sent with each report.
31
46
  * @param version the Code Push version.
@@ -1,7 +1,7 @@
1
1
  import { AppState, findNodeHandle, Platform } from 'react-native';
2
2
  import Report from '../models/Report';
3
3
  import { emitter, NativeEvents, NativeLuciq } from '../native/NativeLuciq';
4
- import { registerFeatureFlagsListener, initFeatureFlagsCache } from '../utils/FeatureFlags';
4
+ import { registerFeatureFlagsListener } from '../utils/FeatureFlags';
5
5
  import { LogLevel, NetworkInterceptionMode, ReproStepsMode, StringKey, } from '../utils/Enums';
6
6
  import LuciqUtils, { checkNetworkRequestHandlers, resetNativeObfuscationListener, setApmNetworkFlagsIfChanged, stringifyIfNotString, } from '../utils/LuciqUtils';
7
7
  import * as NetworkLogger from './NetworkLogger';
@@ -50,7 +50,6 @@ function reportCurrentViewForAndroid(screenName) {
50
50
  * @param config SDK configurations. See {@link LuciqConfig} for more info.
51
51
  */
52
52
  export const init = (config) => {
53
- initFeatureFlagsCache();
54
53
  if (Platform.OS === 'android') {
55
54
  // Add android feature flags listener for android
56
55
  registerFeatureFlagsListener();
@@ -91,6 +90,27 @@ export const init = (config) => {
91
90
  export const setAppVariant = (appVariant) => {
92
91
  NativeLuciq.setAppVariant(appVariant);
93
92
  };
93
+ /**
94
+ * Enables or disables WebView monitoring.
95
+ * @param isEnabled A boolean to enable/disable WebView monitoring.
96
+ */
97
+ export const setWebViewMonitoringEnabled = (isEnabled) => {
98
+ NativeLuciq.setWebViewMonitoringEnabled(isEnabled);
99
+ };
100
+ /**
101
+ * Enables or disables WebView network tracking.
102
+ * @param isEnabled A boolean to enable/disable WebView network tracking.
103
+ */
104
+ export const setWebViewNetworkTrackingEnabled = (isEnabled) => {
105
+ NativeLuciq.setWebViewNetworkTrackingEnabled(isEnabled);
106
+ };
107
+ /**
108
+ * Enables or disables WebView user interactions tracking.
109
+ * @param isEnabled A boolean to enable/disable WebView user interactions tracking.
110
+ */
111
+ export const setWebViewUserInteractionsTrackingEnabled = (isEnabled) => {
112
+ NativeLuciq.setWebViewUserInteractionsTrackingEnabled(isEnabled);
113
+ };
94
114
  /**
95
115
  * Handles app state changes and updates APM network flags if necessary.
96
116
  */
@@ -3,6 +3,11 @@ import { NetworkData, ProgressCallback } from '../utils/XhrNetworkInterceptor';
3
3
  import { NetworkListenerType } from '../native/NativeNetworkLogger';
4
4
  export type { NetworkData };
5
5
  export type NetworkDataObfuscationHandler = (data: NetworkData) => Promise<NetworkData>;
6
+ /**
7
+ * Sets whether network logs should be sent with bug reports.
8
+ * It is enabled by default.
9
+ * @param isEnabled
10
+ */
6
11
  export declare const setEnabled: (isEnabled: boolean) => void;
7
12
  /**
8
13
  * @internal
@@ -20,25 +20,21 @@ function getPortFromUrl(url) {
20
20
  * It is enabled by default.
21
21
  * @param isEnabled
22
22
  */
23
- const NET_TAG = 'LCQ-RN-NET:';
24
23
  export const setEnabled = (isEnabled) => {
25
24
  if (isEnabled) {
26
25
  xhr.enableInterception();
27
26
  xhr.setOnDoneCallback(async (network) => {
28
- Logger.debug(NET_TAG, `[NetworkLogger] onDoneCallback received: ${network.method} ${network.url}, status=${network.responseCode}`);
29
27
  // eslint-disable-next-line no-new-func
30
28
  const predicate = Function('network', 'return ' + _requestFilterExpression);
31
29
  if (!predicate(network)) {
32
30
  const MAX_NETWORK_BODY_SIZE_IN_BYTES = await NativeLuciq.getNetworkBodyMaxSize();
33
31
  try {
34
32
  if (_networkDataObfuscationHandler) {
35
- Logger.debug(NET_TAG, `[NetworkLogger] Running obfuscation handler for ${network.url}`);
36
33
  network = await _networkDataObfuscationHandler(network);
37
34
  }
38
35
  if (__DEV__) {
39
36
  const urlPort = getPortFromUrl(network.url);
40
37
  if (urlPort === LuciqRNConfig.metroDevServerPort) {
41
- Logger.debug(NET_TAG, `[NetworkLogger] Skipping Metro dev server request: ${network.url}`);
42
38
  return;
43
39
  }
44
40
  }
@@ -58,16 +54,12 @@ export const setEnabled = (isEnabled) => {
58
54
  network.responseBody = `Body is omitted because content type ${network.contentType} isn't supported`;
59
55
  Logger.warn(`LCQ-RN: The response body for the network request with URL ${network.url} has been omitted because the content type ${network.contentType} isn't supported.`);
60
56
  }
61
- Logger.debug(NET_TAG, `[NetworkLogger] Reporting network log to native: ${network.method} ${network.url}`);
62
57
  reportNetworkLog(network);
63
58
  }
64
59
  catch (e) {
65
- Logger.error(NET_TAG, `[NetworkLogger] Error processing network log for ${network.url}:`, e);
60
+ Logger.error(e);
66
61
  }
67
62
  }
68
- else {
69
- Logger.debug(NET_TAG, `[NetworkLogger] Request filtered out by predicate: ${network.method} ${network.url}, expression="${_requestFilterExpression}"`);
70
- }
71
63
  });
72
64
  }
73
65
  else {
@@ -77,6 +77,9 @@ export interface LuciqNativeModule extends NativeModule {
77
77
  getNetworkBodyMaxSize(): Promise<number>;
78
78
  setTheme(theme: ThemeConfig): void;
79
79
  setFullscreen(isEnabled: boolean): void;
80
+ setWebViewMonitoringEnabled(isEnabled: boolean): void;
81
+ setWebViewNetworkTrackingEnabled(isEnabled: boolean): void;
82
+ setWebViewUserInteractionsTrackingEnabled(isEnabled: boolean): void;
80
83
  }
81
84
  export declare const NativeLuciq: LuciqNativeModule;
82
85
  export declare enum NativeEvents {
@@ -1,9 +1,3 @@
1
- export declare function initFeatureFlagsCache(): Promise<void>;
2
- export declare function getCachedW3cFlags(): {
3
- isW3cExternalTraceIDEnabled: boolean;
4
- isW3cExternalGeneratedHeaderEnabled: boolean;
5
- isW3cCaughtHeaderEnabled: boolean;
6
- };
7
1
  export declare const FeatureFlags: {
8
2
  isW3ExternalTraceID: () => Promise<boolean>;
9
3
  isW3ExternalGeneratedHeader: () => Promise<boolean>;
@@ -1,34 +1,5 @@
1
1
  import { NativeLuciq } from '../native/NativeLuciq';
2
2
  import { _registerFeatureFlagsChangeListener } from '../modules/Luciq';
3
- import { Logger } from './logger';
4
- const TAG = 'LCQ-RN-NET:';
5
- let cachedW3cFlags = {
6
- isW3cExternalTraceIDEnabled: false,
7
- isW3cExternalGeneratedHeaderEnabled: false,
8
- isW3cCaughtHeaderEnabled: false,
9
- };
10
- export async function initFeatureFlagsCache() {
11
- Logger.debug(TAG, '[FeatureFlags] Initializing W3C feature flags cache from native bridge...');
12
- try {
13
- const [traceID, generatedHeader, caughtHeader] = await Promise.all([
14
- NativeLuciq.isW3ExternalTraceIDEnabled(),
15
- NativeLuciq.isW3ExternalGeneratedHeaderEnabled(),
16
- NativeLuciq.isW3CaughtHeaderEnabled(),
17
- ]);
18
- cachedW3cFlags = {
19
- isW3cExternalTraceIDEnabled: traceID,
20
- isW3cExternalGeneratedHeaderEnabled: generatedHeader,
21
- isW3cCaughtHeaderEnabled: caughtHeader,
22
- };
23
- Logger.debug(TAG, `[FeatureFlags] Cache initialized: traceID=${traceID}, generatedHeader=${generatedHeader}, caughtHeader=${caughtHeader}`);
24
- }
25
- catch (e) {
26
- Logger.debug(TAG, '[FeatureFlags] Failed to initialize cache, using defaults (all false):', e);
27
- }
28
- }
29
- export function getCachedW3cFlags() {
30
- return cachedW3cFlags;
31
- }
32
3
  export const FeatureFlags = {
33
4
  isW3ExternalTraceID: () => NativeLuciq.isW3ExternalTraceIDEnabled(),
34
5
  isW3ExternalGeneratedHeader: () => NativeLuciq.isW3ExternalGeneratedHeaderEnabled(),
@@ -37,12 +8,6 @@ export const FeatureFlags = {
37
8
  };
38
9
  export const registerFeatureFlagsListener = () => {
39
10
  _registerFeatureFlagsChangeListener((res) => {
40
- Logger.debug(TAG, `[FeatureFlags] Flags updated from native listener: traceID=${res.isW3ExternalTraceIDEnabled}, generatedHeader=${res.isW3ExternalGeneratedHeaderEnabled}, caughtHeader=${res.isW3CaughtHeaderEnabled}, bodyLimit=${res.networkBodyLimit}`);
41
- cachedW3cFlags = {
42
- isW3cExternalTraceIDEnabled: res.isW3ExternalTraceIDEnabled,
43
- isW3cExternalGeneratedHeaderEnabled: res.isW3ExternalGeneratedHeaderEnabled,
44
- isW3cCaughtHeaderEnabled: res.isW3CaughtHeaderEnabled,
45
- };
46
11
  FeatureFlags.isW3ExternalTraceID = async () => {
47
12
  return res.isW3ExternalTraceIDEnabled;
48
13
  };