@sentry/react 7.0.0-alpha.1 → 7.0.0-beta.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/cjs/errorboundary.d.ts +1 -0
- package/cjs/errorboundary.d.ts.map +1 -1
- package/cjs/errorboundary.js +43 -48
- package/cjs/errorboundary.js.map +1 -1
- package/cjs/index.js +1 -1
- package/cjs/profiler.js +53 -60
- package/cjs/profiler.js.map +1 -1
- package/cjs/reactrouter.js +22 -26
- package/cjs/reactrouter.js.map +1 -1
- package/cjs/reactrouterv3.js +21 -29
- package/cjs/reactrouterv3.js.map +1 -1
- package/cjs/redux.js +38 -41
- package/cjs/redux.js.map +1 -1
- package/cjs/sdk.js +1 -1
- package/cjs/sdk.js.map +1 -1
- package/esm/constants.js +3 -3
- package/esm/constants.js.map +1 -1
- package/esm/errorboundary.d.ts +1 -0
- package/esm/errorboundary.d.ts.map +1 -1
- package/esm/errorboundary.js +38 -44
- package/esm/errorboundary.js.map +1 -1
- package/esm/flags.js +1 -1
- package/esm/flags.js.map +1 -1
- package/esm/profiler.js +48 -56
- package/esm/profiler.js.map +1 -1
- package/esm/reactrouter.js +18 -23
- package/esm/reactrouter.js.map +1 -1
- package/esm/reactrouterv3.js +20 -28
- package/esm/reactrouterv3.js.map +1 -1
- package/esm/redux.js +38 -41
- package/esm/redux.js.map +1 -1
- package/package.json +4 -5
- package/types/errorboundary.d.ts +1 -0
- package/types/errorboundary.d.ts.map +1 -1
package/cjs/errorboundary.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export declare type FallbackRender = (errorData: {
|
|
|
9
9
|
resetError(): void;
|
|
10
10
|
}) => React.ReactElement;
|
|
11
11
|
export declare type ErrorBoundaryProps = {
|
|
12
|
+
children?: React.ReactNode | (() => React.ReactNode);
|
|
12
13
|
/** If a Sentry report dialog should be rendered on error */
|
|
13
14
|
showDialog?: boolean;
|
|
14
15
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorboundary.d.ts","sourceRoot":"","sources":["../../src/errorboundary.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoB,mBAAmB,EAAE,KAAK,EAA+B,MAAM,iBAAiB,CAAC;AAG5G,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGzD;AAED,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAE3C,oBAAY,cAAc,GAAG,CAAC,SAAS,EAAE;IACvC,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,IAAI,IAAI,CAAC;CACpB,KAAK,KAAK,CAAC,YAAY,CAAC;AAEzB,oBAAY,kBAAkB,GAAG;IAC/B,4DAA4D;IAC5D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,YAAY,GAAG,cAAc,CAAC;IAC/C,yDAAyD;IACzD,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACtE,oCAAoC;IACpC,OAAO,CAAC,IAAI,IAAI,CAAC;IACjB,gFAAgF;IAChF,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IAC3F,uCAAuC;IACvC,SAAS,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IAC7F,2GAA2G;IAC3G,aAAa,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;CACxF,CAAC;AAEF,aAAK,kBAAkB,GAAG;IACxB,cAAc,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC;IACzD,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB,CAAC;AAQF;;;;;GAKG;AACH,cAAM,aAAc,SAAQ,KAAK,CAAC,SAAS,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;IAC1E,KAAK,EAAE,kBAAkB,CAAiB;IAE1C,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG;QAAE,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,EAAE,EAAE,cAAc,EAAE,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI;IAiC9F,iBAAiB,IAAI,IAAI;IAOzB,oBAAoB,IAAI,IAAI;IAQ5B,kBAAkB,EAAE,MAAM,IAAI,CAOnC;IAEK,MAAM,IAAI,KAAK,CAAC,SAAS;CA6BjC;AAGD,iBAAS,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACtD,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EACxC,oBAAoB,EAAE,kBAAkB,GACvC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAiBb;AAED,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"errorboundary.d.ts","sourceRoot":"","sources":["../../src/errorboundary.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoB,mBAAmB,EAAE,KAAK,EAA+B,MAAM,iBAAiB,CAAC;AAG5G,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGzD;AAED,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAE3C,oBAAY,cAAc,GAAG,CAAC,SAAS,EAAE;IACvC,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,IAAI,IAAI,CAAC;CACpB,KAAK,KAAK,CAAC,YAAY,CAAC;AAEzB,oBAAY,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC;IACrD,4DAA4D;IAC5D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,YAAY,GAAG,cAAc,CAAC;IAC/C,yDAAyD;IACzD,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACtE,oCAAoC;IACpC,OAAO,CAAC,IAAI,IAAI,CAAC;IACjB,gFAAgF;IAChF,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IAC3F,uCAAuC;IACvC,SAAS,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IAC7F,2GAA2G;IAC3G,aAAa,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;CACxF,CAAC;AAEF,aAAK,kBAAkB,GAAG;IACxB,cAAc,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC;IACzD,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB,CAAC;AAQF;;;;;GAKG;AACH,cAAM,aAAc,SAAQ,KAAK,CAAC,SAAS,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;IAC1E,KAAK,EAAE,kBAAkB,CAAiB;IAE1C,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG;QAAE,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,EAAE,EAAE,cAAc,EAAE,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI;IAiC9F,iBAAiB,IAAI,IAAI;IAOzB,oBAAoB,IAAI,IAAI;IAQ5B,kBAAkB,EAAE,MAAM,IAAI,CAOnC;IAEK,MAAM,IAAI,KAAK,CAAC,SAAS;CA6BjC;AAGD,iBAAS,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACtD,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EACxC,oBAAoB,EAAE,kBAAkB,GACvC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAiBb;AAED,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,CAAC"}
|
package/cjs/errorboundary.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
const tslib_1 = require("tslib");
|
|
3
|
+
const browser_1 = require("@sentry/browser");
|
|
4
|
+
const utils_1 = require("@sentry/utils");
|
|
5
|
+
const hoist_non_react_statics_1 = tslib_1.__importDefault(require("hoist-non-react-statics"));
|
|
6
|
+
const React = tslib_1.__importStar(require("react"));
|
|
7
|
+
const flags_1 = require("./flags");
|
|
8
8
|
function isAtLeastReact17(version) {
|
|
9
|
-
|
|
9
|
+
const major = version.match(/^([^.]+)/);
|
|
10
10
|
return major !== null && parseInt(major[0]) >= 17;
|
|
11
11
|
}
|
|
12
12
|
exports.isAtLeastReact17 = isAtLeastReact17;
|
|
13
13
|
exports.UNKNOWN_COMPONENT = 'unknown';
|
|
14
|
-
|
|
14
|
+
const INITIAL_STATE = {
|
|
15
15
|
componentStack: null,
|
|
16
16
|
error: null,
|
|
17
17
|
eventId: null,
|
|
@@ -22,32 +22,28 @@ var INITIAL_STATE = {
|
|
|
22
22
|
* Sentry React SDK ErrorBoundary caught an error invoking your application code. This
|
|
23
23
|
* is expected behavior and NOT indicative of a bug with the Sentry React SDK.
|
|
24
24
|
*/
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
var _a = _this.state, error = _a.error, componentStack = _a.componentStack, eventId = _a.eventId;
|
|
25
|
+
class ErrorBoundary extends React.Component {
|
|
26
|
+
constructor() {
|
|
27
|
+
super(...arguments);
|
|
28
|
+
this.state = INITIAL_STATE;
|
|
29
|
+
this.resetErrorBoundary = () => {
|
|
30
|
+
const { onReset } = this.props;
|
|
31
|
+
const { error, componentStack, eventId } = this.state;
|
|
33
32
|
if (onReset) {
|
|
34
33
|
onReset(error, componentStack, eventId);
|
|
35
34
|
}
|
|
36
|
-
|
|
35
|
+
this.setState(INITIAL_STATE);
|
|
37
36
|
};
|
|
38
|
-
return _this;
|
|
39
37
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
var _b = this.props, beforeCapture = _b.beforeCapture, onError = _b.onError, showDialog = _b.showDialog, dialogOptions = _b.dialogOptions;
|
|
44
|
-
browser_1.withScope(function (scope) {
|
|
38
|
+
componentDidCatch(error, { componentStack }) {
|
|
39
|
+
const { beforeCapture, onError, showDialog, dialogOptions } = this.props;
|
|
40
|
+
browser_1.withScope(scope => {
|
|
45
41
|
// If on React version >= 17, create stack trace from componentStack param and links
|
|
46
42
|
// to to the original error using `error.cause` otherwise relies on error param for stacktrace.
|
|
47
43
|
// Linking errors requires the `LinkedErrors` integration be enabled.
|
|
48
44
|
if (isAtLeastReact17(React.version)) {
|
|
49
|
-
|
|
50
|
-
errorBoundaryError.name =
|
|
45
|
+
const errorBoundaryError = new Error(error.message);
|
|
46
|
+
errorBoundaryError.name = `React ErrorBoundary ${errorBoundaryError.name}`;
|
|
51
47
|
errorBoundaryError.stack = componentStack;
|
|
52
48
|
// Using the `LinkedErrors` integration to link the errors together.
|
|
53
49
|
error.cause = errorBoundaryError;
|
|
@@ -55,38 +51,38 @@ var ErrorBoundary = /** @class */ (function (_super) {
|
|
|
55
51
|
if (beforeCapture) {
|
|
56
52
|
beforeCapture(scope, error, componentStack);
|
|
57
53
|
}
|
|
58
|
-
|
|
54
|
+
const eventId = browser_1.captureException(error, { contexts: { react: { componentStack } } });
|
|
59
55
|
if (onError) {
|
|
60
56
|
onError(error, componentStack, eventId);
|
|
61
57
|
}
|
|
62
58
|
if (showDialog) {
|
|
63
|
-
browser_1.showReportDialog(
|
|
59
|
+
browser_1.showReportDialog(Object.assign(Object.assign({}, dialogOptions), { eventId }));
|
|
64
60
|
}
|
|
65
61
|
// componentDidCatch is used over getDerivedStateFromError
|
|
66
62
|
// so that componentStack is accessible through state.
|
|
67
|
-
|
|
63
|
+
this.setState({ error, componentStack, eventId });
|
|
68
64
|
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
65
|
+
}
|
|
66
|
+
componentDidMount() {
|
|
67
|
+
const { onMount } = this.props;
|
|
72
68
|
if (onMount) {
|
|
73
69
|
onMount();
|
|
74
70
|
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
}
|
|
72
|
+
componentWillUnmount() {
|
|
73
|
+
const { error, componentStack, eventId } = this.state;
|
|
74
|
+
const { onUnmount } = this.props;
|
|
79
75
|
if (onUnmount) {
|
|
80
76
|
onUnmount(error, componentStack, eventId);
|
|
81
77
|
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
78
|
+
}
|
|
79
|
+
render() {
|
|
80
|
+
const { fallback, children } = this.props;
|
|
81
|
+
const { error, componentStack, eventId } = this.state;
|
|
86
82
|
if (error) {
|
|
87
|
-
|
|
83
|
+
let element = undefined;
|
|
88
84
|
if (typeof fallback === 'function') {
|
|
89
|
-
element = fallback({ error
|
|
85
|
+
element = fallback({ error, componentStack, resetError: this.resetErrorBoundary, eventId });
|
|
90
86
|
}
|
|
91
87
|
else {
|
|
92
88
|
element = fallback;
|
|
@@ -104,18 +100,17 @@ var ErrorBoundary = /** @class */ (function (_super) {
|
|
|
104
100
|
return children();
|
|
105
101
|
}
|
|
106
102
|
return children;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
}(React.Component));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
110
105
|
exports.ErrorBoundary = ErrorBoundary;
|
|
111
106
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
112
107
|
function withErrorBoundary(WrappedComponent, errorBoundaryOptions) {
|
|
113
108
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
React.createElement(WrappedComponent,
|
|
109
|
+
const componentDisplayName = WrappedComponent.displayName || WrappedComponent.name || exports.UNKNOWN_COMPONENT;
|
|
110
|
+
const Wrapped = (props) => (React.createElement(ErrorBoundary, Object.assign({}, errorBoundaryOptions),
|
|
111
|
+
React.createElement(WrappedComponent, Object.assign({}, props))));
|
|
117
112
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
118
|
-
Wrapped.displayName =
|
|
113
|
+
Wrapped.displayName = `errorBoundary(${componentDisplayName})`;
|
|
119
114
|
// Copy over static methods from Wrapped component to Profiler HOC
|
|
120
115
|
// See: https://reactjs.org/docs/higher-order-components.html#static-methods-must-be-copied-over
|
|
121
116
|
hoist_non_react_statics_1.default(Wrapped, WrappedComponent);
|
package/cjs/errorboundary.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorboundary.js","sourceRoot":"","sources":["../../src/errorboundary.tsx"],"names":[],"mappings":"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","sourcesContent":["import { captureException, ReportDialogOptions, Scope, showReportDialog, withScope } from '@sentry/browser';\nimport { logger } from '@sentry/utils';\nimport hoistNonReactStatics from 'hoist-non-react-statics';\nimport * as React from 'react';\n\nimport { IS_DEBUG_BUILD } from './flags';\n\nexport function isAtLeastReact17(version: string): boolean {\n const major = version.match(/^([^.]+)/);\n return major !== null && parseInt(major[0]) >= 17;\n}\n\nexport const UNKNOWN_COMPONENT = 'unknown';\n\nexport type FallbackRender = (errorData: {\n error: Error;\n componentStack: string | null;\n eventId: string | null;\n resetError(): void;\n}) => React.ReactElement;\n\nexport type ErrorBoundaryProps = {\n /** If a Sentry report dialog should be rendered on error */\n showDialog?: boolean;\n /**\n * Options to be passed into the Sentry report dialog.\n * No-op if {@link showDialog} is false.\n */\n dialogOptions?: ReportDialogOptions;\n /**\n * A fallback component that gets rendered when the error boundary encounters an error.\n *\n * Can either provide a React Component, or a function that returns React Component as\n * a valid fallback prop. If a function is provided, the function will be called with\n * the error, the component stack, and an function that resets the error boundary on error.\n *\n */\n fallback?: React.ReactElement | FallbackRender;\n /** Called when the error boundary encounters an error */\n onError?(error: Error, componentStack: string, eventId: string): void;\n /** Called on componentDidMount() */\n onMount?(): void;\n /** Called if resetError() is called from the fallback render props function */\n onReset?(error: Error | null, componentStack: string | null, eventId: string | null): void;\n /** Called on componentWillUnmount() */\n onUnmount?(error: Error | null, componentStack: string | null, eventId: string | null): void;\n /** Called before the error is captured by Sentry, allows for you to add tags or context using the scope */\n beforeCapture?(scope: Scope, error: Error | null, componentStack: string | null): void;\n};\n\ntype ErrorBoundaryState = {\n componentStack: React.ErrorInfo['componentStack'] | null;\n error: Error | null;\n eventId: string | null;\n};\n\nconst INITIAL_STATE = {\n componentStack: null,\n error: null,\n eventId: null,\n};\n\n/**\n * A ErrorBoundary component that logs errors to Sentry. Requires React >= 16.\n * NOTE: If you are a Sentry user, and you are seeing this stack frame, it means the\n * Sentry React SDK ErrorBoundary caught an error invoking your application code. This\n * is expected behavior and NOT indicative of a bug with the Sentry React SDK.\n */\nclass ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n public state: ErrorBoundaryState = INITIAL_STATE;\n\n public componentDidCatch(error: Error & { cause?: Error }, { componentStack }: React.ErrorInfo): void {\n const { beforeCapture, onError, showDialog, dialogOptions } = this.props;\n\n withScope(scope => {\n // If on React version >= 17, create stack trace from componentStack param and links\n // to to the original error using `error.cause` otherwise relies on error param for stacktrace.\n // Linking errors requires the `LinkedErrors` integration be enabled.\n if (isAtLeastReact17(React.version)) {\n const errorBoundaryError = new Error(error.message);\n errorBoundaryError.name = `React ErrorBoundary ${errorBoundaryError.name}`;\n errorBoundaryError.stack = componentStack;\n\n // Using the `LinkedErrors` integration to link the errors together.\n error.cause = errorBoundaryError;\n }\n\n if (beforeCapture) {\n beforeCapture(scope, error, componentStack);\n }\n const eventId = captureException(error, { contexts: { react: { componentStack } } });\n if (onError) {\n onError(error, componentStack, eventId);\n }\n if (showDialog) {\n showReportDialog({ ...dialogOptions, eventId });\n }\n\n // componentDidCatch is used over getDerivedStateFromError\n // so that componentStack is accessible through state.\n this.setState({ error, componentStack, eventId });\n });\n }\n\n public componentDidMount(): void {\n const { onMount } = this.props;\n if (onMount) {\n onMount();\n }\n }\n\n public componentWillUnmount(): void {\n const { error, componentStack, eventId } = this.state;\n const { onUnmount } = this.props;\n if (onUnmount) {\n onUnmount(error, componentStack, eventId);\n }\n }\n\n public resetErrorBoundary: () => void = () => {\n const { onReset } = this.props;\n const { error, componentStack, eventId } = this.state;\n if (onReset) {\n onReset(error, componentStack, eventId);\n }\n this.setState(INITIAL_STATE);\n };\n\n public render(): React.ReactNode {\n const { fallback, children } = this.props;\n const { error, componentStack, eventId } = this.state;\n\n if (error) {\n let element: React.ReactElement | undefined = undefined;\n if (typeof fallback === 'function') {\n element = fallback({ error, componentStack, resetError: this.resetErrorBoundary, eventId });\n } else {\n element = fallback;\n }\n\n if (React.isValidElement(element)) {\n return element;\n }\n\n if (fallback) {\n IS_DEBUG_BUILD && logger.warn('fallback did not produce a valid ReactElement');\n }\n\n // Fail gracefully if no fallback provided or is not valid\n return null;\n }\n\n if (typeof children === 'function') {\n return children();\n }\n return children;\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction withErrorBoundary<P extends Record<string, any>>(\n WrappedComponent: React.ComponentType<P>,\n errorBoundaryOptions: ErrorBoundaryProps,\n): React.FC<P> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const componentDisplayName = WrappedComponent.displayName || WrappedComponent.name || UNKNOWN_COMPONENT;\n\n const Wrapped: React.FC<P> = (props: P) => (\n <ErrorBoundary {...errorBoundaryOptions}>\n <WrappedComponent {...props} />\n </ErrorBoundary>\n );\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n Wrapped.displayName = `errorBoundary(${componentDisplayName})`;\n\n // Copy over static methods from Wrapped component to Profiler HOC\n // See: https://reactjs.org/docs/higher-order-components.html#static-methods-must-be-copied-over\n hoistNonReactStatics(Wrapped, WrappedComponent);\n return Wrapped;\n}\n\nexport { ErrorBoundary, withErrorBoundary };\n"]}
|
|
1
|
+
{"version":3,"file":"errorboundary.js","sourceRoot":"","sources":["../../src/errorboundary.tsx"],"names":[],"mappings":"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","sourcesContent":["import { captureException, ReportDialogOptions, Scope, showReportDialog, withScope } from '@sentry/browser';\nimport { logger } from '@sentry/utils';\nimport hoistNonReactStatics from 'hoist-non-react-statics';\nimport * as React from 'react';\n\nimport { IS_DEBUG_BUILD } from './flags';\n\nexport function isAtLeastReact17(version: string): boolean {\n const major = version.match(/^([^.]+)/);\n return major !== null && parseInt(major[0]) >= 17;\n}\n\nexport const UNKNOWN_COMPONENT = 'unknown';\n\nexport type FallbackRender = (errorData: {\n error: Error;\n componentStack: string | null;\n eventId: string | null;\n resetError(): void;\n}) => React.ReactElement;\n\nexport type ErrorBoundaryProps = {\n children?: React.ReactNode | (() => React.ReactNode);\n /** If a Sentry report dialog should be rendered on error */\n showDialog?: boolean;\n /**\n * Options to be passed into the Sentry report dialog.\n * No-op if {@link showDialog} is false.\n */\n dialogOptions?: ReportDialogOptions;\n /**\n * A fallback component that gets rendered when the error boundary encounters an error.\n *\n * Can either provide a React Component, or a function that returns React Component as\n * a valid fallback prop. If a function is provided, the function will be called with\n * the error, the component stack, and an function that resets the error boundary on error.\n *\n */\n fallback?: React.ReactElement | FallbackRender;\n /** Called when the error boundary encounters an error */\n onError?(error: Error, componentStack: string, eventId: string): void;\n /** Called on componentDidMount() */\n onMount?(): void;\n /** Called if resetError() is called from the fallback render props function */\n onReset?(error: Error | null, componentStack: string | null, eventId: string | null): void;\n /** Called on componentWillUnmount() */\n onUnmount?(error: Error | null, componentStack: string | null, eventId: string | null): void;\n /** Called before the error is captured by Sentry, allows for you to add tags or context using the scope */\n beforeCapture?(scope: Scope, error: Error | null, componentStack: string | null): void;\n};\n\ntype ErrorBoundaryState = {\n componentStack: React.ErrorInfo['componentStack'] | null;\n error: Error | null;\n eventId: string | null;\n};\n\nconst INITIAL_STATE = {\n componentStack: null,\n error: null,\n eventId: null,\n};\n\n/**\n * A ErrorBoundary component that logs errors to Sentry. Requires React >= 16.\n * NOTE: If you are a Sentry user, and you are seeing this stack frame, it means the\n * Sentry React SDK ErrorBoundary caught an error invoking your application code. This\n * is expected behavior and NOT indicative of a bug with the Sentry React SDK.\n */\nclass ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n public state: ErrorBoundaryState = INITIAL_STATE;\n\n public componentDidCatch(error: Error & { cause?: Error }, { componentStack }: React.ErrorInfo): void {\n const { beforeCapture, onError, showDialog, dialogOptions } = this.props;\n\n withScope(scope => {\n // If on React version >= 17, create stack trace from componentStack param and links\n // to to the original error using `error.cause` otherwise relies on error param for stacktrace.\n // Linking errors requires the `LinkedErrors` integration be enabled.\n if (isAtLeastReact17(React.version)) {\n const errorBoundaryError = new Error(error.message);\n errorBoundaryError.name = `React ErrorBoundary ${errorBoundaryError.name}`;\n errorBoundaryError.stack = componentStack;\n\n // Using the `LinkedErrors` integration to link the errors together.\n error.cause = errorBoundaryError;\n }\n\n if (beforeCapture) {\n beforeCapture(scope, error, componentStack);\n }\n const eventId = captureException(error, { contexts: { react: { componentStack } } });\n if (onError) {\n onError(error, componentStack, eventId);\n }\n if (showDialog) {\n showReportDialog({ ...dialogOptions, eventId });\n }\n\n // componentDidCatch is used over getDerivedStateFromError\n // so that componentStack is accessible through state.\n this.setState({ error, componentStack, eventId });\n });\n }\n\n public componentDidMount(): void {\n const { onMount } = this.props;\n if (onMount) {\n onMount();\n }\n }\n\n public componentWillUnmount(): void {\n const { error, componentStack, eventId } = this.state;\n const { onUnmount } = this.props;\n if (onUnmount) {\n onUnmount(error, componentStack, eventId);\n }\n }\n\n public resetErrorBoundary: () => void = () => {\n const { onReset } = this.props;\n const { error, componentStack, eventId } = this.state;\n if (onReset) {\n onReset(error, componentStack, eventId);\n }\n this.setState(INITIAL_STATE);\n };\n\n public render(): React.ReactNode {\n const { fallback, children } = this.props;\n const { error, componentStack, eventId } = this.state;\n\n if (error) {\n let element: React.ReactElement | undefined = undefined;\n if (typeof fallback === 'function') {\n element = fallback({ error, componentStack, resetError: this.resetErrorBoundary, eventId });\n } else {\n element = fallback;\n }\n\n if (React.isValidElement(element)) {\n return element;\n }\n\n if (fallback) {\n IS_DEBUG_BUILD && logger.warn('fallback did not produce a valid ReactElement');\n }\n\n // Fail gracefully if no fallback provided or is not valid\n return null;\n }\n\n if (typeof children === 'function') {\n return (children as () => React.ReactNode)();\n }\n return children;\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction withErrorBoundary<P extends Record<string, any>>(\n WrappedComponent: React.ComponentType<P>,\n errorBoundaryOptions: ErrorBoundaryProps,\n): React.FC<P> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const componentDisplayName = WrappedComponent.displayName || WrappedComponent.name || UNKNOWN_COMPONENT;\n\n const Wrapped: React.FC<P> = (props: P) => (\n <ErrorBoundary {...errorBoundaryOptions}>\n <WrappedComponent {...props} />\n </ErrorBoundary>\n );\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n Wrapped.displayName = `errorBoundary(${componentDisplayName})`;\n\n // Copy over static methods from Wrapped component to Profiler HOC\n // See: https://reactjs.org/docs/higher-order-components.html#static-methods-must-be-copied-over\n hoistNonReactStatics(Wrapped, WrappedComponent);\n return Wrapped;\n}\n\nexport { ErrorBoundary, withErrorBoundary };\n"]}
|
package/cjs/index.js
CHANGED
package/cjs/profiler.js
CHANGED
|
@@ -1,98 +1,93 @@
|
|
|
1
1
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
|
-
|
|
2
|
+
const tslib_1 = require("tslib");
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
4
4
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
const browser_1 = require("@sentry/browser");
|
|
6
|
+
const utils_1 = require("@sentry/utils");
|
|
7
|
+
const hoist_non_react_statics_1 = tslib_1.__importDefault(require("hoist-non-react-statics"));
|
|
8
|
+
const React = tslib_1.__importStar(require("react"));
|
|
9
|
+
const constants_1 = require("./constants");
|
|
10
10
|
exports.UNKNOWN_COMPONENT = 'unknown';
|
|
11
11
|
/**
|
|
12
12
|
* The Profiler component leverages Sentry's Tracing integration to generate
|
|
13
13
|
* spans based on component lifecycles.
|
|
14
14
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
var _this = _super.call(this, props) || this;
|
|
15
|
+
class Profiler extends React.Component {
|
|
16
|
+
constructor(props) {
|
|
17
|
+
super(props);
|
|
19
18
|
/**
|
|
20
19
|
* The span of the mount activity
|
|
21
20
|
* Made protected for the React Native SDK to access
|
|
22
21
|
*/
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
this._mountSpan = undefined;
|
|
23
|
+
const { name, disabled = false } = this.props;
|
|
25
24
|
if (disabled) {
|
|
26
|
-
return
|
|
25
|
+
return;
|
|
27
26
|
}
|
|
28
|
-
|
|
27
|
+
const activeTransaction = getActiveTransaction();
|
|
29
28
|
if (activeTransaction) {
|
|
30
|
-
|
|
31
|
-
description:
|
|
29
|
+
this._mountSpan = activeTransaction.startChild({
|
|
30
|
+
description: `<${name}>`,
|
|
32
31
|
op: constants_1.REACT_MOUNT_OP,
|
|
33
32
|
});
|
|
34
33
|
}
|
|
35
|
-
return _this;
|
|
36
34
|
}
|
|
37
35
|
// If a component mounted, we can finish the mount activity.
|
|
38
|
-
|
|
36
|
+
componentDidMount() {
|
|
39
37
|
if (this._mountSpan) {
|
|
40
38
|
this._mountSpan.finish();
|
|
41
39
|
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
var _this = this;
|
|
45
|
-
var updateProps = _a.updateProps, _b = _a.includeUpdates, includeUpdates = _b === void 0 ? true : _b;
|
|
40
|
+
}
|
|
41
|
+
componentDidUpdate({ updateProps, includeUpdates = true }) {
|
|
46
42
|
// Only generate an update span if hasUpdateSpan is true, if there is a valid mountSpan,
|
|
47
43
|
// and if the updateProps have changed. It is ok to not do a deep equality check here as it is expensive.
|
|
48
44
|
// We are just trying to give baseline clues for further investigation.
|
|
49
45
|
if (includeUpdates && this._mountSpan && updateProps !== this.props.updateProps) {
|
|
50
46
|
// See what props haved changed between the previous props, and the current props. This is
|
|
51
47
|
// set as data on the span. We just store the prop keys as the values could be potenially very large.
|
|
52
|
-
|
|
48
|
+
const changedProps = Object.keys(updateProps).filter(k => updateProps[k] !== this.props.updateProps[k]);
|
|
53
49
|
if (changedProps.length > 0) {
|
|
54
50
|
// The update span is a point in time span with 0 duration, just signifying that the component
|
|
55
51
|
// has been updated.
|
|
56
|
-
|
|
52
|
+
const now = utils_1.timestampWithMs();
|
|
57
53
|
this._mountSpan.startChild({
|
|
58
54
|
data: {
|
|
59
|
-
changedProps
|
|
55
|
+
changedProps,
|
|
60
56
|
},
|
|
61
|
-
description:
|
|
57
|
+
description: `<${this.props.name}>`,
|
|
62
58
|
endTimestamp: now,
|
|
63
59
|
op: constants_1.REACT_UPDATE_OP,
|
|
64
60
|
startTimestamp: now,
|
|
65
61
|
});
|
|
66
62
|
}
|
|
67
63
|
}
|
|
68
|
-
}
|
|
64
|
+
}
|
|
69
65
|
// If a component is unmounted, we can say it is no longer on the screen.
|
|
70
66
|
// This means we can finish the span representing the component render.
|
|
71
|
-
|
|
72
|
-
|
|
67
|
+
componentWillUnmount() {
|
|
68
|
+
const { name, includeRender = true } = this.props;
|
|
73
69
|
if (this._mountSpan && includeRender) {
|
|
74
70
|
// If we were able to obtain the spanId of the mount activity, we should set the
|
|
75
71
|
// next activity as a child to the component mount activity.
|
|
76
72
|
this._mountSpan.startChild({
|
|
77
|
-
description:
|
|
73
|
+
description: `<${name}>`,
|
|
78
74
|
endTimestamp: utils_1.timestampWithMs(),
|
|
79
75
|
op: constants_1.REACT_RENDER_OP,
|
|
80
76
|
startTimestamp: this._mountSpan.endTimestamp,
|
|
81
77
|
});
|
|
82
78
|
}
|
|
83
|
-
}
|
|
84
|
-
|
|
79
|
+
}
|
|
80
|
+
render() {
|
|
85
81
|
return this.props.children;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
Profiler.defaultProps = {
|
|
89
|
-
disabled: false,
|
|
90
|
-
includeRender: true,
|
|
91
|
-
includeUpdates: true,
|
|
92
|
-
};
|
|
93
|
-
return Profiler;
|
|
94
|
-
}(React.Component));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
95
84
|
exports.Profiler = Profiler;
|
|
85
|
+
// eslint-disable-next-line @typescript-eslint/member-ordering
|
|
86
|
+
Profiler.defaultProps = {
|
|
87
|
+
disabled: false,
|
|
88
|
+
includeRender: true,
|
|
89
|
+
includeUpdates: true,
|
|
90
|
+
};
|
|
96
91
|
/**
|
|
97
92
|
* withProfiler is a higher order component that wraps a
|
|
98
93
|
* component in a {@link Profiler} component. It is recommended that
|
|
@@ -104,10 +99,10 @@ exports.Profiler = Profiler;
|
|
|
104
99
|
function withProfiler(WrappedComponent,
|
|
105
100
|
// We do not want to have `updateProps` given in options, it is instead filled through the HOC.
|
|
106
101
|
options) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
React.createElement(WrappedComponent,
|
|
110
|
-
Wrapped.displayName =
|
|
102
|
+
const componentDisplayName = (options && options.name) || WrappedComponent.displayName || WrappedComponent.name || exports.UNKNOWN_COMPONENT;
|
|
103
|
+
const Wrapped = (props) => (React.createElement(Profiler, Object.assign({}, options, { name: componentDisplayName, updateProps: props }),
|
|
104
|
+
React.createElement(WrappedComponent, Object.assign({}, props))));
|
|
105
|
+
Wrapped.displayName = `profiler(${componentDisplayName})`;
|
|
111
106
|
// Copy over static methods from Wrapped component to Profiler HOC
|
|
112
107
|
// See: https://reactjs.org/docs/higher-order-components.html#static-methods-must-be-copied-over
|
|
113
108
|
hoist_non_react_statics_1.default(Wrapped, WrappedComponent);
|
|
@@ -121,32 +116,31 @@ exports.withProfiler = withProfiler;
|
|
|
121
116
|
* Requires React 16.8 or above.
|
|
122
117
|
* @param name displayName of component being profiled
|
|
123
118
|
*/
|
|
124
|
-
function useProfiler(name, options
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
var _a = tslib_1.__read(React.useState(function () {
|
|
119
|
+
function useProfiler(name, options = {
|
|
120
|
+
disabled: false,
|
|
121
|
+
hasRenderSpan: true,
|
|
122
|
+
}) {
|
|
123
|
+
const [mountSpan] = React.useState(() => {
|
|
130
124
|
if (options && options.disabled) {
|
|
131
125
|
return undefined;
|
|
132
126
|
}
|
|
133
|
-
|
|
127
|
+
const activeTransaction = getActiveTransaction();
|
|
134
128
|
if (activeTransaction) {
|
|
135
129
|
return activeTransaction.startChild({
|
|
136
|
-
description:
|
|
130
|
+
description: `<${name}>`,
|
|
137
131
|
op: constants_1.REACT_MOUNT_OP,
|
|
138
132
|
});
|
|
139
133
|
}
|
|
140
134
|
return undefined;
|
|
141
|
-
})
|
|
142
|
-
React.useEffect(
|
|
135
|
+
});
|
|
136
|
+
React.useEffect(() => {
|
|
143
137
|
if (mountSpan) {
|
|
144
138
|
mountSpan.finish();
|
|
145
139
|
}
|
|
146
|
-
return
|
|
140
|
+
return () => {
|
|
147
141
|
if (mountSpan && options.hasRenderSpan) {
|
|
148
142
|
mountSpan.startChild({
|
|
149
|
-
description:
|
|
143
|
+
description: `<${name}>`,
|
|
150
144
|
endTimestamp: utils_1.timestampWithMs(),
|
|
151
145
|
op: constants_1.REACT_RENDER_OP,
|
|
152
146
|
startTimestamp: mountSpan.endTimestamp,
|
|
@@ -159,10 +153,9 @@ function useProfiler(name, options) {
|
|
|
159
153
|
}
|
|
160
154
|
exports.useProfiler = useProfiler;
|
|
161
155
|
/** Grabs active transaction off scope */
|
|
162
|
-
function getActiveTransaction(hub) {
|
|
163
|
-
if (hub === void 0) { hub = browser_1.getCurrentHub(); }
|
|
156
|
+
function getActiveTransaction(hub = browser_1.getCurrentHub()) {
|
|
164
157
|
if (hub) {
|
|
165
|
-
|
|
158
|
+
const scope = hub.getScope();
|
|
166
159
|
if (scope) {
|
|
167
160
|
return scope.getTransaction();
|
|
168
161
|
}
|
package/cjs/profiler.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profiler.js","sourceRoot":"","sources":["../../src/profiler.tsx"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { getCurrentHub, Hub } from '@sentry/browser';\nimport { Span, Transaction } from '@sentry/types';\nimport { timestampWithMs } from '@sentry/utils';\nimport hoistNonReactStatics from 'hoist-non-react-statics';\nimport * as React from 'react';\n\nimport { REACT_MOUNT_OP, REACT_RENDER_OP, REACT_UPDATE_OP } from './constants';\n\nexport const UNKNOWN_COMPONENT = 'unknown';\n\nexport type ProfilerProps = {\n // The name of the component being profiled.\n name: string;\n // If the Profiler is disabled. False by default. This is useful if you want to disable profilers\n // in certain environments.\n disabled?: boolean;\n // If time component is on page should be displayed as spans. True by default.\n includeRender?: boolean;\n // If component updates should be displayed as spans. True by default.\n includeUpdates?: boolean;\n // props given to component being profiled.\n updateProps: { [key: string]: unknown };\n};\n\n/**\n * The Profiler component leverages Sentry's Tracing integration to generate\n * spans based on component lifecycles.\n */\nclass Profiler extends React.Component<ProfilerProps> {\n /**\n * The span of the mount activity\n * Made protected for the React Native SDK to access\n */\n protected _mountSpan: Span | undefined = undefined;\n\n // eslint-disable-next-line @typescript-eslint/member-ordering\n public static defaultProps: Partial<ProfilerProps> = {\n disabled: false,\n includeRender: true,\n includeUpdates: true,\n };\n\n public constructor(props: ProfilerProps) {\n super(props);\n const { name, disabled = false } = this.props;\n\n if (disabled) {\n return;\n }\n\n const activeTransaction = getActiveTransaction();\n if (activeTransaction) {\n this._mountSpan = activeTransaction.startChild({\n description: `<${name}>`,\n op: REACT_MOUNT_OP,\n });\n }\n }\n\n // If a component mounted, we can finish the mount activity.\n public componentDidMount(): void {\n if (this._mountSpan) {\n this._mountSpan.finish();\n }\n }\n\n public componentDidUpdate({ updateProps, includeUpdates = true }: ProfilerProps): void {\n // Only generate an update span if hasUpdateSpan is true, if there is a valid mountSpan,\n // and if the updateProps have changed. It is ok to not do a deep equality check here as it is expensive.\n // We are just trying to give baseline clues for further investigation.\n if (includeUpdates && this._mountSpan && updateProps !== this.props.updateProps) {\n // See what props haved changed between the previous props, and the current props. This is\n // set as data on the span. We just store the prop keys as the values could be potenially very large.\n const changedProps = Object.keys(updateProps).filter(k => updateProps[k] !== this.props.updateProps[k]);\n if (changedProps.length > 0) {\n // The update span is a point in time span with 0 duration, just signifying that the component\n // has been updated.\n const now = timestampWithMs();\n this._mountSpan.startChild({\n data: {\n changedProps,\n },\n description: `<${this.props.name}>`,\n endTimestamp: now,\n op: REACT_UPDATE_OP,\n startTimestamp: now,\n });\n }\n }\n }\n\n // If a component is unmounted, we can say it is no longer on the screen.\n // This means we can finish the span representing the component render.\n public componentWillUnmount(): void {\n const { name, includeRender = true } = this.props;\n\n if (this._mountSpan && includeRender) {\n // If we were able to obtain the spanId of the mount activity, we should set the\n // next activity as a child to the component mount activity.\n this._mountSpan.startChild({\n description: `<${name}>`,\n endTimestamp: timestampWithMs(),\n op: REACT_RENDER_OP,\n startTimestamp: this._mountSpan.endTimestamp,\n });\n }\n }\n\n public render(): React.ReactNode {\n return this.props.children;\n }\n}\n\n/**\n * withProfiler is a higher order component that wraps a\n * component in a {@link Profiler} component. It is recommended that\n * the higher order component be used over the regular {@link Profiler} component.\n *\n * @param WrappedComponent component that is wrapped by Profiler\n * @param options the {@link ProfilerProps} you can pass into the Profiler\n */\nfunction withProfiler<P extends Record<string, any>>(\n WrappedComponent: React.ComponentType<P>,\n // We do not want to have `updateProps` given in options, it is instead filled through the HOC.\n options?: Pick<Partial<ProfilerProps>, Exclude<keyof ProfilerProps, 'updateProps'>>,\n): React.FC<P> {\n const componentDisplayName =\n (options && options.name) || WrappedComponent.displayName || WrappedComponent.name || UNKNOWN_COMPONENT;\n\n const Wrapped: React.FC<P> = (props: P) => (\n <Profiler {...options} name={componentDisplayName} updateProps={props}>\n <WrappedComponent {...props} />\n </Profiler>\n );\n\n Wrapped.displayName = `profiler(${componentDisplayName})`;\n\n // Copy over static methods from Wrapped component to Profiler HOC\n // See: https://reactjs.org/docs/higher-order-components.html#static-methods-must-be-copied-over\n hoistNonReactStatics(Wrapped, WrappedComponent);\n return Wrapped;\n}\n\n/**\n *\n * `useProfiler` is a React hook that profiles a React component.\n *\n * Requires React 16.8 or above.\n * @param name displayName of component being profiled\n */\nfunction useProfiler(\n name: string,\n options: { disabled?: boolean; hasRenderSpan?: boolean } = {\n disabled: false,\n hasRenderSpan: true,\n },\n): void {\n const [mountSpan] = React.useState(() => {\n if (options && options.disabled) {\n return undefined;\n }\n\n const activeTransaction = getActiveTransaction();\n if (activeTransaction) {\n return activeTransaction.startChild({\n description: `<${name}>`,\n op: REACT_MOUNT_OP,\n });\n }\n\n return undefined;\n });\n\n React.useEffect(() => {\n if (mountSpan) {\n mountSpan.finish();\n }\n\n return (): void => {\n if (mountSpan && options.hasRenderSpan) {\n mountSpan.startChild({\n description: `<${name}>`,\n endTimestamp: timestampWithMs(),\n op: REACT_RENDER_OP,\n startTimestamp: mountSpan.endTimestamp,\n });\n }\n };\n // We only want this to run once.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n}\n\nexport { withProfiler, Profiler, useProfiler };\n\n/** Grabs active transaction off scope */\nexport function getActiveTransaction<T extends Transaction>(hub: Hub = getCurrentHub()): T | undefined {\n if (hub) {\n const scope = hub.getScope();\n if (scope) {\n return scope.getTransaction() as T | undefined;\n }\n }\n\n return undefined;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"profiler.js","sourceRoot":"","sources":["../../src/profiler.tsx"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { getCurrentHub, Hub } from '@sentry/browser';\nimport { Span, Transaction } from '@sentry/types';\nimport { timestampWithMs } from '@sentry/utils';\nimport hoistNonReactStatics from 'hoist-non-react-statics';\nimport * as React from 'react';\n\nimport { REACT_MOUNT_OP, REACT_RENDER_OP, REACT_UPDATE_OP } from './constants';\n\nexport const UNKNOWN_COMPONENT = 'unknown';\n\nexport type ProfilerProps = {\n // The name of the component being profiled.\n name: string;\n // If the Profiler is disabled. False by default. This is useful if you want to disable profilers\n // in certain environments.\n disabled?: boolean;\n // If time component is on page should be displayed as spans. True by default.\n includeRender?: boolean;\n // If component updates should be displayed as spans. True by default.\n includeUpdates?: boolean;\n // props given to component being profiled.\n updateProps: { [key: string]: unknown };\n};\n\n/**\n * The Profiler component leverages Sentry's Tracing integration to generate\n * spans based on component lifecycles.\n */\nclass Profiler extends React.Component<ProfilerProps> {\n /**\n * The span of the mount activity\n * Made protected for the React Native SDK to access\n */\n protected _mountSpan: Span | undefined = undefined;\n\n // eslint-disable-next-line @typescript-eslint/member-ordering\n public static defaultProps: Partial<ProfilerProps> = {\n disabled: false,\n includeRender: true,\n includeUpdates: true,\n };\n\n public constructor(props: ProfilerProps) {\n super(props);\n const { name, disabled = false } = this.props;\n\n if (disabled) {\n return;\n }\n\n const activeTransaction = getActiveTransaction();\n if (activeTransaction) {\n this._mountSpan = activeTransaction.startChild({\n description: `<${name}>`,\n op: REACT_MOUNT_OP,\n });\n }\n }\n\n // If a component mounted, we can finish the mount activity.\n public componentDidMount(): void {\n if (this._mountSpan) {\n this._mountSpan.finish();\n }\n }\n\n public componentDidUpdate({ updateProps, includeUpdates = true }: ProfilerProps): void {\n // Only generate an update span if hasUpdateSpan is true, if there is a valid mountSpan,\n // and if the updateProps have changed. It is ok to not do a deep equality check here as it is expensive.\n // We are just trying to give baseline clues for further investigation.\n if (includeUpdates && this._mountSpan && updateProps !== this.props.updateProps) {\n // See what props haved changed between the previous props, and the current props. This is\n // set as data on the span. We just store the prop keys as the values could be potenially very large.\n const changedProps = Object.keys(updateProps).filter(k => updateProps[k] !== this.props.updateProps[k]);\n if (changedProps.length > 0) {\n // The update span is a point in time span with 0 duration, just signifying that the component\n // has been updated.\n const now = timestampWithMs();\n this._mountSpan.startChild({\n data: {\n changedProps,\n },\n description: `<${this.props.name}>`,\n endTimestamp: now,\n op: REACT_UPDATE_OP,\n startTimestamp: now,\n });\n }\n }\n }\n\n // If a component is unmounted, we can say it is no longer on the screen.\n // This means we can finish the span representing the component render.\n public componentWillUnmount(): void {\n const { name, includeRender = true } = this.props;\n\n if (this._mountSpan && includeRender) {\n // If we were able to obtain the spanId of the mount activity, we should set the\n // next activity as a child to the component mount activity.\n this._mountSpan.startChild({\n description: `<${name}>`,\n endTimestamp: timestampWithMs(),\n op: REACT_RENDER_OP,\n startTimestamp: this._mountSpan.endTimestamp,\n });\n }\n }\n\n public render(): React.ReactNode {\n return this.props.children;\n }\n}\n\n/**\n * withProfiler is a higher order component that wraps a\n * component in a {@link Profiler} component. It is recommended that\n * the higher order component be used over the regular {@link Profiler} component.\n *\n * @param WrappedComponent component that is wrapped by Profiler\n * @param options the {@link ProfilerProps} you can pass into the Profiler\n */\nfunction withProfiler<P extends Record<string, any>>(\n WrappedComponent: React.ComponentType<P>,\n // We do not want to have `updateProps` given in options, it is instead filled through the HOC.\n options?: Pick<Partial<ProfilerProps>, Exclude<keyof ProfilerProps, 'updateProps'>>,\n): React.FC<P> {\n const componentDisplayName =\n (options && options.name) || WrappedComponent.displayName || WrappedComponent.name || UNKNOWN_COMPONENT;\n\n const Wrapped: React.FC<P> = (props: P) => (\n <Profiler {...options} name={componentDisplayName} updateProps={props}>\n <WrappedComponent {...props} />\n </Profiler>\n );\n\n Wrapped.displayName = `profiler(${componentDisplayName})`;\n\n // Copy over static methods from Wrapped component to Profiler HOC\n // See: https://reactjs.org/docs/higher-order-components.html#static-methods-must-be-copied-over\n hoistNonReactStatics(Wrapped, WrappedComponent);\n return Wrapped;\n}\n\n/**\n *\n * `useProfiler` is a React hook that profiles a React component.\n *\n * Requires React 16.8 or above.\n * @param name displayName of component being profiled\n */\nfunction useProfiler(\n name: string,\n options: { disabled?: boolean; hasRenderSpan?: boolean } = {\n disabled: false,\n hasRenderSpan: true,\n },\n): void {\n const [mountSpan] = React.useState(() => {\n if (options && options.disabled) {\n return undefined;\n }\n\n const activeTransaction = getActiveTransaction();\n if (activeTransaction) {\n return activeTransaction.startChild({\n description: `<${name}>`,\n op: REACT_MOUNT_OP,\n });\n }\n\n return undefined;\n });\n\n React.useEffect(() => {\n if (mountSpan) {\n mountSpan.finish();\n }\n\n return (): void => {\n if (mountSpan && options.hasRenderSpan) {\n mountSpan.startChild({\n description: `<${name}>`,\n endTimestamp: timestampWithMs(),\n op: REACT_RENDER_OP,\n startTimestamp: mountSpan.endTimestamp,\n });\n }\n };\n // We only want this to run once.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n}\n\nexport { withProfiler, Profiler, useProfiler };\n\n/** Grabs active transaction off scope */\nexport function getActiveTransaction<T extends Transaction>(hub: Hub = getCurrentHub()): T | undefined {\n if (hub) {\n const scope = hub.getScope();\n if (scope) {\n return scope.getTransaction() as T | undefined;\n }\n }\n\n return undefined;\n}\n"]}
|
package/cjs/reactrouter.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
const tslib_1 = require("tslib");
|
|
3
|
+
const utils_1 = require("@sentry/utils");
|
|
4
|
+
const hoist_non_react_statics_1 = tslib_1.__importDefault(require("hoist-non-react-statics"));
|
|
5
|
+
const React = tslib_1.__importStar(require("react"));
|
|
6
6
|
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const global = utils_1.getGlobalObject();
|
|
8
|
+
let activeTransaction;
|
|
9
9
|
function reactRouterV4Instrumentation(history, routes, matchPath) {
|
|
10
10
|
return createReactRouterInstrumentation(history, 'react-router-v4', routes, matchPath);
|
|
11
11
|
}
|
|
@@ -14,8 +14,7 @@ function reactRouterV5Instrumentation(history, routes, matchPath) {
|
|
|
14
14
|
return createReactRouterInstrumentation(history, 'react-router-v5', routes, matchPath);
|
|
15
15
|
}
|
|
16
16
|
exports.reactRouterV5Instrumentation = reactRouterV5Instrumentation;
|
|
17
|
-
function createReactRouterInstrumentation(history, name, allRoutes, matchPath) {
|
|
18
|
-
if (allRoutes === void 0) { allRoutes = []; }
|
|
17
|
+
function createReactRouterInstrumentation(history, name, allRoutes = [], matchPath) {
|
|
19
18
|
function getInitPathName() {
|
|
20
19
|
if (history && history.location) {
|
|
21
20
|
return history.location.pathname;
|
|
@@ -29,19 +28,17 @@ function createReactRouterInstrumentation(history, name, allRoutes, matchPath) {
|
|
|
29
28
|
if (allRoutes.length === 0 || !matchPath) {
|
|
30
29
|
return pathname;
|
|
31
30
|
}
|
|
32
|
-
|
|
31
|
+
const branches = matchRoutes(allRoutes, pathname, matchPath);
|
|
33
32
|
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
34
|
-
for (
|
|
33
|
+
for (let x = 0; x < branches.length; x++) {
|
|
35
34
|
if (branches[x].match.isExact) {
|
|
36
35
|
return branches[x].match.path;
|
|
37
36
|
}
|
|
38
37
|
}
|
|
39
38
|
return pathname;
|
|
40
39
|
}
|
|
41
|
-
return
|
|
42
|
-
|
|
43
|
-
if (startTransactionOnLocationChange === void 0) { startTransactionOnLocationChange = true; }
|
|
44
|
-
var initPathName = getInitPathName();
|
|
40
|
+
return (customStartTransaction, startTransactionOnPageLoad = true, startTransactionOnLocationChange = true) => {
|
|
41
|
+
const initPathName = getInitPathName();
|
|
45
42
|
if (startTransactionOnPageLoad && initPathName) {
|
|
46
43
|
activeTransaction = customStartTransaction({
|
|
47
44
|
name: getTransactionName(initPathName),
|
|
@@ -52,18 +49,18 @@ function createReactRouterInstrumentation(history, name, allRoutes, matchPath) {
|
|
|
52
49
|
});
|
|
53
50
|
}
|
|
54
51
|
if (startTransactionOnLocationChange && history.listen) {
|
|
55
|
-
history.listen(
|
|
52
|
+
history.listen((location, action) => {
|
|
56
53
|
if (action && (action === 'PUSH' || action === 'POP')) {
|
|
57
54
|
if (activeTransaction) {
|
|
58
55
|
activeTransaction.finish();
|
|
59
56
|
}
|
|
60
|
-
|
|
57
|
+
const tags = {
|
|
61
58
|
'routing.instrumentation': name,
|
|
62
59
|
};
|
|
63
60
|
activeTransaction = customStartTransaction({
|
|
64
61
|
name: getTransactionName(location.pathname),
|
|
65
62
|
op: 'navigation',
|
|
66
|
-
tags
|
|
63
|
+
tags,
|
|
67
64
|
});
|
|
68
65
|
}
|
|
69
66
|
});
|
|
@@ -74,16 +71,15 @@ function createReactRouterInstrumentation(history, name, allRoutes, matchPath) {
|
|
|
74
71
|
* Matches a set of routes to a pathname
|
|
75
72
|
* Based on implementation from
|
|
76
73
|
*/
|
|
77
|
-
function matchRoutes(routes, pathname, matchPath, branch) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
var match = route.path
|
|
74
|
+
function matchRoutes(routes, pathname, matchPath, branch = []) {
|
|
75
|
+
routes.some(route => {
|
|
76
|
+
const match = route.path
|
|
81
77
|
? matchPath(pathname, route)
|
|
82
78
|
: branch.length
|
|
83
79
|
? branch[branch.length - 1].match // use parent match
|
|
84
80
|
: computeRootMatch(pathname); // use default "root" match
|
|
85
81
|
if (match) {
|
|
86
|
-
branch.push({ route
|
|
82
|
+
branch.push({ route, match });
|
|
87
83
|
if (route.routes) {
|
|
88
84
|
matchRoutes(route.routes, pathname, matchPath, branch);
|
|
89
85
|
}
|
|
@@ -97,17 +93,17 @@ function computeRootMatch(pathname) {
|
|
|
97
93
|
}
|
|
98
94
|
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */
|
|
99
95
|
function withSentryRouting(Route) {
|
|
100
|
-
|
|
101
|
-
|
|
96
|
+
const componentDisplayName = Route.displayName || Route.name;
|
|
97
|
+
const WrappedRoute = (props) => {
|
|
102
98
|
if (activeTransaction && props && props.computedMatch && props.computedMatch.isExact) {
|
|
103
99
|
activeTransaction.setName(props.computedMatch.path);
|
|
104
100
|
}
|
|
105
101
|
// @ts-ignore Setting more specific React Component typing for `R` generic above
|
|
106
102
|
// will break advanced type inference done by react router params:
|
|
107
103
|
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/13dc4235c069e25fe7ee16e11f529d909f9f3ff8/types/react-router/index.d.ts#L154-L164
|
|
108
|
-
return React.createElement(Route,
|
|
104
|
+
return React.createElement(Route, Object.assign({}, props));
|
|
109
105
|
};
|
|
110
|
-
WrappedRoute.displayName =
|
|
106
|
+
WrappedRoute.displayName = `sentryRoute(${componentDisplayName})`;
|
|
111
107
|
hoist_non_react_statics_1.default(WrappedRoute, Route);
|
|
112
108
|
// @ts-ignore Setting more specific React Component typing for `R` generic above
|
|
113
109
|
// will break advanced type inference done by react router params:
|