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

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 {
@@ -1 +1 @@
1
- -keep class com.luciq.** {*;}
1
+ -keep class ai.luciq.** {*;}
@@ -30,6 +30,8 @@ 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
+
33
35
  public RNLuciqAPMModule(ReactApplicationContext reactApplicationContext) {
34
36
  super(reactApplicationContext);
35
37
  }
@@ -328,6 +330,7 @@ public class RNLuciqAPMModule extends EventEmitterModule {
328
330
  @Nullable final String gqLCQueryName,
329
331
  @Nullable final String serverErrorMessage
330
332
  ) {
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);
331
334
  try {
332
335
  APMNetworkLogger networkLogger = new APMNetworkLogger();
333
336
 
@@ -349,8 +352,10 @@ public class RNLuciqAPMModule extends EventEmitterModule {
349
352
  }
350
353
 
351
354
  } catch (Exception e) {
355
+ Log.e(NET_TAG, "[networkLogAndroid-APM] Error parsing W3C attributes for " + requestMethod + " " + requestUrl, e);
352
356
  e.printStackTrace();
353
357
  }
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"));
354
359
  APMCPNetworkLog.W3CExternalTraceAttributes w3cExternalTraceAttributes =
355
360
  new APMCPNetworkLog.W3CExternalTraceAttributes(
356
361
  isW3cHeaderFound,
@@ -382,13 +387,17 @@ public class RNLuciqAPMModule extends EventEmitterModule {
382
387
  serverErrorMessage,
383
388
  w3cExternalTraceAttributes
384
389
  );
390
+ Log.d(NET_TAG, "[networkLogAndroid-APM] Successfully invoked APMNetworkLogger.log via reflection: " + requestMethod + " " + requestUrl);
385
391
  } else {
392
+ Log.e(NET_TAG, "[networkLogAndroid-APM] APMNetworkLogger.log method NOT found by reflection — network log will be lost: " + requestMethod + " " + requestUrl);
386
393
  Log.e("IB-CP-Bridge", "APMNetworkLogger.log was not found by reflection");
387
394
  }
388
395
  } catch (Throwable e) {
396
+ Log.e(NET_TAG, "[networkLogAndroid-APM] Exception invoking APMNetworkLogger.log: " + e.getMessage() + " for " + requestMethod + " " + requestUrl, e);
389
397
  e.printStackTrace();
390
398
  }
391
399
  } catch (Throwable e) {
400
+ Log.e(NET_TAG, "[networkLogAndroid-APM] Top-level exception: " + e.getMessage() + " for " + requestMethod + " " + requestUrl, e);
392
401
  e.printStackTrace();
393
402
  }
394
403
  }
@@ -32,6 +32,8 @@ 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
+
35
37
  public final ConcurrentHashMap<String, OnCompleteCallback<NetworkLogSnapshot>> callbackMap = new ConcurrentHashMap<String, OnCompleteCallback<NetworkLogSnapshot>>();
36
38
 
