Skip to content

Commit 1c798b2

Browse files
committed
Split sentry file into multiple files, Fix stacktrace merging performance for > 0.46
1 parent c774683 commit 1c798b2

File tree

4 files changed

+1038
-232
lines changed

4 files changed

+1038
-232
lines changed

lib/NativeClient.js

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
import {NativeModules, NativeEventEmitter} from 'react-native';
2+
const {RNSentry, RNSentryEventEmitter} = NativeModules;
3+
import {Sentry, SentrySeverity, SentryLog} from './Sentry';
4+
5+
const DEFAULT_MODULE_IGNORES = [
6+
'AccessibilityManager',
7+
'ActionSheetManager',
8+
'AlertManager',
9+
'AppState',
10+
'AsyncLocalStorage',
11+
'Clipboard',
12+
'DevLoadingView',
13+
'DevMenu',
14+
'ExceptionsManager',
15+
'I18nManager',
16+
'ImageEditingManager',
17+
'ImageStoreManager',
18+
'ImageViewManager',
19+
'IOSConstants',
20+
'JSCExecutor',
21+
'JSCSamplingProfiler',
22+
'KeyboardObserver',
23+
'LinkingManager',
24+
'LocationObserver',
25+
'NativeAnimatedModule',
26+
'NavigatorManager',
27+
'NetInfo',
28+
'Networking',
29+
'RedBox',
30+
'ScrollViewManager',
31+
'SettingsManager',
32+
'SourceCode',
33+
'StatusBarManager',
34+
'Timing',
35+
'UIManager',
36+
'Vibration',
37+
'WebSocketModule',
38+
'WebViewManager'
39+
];
40+
41+
export class NativeClient {
42+
constructor(dsn, options) {
43+
if (dsn.constructor !== String) {
44+
throw new Error('Sentry: A DSN must be provided');
45+
}
46+
if (!RNSentry) {
47+
throw new Error('Sentry: There is no native client installed.');
48+
}
49+
50+
this._dsn = dsn;
51+
this._activatedMerging = false;
52+
this.options = {
53+
ignoreModulesExclude: [],
54+
ignoreModulesInclude: [],
55+
deactivateStacktraceMerging: false
56+
};
57+
Object.assign(this.options, options);
58+
59+
RNSentry.startWithDsnString(this._dsn);
60+
if (this.options.deactivateStacktraceMerging === false) {
61+
this._activateStacktraceMerging();
62+
}
63+
RNSentry.setLogLevel(options.logLevel);
64+
}
65+
66+
nativeCrash() {
67+
RNSentry.crash();
68+
}
69+
70+
captureEvent(event) {
71+
RNSentry.captureEvent(event);
72+
}
73+
74+
setUserContext(user) {
75+
RNSentry.setUser(user);
76+
}
77+
78+
setTagsContext(tags) {
79+
RNSentry.setTags(tags);
80+
}
81+
82+
setExtraContext(extra) {
83+
RNSentry.setExtra(extra);
84+
}
85+
86+
addExtraContext(key, value) {
87+
RNSentry.addExtra(key, value);
88+
}
89+
90+
captureBreadcrumb(crumb) {
91+
RNSentry.captureBreadcrumb(crumb);
92+
}
93+
94+
clearContext() {
95+
RNSentry.clearContext();
96+
}
97+
98+
_activateStacktraceMerging = async () => {
99+
return RNSentry.activateStacktraceMerging()
100+
.then(activated => {
101+
if (this._activatedMerging) {
102+
return;
103+
}
104+
this._ignoredModules = {};
105+
const BatchedBridge = require('react-native/Libraries/BatchedBridge/BatchedBridge');
106+
if (typeof __fbBatchedBridgeConfig !== 'undefined') {
107+
__fbBatchedBridgeConfig.remoteModuleConfig.forEach((module, moduleID) => {
108+
if (
109+
module !== null &&
110+
this.options.ignoreModulesExclude.indexOf(module[0]) === -1 &&
111+
(DEFAULT_MODULE_IGNORES.indexOf(module[0]) >= 0 ||
112+
this.options.ignoreModulesInclude.indexOf(module[0]) >= 0)
113+
) {
114+
this._ignoredModules[moduleID] = true;
115+
}
116+
});
117+
} else if (BatchedBridge._remoteModuleTable) {
118+
for (var module in BatchedBridge._remoteModuleTable) {
119+
if (BatchedBridge._remoteModuleTable.hasOwnProperty(module)) {
120+
let moduleName = BatchedBridge._remoteModuleTable[module];
121+
if (
122+
this.options.ignoreModulesExclude.indexOf(moduleName) === -1 &&
123+
(DEFAULT_MODULE_IGNORES.indexOf(moduleName) >= 0 ||
124+
this.options.ignoreModulesInclude.indexOf(moduleName) >= 0)
125+
) {
126+
this._ignoredModules[module] = true;
127+
}
128+
}
129+
}
130+
}
131+
this._activatedMerging = true;
132+
this._overwriteEnqueueNativeCall();
133+
})
134+
.catch(function(reason) {
135+
console.log(reason);
136+
});
137+
};
138+
139+
_overwriteEnqueueNativeCall() {
140+
const BatchedBridge = require('react-native/Libraries/BatchedBridge/BatchedBridge');
141+
const original = BatchedBridge.enqueueNativeCall;
142+
const that = this;
143+
BatchedBridge.enqueueNativeCall = function(
144+
moduleID: number,
145+
methodID: number,
146+
params: Array<any>,
147+
onFail: ?Function,
148+
onSucc: ?Function
149+
) {
150+
if (that._ignoredModules[moduleID]) {
151+
return original.apply(this, arguments);
152+
}
153+
params.push({
154+
__sentry_stack: new Error().stack
155+
});
156+
return original.apply(this, arguments);
157+
};
158+
}
159+
}

