Skip to content

Commit 1e5bfae

Browse files
authored
Feature/network logging (#26)
* ✨ add custom listeners and constants * ✨ add responseObfuscationHandler and setRequestFilterPredicate * ✨ add XMLHttpRequest network interceptor * ✨ add setOnProgressForRequestHandler * ✨ add network log support for iOS * 🐛 fix network logging disabled in ios, duration always 0, status code nil and responseHeaders not parsed as an NSDictionary * 🐛 fix issue with XHR undefined and handle getting json response from blob * 📝 change duration to be measured in ms instead of s * 📝 Move all network logging APIs to a separate NetworkLogger module * 🐛 add missing comma causing breaking iOS build * ✨ Enable network logging by default * ✨ Add typescript type defs for the NetworkLogger module * 🔥 remove ios debug logs * Add network logging guide to the README * 📝 change name of API
1 parent c315e04 commit 1e5bfae

File tree

8 files changed

+314
-3
lines changed

8 files changed

+314
-3
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,18 @@ export INSTABUG_APP_TOKEN="YOUR_APP_TOKEN"
197197
bash "../node_modules/instabug-reactnative/ios/upload_sourcemap.sh"
198198
```
199199
200+
## Network Logging
201+
202+
Instabug network logging is enabled by default. It intercepts any requests performed with `fetch` or `XMLHttpRequest` and attaches them to the report that will be sent to the dashboard. To disable network logs:
203+
204+
```javascript
205+
import { NetworkLogger } from 'instabug-reactnative';
206+
```
207+
208+
```javascript
209+
NetworkLogger.setEnabled(false);
210+
```
211+
200212
## Documentation
201213
202214
For more details about the supported APIs and how to use them, check our [**Documentation**](https://docs.instabug.com/docs/react-native-overview).

android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,6 @@ public void run() {
544544
});
545545
}
546546

547-
548547
/**
549548
* Sets whether attachments in bug reporting and in-app messaging are enabled or not.
550549
*
@@ -1889,6 +1888,29 @@ public void setEmailFieldRequiredForFeatureRequests(boolean isEmailRequired, Rea
18891888
}
18901889
}
18911890

1891+
/**
1892+
* Extracts HTTP connection properties. Request method, Headers, Date, Url and Response code
1893+
*
1894+
* @param jsonObject the JSON object containing all HTTP connection properties
1895+
* @throws JSONException
1896+
*/
1897+
@ReactMethod
1898+
public void networkLog(String jsonObject) throws JSONException {
1899+
NetworkLog networkLog = new NetworkLog();
1900+
String date = System.currentTimeMillis()+"";
1901+
networkLog.setDate(date);
1902+
JSONObject newJSONObject = new JSONObject(jsonObject);
1903+
networkLog.setUrl(newJSONObject.getString("url"));
1904+
networkLog.setRequest(newJSONObject.getString("requestBody"));
1905+
networkLog.setResponse(newJSONObject.getString("responseBody"));
1906+
networkLog.setMethod(newJSONObject.getString("method"));
1907+
networkLog.setResponseCode(newJSONObject.getInt("responseCode"));
1908+
networkLog.setRequestHeaders(newJSONObject.getString("requestHeaders"));
1909+
networkLog.setResponseHeaders(newJSONObject.getString("responseHeaders"));
1910+
networkLog.insert();
1911+
}
1912+
1913+
18921914
@ReactMethod
18931915
public void setSecureViews(ReadableArray ids) {
18941916
int[] arrayOfIds = new int[ids.size()];

index.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ export namespace Surveys {
112112
): void;
113113
function setShouldShowWelcomeScreen(shouldShowWelcomeScreen: boolean): void;
114114
}
115+
export namespace NetworkLogger {
116+
function setEnabled(isEnabled: boolean): void;
117+
function setNetworkDataObfuscationHandler(handler: () => void): void;
118+
function setRequestFilterExpression(expression: string): void;
119+
function setProgressHandlerForRequest(handler: () => void): void;
120+
}
115121
export function startWithToken(
116122
token: string,
117123
invocationEvent: invocationEvent[]

index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ import FeatureRequests from './modules/FeatureRequests';
1414
import Chats from './modules/Chats';
1515
import Replies from './modules/Replies';
1616
import CrashReporting from './modules/CrashReporting';
17+
import NetworkLogger from './modules/NetworkLogger';
1718

1819
InstabugUtils.captureJsErrors();
20+
NetworkLogger.setEnabled(true);
21+
22+
1923

2024
/**
2125
* Instabug
@@ -973,7 +977,8 @@ export {
973977
FeatureRequests,
974978
Chats,
975979
Replies,
976-
CrashReporting
980+
CrashReporting,
981+
NetworkLogger
977982
};
978983

979984
export default InstabugModule;

ios/RNInstabug/InstabugReactBridge.m

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ @implementation InstabugReactBridge
2727
@"IBGWillShowSurvey",
2828
@"IBGDidDismissSurvey",
2929
@"IBGDidSelectPromptOptionHandler",
30+
@"IBGSetNetworkDataObfuscationHandler",
3031
@"IBGOnNewReplyReceivedCallback"
3132
];
3233
}
@@ -46,13 +47,15 @@ - (dispatch_queue_t)methodQueue {
4647
[Instabug startWithToken:token invocationEvents:invocationEvents];
4748
RCTAddLogFunction(InstabugReactLogFunction);
4849
RCTSetLogThreshold(RCTLogLevelInfo);
49-
IBGNetworkLogger.enabled = NO;
50+
5051
SEL setCrossPlatformSEL = NSSelectorFromString(@"setCrossPlatform:");
5152
if ([[Instabug class] respondsToSelector:setCrossPlatformSEL]) {
5253
[[Instabug class] performSelector:setCrossPlatformSEL withObject:@(true)];
5354
}
5455

56+
IBGNetworkLogger.enabled = YES;
5557
[self setBaseUrlForDeprecationLogs];
58+
5659
}
5760

5861
RCT_EXPORT_METHOD(callPrivateApi:(NSString *)apiName apiParam: (NSString *) param) {
@@ -530,11 +533,44 @@ - (dispatch_queue_t)methodQueue {
530533
callback(@[[NSNumber numberWithBool:result]]);
531534
}
532535

536+
RCT_EXPORT_METHOD(networkLog:(NSDictionary *) networkData) {
537+
NSString* url = networkData[@"url"];
538+
NSString* method = networkData[@"method"];
539+
NSString* requestBody = networkData[@"requestBody"];
540+
NSString* responseBody = networkData[@"responseBody"];
541+
int32_t responseCode = [networkData[@"responseCode"] integerValue];
542+
NSDictionary* requestHeaders = networkData[@"requestHeaders"];
543+
NSDictionary* responseHeaders = networkData[@"responseHeaders"];
544+
NSString* contentType = networkData[@"contentType"];
545+
double duration = [networkData[@"duration"] doubleValue];
546+
547+
SEL networkLogSEL = NSSelectorFromString(@"addNetworkLogWithUrl:method:requestBody:responseBody:responseCode:requestHeaders:responseHeaders:contentType:duration:");
548+
549+
if([[IBGNetworkLogger class] respondsToSelector:networkLogSEL]) {
550+
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[[IBGNetworkLogger class] methodSignatureForSelector:networkLogSEL]];
551+
[inv setSelector:networkLogSEL];
552+
[inv setTarget:[IBGNetworkLogger class]];
553+
554+
[inv setArgument:&(url) atIndex:2];
555+
[inv setArgument:&(method) atIndex:3];
556+
[inv setArgument:&(requestBody) atIndex:4];
557+
[inv setArgument:&(responseBody) atIndex:5];
558+
[inv setArgument:&(responseCode) atIndex:6];
559+
[inv setArgument:&(requestHeaders) atIndex:7];
560+
[inv setArgument:&(responseHeaders) atIndex:8];
561+
[inv setArgument:&(contentType) atIndex:9];
562+
[inv setArgument:&(duration) atIndex:10];
563+
564+
[inv invoke];
565+
}
566+
}
567+
533568
RCT_EXPORT_METHOD(hideView: (nonnull NSNumber *)reactTag) {
534569
UIView* view = [self.bridge.uiManager viewForReactTag:reactTag];
535570
view.instabug_privateView = true;
536571

537572
}
573+
538574
RCT_EXPORT_METHOD(show) {
539575
[Instabug show];
540576
}
@@ -589,6 +625,7 @@ - (dispatch_queue_t)methodQueue {
589625
} else {
590626
IBGReplies.didReceiveReplyHandler = nil;
591627
}
628+
592629
}
593630

594631
- (NSDictionary *)constantsToExport

modules/NetworkLogger.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { NativeModules, Platform } from 'react-native';
2+
import xhr from '../utils/XhrNetworkInterceptor';
3+
import IBGEventEmitter from '../utils/IBGEventEmitter.js';
4+
import InstabugConstants from '../utils/InstabugConstants';
5+
let { Instabug } = NativeModules;
6+
7+
8+
var _networkDataObfuscationHandlerSet = false;
9+
var _requestFilterExpression = false;
10+
11+
/**
12+
* NetworkLogger
13+
* @exports NetworkLogger
14+
*/
15+
export default {
16+
/**
17+
* Sets whether network logs should be sent with bug reports.
18+
* It is enabled by default.
19+
* @param {boolean} isEnabled
20+
*/
21+
setEnabled(isEnabled) {
22+
if (isEnabled) {
23+
xhr.enableInterception();
24+
xhr.setOnDoneCallback(network => {
25+
if (!eval(_requestFilterExpression)) {
26+
if (_networkDataObfuscationHandlerSet) {
27+
IBGEventEmitter.emit(
28+
InstabugConstants.NETWORK_DATA_OBFUSCATION_HANDLER_EVENT,
29+
network
30+
);
31+
} else {
32+
if (Platform.OS === 'android') {
33+
Instabug.networkLog(JSON.stringify(network));
34+
} else {
35+
Instabug.networkLog(network);
36+
}
37+
}
38+
}
39+
});
40+
} else {
41+
xhr.disableInterception();
42+
}
43+
},
44+
45+
/**
46+
* Obfuscates any response data.
47+
* @param {function} handler
48+
*/
49+
setNetworkDataObfuscationHandler(handler) {
50+
if (handler !== null) {
51+
_networkDataObfuscationHandlerSet = true;
52+
}
53+
IBGEventEmitter.addListener(
54+
InstabugConstants.NETWORK_DATA_OBFUSCATION_HANDLER_EVENT,
55+
async data => {
56+
try {
57+
const newData = await handler(data);
58+
if (Platform.OS === 'android') {
59+
Instabug.networkLog(JSON.stringify(newData));
60+
} else {
61+
Instabug.networkLog(newData);
62+
}
63+
} catch (e) {
64+
console.error(e);
65+
}
66+
}
67+
);
68+
},
69+
70+
71+
/**
72+
* Omit requests from being logged based on either their request or response details
73+
* @param {string} expression
74+
*/
75+
setRequestFilterExpression(expression) {
76+
_requestFilterExpression = expression;
77+
},
78+
79+
/**
80+
* Returns progress in terms of totalBytesSent and totalBytesExpectedToSend a network request.
81+
* @param {function} handler
82+
*/
83+
setProgressHandlerForRequest(handler) {
84+
xhr.setOnProgressCallback(handler);
85+
},
86+
87+
88+
};

utils/InstabugConstants.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default {
2+
NETWORK_DATA_OBFUSCATION_HANDLER_EVENT: 'IBGSetNetworkDataObfuscationHandler',
3+
};

0 commit comments

Comments
 (0)