@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/esm/profiler.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { __assign, __extends, __read } from "tslib";
|
|
2
1
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
3
2
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
4
3
|
import { getCurrentHub } from '@sentry/browser';
|
|
@@ -6,91 +5,86 @@ import { timestampWithMs } from '@sentry/utils';
|
|
|
6
5
|
import hoistNonReactStatics from 'hoist-non-react-statics';
|
|
7
6
|
import * as React from 'react';
|
|
8
7
|
import { REACT_MOUNT_OP, REACT_RENDER_OP, REACT_UPDATE_OP } from './constants';
|
|
9
|
-
export
|
|
8
|
+
export const UNKNOWN_COMPONENT = 'unknown';
|
|
10
9
|
/**
|
|
11
10
|
* The Profiler component leverages Sentry's Tracing integration to generate
|
|
12
11
|
* spans based on component lifecycles.
|
|
13
12
|
*/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
var _this = _super.call(this, props) || this;
|
|
13
|
+
class Profiler extends React.Component {
|
|
14
|
+
constructor(props) {
|
|
15
|
+
super(props);
|
|
18
16
|
/**
|
|
19
17
|
* The span of the mount activity
|
|
20
18
|
* Made protected for the React Native SDK to access
|
|
21
19
|
*/
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
this._mountSpan = undefined;
|
|
21
|
+
const { name, disabled = false } = this.props;
|
|
24
22
|
if (disabled) {
|
|
25
|
-
return
|
|
23
|
+
return;
|
|
26
24
|
}
|
|
27
|
-
|
|
25
|
+
const activeTransaction = getActiveTransaction();
|
|
28
26
|
if (activeTransaction) {
|
|
29
|
-
|
|
30
|
-
description:
|
|
27
|
+
this._mountSpan = activeTransaction.startChild({
|
|
28
|
+
description: `<${name}>`,
|
|
31
29
|
op: REACT_MOUNT_OP,
|
|
32
30
|
});
|
|
33
31
|
}
|
|
34
|
-
return _this;
|
|
35
32
|
}
|
|
36
33
|
// If a component mounted, we can finish the mount activity.
|
|
37
|
-
|
|
34
|
+
componentDidMount() {
|
|
38
35
|
if (this._mountSpan) {
|
|
39
36
|
this._mountSpan.finish();
|
|
40
37
|
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
var _this = this;
|
|
44
|
-
var updateProps = _a.updateProps, _b = _a.includeUpdates, includeUpdates = _b === void 0 ? true : _b;
|
|
38
|
+
}
|
|
39
|
+
componentDidUpdate({ updateProps, includeUpdates = true }) {
|
|
45
40
|
// Only generate an update span if hasUpdateSpan is true, if there is a valid mountSpan,
|
|
46
41
|
// and if the updateProps have changed. It is ok to not do a deep equality check here as it is expensive.
|
|
47
42
|
// We are just trying to give baseline clues for further investigation.
|
|
48
43
|
if (includeUpdates && this._mountSpan && updateProps !== this.props.updateProps) {
|
|
49
44
|
// See what props haved changed between the previous props, and the current props. This is
|
|
50
45
|
// set as data on the span. We just store the prop keys as the values could be potenially very large.
|
|
51
|
-
|
|
46
|
+
const changedProps = Object.keys(updateProps).filter(k => updateProps[k] !== this.props.updateProps[k]);
|
|
52
47
|
if (changedProps.length > 0) {
|
|
53
48
|
// The update span is a point in time span with 0 duration, just signifying that the component
|
|
54
49
|
// has been updated.
|
|
55
|
-
|
|
50
|
+
const now = timestampWithMs();
|
|
56
51
|
this._mountSpan.startChild({
|
|
57
52
|
data: {
|
|
58
|
-
changedProps
|
|
53
|
+
changedProps,
|
|
59
54
|
},
|
|
60
|
-
description:
|
|
55
|
+
description: `<${this.props.name}>`,
|
|
61
56
|
endTimestamp: now,
|
|
62
57
|
op: REACT_UPDATE_OP,
|
|
63
58
|
startTimestamp: now,
|
|
64
59
|
});
|
|
65
60
|
}
|
|
66
61
|
}
|
|
67
|
-
}
|
|
62
|
+
}
|
|
68
63
|
// If a component is unmounted, we can say it is no longer on the screen.
|
|
69
64
|
// This means we can finish the span representing the component render.
|
|
70
|
-
|
|
71
|
-
|
|
65
|
+
componentWillUnmount() {
|
|
66
|
+
const { name, includeRender = true } = this.props;
|
|
72
67
|
if (this._mountSpan && includeRender) {
|
|
73
68
|
// If we were able to obtain the spanId of the mount activity, we should set the
|
|
74
69
|
// next activity as a child to the component mount activity.
|
|
75
70
|
this._mountSpan.startChild({
|
|
76
|
-
description:
|
|
71
|
+
description: `<${name}>`,
|
|
77
72
|
endTimestamp: timestampWithMs(),
|
|
78
73
|
op: REACT_RENDER_OP,
|
|
79
74
|
startTimestamp: this._mountSpan.endTimestamp,
|
|
80
75
|
});
|
|
81
76
|
}
|
|
82
|
-
}
|
|
83
|
-
|
|
77
|
+
}
|
|
78
|
+
render() {
|
|
84
79
|
return this.props.children;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}(React.Component));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/member-ordering
|
|
83
|
+
Profiler.defaultProps = {
|
|
84
|
+
disabled: false,
|
|
85
|
+
includeRender: true,
|
|
86
|
+
includeUpdates: true,
|
|
87
|
+
};
|
|
94
88
|
/**
|
|
95
89
|
* withProfiler is a higher order component that wraps a
|
|
96
90
|
* component in a {@link Profiler} component. It is recommended that
|
|
@@ -102,10 +96,10 @@ var Profiler = /** @class */ (function (_super) {
|
|
|
102
96
|
function withProfiler(WrappedComponent,
|
|
103
97
|
// We do not want to have `updateProps` given in options, it is instead filled through the HOC.
|
|
104
98
|
options) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
React.createElement(WrappedComponent,
|
|
108
|
-
Wrapped.displayName =
|
|
99
|
+
const componentDisplayName = (options && options.name) || WrappedComponent.displayName || WrappedComponent.name || UNKNOWN_COMPONENT;
|
|
100
|
+
const Wrapped = (props) => (React.createElement(Profiler, Object.assign({}, options, { name: componentDisplayName, updateProps: props }),
|
|
101
|
+
React.createElement(WrappedComponent, Object.assign({}, props))));
|
|
102
|
+
Wrapped.displayName = `profiler(${componentDisplayName})`;
|
|
109
103
|
// Copy over static methods from Wrapped component to Profiler HOC
|
|
110
104
|
// See: https://reactjs.org/docs/higher-order-components.html#static-methods-must-be-copied-over
|
|
111
105
|
hoistNonReactStatics(Wrapped, WrappedComponent);
|
|
@@ -118,32 +112,31 @@ options) {
|
|
|
118
112
|
* Requires React 16.8 or above.
|
|
119
113
|
* @param name displayName of component being profiled
|
|
120
114
|
*/
|
|
121
|
-
function useProfiler(name, options
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
var _a = __read(React.useState(function () {
|
|
115
|
+
function useProfiler(name, options = {
|
|
116
|
+
disabled: false,
|
|
117
|
+
hasRenderSpan: true,
|
|
118
|
+
}) {
|
|
119
|
+
const [mountSpan] = React.useState(() => {
|
|
127
120
|
if (options && options.disabled) {
|
|
128
121
|
return undefined;
|
|
129
122
|
}
|
|
130
|
-
|
|
123
|
+
const activeTransaction = getActiveTransaction();
|
|
131
124
|
if (activeTransaction) {
|
|
132
125
|
return activeTransaction.startChild({
|
|
133
|
-
description:
|
|
126
|
+
description: `<${name}>`,
|
|
134
127
|
op: REACT_MOUNT_OP,
|
|
135
128
|
});
|
|
136
129
|
}
|
|
137
130
|
return undefined;
|
|
138
|
-
})
|
|
139
|
-
React.useEffect(
|
|
131
|
+
});
|
|
132
|
+
React.useEffect(() => {
|
|
140
133
|
if (mountSpan) {
|
|
141
134
|
mountSpan.finish();
|
|
142
135
|
}
|
|
143
|
-
return
|
|
136
|
+
return () => {
|
|
144
137
|
if (mountSpan && options.hasRenderSpan) {
|
|
145
138
|
mountSpan.startChild({
|
|
146
|
-
description:
|
|
139
|
+
description: `<${name}>`,
|
|
147
140
|
endTimestamp: timestampWithMs(),
|
|
148
141
|
op: REACT_RENDER_OP,
|
|
149
142
|
startTimestamp: mountSpan.endTimestamp,
|
|
@@ -156,10 +149,9 @@ function useProfiler(name, options) {
|
|
|
156
149
|
}
|
|
157
150
|
export { withProfiler, Profiler, useProfiler };
|
|
158
151
|
/** Grabs active transaction off scope */
|
|
159
|
-
export function getActiveTransaction(hub) {
|
|
160
|
-
if (hub === void 0) { hub = getCurrentHub(); }
|
|
152
|
+
export function getActiveTransaction(hub = getCurrentHub()) {
|
|
161
153
|
if (hub) {
|
|
162
|
-
|
|
154
|
+
const scope = hub.getScope();
|
|
163
155
|
if (scope) {
|
|
164
156
|
return scope.getTransaction();
|
|
165
157
|
}
|
package/esm/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/esm/reactrouter.js
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import { __assign } from "tslib";
|
|
2
1
|
import { getGlobalObject } from '@sentry/utils';
|
|
3
2
|
import hoistNonReactStatics from 'hoist-non-react-statics';
|
|
4
3
|
import * as React from 'react';
|
|
5
4
|
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
const global = getGlobalObject();
|
|
6
|
+
let activeTransaction;
|
|
8
7
|
export function reactRouterV4Instrumentation(history, routes, matchPath) {
|
|
9
8
|
return createReactRouterInstrumentation(history, 'react-router-v4', routes, matchPath);
|
|
10
9
|
}
|
|
11
10
|
export function reactRouterV5Instrumentation(history, routes, matchPath) {
|
|
12
11
|
return createReactRouterInstrumentation(history, 'react-router-v5', routes, matchPath);
|
|
13
12
|
}
|
|
14
|
-
function createReactRouterInstrumentation(history, name, allRoutes, matchPath) {
|
|
15
|
-
if (allRoutes === void 0) { allRoutes = []; }
|
|
13
|
+
function createReactRouterInstrumentation(history, name, allRoutes = [], matchPath) {
|
|
16
14
|
function getInitPathName() {
|
|
17
15
|
if (history && history.location) {
|
|
18
16
|
return history.location.pathname;
|
|
@@ -26,19 +24,17 @@ function createReactRouterInstrumentation(history, name, allRoutes, matchPath) {
|
|
|
26
24
|
if (allRoutes.length === 0 || !matchPath) {
|
|
27
25
|
return pathname;
|
|
28
26
|
}
|
|
29
|
-
|
|
27
|
+
const branches = matchRoutes(allRoutes, pathname, matchPath);
|
|
30
28
|
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
31
|
-
for (
|
|
29
|
+
for (let x = 0; x < branches.length; x++) {
|
|
32
30
|
if (branches[x].match.isExact) {
|
|
33
31
|
return branches[x].match.path;
|
|
34
32
|
}
|
|
35
33
|
}
|
|
36
34
|
return pathname;
|
|
37
35
|
}
|
|
38
|
-
return
|
|
39
|
-
|
|
40
|
-
if (startTransactionOnLocationChange === void 0) { startTransactionOnLocationChange = true; }
|
|
41
|
-
var initPathName = getInitPathName();
|
|
36
|
+
return (customStartTransaction, startTransactionOnPageLoad = true, startTransactionOnLocationChange = true) => {
|
|
37
|
+
const initPathName = getInitPathName();
|
|
42
38
|
if (startTransactionOnPageLoad && initPathName) {
|
|
43
39
|
activeTransaction = customStartTransaction({
|
|
44
40
|
name: getTransactionName(initPathName),
|
|
@@ -49,18 +45,18 @@ function createReactRouterInstrumentation(history, name, allRoutes, matchPath) {
|
|
|
49
45
|
});
|
|
50
46
|
}
|
|
51
47
|
if (startTransactionOnLocationChange && history.listen) {
|
|
52
|
-
history.listen(
|
|
48
|
+
history.listen((location, action) => {
|
|
53
49
|
if (action && (action === 'PUSH' || action === 'POP')) {
|
|
54
50
|
if (activeTransaction) {
|
|
55
51
|
activeTransaction.finish();
|
|
56
52
|
}
|
|
57
|
-
|
|
53
|
+
const tags = {
|
|
58
54
|
'routing.instrumentation': name,
|
|
59
55
|
};
|
|
60
56
|
activeTransaction = customStartTransaction({
|
|
61
57
|
name: getTransactionName(location.pathname),
|
|
62
58
|
op: 'navigation',
|
|
63
|
-
tags
|
|
59
|
+
tags,
|
|
64
60
|
});
|
|
65
61
|
}
|
|
66
62
|
});
|
|
@@ -71,16 +67,15 @@ function createReactRouterInstrumentation(history, name, allRoutes, matchPath) {
|
|
|
71
67
|
* Matches a set of routes to a pathname
|
|
72
68
|
* Based on implementation from
|
|
73
69
|
*/
|
|
74
|
-
function matchRoutes(routes, pathname, matchPath, branch) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
var match = route.path
|
|
70
|
+
function matchRoutes(routes, pathname, matchPath, branch = []) {
|
|
71
|
+
routes.some(route => {
|
|
72
|
+
const match = route.path
|
|
78
73
|
? matchPath(pathname, route)
|
|
79
74
|
: branch.length
|
|
80
75
|
? branch[branch.length - 1].match // use parent match
|
|
81
76
|
: computeRootMatch(pathname); // use default "root" match
|
|
82
77
|
if (match) {
|
|
83
|
-
branch.push({ route
|
|
78
|
+
branch.push({ route, match });
|
|
84
79
|
if (route.routes) {
|
|
85
80
|
matchRoutes(route.routes, pathname, matchPath, branch);
|
|
86
81
|
}
|
|
@@ -94,17 +89,17 @@ function computeRootMatch(pathname) {
|
|
|
94
89
|
}
|
|
95
90
|
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */
|
|
96
91
|
export function withSentryRouting(Route) {
|
|
97
|
-
|
|
98
|
-
|
|
92
|
+
const componentDisplayName = Route.displayName || Route.name;
|
|
93
|
+
const WrappedRoute = (props) => {
|
|
99
94
|
if (activeTransaction && props && props.computedMatch && props.computedMatch.isExact) {
|
|
100
95
|
activeTransaction.setName(props.computedMatch.path);
|
|
101
96
|
}
|
|
102
97
|
// @ts-ignore Setting more specific React Component typing for `R` generic above
|
|
103
98
|
// will break advanced type inference done by react router params:
|
|
104
99
|
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/13dc4235c069e25fe7ee16e11f529d909f9f3ff8/types/react-router/index.d.ts#L154-L164
|
|
105
|
-
return React.createElement(Route,
|
|
100
|
+
return React.createElement(Route, Object.assign({}, props));
|
|
106
101
|
};
|
|
107
|
-
WrappedRoute.displayName =
|
|
102
|
+
WrappedRoute.displayName = `sentryRoute(${componentDisplayName})`;
|
|
108
103
|
hoistNonReactStatics(WrappedRoute, Route);
|
|
109
104
|
// @ts-ignore Setting more specific React Component typing for `R` generic above
|
|
110
105
|
// will break advanced type inference done by react router params:
|
package/esm/reactrouter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reactrouter.js","sourceRoot":"","sources":["../../src/reactrouter.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reactrouter.js","sourceRoot":"","sources":["../../src/reactrouter.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Transaction } from '@sentry/types';\nimport { getGlobalObject } from '@sentry/utils';\nimport hoistNonReactStatics from 'hoist-non-react-statics';\nimport * as React from 'react';\n\nimport { Action, Location, ReactRouterInstrumentation } from './types';\n\n// We need to disable eslint no-explict-any because any is required for the\n// react-router typings.\n/* eslint-disable @typescript-eslint/no-explicit-any */\ntype Match = { path: string; url: string; params: Record<string, any>; isExact: boolean };\n\nexport type RouterHistory = {\n location?: Location;\n listen?(cb: (location: Location, action: Action) => void): void;\n} & Record<string, any>;\n\nexport type RouteConfig = {\n [propName: string]: any;\n path?: string | string[];\n exact?: boolean;\n component?: JSX.Element;\n routes?: RouteConfig[];\n};\n\ntype MatchPath = (pathname: string, props: string | string[] | any, parent?: Match | null) => Match | null;\n/* eslint-enable @typescript-eslint/no-explicit-any */\n\nconst global = getGlobalObject<Window>();\n\nlet activeTransaction: Transaction | undefined;\n\nexport function reactRouterV4Instrumentation(\n history: RouterHistory,\n routes?: RouteConfig[],\n matchPath?: MatchPath,\n): ReactRouterInstrumentation {\n return createReactRouterInstrumentation(history, 'react-router-v4', routes, matchPath);\n}\n\nexport function reactRouterV5Instrumentation(\n history: RouterHistory,\n routes?: RouteConfig[],\n matchPath?: MatchPath,\n): ReactRouterInstrumentation {\n return createReactRouterInstrumentation(history, 'react-router-v5', routes, matchPath);\n}\n\nfunction createReactRouterInstrumentation(\n history: RouterHistory,\n name: string,\n allRoutes: RouteConfig[] = [],\n matchPath?: MatchPath,\n): ReactRouterInstrumentation {\n function getInitPathName(): string | undefined {\n if (history && history.location) {\n return history.location.pathname;\n }\n\n if (global && global.location) {\n return global.location.pathname;\n }\n\n return undefined;\n }\n\n function getTransactionName(pathname: string): string {\n if (allRoutes.length === 0 || !matchPath) {\n return pathname;\n }\n\n const branches = matchRoutes(allRoutes, pathname, matchPath);\n // eslint-disable-next-line @typescript-eslint/prefer-for-of\n for (let x = 0; x < branches.length; x++) {\n if (branches[x].match.isExact) {\n return branches[x].match.path;\n }\n }\n\n return pathname;\n }\n\n return (customStartTransaction, startTransactionOnPageLoad = true, startTransactionOnLocationChange = true): void => {\n const initPathName = getInitPathName();\n if (startTransactionOnPageLoad && initPathName) {\n activeTransaction = customStartTransaction({\n name: getTransactionName(initPathName),\n op: 'pageload',\n tags: {\n 'routing.instrumentation': name,\n },\n });\n }\n\n if (startTransactionOnLocationChange && history.listen) {\n history.listen((location, action) => {\n if (action && (action === 'PUSH' || action === 'POP')) {\n if (activeTransaction) {\n activeTransaction.finish();\n }\n const tags = {\n 'routing.instrumentation': name,\n };\n\n activeTransaction = customStartTransaction({\n name: getTransactionName(location.pathname),\n op: 'navigation',\n tags,\n });\n }\n });\n }\n };\n}\n\n/**\n * Matches a set of routes to a pathname\n * Based on implementation from\n */\nfunction matchRoutes(\n routes: RouteConfig[],\n pathname: string,\n matchPath: MatchPath,\n branch: Array<{ route: RouteConfig; match: Match }> = [],\n): Array<{ route: RouteConfig; match: Match }> {\n routes.some(route => {\n const match = route.path\n ? matchPath(pathname, route)\n : branch.length\n ? branch[branch.length - 1].match // use parent match\n : computeRootMatch(pathname); // use default \"root\" match\n\n if (match) {\n branch.push({ route, match });\n\n if (route.routes) {\n matchRoutes(route.routes, pathname, matchPath, branch);\n }\n }\n\n return !!match;\n });\n\n return branch;\n}\n\nfunction computeRootMatch(pathname: string): Match {\n return { path: '/', url: '/', params: {}, isExact: pathname === '/' };\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */\nexport function withSentryRouting<P extends Record<string, any>, R extends React.ComponentType<P>>(Route: R): R {\n const componentDisplayName = (Route as any).displayName || (Route as any).name;\n\n const WrappedRoute: React.FC<P> = (props: P) => {\n if (activeTransaction && props && props.computedMatch && props.computedMatch.isExact) {\n activeTransaction.setName(props.computedMatch.path);\n }\n\n // @ts-ignore Setting more specific React Component typing for `R` generic above\n // will break advanced type inference done by react router params:\n // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/13dc4235c069e25fe7ee16e11f529d909f9f3ff8/types/react-router/index.d.ts#L154-L164\n return <Route {...props} />;\n };\n\n WrappedRoute.displayName = `sentryRoute(${componentDisplayName})`;\n hoistNonReactStatics(WrappedRoute, Route);\n // @ts-ignore Setting more specific React Component typing for `R` generic above\n // will break advanced type inference done by react router params:\n // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/13dc4235c069e25fe7ee16e11f529d909f9f3ff8/types/react-router/index.d.ts#L154-L164\n return WrappedRoute;\n}\n/* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */\n"]}
|
package/esm/reactrouterv3.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getGlobalObject } from '@sentry/utils';
|
|
2
|
-
|
|
2
|
+
const global = getGlobalObject();
|
|
3
3
|
/**
|
|
4
4
|
* Creates routing instrumentation for React Router v3
|
|
5
5
|
* Works for React Router >= 3.2.0 and < 4.0.0
|
|
@@ -9,14 +9,12 @@ var global = getGlobalObject();
|
|
|
9
9
|
* @param match `Router.match` utility
|
|
10
10
|
*/
|
|
11
11
|
export function reactRouterV3Instrumentation(history, routes, match) {
|
|
12
|
-
return
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
var activeTransaction;
|
|
16
|
-
var prevName;
|
|
12
|
+
return (startTransaction, startTransactionOnPageLoad = true, startTransactionOnLocationChange = true) => {
|
|
13
|
+
let activeTransaction;
|
|
14
|
+
let prevName;
|
|
17
15
|
// Have to use global.location because history.location might not be defined.
|
|
18
16
|
if (startTransactionOnPageLoad && global && global.location) {
|
|
19
|
-
normalizeTransactionName(routes, global.location, match,
|
|
17
|
+
normalizeTransactionName(routes, global.location, match, (localName) => {
|
|
20
18
|
prevName = localName;
|
|
21
19
|
activeTransaction = startTransaction({
|
|
22
20
|
name: prevName,
|
|
@@ -28,23 +26,23 @@ export function reactRouterV3Instrumentation(history, routes, match) {
|
|
|
28
26
|
});
|
|
29
27
|
}
|
|
30
28
|
if (startTransactionOnLocationChange && history.listen) {
|
|
31
|
-
history.listen(
|
|
29
|
+
history.listen(location => {
|
|
32
30
|
if (location.action === 'PUSH' || location.action === 'POP') {
|
|
33
31
|
if (activeTransaction) {
|
|
34
32
|
activeTransaction.finish();
|
|
35
33
|
}
|
|
36
|
-
|
|
34
|
+
const tags = {
|
|
37
35
|
'routing.instrumentation': 'react-router-v3',
|
|
38
36
|
};
|
|
39
37
|
if (prevName) {
|
|
40
|
-
|
|
38
|
+
tags.from = prevName;
|
|
41
39
|
}
|
|
42
|
-
normalizeTransactionName(routes, location, match,
|
|
40
|
+
normalizeTransactionName(routes, location, match, (localName) => {
|
|
43
41
|
prevName = localName;
|
|
44
42
|
activeTransaction = startTransaction({
|
|
45
43
|
name: prevName,
|
|
46
44
|
op: 'navigation',
|
|
47
|
-
tags
|
|
45
|
+
tags,
|
|
48
46
|
});
|
|
49
47
|
});
|
|
50
48
|
}
|
|
@@ -56,15 +54,15 @@ export function reactRouterV3Instrumentation(history, routes, match) {
|
|
|
56
54
|
* Normalize transaction names using `Router.match`
|
|
57
55
|
*/
|
|
58
56
|
function normalizeTransactionName(appRoutes, location, match, callback) {
|
|
59
|
-
|
|
57
|
+
let name = location.pathname;
|
|
60
58
|
match({
|
|
61
|
-
location
|
|
59
|
+
location,
|
|
62
60
|
routes: appRoutes,
|
|
63
|
-
},
|
|
61
|
+
}, (error, _redirectLocation, renderProps) => {
|
|
64
62
|
if (error || !renderProps) {
|
|
65
63
|
return callback(name);
|
|
66
64
|
}
|
|
67
|
-
|
|
65
|
+
const routePath = getRouteStringFromRoutes(renderProps.routes || []);
|
|
68
66
|
if (routePath.length === 0 || routePath === '/*') {
|
|
69
67
|
return callback(name);
|
|
70
68
|
}
|
|
@@ -79,10 +77,10 @@ function getRouteStringFromRoutes(routes) {
|
|
|
79
77
|
if (!Array.isArray(routes) || routes.length === 0) {
|
|
80
78
|
return '';
|
|
81
79
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
for (
|
|
85
|
-
|
|
80
|
+
const routesWithPaths = routes.filter((route) => !!route.path);
|
|
81
|
+
let index = -1;
|
|
82
|
+
for (let x = routesWithPaths.length - 1; x >= 0; x--) {
|
|
83
|
+
const route = routesWithPaths[x];
|
|
86
84
|
if (route.path && route.path.startsWith('/')) {
|
|
87
85
|
index = x;
|
|
88
86
|
break;
|
|
@@ -90,14 +88,8 @@ function getRouteStringFromRoutes(routes) {
|
|
|
90
88
|
}
|
|
91
89
|
return routesWithPaths
|
|
92
90
|
.slice(index)
|
|
93
|
-
.filter(
|
|
94
|
-
|
|
95
|
-
return !!path;
|
|
96
|
-
})
|
|
97
|
-
.map(function (_a) {
|
|
98
|
-
var path = _a.path;
|
|
99
|
-
return path;
|
|
100
|
-
})
|
|
91
|
+
.filter(({ path }) => !!path)
|
|
92
|
+
.map(({ path }) => path)
|
|
101
93
|
.join('');
|
|
102
94
|
}
|
|
103
95
|
//# sourceMappingURL=reactrouterv3.js.map
|
package/esm/reactrouterv3.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reactrouterv3.js","sourceRoot":"","sources":["../../src/reactrouterv3.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAoBhD,
|
|
1
|
+
{"version":3,"file":"reactrouterv3.js","sourceRoot":"","sources":["../../src/reactrouterv3.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAoBhD,MAAM,MAAM,GAAG,eAAe,EAAU,CAAC;AAEzC;;;;;;;GAOG;AACH,MAAM,UAAU,4BAA4B,CAC1C,OAAkB,EAClB,MAAe,EACf,KAAY;IAEZ,OAAO,CACL,gBAA0E,EAC1E,6BAAsC,IAAI,EAC1C,mCAA4C,IAAI,EAChD,EAAE;QACF,IAAI,iBAA0C,CAAC;QAC/C,IAAI,QAA4B,CAAC;QAEjC,6EAA6E;QAC7E,IAAI,0BAA0B,IAAI,MAAM,IAAI,MAAM,CAAC,QAAQ,EAAE;YAC3D,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,QAA+B,EAAE,KAAK,EAAE,CAAC,SAAiB,EAAE,EAAE;gBACpG,QAAQ,GAAG,SAAS,CAAC;gBACrB,iBAAiB,GAAG,gBAAgB,CAAC;oBACnC,IAAI,EAAE,QAAQ;oBACd,EAAE,EAAE,UAAU;oBACd,IAAI,EAAE;wBACJ,yBAAyB,EAAE,iBAAiB;qBAC7C;iBACF,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;SACJ;QAED,IAAI,gCAAgC,IAAI,OAAO,CAAC,MAAM,EAAE;YACtD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE;gBACxB,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,IAAI,QAAQ,CAAC,MAAM,KAAK,KAAK,EAAE;oBAC3D,IAAI,iBAAiB,EAAE;wBACrB,iBAAiB,CAAC,MAAM,EAAE,CAAC;qBAC5B;oBACD,MAAM,IAAI,GAA8B;wBACtC,yBAAyB,EAAE,iBAAiB;qBAC7C,CAAC;oBACF,IAAI,QAAQ,EAAE;wBACZ,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC;qBACtB;oBACD,wBAAwB,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,SAAiB,EAAE,EAAE;wBACtE,QAAQ,GAAG,SAAS,CAAC;wBACrB,iBAAiB,GAAG,gBAAgB,CAAC;4BACnC,IAAI,EAAE,QAAQ;4BACd,EAAE,EAAE,YAAY;4BAChB,IAAI;yBACL,CAAC,CAAC;oBACL,CAAC,CAAC,CAAC;iBACJ;YACH,CAAC,CAAC,CAAC;SACJ;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,wBAAwB,CAC/B,SAAkB,EAClB,QAAkB,EAClB,KAAY,EACZ,QAAoC;IAEpC,IAAI,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC;IAC7B,KAAK,CACH;QACE,QAAQ;QACR,MAAM,EAAE,SAAS;KAClB,EACD,CAAC,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,EAAE;QACxC,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE;YACzB,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;SACvB;QAED,MAAM,SAAS,GAAG,wBAAwB,CAAC,WAAW,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QACrE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,SAAS,KAAK,IAAI,EAAE;YAChD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;SACvB;QAED,IAAI,GAAG,SAAS,CAAC;QACjB,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC,CACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,wBAAwB,CAAC,MAAe;IAC/C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;QACjD,OAAO,EAAE,CAAC;KACX;IAED,MAAM,eAAe,GAAY,MAAM,CAAC,MAAM,CAAC,CAAC,KAAY,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE/E,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;QACpD,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;YAC5C,KAAK,GAAG,CAAC,CAAC;YACV,MAAM;SACP;KACF;IAED,OAAO,eAAe;SACnB,KAAK,CAAC,KAAK,CAAC;SACZ,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAC5B,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC;SACvB,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC","sourcesContent":["import { Primitive, Transaction, TransactionContext } from '@sentry/types';\nimport { getGlobalObject } from '@sentry/utils';\n\nimport { Location, ReactRouterInstrumentation } from './types';\n\n// Many of the types below had to be mocked out to prevent typescript issues\n// these types are required for correct functionality.\n\ntype HistoryV3 = {\n location?: Location;\n listen?(cb: (location: Location) => void): void;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n} & Record<string, any>;\n\nexport type Route = { path?: string; childRoutes?: Route[] };\n\nexport type Match = (\n props: { location: Location; routes: Route[] },\n cb: (error?: Error, _redirectLocation?: Location, renderProps?: { routes?: Route[] }) => void,\n) => void;\n\nconst global = getGlobalObject<Window>();\n\n/**\n * Creates routing instrumentation for React Router v3\n * Works for React Router >= 3.2.0 and < 4.0.0\n *\n * @param history object from the `history` library\n * @param routes a list of all routes, should be\n * @param match `Router.match` utility\n */\nexport function reactRouterV3Instrumentation(\n history: HistoryV3,\n routes: Route[],\n match: Match,\n): ReactRouterInstrumentation {\n return (\n startTransaction: (context: TransactionContext) => Transaction | undefined,\n startTransactionOnPageLoad: boolean = true,\n startTransactionOnLocationChange: boolean = true,\n ) => {\n let activeTransaction: Transaction | undefined;\n let prevName: string | undefined;\n\n // Have to use global.location because history.location might not be defined.\n if (startTransactionOnPageLoad && global && global.location) {\n normalizeTransactionName(routes, global.location as unknown as Location, match, (localName: string) => {\n prevName = localName;\n activeTransaction = startTransaction({\n name: prevName,\n op: 'pageload',\n tags: {\n 'routing.instrumentation': 'react-router-v3',\n },\n });\n });\n }\n\n if (startTransactionOnLocationChange && history.listen) {\n history.listen(location => {\n if (location.action === 'PUSH' || location.action === 'POP') {\n if (activeTransaction) {\n activeTransaction.finish();\n }\n const tags: Record<string, Primitive> = {\n 'routing.instrumentation': 'react-router-v3',\n };\n if (prevName) {\n tags.from = prevName;\n }\n normalizeTransactionName(routes, location, match, (localName: string) => {\n prevName = localName;\n activeTransaction = startTransaction({\n name: prevName,\n op: 'navigation',\n tags,\n });\n });\n }\n });\n }\n };\n}\n\n/**\n * Normalize transaction names using `Router.match`\n */\nfunction normalizeTransactionName(\n appRoutes: Route[],\n location: Location,\n match: Match,\n callback: (pathname: string) => void,\n): void {\n let name = location.pathname;\n match(\n {\n location,\n routes: appRoutes,\n },\n (error, _redirectLocation, renderProps) => {\n if (error || !renderProps) {\n return callback(name);\n }\n\n const routePath = getRouteStringFromRoutes(renderProps.routes || []);\n if (routePath.length === 0 || routePath === '/*') {\n return callback(name);\n }\n\n name = routePath;\n return callback(name);\n },\n );\n}\n\n/**\n * Generate route name from array of routes\n */\nfunction getRouteStringFromRoutes(routes: Route[]): string {\n if (!Array.isArray(routes) || routes.length === 0) {\n return '';\n }\n\n const routesWithPaths: Route[] = routes.filter((route: Route) => !!route.path);\n\n let index = -1;\n for (let x = routesWithPaths.length - 1; x >= 0; x--) {\n const route = routesWithPaths[x];\n if (route.path && route.path.startsWith('/')) {\n index = x;\n break;\n }\n }\n\n return routesWithPaths\n .slice(index)\n .filter(({ path }) => !!path)\n .map(({ path }) => path)\n .join('');\n}\n"]}
|