Skip to content

Commit e9db290

Browse files
committed
use client hooks
1 parent ffc15f2 commit e9db290

File tree

3 files changed

+44
-37
lines changed

3 files changed

+44
-37
lines changed

packages/browser/src/profiling/index.ts

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,7 @@
1-
import type { Profiler, ProfilingIntegration } from '@sentry/core';
1+
import type { Profiler } from '@sentry/core';
22
import { debug, getClient } from '@sentry/core';
33
import { DEBUG_BUILD } from '../debug-build';
44

5-
function isProfilingIntegrationWithProfiler(
6-
integration: ProfilingIntegration | undefined,
7-
): integration is ProfilingIntegration {
8-
return (
9-
!!integration &&
10-
typeof integration['_profiler'] !== 'undefined' &&
11-
typeof integration['_profiler']['start'] === 'function' &&
12-
typeof integration['_profiler']['stop'] === 'function'
13-
);
14-
}
15-
165
/**
176
* Starts the Sentry UI profiler.
187
* This mode is exclusive with the transaction profiler and will only work if the profilesSampleRate is set to a falsy value.
@@ -25,19 +14,14 @@ function startProfiler(): void {
2514
return;
2615
}
2716

28-
const integration = client.getIntegrationByName<ProfilingIntegration>('BrowserProfiling');
17+
const integration = client.getIntegrationByName('BrowserProfiling');
2918

3019
if (!integration) {
3120
DEBUG_BUILD && debug.warn('BrowserProfiling integration is not available');
3221
return;
3322
}
3423

35-
if (!isProfilingIntegrationWithProfiler(integration)) {
36-
DEBUG_BUILD && debug.warn('Profiler is not available on profiling integration.');
37-
return;
38-
}
39-
40-
integration._profiler.start();
24+
client.emit('startUIProfiler');
4125
}
4226

4327
/**
@@ -51,18 +35,13 @@ function stopProfiler(): void {
5135
return;
5236
}
5337

54-
const integration = client.getIntegrationByName<ProfilingIntegration>('BrowserProfiling');
38+
const integration = client.getIntegrationByName('BrowserProfiling');
5539
if (!integration) {
5640
DEBUG_BUILD && debug.warn('ProfilingIntegration is not available');
5741
return;
5842
}
5943

60-
if (!isProfilingIntegrationWithProfiler(integration)) {
61-
DEBUG_BUILD && debug.warn('Profiler is not available on profiling integration.');
62-
return;
63-
}
64-
65-
integration._profiler.stop();
44+
client.emit('stopUIProfiler');
6645
}
6746

6847
/**

packages/browser/src/profiling/integration.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { EventEnvelope, Integration, IntegrationFn, Profile, Span } from '@sentry/core';
1+
import type { EventEnvelope, IntegrationFn, Profile, Span } from '@sentry/core';
22
import { debug, defineIntegration, getActiveSpan, getRootSpan, hasSpansEnabled } from '@sentry/core';
33
import type { BrowserOptions } from '../client';
44
import { DEBUG_BUILD } from '../debug-build';
@@ -23,9 +23,9 @@ const INTEGRATION_NAME = 'BrowserProfiling';
2323
const _browserProfilingIntegration = (() => {
2424
return {
2525
name: INTEGRATION_NAME,
26-
_profiler: new UIProfiler(),
2726
setup(client) {
2827
const options = client.getOptions() as BrowserOptions;
28+
const profiler = new UIProfiler();
2929

3030
if (!hasLegacyProfiling(options) && !options.profileLifecycle) {
3131
// Set default lifecycle mode
@@ -52,8 +52,12 @@ const _browserProfilingIntegration = (() => {
5252
if (!hasLegacyProfiling(options)) {
5353
const lifecycleMode = options.profileLifecycle;
5454

55+
// Registering hooks in all lifecycle modes to be able to notify users in case they want to start/stop the profiler manually in `trace` mode
56+
client.on('startUIProfiler', () => profiler.start());
57+
client.on('stopUIProfiler', () => profiler.stop());
58+
5559
if (lifecycleMode === 'manual') {
56-
this._profiler.initialize(client);
60+
profiler.initialize(client);
5761
} else if (lifecycleMode === 'trace') {
5862
if (!hasSpansEnabled(options)) {
5963
DEBUG_BUILD &&
@@ -63,19 +67,19 @@ const _browserProfilingIntegration = (() => {
6367
return;
6468
}
6569

66-
this._profiler.initialize(client);
70+
profiler.initialize(client);
6771

6872
// If there is an active, sampled root span already, notify the profiler
6973
if (rootSpan) {
70-
this._profiler.notifyRootSpanActive(rootSpan);
74+
profiler.notifyRootSpanActive(rootSpan);
7175
}
7276

7377
// In case rootSpan is created slightly after setup -> schedule microtask to re-check and notify.
7478
WINDOW.setTimeout(() => {
7579
const laterActiveSpan = getActiveSpan();
7680
const laterRootSpan = laterActiveSpan && getRootSpan(laterActiveSpan);
7781
if (laterRootSpan) {
78-
this._profiler.notifyRootSpanActive(laterRootSpan);
82+
profiler.notifyRootSpanActive(laterRootSpan);
7983
}
8084
}, 0);
8185
}
@@ -151,10 +155,6 @@ const _browserProfilingIntegration = (() => {
151155
return attachProfiledThreadToEvent(event);
152156
},
153157
};
154-
}) satisfies IntegrationFn<BrowserProfilingIntegration>;
155-
156-
interface BrowserProfilingIntegration extends Integration {
157-
_profiler: UIProfiler;
158-
}
158+
}) satisfies IntegrationFn;
159159

160160
export const browserProfilingIntegration = defineIntegration(_browserProfilingIntegration);

packages/core/src/client.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,24 @@ export abstract class Client<O extends ClientOptions = ClientOptions> {
794794
callback: (request: unknown, response: unknown, normalizedRequest: RequestEventData) => void,
795795
): () => void;
796796

797+
/**
798+
* A hook that is called when the UI Profiler should start profiling.
799+
*
800+
* This hook is called when running `Sentry.uiProfiler.startProfiler()`.
801+
*
802+
* @returns {() => void} A function that, when executed, removes the registered callback.
803+
*/
804+
public on(hook: 'startUIProfiler', callback: () => void): () => void;
805+
806+
/**
807+
* A hook that is called when the UI Profiler should stop profiling.
808+
*
809+
* This hook is called when running `Sentry.uiProfiler.stopProfiler()`.
810+
*
811+
* @returns {() => void} A function that, when executed, removes the registered callback.
812+
*/
813+
public on(hook: 'stopUIProfiler', callback: () => void): () => void;
814+
797815
/**
798816
* Register a hook on this client.
799817
*/
@@ -1003,6 +1021,16 @@ export abstract class Client<O extends ClientOptions = ClientOptions> {
10031021
normalizedRequest: RequestEventData,
10041022
): void;
10051023

1024+
/**
1025+
* Emit a hook event for starting the UI Profiler.
1026+
*/
1027+
public emit(hook: 'startUIProfiler'): void;
1028+
1029+
/**
1030+
* Emit a hook event for stopping the UI Profiler.
1031+
*/
1032+
public emit(hook: 'stopUIProfiler'): void;
1033+
10061034
/**
10071035
* Emit a hook that was previously registered via `on()`.
10081036
*/

0 commit comments

Comments
 (0)