37
39
  public RNLuciqNetworkLoggerModule(ReactApplicationContext reactContext) {
@@ -57,7 +59,9 @@ public class RNLuciqNetworkLoggerModule extends EventEmitterModule {
57
59
  }
58
60
 
59
61
  private boolean getFlagValue(String key) {
60
- return InternalAPM._isFeatureEnabledCP(key, "");
62
+ boolean value = InternalAPM._isFeatureEnabledCP(key, "");
63
+ Log.d(NET_TAG, "[getFlagValue] key=" + key + ", value=" + value);
64
+ return value;
61
65
  }
62
66
 
63
67
  private WritableMap convertFromMapToWritableMap(Map<String, Object> map) {
@@ -86,14 +90,18 @@ public class RNLuciqNetworkLoggerModule extends EventEmitterModule {
86
90
  */
87
91
  @ReactMethod
88
92
  public void isNativeInterceptionEnabled(Promise promise) {
93
+ Log.d(NET_TAG, "[isNativeInterceptionEnabled] Querying CP_NATIVE_INTERCEPTION_ENABLED flag");
89
94
  MainThreadHandler.runOnMainThread(new Runnable() {
90
95
  @Override
91
96
  public void run() {
92
97
  try {
93
- promise.resolve(getFlagValue(CP_NATIVE_INTERCEPTION_ENABLED));
98
+ boolean enabled = getFlagValue(CP_NATIVE_INTERCEPTION_ENABLED);
99
+ Log.d(NET_TAG, "[isNativeInterceptionEnabled] Result=" + enabled);
100
+ promise.resolve(enabled);
94
101
  } catch (Exception e) {
102
+ Log.e(NET_TAG, "[isNativeInterceptionEnabled] Error — falling back to false (JS interceptor)", e);
95
103
  e.printStackTrace();
96
- promise.resolve(false); // Will rollback to JS interceptor
104
+ promise.resolve(false);
97
105
  }
98
106
 
99
107
  }
@@ -107,14 +115,18 @@ public class RNLuciqNetworkLoggerModule extends EventEmitterModule {
107
115
  */
108
116
  @ReactMethod
109
117
  public void hasAPMNetworkPlugin(Promise promise) {
118
+ Log.d(NET_TAG, "[hasAPMNetworkPlugin] Querying APM_NETWORK_PLUGIN_INSTALLED flag");
110
119
  MainThreadHandler.runOnMainThread(new Runnable() {
111
120
  @Override
112
121
  public void run() {
113
122
  try {
114
- promise.resolve(getFlagValue(APM_NETWORK_PLUGIN_INSTALLED));
123
+ boolean hasPlugin = getFlagValue(APM_NETWORK_PLUGIN_INSTALLED);
124
+ Log.d(NET_TAG, "[hasAPMNetworkPlugin] Result=" + hasPlugin);
125
+ promise.resolve(hasPlugin);
115
126
  } catch (Exception e) {
127
+ Log.e(NET_TAG, "[hasAPMNetworkPlugin] Error — falling back to false", e);
116
128
  e.printStackTrace();
117
- promise.resolve(false); // Will rollback to JS interceptor
129
+ promise.resolve(false);
118
130
  }
119
131
 
120
132
  }
@@ -124,12 +136,14 @@ public class RNLuciqNetworkLoggerModule extends EventEmitterModule {
124
136
 
125
137
  @ReactMethod
126
138
  public void registerNetworkLogsListener() {
139
+ Log.d(NET_TAG, "[registerNetworkLogsListener] Registering network log sanitizer");
127
140
  MainThreadHandler.runOnMainThread(new Runnable() {
128
141
  @Override
129
142
  public void run() {
130
143
  InternalAPM._registerNetworkLogSanitizer((networkLogSnapshot, onCompleteCallback) -> {
131
144
  final String id = String.valueOf(onCompleteCallback.hashCode());
132
145
  callbackMap.put(id, onCompleteCallback);
146
+ Log.d(NET_TAG, "[NetworkLogSanitizer] Received snapshot — id=" + id + ", url=" + networkLogSnapshot.getUrl() + ", responseCode=" + networkLogSnapshot.getResponseCode() + ", callbackMapSize=" + callbackMap.size());
133
147
 
134
148
  WritableMap networkSnapshotParams = Arguments.createMap();
135
149
  networkSnapshotParams.putString("id", id);
@@ -147,6 +161,7 @@ public class RNLuciqNetworkLoggerModule extends EventEmitterModule {
147
161
  }
148
162
 
149
163
  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());
150
165
  });
151
166
  }
152
167
  });
@@ -154,10 +169,12 @@ public class RNLuciqNetworkLoggerModule extends EventEmitterModule {
154
169
 
155
170
  @ReactMethod
156
171
  public void resetNetworkLogsListener() {
172
+ Log.d(NET_TAG, "[resetNetworkLogsListener] Clearing network log sanitizer, callbackMapSize=" + callbackMap.size());
157
173
  MainThreadHandler.runOnMainThread(new Runnable() {
158
174
  @Override
159
175
  public void run() {
160
176
  InternalAPM._registerNetworkLogSanitizer(null);
177
+ Log.d(NET_TAG, "[resetNetworkLogsListener] Sanitizer cleared");
161
178
  }
162
179
  });
163
180
  }
@@ -172,23 +189,28 @@ public class RNLuciqNetworkLoggerModule extends EventEmitterModule {
172
189
  ReadableMap requestHeaders,
173
190
  ReadableMap responseHeaders
174
191
  ) {
192
+ Log.d(NET_TAG, "[updateNetworkLogSnapshot] callbackID=" + callbackID + ", url=" + url + ", responseCode=" + responseCode + ", callbackMapSize=" + callbackMap.size());
175
193
  try {
176
- // Convert ReadableMap to a Java Map for easier handling
177
194
  Map<String, Object> requestHeadersMap = convertReadableMapToMap(requestHeaders);
178
195
  Map<String, Object> responseHeadersMap = convertReadableMapToMap(responseHeaders);
179
196
 
180
197
  NetworkLogSnapshot modifiedSnapshot = null;
181
198
  if (!url.isEmpty()) {
182
199
  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)");
183
202
  }
184
203
 
185
204
  final OnCompleteCallback<NetworkLogSnapshot> callback = callbackMap.get(callbackID);
186
205
  if (callback != null) {
187
206
  callback.onComplete(modifiedSnapshot);
188
207
  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());
189
211
  }
190
212
  } catch (Exception e) {
191
- // Reject the promise to indicate an error occurred
213
+ Log.e(NET_TAG, "[updateNetworkLogSnapshot] Exception processing snapshot: " + e.getMessage() + " for callbackID=" + callbackID, e);
192
214
  Log.e("IB-CP-Bridge", "LuciqNetworkLogger.updateNetworkLogSnapshot failed to parse the network snapshot object.");
193
215
  }
194
216
  }
@@ -86,6 +86,7 @@ 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";
89
90
 
90
91
  private LuciqCustomTextPlaceHolder placeHolders;
91
92
  private static Report currentReport;
@@ -163,6 +164,7 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
163
164
 
164
165
 
165
166
  ) {
167
+ Log.d(NET_TAG, "[init] Called — logLevel=" + logLevel + ", useNativeNetworkInterception=" + useNativeNetworkInterception + ", codePushVersion=" + codePushVersion + ", appVariant=" + appVariant);
166
168
  MainThreadHandler.runOnMainThread(new Runnable() {
167
169
  @Override
168
170
  public void run() {
@@ -204,6 +206,7 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
204
206
  }
205
207
 
206
208
  builder.build();
209
+ Log.d(NET_TAG, "[init] SDK build complete");
207
210
  }
208
211
  });
209
212
  }
@@ -969,6 +972,7 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
969
972
  final String requestHeaders,
970
973
  final String responseHeaders,
971
974
  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));
972
976
  try {
973
977
  final String date = String.valueOf(System.currentTimeMillis());
974
978
 
@@ -985,11 +989,14 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
985
989
  networkLog.setRequestHeaders(requestHeaders);
986
990
  networkLog.setResponseHeaders(responseHeaders);
987
991
  } catch (OutOfMemoryError | Exception exception) {
992
+ Log.e(NET_TAG, "[networkLogAndroid-Core] OOM/Error setting log contents: " + exception.getMessage() + " for " + method + " " + url);
988
993
  Log.d(TAG, "Error: " + exception.getMessage() + "while trying to set network log contents (request body, response body, request headers, and response headers).");
989
994
  }
990
995
 
991
996
  networkLog.insert();
997
+ Log.d(NET_TAG, "[networkLogAndroid-Core] Successfully inserted NetworkLog: " + method + " " + url);
992
998
  } catch (OutOfMemoryError | Exception exception) {
999
+ Log.e(NET_TAG, "[networkLogAndroid-Core] OOM/Error inserting network log: " + exception.getMessage() + " for " + method + " " + url);
993
1000
  Log.d(TAG, "Error: " + exception.getMessage() + "while trying to insert a network log");
994
1001
  }
995
1002
  }
@@ -1170,7 +1177,7 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
1170
1177
  */
1171
1178
  @ReactMethod
1172
1179
  public void registerFeatureFlagsChangeListener() {
1173
-
1180
+ Log.d(NET_TAG, "[registerFeatureFlagsChangeListener] Registering native feature flags listener");
1174
1181
  MainThreadHandler.runOnMainThread(new Runnable() {
1175
1182
  @Override
1176
1183
  public void run() {
@@ -1178,6 +1185,7 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
1178
1185
  InternalCore.INSTANCE._setFeaturesStateListener(new FeaturesStateListener() {
1179
1186
  @Override
1180
1187
  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());
1181
1189
  WritableMap params = Arguments.createMap();
1182
1190
  params.putBoolean("isW3ExternalTraceIDEnabled", featuresState.isW3CExternalTraceIdEnabled());
1183
1191
  params.putBoolean("isW3ExternalGeneratedHeaderEnabled", featuresState.isAttachingGeneratedHeaderEnabled());
@@ -1185,9 +1193,11 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
1185
1193
  params.putInt("networkBodyLimit",featuresState.getNetworkLogCharLimit());
1186
1194
 
1187
1195
  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);
1188
1197
  }
1189
1198
  });
1190
1199
  } catch (Exception e) {
1200
+ Log.e(NET_TAG, "[registerFeatureFlagsChangeListener] Failed to register listener", e);
1191
1201
  e.printStackTrace();
1192
1202
  }
1193
1203
 
@@ -1202,13 +1212,16 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
1202
1212
  */
1203
1213
  @ReactMethod
1204
1214
  public void isW3ExternalTraceIDEnabled(Promise promise) {
1205
-
1215
+ Log.d(NET_TAG, "[isW3ExternalTraceIDEnabled] Querying native flag");
1206
1216
  MainThreadHandler.runOnMainThread(new Runnable() {
1207
1217
  @Override
1208
1218
  public void run() {
1209
1219
  try {
1210
- promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_EXTERNAL_TRACE_ID));
1220
+ boolean enabled = InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_EXTERNAL_TRACE_ID);
1221
+ Log.d(NET_TAG, "[isW3ExternalTraceIDEnabled] Result=" + enabled);
1222
+ promise.resolve(enabled);
1211
1223
  } catch (Exception e) {
1224
+ Log.e(NET_TAG, "[isW3ExternalTraceIDEnabled] Error querying flag", e);
1212
1225
  e.printStackTrace();
1213
1226
  promise.resolve(false);
1214
1227
  }
@@ -1224,13 +1237,16 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
1224
1237
  */
1225
1238
  @ReactMethod
1226
1239
  public void isW3ExternalGeneratedHeaderEnabled(Promise promise) {
1227
-
1240
+ Log.d(NET_TAG, "[isW3ExternalGeneratedHeaderEnabled] Querying native flag");
1228
1241
  MainThreadHandler.runOnMainThread(new Runnable() {
1229
1242
  @Override
1230
1243
  public void run() {
1231
1244
  try {
1232
- promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_GENERATED_HEADER));
1245
+ boolean enabled = InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_GENERATED_HEADER);
1246
+ Log.d(NET_TAG, "[isW3ExternalGeneratedHeaderEnabled] Result=" + enabled);
1247
+ promise.resolve(enabled);
1233
1248
  } catch (Exception e) {
1249
+ Log.e(NET_TAG, "[isW3ExternalGeneratedHeaderEnabled] Error querying flag", e);
1234
1250
  e.printStackTrace();
1235
1251
  promise.resolve(false);
1236
1252
  }
@@ -1245,13 +1261,16 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
1245
1261
  */
1246
1262
  @ReactMethod
1247
1263
  public void isW3CaughtHeaderEnabled(Promise promise) {
1248
-
1264
+ Log.d(NET_TAG, "[isW3CaughtHeaderEnabled] Querying native flag");
1249
1265
  MainThreadHandler.runOnMainThread(new Runnable() {
1250
1266
  @Override
1251
1267
  public void run() {
1252
1268
  try {
1253
- promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_CAPTURED_HEADER));
1269
+ boolean enabled = InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_CAPTURED_HEADER);
1270
+ Log.d(NET_TAG, "[isW3CaughtHeaderEnabled] Result=" + enabled);
1271
+ promise.resolve(enabled);
1254
1272
  } catch (Exception e) {
1273
+ Log.e(NET_TAG, "[isW3CaughtHeaderEnabled] Error querying flag", e);
1255
1274
  e.printStackTrace();
1256
1275
  promise.resolve(false);
1257
1276
  }
@@ -1345,13 +1364,16 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
1345
1364
  */
1346
1365
  @ReactMethod
1347
1366
  public void getNetworkBodyMaxSize(Promise promise) {
1348
-
1367
+ Log.d(NET_TAG, "[getNetworkBodyMaxSize] Querying network body size limit");
1349
1368
  MainThreadHandler.runOnMainThread(new Runnable() {
1350
1369
  @Override
1351
1370
  public void run() {
1352
1371
  try {
1353
- promise.resolve(InternalCore.INSTANCE.get_networkLogCharLimit());
1372
+ Object limit = InternalCore.INSTANCE.get_networkLogCharLimit();
1373
+ Log.d(NET_TAG, "[getNetworkBodyMaxSize] Result=" + limit);
1374
+ promise.resolve(limit);
1354
1375
  } catch (Exception e) {
1376
+ Log.e(NET_TAG, "[getNetworkBodyMaxSize] Error querying limit", e);
1355
1377
  e.printStackTrace();
1356
1378
  promise.resolve(false);
1357
1379
  }
@@ -1373,6 +1395,49 @@ public class RNLuciqReactnativeModule extends EventEmitterModule {
1373
1395
  e.printStackTrace();
1374
1396
  }
1375
1397
  }
1398
+
1399
+ /**
1400
+ * Enables or disables WebView monitoring.
1401
+ *
1402
+ * @param isEnabled A boolean to enable/disable WebView monitoring.
1403
+ */
1404
+ @ReactMethod
1405
+ public void setWebViewMonitoringEnabled(final boolean isEnabled) {
1406
+ try {
1407
+ Luciq.setWebViewMonitoringEnabled(isEnabled);
1408
+ } catch (Exception e) {
1409
+ e.printStackTrace();
1410
+ }
1411
+ }
1412
+
1413
+ /**
1414
+ * Enables or disables WebView network tracking.
1415
+ *
1416
+ * @param isEnabled A boolean to enable/disable WebView network tracking.
1417
+ */
1418
+ @ReactMethod
1419
+ public void setWebViewNetworkTrackingEnabled(final boolean isEnabled) {
1420
+ try {
1421
+ Luciq.setWebViewNetworkTrackingEnabled(isEnabled);
1422
+ } catch (Exception e) {
1423
+ e.printStackTrace();
1424
+ }
1425
+ }
1426
+
1427
+ /**
1428
+ * Enables or disables WebView user interactions tracking.
1429
+ *
1430
+ * @param isEnabled A boolean to enable/disable WebView user interactions tracking.
1431
+ */
1432
+ @ReactMethod
1433
+ public void setWebViewUserInteractionsTrackingEnabled(final boolean isEnabled) {
1434
+ try {
1435
+ Luciq.setWebViewUserInteractionsTrackingEnabled(isEnabled);
1436
+ } catch (Exception e) {
1437
+ e.printStackTrace();
1438
+ }
1439
+ }
1440
+
1376
1441
  /**
1377
1442
  * Sets the theme for Luciq using a configuration object.
1378
1443
  *
@@ -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,5 +1,7 @@
1
1
  package ai.luciq.reactlibrary.utils;
2
2
 
3
+ import android.util.Log;
4
+
3
5
  import androidx.annotation.Nullable;
4
6
  import androidx.annotation.VisibleForTesting;
5
7
 
@@ -10,6 +12,7 @@ import com.facebook.react.bridge.WritableMap;
10
12
  import com.facebook.react.modules.core.DeviceEventManagerModule;
11
13
 
12
14
  public abstract class EventEmitterModule extends ReactContextBaseJavaModule {
15
+ private static final String NET_TAG = "LCQ-RN-NET";
13
16
  private int listenerCount = 0;
14
17
 
15
18
  public EventEmitterModule(ReactApplicationContext context) {
@@ -22,14 +25,18 @@ public abstract class EventEmitterModule extends ReactContextBaseJavaModule {
22
25
  getReactApplicationContext()
23
26
  .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
24
27
  .emit(event, params);
28
+ } else {
29
+ Log.w(NET_TAG, "[EventEmitter] Event DROPPED (no JS listeners): event=" + event + ", module=" + getName() + ", listenerCount=0");
25
30
  }
26
31
  }
27
32
 
28
33
  protected void addListener(String ignoredEvent) {
29
34
  listenerCount++;
35
+ Log.d(NET_TAG, "[EventEmitter] addListener — module=" + getName() + ", event=" + ignoredEvent + ", listenerCount=" + listenerCount);
30
36
  }
31
37
 
32
38
  protected void removeListeners(Integer count) {
33
39
  listenerCount -= count;
40
+ Log.d(NET_TAG, "[EventEmitter] removeListeners — module=" + getName() + ", removed=" + count + ", listenerCount=" + listenerCount);
34
41
  }
35
42
  }
@@ -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 } from '../utils/FeatureFlags';
4
+ import { registerFeatureFlagsListener, initFeatureFlagsCache } 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,6 +50,7 @@ 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();
53
54
  if (Platform.OS === 'android') {
54
55
  // Add android feature flags listener for android
55
56
  registerFeatureFlagsListener();
@@ -90,6 +91,27 @@ export const init = (config) => {
90
91
  export const setAppVariant = (appVariant) => {
91
92
  NativeLuciq.setAppVariant(appVariant);
92
93
  };
94
+ /**
95
+ * Enables or disables WebView monitoring.
96
+ * @param isEnabled A boolean to enable/disable WebView monitoring.
97
+ */
98
+ export const setWebViewMonitoringEnabled = (isEnabled) => {
99
+ NativeLuciq.setWebViewMonitoringEnabled(isEnabled);
100
+ };
101
+ /**
102
+ * Enables or disables WebView network tracking.
103
+ * @param isEnabled A boolean to enable/disable WebView network tracking.
104
+ */
105
+ export const setWebViewNetworkTrackingEnabled = (isEnabled) => {
106
+ NativeLuciq.setWebViewNetworkTrackingEnabled(isEnabled);
107
+ };
108
+ /**
109
+ * Enables or disables WebView user interactions tracking.
110
+ * @param isEnabled A boolean to enable/disable WebView user interactions tracking.
111
+ */
112
+ export const setWebViewUserInteractionsTrackingEnabled = (isEnabled) => {
113
+ NativeLuciq.setWebViewUserInteractionsTrackingEnabled(isEnabled);
114
+ };
93
115
  /**
94
116
  * Handles app state changes and updates APM network flags if necessary.
95
117
  */
@@ -3,11 +3,6 @@ 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
- */
11
6
  export declare const setEnabled: (isEnabled: boolean) => void;
12
7
  /**
13
8
  * @internal
@@ -20,21 +20,25 @@ function getPortFromUrl(url) {
20
20
  * It is enabled by default.
21
21
  * @param isEnabled
22
22
  */
23
+ const NET_TAG = 'LCQ-RN-NET:';
23
24
  export const setEnabled = (isEnabled) => {
24
25
  if (isEnabled) {
25
26
  xhr.enableInterception();
26
27
  xhr.setOnDoneCallback(async (network) => {
28
+ Logger.debug(NET_TAG, `[NetworkLogger] onDoneCallback received: ${network.method} ${network.url}, status=${network.responseCode}`);
27
29
  // eslint-disable-next-line no-new-func
28
30
  const predicate = Function('network', 'return ' + _requestFilterExpression);
29
31
  if (!predicate(network)) {
30
32
  const MAX_NETWORK_BODY_SIZE_IN_BYTES = await NativeLuciq.getNetworkBodyMaxSize();
31
33
  try {
32
34
  if (_networkDataObfuscationHandler) {
35
+ Logger.debug(NET_TAG, `[NetworkLogger] Running obfuscation handler for ${network.url}`);
33
36
  network = await _networkDataObfuscationHandler(network);
34
37
  }
35
38
  if (__DEV__) {
36
39
  const urlPort = getPortFromUrl(network.url);
37
40
  if (urlPort === LuciqRNConfig.metroDevServerPort) {
41
+ Logger.debug(NET_TAG, `[NetworkLogger] Skipping Metro dev server request: ${network.url}`);
38
42
  return;
39
43
  }
40
44
  }
@@ -54,12 +58,16 @@ export const setEnabled = (isEnabled) => {
54
58
  network.responseBody = `Body is omitted because content type ${network.contentType} isn't supported`;
55
59
  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.`);
56
60
  }
61
+ Logger.debug(NET_TAG, `[NetworkLogger] Reporting network log to native: ${network.method} ${network.url}`);
57
62
  reportNetworkLog(network);
58
63
  }
59
64
  catch (e) {
60
- Logger.error(e);
65
+ Logger.error(NET_TAG, `[NetworkLogger] Error processing network log for ${network.url}:`, e);
61
66
  }
62
67
  }
68
+ else {
69
+ Logger.debug(NET_TAG, `[NetworkLogger] Request filtered out by predicate: ${network.method} ${network.url}, expression="${_requestFilterExpression}"`);
70
+ }
63
71
  });
64
72
  }
65
73
  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,3 +1,9 @@
1
+ export declare function initFeatureFlagsCache(): Promise<void>;
2
+ export declare function getCachedW3cFlags(): {
3
+ isW3cExternalTraceIDEnabled: boolean;
4
+ isW3cExternalGeneratedHeaderEnabled: boolean;
5
+ isW3cCaughtHeaderEnabled: boolean;
6
+ };
1
7
  export declare const FeatureFlags: {
2
8
  isW3ExternalTraceID: () => Promise<boolean>;
3
9
  isW3ExternalGeneratedHeader: () => Promise<boolean>;