@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 +15 -0
- package/android/native.gradle +1 -1
- package/android/src/main/java/ai/luciq/reactlibrary/RNLuciqAPMModule.java +0 -9
- package/android/src/main/java/ai/luciq/reactlibrary/RNLuciqNetworkLoggerModule.java +7 -29
- package/android/src/main/java/ai/luciq/reactlibrary/RNLuciqReactnativeModule.java +52 -31
- package/android/src/main/java/ai/luciq/reactlibrary/RNLuciqReactnativePackage.java +2 -0
- package/android/src/main/java/ai/luciq/reactlibrary/utils/EventEmitterModule.java +0 -7
- package/android/src/main/java/ai/luciq/reactlibrary/utils/ReportUtil.java +0 -7
- package/dist/modules/Luciq.d.ts +15 -0
- package/dist/modules/Luciq.js +22 -2
- package/dist/modules/NetworkLogger.d.ts +5 -0
- package/dist/modules/NetworkLogger.js +1 -9
- package/dist/native/NativeLuciq.d.ts +3 -0
- package/dist/utils/FeatureFlags.d.ts +0 -6
- package/dist/utils/FeatureFlags.js +0 -35
- package/dist/utils/LuciqUtils.js +0 -6
- package/dist/utils/XhrNetworkInterceptor.js +53 -85
- package/ios/RNLuciq/LuciqReactBridge.m +12 -0
- package/ios/native.rb +1 -1
- package/package.json +2 -1
- package/src/modules/Luciq.ts +25 -3
- package/src/modules/NetworkLogger.ts +1 -26
- package/src/native/NativeLuciq.ts +5 -0
- package/src/utils/FeatureFlags.ts +0 -44
- package/src/utils/LuciqUtils.ts +0 -15
- package/src/utils/XhrNetworkInterceptor.ts +55 -128
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
|
package/android/native.gradle
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1205
|
+
|
|
1216
1206
|
MainThreadHandler.runOnMainThread(new Runnable() {
|
|
1217
1207
|
@Override
|
|
1218
1208
|
public void run() {
|
|
1219
1209
|
try {
|
|
1220
|
-
|
|
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
|
-
|
|
1227
|
+
|
|
1241
1228
|
MainThreadHandler.runOnMainThread(new Runnable() {
|
|
1242
1229
|
@Override
|
|
1243
1230
|
public void run() {
|
|
1244
1231
|
try {
|
|
1245
|
-
|
|
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
|
-
|
|
1248
|
+
|
|
1265
1249
|
MainThreadHandler.runOnMainThread(new Runnable() {
|
|
1266
1250
|
@Override
|
|
1267
1251
|
public void run() {
|
|
1268
1252
|
try {
|
|
1269
|
-
|
|
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
|
-
|
|
1348
|
+
|
|
1368
1349
|
MainThreadHandler.runOnMainThread(new Runnable() {
|
|
1369
1350
|
@Override
|
|
1370
1351
|
public void run() {
|
|
1371
1352
|
try {
|
|
1372
|
-
|
|
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
|
/**
|
package/dist/modules/Luciq.d.ts
CHANGED
|
@@ -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.
|
package/dist/modules/Luciq.js
CHANGED
|
@@ -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
|
|
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(
|
|
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
|
};
|