1
1
import { getCurrentHub } from '@sentry/browser' ;
2
- import { Integration , IntegrationClass } from '@sentry/types' ;
2
+ import { Integration , IntegrationClass , Span } from '@sentry/types' ;
3
3
import { logger } from '@sentry/utils' ;
4
4
import * as hoistNonReactStatic from 'hoist-non-react-statics' ;
5
5
import * as React from 'react' ;
@@ -88,20 +88,41 @@ const popActivity = (activity: number | null): void => {
88
88
} ;
89
89
90
90
export type ProfilerProps = {
91
+ // The name of the component being profiled.
91
92
name : string ;
93
+ // If the Profiler is disabled. False by default.
94
+ disabled ?: boolean ;
92
95
} ;
93
96
97
+ /**
98
+ * The Profiler component leverages Sentry's Tracing integration to generate
99
+ * spans based on component lifecycles.
100
+ */
94
101
class Profiler extends React . Component < ProfilerProps > {
95
102
public activity : number | null = null ;
103
+ // The activity representing when a component was mounted onto a page.
104
+ public mountInfo : {
105
+ activity : number | null ;
106
+ span : Span | null ;
107
+ } = {
108
+ activity : null ,
109
+ span : null ,
110
+ } ;
111
+ // The activity representing how long a component was on the page.
112
+ public visibleActivity : number | null = null ;
96
113
97
114
public constructor ( props : ProfilerProps ) {
98
115
super ( props ) ;
116
+ const { name, disabled = false } = this . props ;
117
+
118
+ if ( disabled ) {
119
+ return ;
120
+ }
99
121
100
- // We should check for tracing integration per Profiler instance
101
122
if ( getTracingIntegration ( ) ) {
102
- this . activity = pushActivity ( this . props . name ) ;
123
+ this . activity = pushActivity ( name ) ;
103
124
} else {
104
- warnAboutTracing ( this . props . name ) ;
125
+ warnAboutTracing ( name ) ;
105
126
}
106
127
}
107
128
@@ -117,8 +138,10 @@ class Profiler extends React.Component<ProfilerProps> {
117
138
}
118
139
119
140
public finishProfile = ( ) => {
120
- popActivity ( this . activity ) ;
121
- this . activity = null ;
141
+ afterNextFrame ( ( ) => {
142
+ popActivity ( this . activity ) ;
143
+ this . activity = null ;
144
+ } ) ;
122
145
} ;
123
146
124
147
public render ( ) : React . ReactNode {
@@ -131,13 +154,17 @@ class Profiler extends React.Component<ProfilerProps> {
131
154
* component in a {@link Profiler} component.
132
155
*
133
156
* @param WrappedComponent component that is wrapped by Profiler
134
- * @param name displayName of component being profiled
157
+ * @param options the { @link ProfilerProps} you can pass into the Profiler
135
158
*/
136
- function withProfiler < P extends object > ( WrappedComponent : React . ComponentType < P > , name ?: string ) : React . FC < P > {
137
- const componentDisplayName = name || WrappedComponent . displayName || WrappedComponent . name || UNKNOWN_COMPONENT ;
159
+ function withProfiler < P extends object > (
160
+ WrappedComponent : React . ComponentType < P > ,
161
+ options ?: Partial < ProfilerProps > ,
162
+ ) : React . FC < P > {
163
+ const componentDisplayName =
164
+ ( options && options . name ) || WrappedComponent . displayName || WrappedComponent . name || UNKNOWN_COMPONENT ;
138
165
139
166
const Wrapped : React . FC < P > = ( props : P ) => (
140
- < Profiler name = { componentDisplayName } >
167
+ < Profiler name = { componentDisplayName } disabled = { options && options . disabled } >
141
168
< WrappedComponent { ...props } />
142
169
</ Profiler >
143
170
) ;
0 commit comments