lib/RavenClient.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import Raven from 'raven-js';
2+
import {Sentry, SentrySeverity, SentryLog} from './Sentry';
3+
4+
export class RavenClient {
5+
constructor(dsn, options) {
6+
if (dsn.constructor !== String) {
7+
throw new Error('SentryClient: A DSN must be provided');
8+
}
9+
this._dsn = dsn;
10+
this.options = {
11+
allowSecretKey: true,
12+
allowDuplicates: Sentry.isNativeClientAvailable()
13+
};
14+
Object.assign(this.options, options);
15+
Raven.addPlugin(
16+
require('./raven-plugin'),
17+
{
18+
nativeClientAvailable: Sentry.isNativeClientAvailable()
19+
},
20+
data => {
21+
if (Sentry.options.internal) {
22+
data.dist = Sentry.options.internal['dist'];
23+
}
24+
}
25+
);
26+
27+
Raven.config(dsn, this.options).install();
28+
if (options.logLevel >= SentryLog.Debug) {
29+
Raven.debug = true;
30+
}
31+
if (Sentry.isNativeClientAvailable()) {
32+
// We overwrite the default transport handler when the native
33+
// client is available, because we want to send the event with native
34+
Raven.setTransport(options => {
35+
Sentry._captureEvent(options.data);
36+
});
37+
Raven.setBreadcrumbCallback(Sentry._breadcrumbCallback);
38+
const oldCaptureBreadcrumb = Raven.captureBreadcrumb;
39+
Raven.captureBreadcrumb = function(obj) {
40+
if (obj.data && typeof obj.data === 'object') {
41+
obj.data = Object.assign({}, obj.data);
42+
}
43+
return oldCaptureBreadcrumb.apply(this, arguments);
44+
};
45+
}
46+
}
47+
48+
setDataCallback(callback) {
49+
Raven.setDataCallback(callback);
50+
}
51+
52+
setUserContext(user) {
53+
Raven.setUserContext(user);
54+
}
55+
56+
setTagsContext(tags) {
57+
Raven.setTagsContext(tags);
58+
}
59+
60+
setExtraContext(extra) {
61+
Raven.setExtraContext(extra);
62+
}
63+
64+
captureException(ex, options) {
65+
Raven.captureException(ex, options);
66+
}
67+
68+
captureBreadcrumb(msg, options) {
69+
Raven.captureBreadcrumb(msg, options);
70+
}
71+
72+
captureMessage(message, options) {
73+
Raven.captureMessage(message, options);
74+
}
75+
76+
setRelease(release) {
77+
Raven.setRelease(release);
78+
}
79+
80+
clearContext() {
81+
return Raven.clearContext();
82+
}
83+
84+
context(options, func, args) {
85+
return Raven.context(options, func, args);
86+
}
87+
88+
wrap(options, func, _before) {
89+
return Raven.wrap(options, func, _before);
90+
}
91+
}

0 commit comments

Comments
 (0)