@sentry/browser 10.25.0 → 10.27.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/build/npm/cjs/dev/client.js +0 -1
- package/build/npm/cjs/dev/client.js.map +1 -1
- package/build/npm/cjs/dev/index.js +2 -0
- package/build/npm/cjs/dev/index.js.map +1 -1
- package/build/npm/cjs/dev/profiling/{lifecycleMode/traceLifecycleProfiler.js → UIProfiler.js} +158 -103
- package/build/npm/cjs/dev/profiling/UIProfiler.js.map +1 -0
- package/build/npm/cjs/dev/profiling/index.js +59 -0
- package/build/npm/cjs/dev/profiling/index.js.map +1 -0
- package/build/npm/cjs/dev/profiling/integration.js +13 -11
- package/build/npm/cjs/dev/profiling/integration.js.map +1 -1
- package/build/npm/cjs/dev/profiling/utils.js +11 -5
- package/build/npm/cjs/dev/profiling/utils.js.map +1 -1
- package/build/npm/cjs/prod/client.js +0 -1
- package/build/npm/cjs/prod/client.js.map +1 -1
- package/build/npm/cjs/prod/index.js +2 -0
- package/build/npm/cjs/prod/index.js.map +1 -1
- package/build/npm/cjs/prod/profiling/{lifecycleMode/traceLifecycleProfiler.js → UIProfiler.js} +158 -103
- package/build/npm/cjs/prod/profiling/UIProfiler.js.map +1 -0
- package/build/npm/cjs/prod/profiling/index.js +59 -0
- package/build/npm/cjs/prod/profiling/index.js.map +1 -0
- package/build/npm/cjs/prod/profiling/integration.js +13 -11
- package/build/npm/cjs/prod/profiling/integration.js.map +1 -1
- package/build/npm/cjs/prod/profiling/utils.js +11 -5
- package/build/npm/cjs/prod/profiling/utils.js.map +1 -1
- package/build/npm/esm/dev/client.js +0 -1
- package/build/npm/esm/dev/client.js.map +1 -1
- package/build/npm/esm/dev/index.js +1 -0
- package/build/npm/esm/dev/index.js.map +1 -1
- package/build/npm/esm/dev/package.json +1 -1
- package/build/npm/esm/dev/profiling/{lifecycleMode/traceLifecycleProfiler.js → UIProfiler.js} +159 -104
- package/build/npm/esm/dev/profiling/UIProfiler.js.map +1 -0
- package/build/npm/esm/dev/profiling/index.js +57 -0
- package/build/npm/esm/dev/profiling/index.js.map +1 -0
- package/build/npm/esm/dev/profiling/integration.js +14 -12
- package/build/npm/esm/dev/profiling/integration.js.map +1 -1
- package/build/npm/esm/dev/profiling/utils.js +12 -6
- package/build/npm/esm/dev/profiling/utils.js.map +1 -1
- package/build/npm/esm/prod/client.js +0 -1
- package/build/npm/esm/prod/client.js.map +1 -1
- package/build/npm/esm/prod/index.js +1 -0
- package/build/npm/esm/prod/index.js.map +1 -1
- package/build/npm/esm/prod/package.json +1 -1
- package/build/npm/esm/prod/profiling/{lifecycleMode/traceLifecycleProfiler.js → UIProfiler.js} +159 -104
- package/build/npm/esm/prod/profiling/UIProfiler.js.map +1 -0
- package/build/npm/esm/prod/profiling/index.js +57 -0
- package/build/npm/esm/prod/profiling/index.js.map +1 -0
- package/build/npm/esm/prod/profiling/integration.js +14 -12
- package/build/npm/esm/prod/profiling/integration.js.map +1 -1
- package/build/npm/esm/prod/profiling/utils.js +12 -6
- package/build/npm/esm/prod/profiling/utils.js.map +1 -1
- package/build/npm/types/client.d.ts.map +1 -1
- package/build/npm/types/exports.d.ts +1 -0
- package/build/npm/types/exports.d.ts.map +1 -1
- package/build/npm/{types-ts3.8/profiling/lifecycleMode/traceLifecycleProfiler.d.ts → types/profiling/UIProfiler.d.ts} +75 -70
- package/build/npm/types/profiling/UIProfiler.d.ts.map +1 -0
- package/build/npm/types/profiling/index.d.ts +8 -0
- package/build/npm/types/profiling/index.d.ts.map +1 -0
- package/build/npm/types/profiling/integration.d.ts.map +1 -1
- package/build/npm/types/profiling/utils.d.ts +1 -1
- package/build/npm/types/profiling/utils.d.ts.map +1 -1
- package/build/npm/types-ts3.8/exports.d.ts +1 -0
- package/build/npm/{types/profiling/lifecycleMode/traceLifecycleProfiler.d.ts → types-ts3.8/profiling/UIProfiler.d.ts} +75 -70
- package/build/npm/types-ts3.8/profiling/index.d.ts +8 -0
- package/build/npm/types-ts3.8/profiling/utils.d.ts +1 -1
- package/package.json +7 -7
- package/build/npm/cjs/dev/profiling/lifecycleMode/traceLifecycleProfiler.js.map +0 -1
- package/build/npm/cjs/prod/profiling/lifecycleMode/traceLifecycleProfiler.js.map +0 -1
- package/build/npm/esm/dev/profiling/lifecycleMode/traceLifecycleProfiler.js.map +0 -1
- package/build/npm/esm/prod/profiling/lifecycleMode/traceLifecycleProfiler.js.map +0 -1
- package/build/npm/types/profiling/lifecycleMode/traceLifecycleProfiler.d.ts.map +0 -1
|
@@ -50,7 +50,6 @@ class BrowserClient extends core.Client {
|
|
|
50
50
|
|
|
51
51
|
// Flush logs and metrics when page becomes hidden (e.g., tab switch, navigation)
|
|
52
52
|
// todo(v11): Remove the experimental flag
|
|
53
|
-
// eslint-disable-next-line deprecation/deprecation
|
|
54
53
|
if (helpers.WINDOW.document && (sendClientReports || enableLogs || enableMetrics)) {
|
|
55
54
|
helpers.WINDOW.document.addEventListener('visibilitychange', () => {
|
|
56
55
|
if (helpers.WINDOW.document.visibilityState === 'hidden') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sources":["../../../../src/client.ts"],"sourcesContent":["import type {\n BrowserClientProfilingOptions,\n BrowserClientReplayOptions,\n ClientOptions,\n Event,\n EventHint,\n Options as CoreOptions,\n ParameterizedString,\n Scope,\n SeverityLevel,\n} from '@sentry/core';\nimport {\n _INTERNAL_flushLogsBuffer,\n _INTERNAL_flushMetricsBuffer,\n addAutoIpAddressToSession,\n applySdkMetadata,\n Client,\n getSDKSource,\n} from '@sentry/core';\nimport { eventFromException, eventFromMessage } from './eventbuilder';\nimport { WINDOW } from './helpers';\nimport type { BrowserTransportOptions } from './transports/types';\n\n/**\n * A magic string that build tooling can leverage in order to inject a release value into the SDK.\n */\ndeclare const __SENTRY_RELEASE__: string | undefined;\n\ntype BrowserSpecificOptions = BrowserClientReplayOptions &\n BrowserClientProfilingOptions & {\n /** If configured, this URL will be used as base URL for lazy loading integration. */\n cdnBaseUrl?: string;\n\n /**\n * Important: Only set this option if you know what you are doing!\n *\n * By default, the SDK will check if `Sentry.init` is called in a browser extension.\n * In case it is, it will stop initialization and log a warning\n * because browser extensions require a different Sentry initialization process:\n * https://docs.sentry.io/platforms/javascript/best-practices/shared-environments/\n *\n * Setting up the SDK in a browser extension with global error monitoring is not recommended\n * and will likely flood you with errors from other web sites or extensions. This can heavily\n * impact your quota and cause interference with your and other Sentry SDKs in shared environments.\n *\n * If this check wrongfully flags your setup as a browser extension, you can set this\n * option to `true` to skip the check.\n *\n * @default false\n */\n skipBrowserExtensionCheck?: boolean;\n\n /**\n * If set to `true`, the SDK propagates the W3C `traceparent` header to any outgoing requests,\n * in addition to the `sentry-trace` and `baggage` headers. Use the {@link CoreOptions.tracePropagationTargets}\n * option to control to which outgoing requests the header will be attached.\n *\n * **Important:** If you set this option to `true`, make sure that you configured your servers'\n * CORS settings to allow the `traceparent` header. Otherwise, requests might get blocked.\n *\n * @see https://www.w3.org/TR/trace-context/\n *\n * @default false\n */\n propagateTraceparent?: boolean;\n\n /**\n * If you use Spotlight by Sentry during development, use\n * this option to forward captured Sentry events to Spotlight.\n *\n * Either set it to true, or provide a specific Spotlight Sidecar URL.\n *\n * More details: https://spotlightjs.com/\n *\n * IMPORTANT: Only set this option to `true` while developing, not in production!\n */\n spotlight?: boolean | string;\n };\n/**\n * Configuration options for the Sentry Browser SDK.\n * @see @sentry/core Options for more information.\n */\nexport type BrowserOptions = CoreOptions<BrowserTransportOptions> & BrowserSpecificOptions;\n\n/**\n * Configuration options for the Sentry Browser SDK Client class\n * @see BrowserClient for more information.\n */\nexport type BrowserClientOptions = ClientOptions<BrowserTransportOptions> & BrowserSpecificOptions;\n\n/**\n * The Sentry Browser SDK Client.\n *\n * @see BrowserOptions for documentation on configuration options.\n * @see SentryClient for usage documentation.\n */\nexport class BrowserClient extends Client<BrowserClientOptions> {\n /**\n * Creates a new Browser SDK instance.\n *\n * @param options Configuration options for this SDK.\n */\n public constructor(options: BrowserClientOptions) {\n const opts = applyDefaultOptions(options);\n const sdkSource = WINDOW.SENTRY_SDK_SOURCE || getSDKSource();\n applySdkMetadata(opts, 'browser', ['browser'], sdkSource);\n\n // Only allow IP inferral by Relay if sendDefaultPii is true\n if (opts._metadata?.sdk) {\n opts._metadata.sdk.settings = {\n infer_ip: opts.sendDefaultPii ? 'auto' : 'never',\n // purposefully allowing already passed settings to override the default\n ...opts._metadata.sdk.settings,\n };\n }\n\n super(opts);\n\n const {\n sendDefaultPii,\n sendClientReports,\n enableLogs,\n _experiments,\n enableMetrics: enableMetricsOption,\n } = this._options;\n\n // todo(v11): Remove the experimental flag\n // eslint-disable-next-line deprecation/deprecation\n const enableMetrics = enableMetricsOption ?? _experiments?.enableMetrics ?? true;\n\n // Flush logs and metrics when page becomes hidden (e.g., tab switch, navigation)\n // todo(v11): Remove the experimental flag\n
|
|
1
|
+
{"version":3,"file":"client.js","sources":["../../../../src/client.ts"],"sourcesContent":["import type {\n BrowserClientProfilingOptions,\n BrowserClientReplayOptions,\n ClientOptions,\n Event,\n EventHint,\n Options as CoreOptions,\n ParameterizedString,\n Scope,\n SeverityLevel,\n} from '@sentry/core';\nimport {\n _INTERNAL_flushLogsBuffer,\n _INTERNAL_flushMetricsBuffer,\n addAutoIpAddressToSession,\n applySdkMetadata,\n Client,\n getSDKSource,\n} from '@sentry/core';\nimport { eventFromException, eventFromMessage } from './eventbuilder';\nimport { WINDOW } from './helpers';\nimport type { BrowserTransportOptions } from './transports/types';\n\n/**\n * A magic string that build tooling can leverage in order to inject a release value into the SDK.\n */\ndeclare const __SENTRY_RELEASE__: string | undefined;\n\ntype BrowserSpecificOptions = BrowserClientReplayOptions &\n BrowserClientProfilingOptions & {\n /** If configured, this URL will be used as base URL for lazy loading integration. */\n cdnBaseUrl?: string;\n\n /**\n * Important: Only set this option if you know what you are doing!\n *\n * By default, the SDK will check if `Sentry.init` is called in a browser extension.\n * In case it is, it will stop initialization and log a warning\n * because browser extensions require a different Sentry initialization process:\n * https://docs.sentry.io/platforms/javascript/best-practices/shared-environments/\n *\n * Setting up the SDK in a browser extension with global error monitoring is not recommended\n * and will likely flood you with errors from other web sites or extensions. This can heavily\n * impact your quota and cause interference with your and other Sentry SDKs in shared environments.\n *\n * If this check wrongfully flags your setup as a browser extension, you can set this\n * option to `true` to skip the check.\n *\n * @default false\n */\n skipBrowserExtensionCheck?: boolean;\n\n /**\n * If set to `true`, the SDK propagates the W3C `traceparent` header to any outgoing requests,\n * in addition to the `sentry-trace` and `baggage` headers. Use the {@link CoreOptions.tracePropagationTargets}\n * option to control to which outgoing requests the header will be attached.\n *\n * **Important:** If you set this option to `true`, make sure that you configured your servers'\n * CORS settings to allow the `traceparent` header. Otherwise, requests might get blocked.\n *\n * @see https://www.w3.org/TR/trace-context/\n *\n * @default false\n */\n propagateTraceparent?: boolean;\n\n /**\n * If you use Spotlight by Sentry during development, use\n * this option to forward captured Sentry events to Spotlight.\n *\n * Either set it to true, or provide a specific Spotlight Sidecar URL.\n *\n * More details: https://spotlightjs.com/\n *\n * IMPORTANT: Only set this option to `true` while developing, not in production!\n */\n spotlight?: boolean | string;\n };\n/**\n * Configuration options for the Sentry Browser SDK.\n * @see @sentry/core Options for more information.\n */\nexport type BrowserOptions = CoreOptions<BrowserTransportOptions> & BrowserSpecificOptions;\n\n/**\n * Configuration options for the Sentry Browser SDK Client class\n * @see BrowserClient for more information.\n */\nexport type BrowserClientOptions = ClientOptions<BrowserTransportOptions> & BrowserSpecificOptions;\n\n/**\n * The Sentry Browser SDK Client.\n *\n * @see BrowserOptions for documentation on configuration options.\n * @see SentryClient for usage documentation.\n */\nexport class BrowserClient extends Client<BrowserClientOptions> {\n /**\n * Creates a new Browser SDK instance.\n *\n * @param options Configuration options for this SDK.\n */\n public constructor(options: BrowserClientOptions) {\n const opts = applyDefaultOptions(options);\n const sdkSource = WINDOW.SENTRY_SDK_SOURCE || getSDKSource();\n applySdkMetadata(opts, 'browser', ['browser'], sdkSource);\n\n // Only allow IP inferral by Relay if sendDefaultPii is true\n if (opts._metadata?.sdk) {\n opts._metadata.sdk.settings = {\n infer_ip: opts.sendDefaultPii ? 'auto' : 'never',\n // purposefully allowing already passed settings to override the default\n ...opts._metadata.sdk.settings,\n };\n }\n\n super(opts);\n\n const {\n sendDefaultPii,\n sendClientReports,\n enableLogs,\n _experiments,\n enableMetrics: enableMetricsOption,\n } = this._options;\n\n // todo(v11): Remove the experimental flag\n // eslint-disable-next-line deprecation/deprecation\n const enableMetrics = enableMetricsOption ?? _experiments?.enableMetrics ?? true;\n\n // Flush logs and metrics when page becomes hidden (e.g., tab switch, navigation)\n // todo(v11): Remove the experimental flag\n if (WINDOW.document && (sendClientReports || enableLogs || enableMetrics)) {\n WINDOW.document.addEventListener('visibilitychange', () => {\n if (WINDOW.document.visibilityState === 'hidden') {\n if (sendClientReports) {\n this._flushOutcomes();\n }\n if (enableLogs) {\n _INTERNAL_flushLogsBuffer(this);\n }\n\n if (enableMetrics) {\n _INTERNAL_flushMetricsBuffer(this);\n }\n }\n });\n }\n\n if (sendDefaultPii) {\n this.on('beforeSendSession', addAutoIpAddressToSession);\n }\n }\n\n /**\n * @inheritDoc\n */\n public eventFromException(exception: unknown, hint?: EventHint): PromiseLike<Event> {\n return eventFromException(this._options.stackParser, exception, hint, this._options.attachStacktrace);\n }\n\n /**\n * @inheritDoc\n */\n public eventFromMessage(\n message: ParameterizedString,\n level: SeverityLevel = 'info',\n hint?: EventHint,\n ): PromiseLike<Event> {\n return eventFromMessage(this._options.stackParser, message, level, hint, this._options.attachStacktrace);\n }\n\n /**\n * @inheritDoc\n */\n protected _prepareEvent(\n event: Event,\n hint: EventHint,\n currentScope: Scope,\n isolationScope: Scope,\n ): PromiseLike<Event | null> {\n event.platform = event.platform || 'javascript';\n\n return super._prepareEvent(event, hint, currentScope, isolationScope);\n }\n}\n\n/** Exported only for tests. */\nexport function applyDefaultOptions<T extends Partial<BrowserClientOptions>>(optionsArg: T): T {\n return {\n release:\n typeof __SENTRY_RELEASE__ === 'string' // This allows build tooling to find-and-replace __SENTRY_RELEASE__ to inject a release value\n ? __SENTRY_RELEASE__\n : WINDOW.SENTRY_RELEASE?.id, // This supports the variable that sentry-webpack-plugin injects\n sendClientReports: true,\n // We default this to true, as it is the safer scenario\n parentSpanIsAlwaysRootSpan: true,\n ...optionsArg,\n };\n}\n"],"names":["Client","WINDOW","getSDKSource","applySdkMetadata","_INTERNAL_flushLogsBuffer","_INTERNAL_flushMetricsBuffer","addAutoIpAddressToSession","eventFromException","eventFromMessage"],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ const core = require('@sentry/core');
|
|
|
6
6
|
const helpers = require('./helpers.js');
|
|
7
7
|
const client = require('./client.js');
|
|
8
8
|
const fetch = require('./transports/fetch.js');
|
|
9
|
+
const index = require('./profiling/index.js');
|
|
9
10
|
const stackParsers = require('./stack-parsers.js');
|
|
10
11
|
const eventbuilder = require('./eventbuilder.js');
|
|
11
12
|
const userfeedback = require('./userfeedback.js');
|
|
@@ -124,6 +125,7 @@ exports.zodErrorsIntegration = core.zodErrorsIntegration;
|
|
|
124
125
|
exports.WINDOW = helpers.WINDOW;
|
|
125
126
|
exports.BrowserClient = client.BrowserClient;
|
|
126
127
|
exports.makeFetchTransport = fetch.makeFetchTransport;
|
|
128
|
+
exports.uiProfiler = index.uiProfiler;
|
|
127
129
|
exports.chromeStackLineParser = stackParsers.chromeStackLineParser;
|
|
128
130
|
exports.defaultStackLineParsers = stackParsers.defaultStackLineParsers;
|
|
129
131
|
exports.defaultStackParser = stackParsers.defaultStackParser;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/build/npm/cjs/dev/profiling/{lifecycleMode/traceLifecycleProfiler.js → UIProfiler.js}
RENAMED
|
@@ -1,129 +1,114 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
const core = require('@sentry/core');
|
|
4
|
-
const debugBuild = require('
|
|
5
|
-
const utils = require('
|
|
4
|
+
const debugBuild = require('../debug-build.js');
|
|
5
|
+
const utils = require('./utils.js');
|
|
6
6
|
|
|
7
7
|
const CHUNK_INTERVAL_MS = 60000; // 1 minute
|
|
8
8
|
// Maximum length for trace lifecycle profiling per root span (e.g. if spanEnd never fires)
|
|
9
|
-
const MAX_ROOT_SPAN_PROFILE_MS = 300000; // 5 minutes
|
|
9
|
+
const MAX_ROOT_SPAN_PROFILE_MS = 300000; // 5 minutes max per root span in trace mode
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
12
|
+
* UIProfiler (Profiling V2):
|
|
13
|
+
* Supports two lifecycle modes:
|
|
14
|
+
* - 'manual': controlled explicitly via start()/stop()
|
|
15
|
+
* - 'trace': automatically runs while there are active sampled root spans
|
|
16
16
|
*
|
|
17
17
|
* Profiles are emitted as standalone `profile_chunk` envelopes either when:
|
|
18
18
|
* - there are no more sampled root spans, or
|
|
19
19
|
* - the 60s chunk timer elapses while profiling is running.
|
|
20
20
|
*/
|
|
21
|
-
class
|
|
21
|
+
class UIProfiler {
|
|
22
22
|
|
|
23
|
-
//
|
|
23
|
+
// Manual + Trace
|
|
24
|
+
// one per Profiler session
|
|
25
|
+
// current profiler instance active flag
|
|
26
|
+
// sampling decision for entire session
|
|
24
27
|
|
|
25
|
-
//
|
|
28
|
+
// Trace-only
|
|
26
29
|
|
|
27
30
|
constructor() {
|
|
28
31
|
this._client = undefined;
|
|
29
32
|
this._profiler = undefined;
|
|
30
33
|
this._chunkTimer = undefined;
|
|
31
|
-
|
|
32
|
-
this._rootSpanTimeouts = new Map();
|
|
34
|
+
|
|
33
35
|
this._profilerId = undefined;
|
|
34
36
|
this._isRunning = false;
|
|
35
37
|
this._sessionSampled = false;
|
|
38
|
+
this._lifecycleMode = undefined;
|
|
39
|
+
|
|
40
|
+
this._activeRootSpanIds = new Set();
|
|
41
|
+
this._rootSpanTimeouts = new Map();
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
/**
|
|
39
|
-
* Initialize the profiler with client
|
|
45
|
+
* Initialize the profiler with client, session sampling and lifecycle mode.
|
|
40
46
|
*/
|
|
41
|
-
initialize(client
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
initialize(client) {
|
|
48
|
+
const lifecycleMode = (client.getOptions() ).profileLifecycle;
|
|
49
|
+
const sessionSampled = utils.shouldProfileSession(client.getOptions());
|
|
44
50
|
|
|
45
|
-
debugBuild.DEBUG_BUILD && core.debug.log(
|
|
51
|
+
debugBuild.DEBUG_BUILD && core.debug.log(`[Profiling] Initializing profiler (lifecycle='${lifecycleMode}').`);
|
|
52
|
+
|
|
53
|
+
if (!sessionSampled) {
|
|
54
|
+
debugBuild.DEBUG_BUILD && core.debug.log('[Profiling] Session not sampled. Skipping lifecycle profiler initialization.');
|
|
55
|
+
}
|
|
46
56
|
|
|
57
|
+
// One Profiler ID per profiling session (user session)
|
|
58
|
+
this._profilerId = core.uuid4();
|
|
47
59
|
this._client = client;
|
|
48
60
|
this._sessionSampled = sessionSampled;
|
|
61
|
+
this._lifecycleMode = lifecycleMode;
|
|
49
62
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
if (span !== core.getRootSpan(span)) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
// Only count sampled root spans
|
|
59
|
-
if (!span.isRecording()) {
|
|
60
|
-
debugBuild.DEBUG_BUILD && core.debug.log('[Profiling] Discarding profile because root span was not sampled.');
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Matching root spans with profiles
|
|
65
|
-
core.getGlobalScope().setContext('profile', {
|
|
66
|
-
profiler_id: this._profilerId,
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
const spanId = span.spanContext().spanId;
|
|
70
|
-
if (!spanId) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
if (this._activeRootSpanIds.has(spanId)) {
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
this._activeRootSpanIds.add(spanId);
|
|
78
|
-
const rootSpanCount = this._activeRootSpanIds.size;
|
|
79
|
-
|
|
80
|
-
const timeout = setTimeout(() => {
|
|
81
|
-
this._onRootSpanTimeout(spanId);
|
|
82
|
-
}, MAX_ROOT_SPAN_PROFILE_MS);
|
|
83
|
-
this._rootSpanTimeouts.set(spanId, timeout);
|
|
84
|
-
|
|
85
|
-
if (rootSpanCount === 1) {
|
|
86
|
-
debugBuild.DEBUG_BUILD &&
|
|
87
|
-
core.debug.log(
|
|
88
|
-
`[Profiling] Root span with ID ${spanId} started. Will continue profiling for as long as there are active root spans (currently: ${rootSpanCount}).`,
|
|
89
|
-
);
|
|
63
|
+
if (lifecycleMode === 'trace') {
|
|
64
|
+
this._setupTraceLifecycleListeners(client);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
90
67
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
68
|
+
/** Starts UI profiling (only effective in 'manual' mode and when sampled). */
|
|
69
|
+
start() {
|
|
70
|
+
if (this._lifecycleMode === 'trace') {
|
|
71
|
+
debugBuild.DEBUG_BUILD &&
|
|
72
|
+
core.debug.warn(
|
|
73
|
+
'[Profiling] `profileLifecycle` is set to "trace". Calls to `uiProfiler.start()` are ignored in trace mode.',
|
|
74
|
+
);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
94
77
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
78
|
+
if (this._isRunning) {
|
|
79
|
+
debugBuild.DEBUG_BUILD && core.debug.warn('[Profiling] Profile session is already running, `uiProfiler.start()` is a no-op.');
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
99
82
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
83
|
+
if (!this._sessionSampled) {
|
|
84
|
+
debugBuild.DEBUG_BUILD && core.debug.warn('[Profiling] Session is not sampled, `uiProfiler.start()` is a no-op.');
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
104
87
|
|
|
105
|
-
|
|
106
|
-
|
|
88
|
+
this._beginProfiling();
|
|
89
|
+
}
|
|
107
90
|
|
|
91
|
+
/** Stops UI profiling (only effective in 'manual' mode). */
|
|
92
|
+
stop() {
|
|
93
|
+
if (this._lifecycleMode === 'trace') {
|
|
108
94
|
debugBuild.DEBUG_BUILD &&
|
|
109
|
-
core.debug.
|
|
110
|
-
|
|
95
|
+
core.debug.warn(
|
|
96
|
+
'[Profiling] `profileLifecycle` is set to "trace". Calls to `uiProfiler.stop()` are ignored in trace mode.',
|
|
111
97
|
);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
debugBuild.DEBUG_BUILD && core.debug.error('[Profiling] Failed to collect current profile chunk on `spanEnd`:', e);
|
|
115
|
-
});
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
116
100
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
101
|
+
if (!this._isRunning) {
|
|
102
|
+
debugBuild.DEBUG_BUILD && core.debug.warn('[Profiling] Profiler is not running, `uiProfiler.stop()` is a no-op.');
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
this._endProfiling();
|
|
120
107
|
}
|
|
121
108
|
|
|
122
|
-
/**
|
|
123
|
-
* Handle an already-active root span at integration setup time.
|
|
124
|
-
*/
|
|
109
|
+
/** Handle an already-active root span at integration setup time (used only in trace mode). */
|
|
125
110
|
notifyRootSpanActive(rootSpan) {
|
|
126
|
-
if (!this._sessionSampled) {
|
|
111
|
+
if (this._lifecycleMode !== 'trace' || !this._sessionSampled) {
|
|
127
112
|
return;
|
|
128
113
|
}
|
|
129
114
|
|
|
@@ -132,7 +117,7 @@ class BrowserTraceLifecycleProfiler {
|
|
|
132
117
|
return;
|
|
133
118
|
}
|
|
134
119
|
|
|
135
|
-
this.
|
|
120
|
+
this._registerTraceRootSpan(spanId);
|
|
136
121
|
|
|
137
122
|
const rootSpanCount = this._activeRootSpanIds.size;
|
|
138
123
|
|
|
@@ -140,25 +125,28 @@ class BrowserTraceLifecycleProfiler {
|
|
|
140
125
|
debugBuild.DEBUG_BUILD &&
|
|
141
126
|
core.debug.log('[Profiling] Detected already active root span during setup. Active root spans now:', rootSpanCount);
|
|
142
127
|
|
|
143
|
-
this.
|
|
128
|
+
this._beginProfiling();
|
|
144
129
|
}
|
|
145
130
|
}
|
|
146
131
|
|
|
147
132
|
/**
|
|
148
|
-
*
|
|
133
|
+
* Begin profiling if not already running.
|
|
149
134
|
*/
|
|
150
|
-
|
|
135
|
+
_beginProfiling() {
|
|
151
136
|
if (this._isRunning) {
|
|
152
137
|
return;
|
|
153
138
|
}
|
|
154
139
|
this._isRunning = true;
|
|
155
140
|
|
|
156
|
-
debugBuild.DEBUG_BUILD && core.debug.log('[Profiling] Started profiling with
|
|
141
|
+
debugBuild.DEBUG_BUILD && core.debug.log('[Profiling] Started profiling with profiler ID:', this._profilerId);
|
|
142
|
+
|
|
143
|
+
// Expose profiler_id to match root spans with profiles
|
|
144
|
+
core.getGlobalScope().setContext('profile', { profiler_id: this._profilerId });
|
|
157
145
|
|
|
158
146
|
this._startProfilerInstance();
|
|
159
147
|
|
|
160
148
|
if (!this._profiler) {
|
|
161
|
-
debugBuild.DEBUG_BUILD && core.debug.log('[Profiling]
|
|
149
|
+
debugBuild.DEBUG_BUILD && core.debug.log('[Profiling] Failed to start JS Profiler; stopping.');
|
|
162
150
|
this._resetProfilerInfo();
|
|
163
151
|
return;
|
|
164
152
|
}
|
|
@@ -166,15 +154,13 @@ class BrowserTraceLifecycleProfiler {
|
|
|
166
154
|
this._startPeriodicChunking();
|
|
167
155
|
}
|
|
168
156
|
|
|
169
|
-
/**
|
|
170
|
-
|
|
171
|
-
*/
|
|
172
|
-
stop() {
|
|
157
|
+
/** End profiling session; final chunk will be collected and sent. */
|
|
158
|
+
_endProfiling() {
|
|
173
159
|
if (!this._isRunning) {
|
|
174
160
|
return;
|
|
175
161
|
}
|
|
176
|
-
|
|
177
162
|
this._isRunning = false;
|
|
163
|
+
|
|
178
164
|
if (this._chunkTimer) {
|
|
179
165
|
clearTimeout(this._chunkTimer);
|
|
180
166
|
this._chunkTimer = undefined;
|
|
@@ -186,10 +172,73 @@ class BrowserTraceLifecycleProfiler {
|
|
|
186
172
|
this._collectCurrentChunk().catch(e => {
|
|
187
173
|
debugBuild.DEBUG_BUILD && core.debug.error('[Profiling] Failed to collect current profile chunk on `stop()`:', e);
|
|
188
174
|
});
|
|
175
|
+
|
|
176
|
+
// Manual: Clear profiling context so spans outside start()/stop() aren't marked as profiled
|
|
177
|
+
// Trace: Profile context is kept for the whole session duration
|
|
178
|
+
if (this._lifecycleMode === 'manual') {
|
|
179
|
+
core.getGlobalScope().setContext('profile', {});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** Trace-mode: attach spanStart/spanEnd listeners. */
|
|
184
|
+
_setupTraceLifecycleListeners(client) {
|
|
185
|
+
client.on('spanStart', span => {
|
|
186
|
+
if (!this._sessionSampled) {
|
|
187
|
+
debugBuild.DEBUG_BUILD && core.debug.log('[Profiling] Session not sampled because of negative sampling decision.');
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (span !== core.getRootSpan(span)) {
|
|
191
|
+
return; // only care about root spans
|
|
192
|
+
}
|
|
193
|
+
// Only count sampled root spans
|
|
194
|
+
if (!span.isRecording()) {
|
|
195
|
+
debugBuild.DEBUG_BUILD && core.debug.log('[Profiling] Discarding profile because root span was not sampled.');
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const spanId = span.spanContext().spanId;
|
|
200
|
+
if (!spanId || this._activeRootSpanIds.has(spanId)) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
this._registerTraceRootSpan(spanId);
|
|
205
|
+
|
|
206
|
+
const rootSpanCount = this._activeRootSpanIds.size;
|
|
207
|
+
if (rootSpanCount === 1) {
|
|
208
|
+
debugBuild.DEBUG_BUILD &&
|
|
209
|
+
core.debug.log(
|
|
210
|
+
`[Profiling] Root span ${spanId} started. Profiling active while there are active root spans (count=${rootSpanCount}).`,
|
|
211
|
+
);
|
|
212
|
+
this._beginProfiling();
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
client.on('spanEnd', span => {
|
|
217
|
+
if (!this._sessionSampled) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const spanId = span.spanContext().spanId;
|
|
221
|
+
if (!spanId || !this._activeRootSpanIds.has(spanId)) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
this._activeRootSpanIds.delete(spanId);
|
|
225
|
+
const rootSpanCount = this._activeRootSpanIds.size;
|
|
226
|
+
|
|
227
|
+
debugBuild.DEBUG_BUILD &&
|
|
228
|
+
core.debug.log(
|
|
229
|
+
`[Profiling] Root span with ID ${spanId} ended. Will continue profiling for as long as there are active root spans (currently: ${rootSpanCount}).`,
|
|
230
|
+
);
|
|
231
|
+
if (rootSpanCount === 0) {
|
|
232
|
+
this._collectCurrentChunk().catch(e => {
|
|
233
|
+
debugBuild.DEBUG_BUILD && core.debug.error('[Profiling] Failed to collect current profile chunk on last `spanEnd`:', e);
|
|
234
|
+
});
|
|
235
|
+
this._endProfiling();
|
|
236
|
+
}
|
|
237
|
+
});
|
|
189
238
|
}
|
|
190
239
|
|
|
191
240
|
/**
|
|
192
|
-
* Resets profiling information from scope and resets running state
|
|
241
|
+
* Resets profiling information from scope and resets running state (used on failure)
|
|
193
242
|
*/
|
|
194
243
|
_resetProfilerInfo() {
|
|
195
244
|
this._isRunning = false;
|
|
@@ -204,16 +253,23 @@ class BrowserTraceLifecycleProfiler {
|
|
|
204
253
|
this._rootSpanTimeouts.clear();
|
|
205
254
|
}
|
|
206
255
|
|
|
256
|
+
/** Keep track of root spans and schedule safeguard timeout (trace mode). */
|
|
257
|
+
_registerTraceRootSpan(spanId) {
|
|
258
|
+
this._activeRootSpanIds.add(spanId);
|
|
259
|
+
const timeout = setTimeout(() => this._onRootSpanTimeout(spanId), MAX_ROOT_SPAN_PROFILE_MS);
|
|
260
|
+
this._rootSpanTimeouts.set(spanId, timeout);
|
|
261
|
+
}
|
|
262
|
+
|
|
207
263
|
/**
|
|
208
264
|
* Start a profiler instance if needed.
|
|
209
265
|
*/
|
|
210
266
|
_startProfilerInstance() {
|
|
211
267
|
if (this._profiler?.stopped === false) {
|
|
212
|
-
return;
|
|
268
|
+
return; // already running
|
|
213
269
|
}
|
|
214
270
|
const profiler = utils.startJSSelfProfile();
|
|
215
271
|
if (!profiler) {
|
|
216
|
-
debugBuild.DEBUG_BUILD && core.debug.log('[Profiling] Failed to start JS Profiler
|
|
272
|
+
debugBuild.DEBUG_BUILD && core.debug.log('[Profiling] Failed to start JS Profiler.');
|
|
217
273
|
return;
|
|
218
274
|
}
|
|
219
275
|
this._profiler = profiler;
|
|
@@ -270,14 +326,13 @@ class BrowserTraceLifecycleProfiler {
|
|
|
270
326
|
|
|
271
327
|
this._activeRootSpanIds.delete(rootSpanId);
|
|
272
328
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
this.stop();
|
|
329
|
+
if (this._activeRootSpanIds.size === 0) {
|
|
330
|
+
this._endProfiling();
|
|
276
331
|
}
|
|
277
332
|
}
|
|
278
333
|
|
|
279
334
|
/**
|
|
280
|
-
* Stop
|
|
335
|
+
* Stop current profiler instance, convert profile to chunk & send.
|
|
281
336
|
*/
|
|
282
337
|
async _collectCurrentChunk() {
|
|
283
338
|
const prevProfiler = this._profiler;
|
|
@@ -339,5 +394,5 @@ class BrowserTraceLifecycleProfiler {
|
|
|
339
394
|
}
|
|
340
395
|
}
|
|
341
396
|
|
|
342
|
-
exports.
|
|
343
|
-
//# sourceMappingURL=
|
|
397
|
+
exports.UIProfiler = UIProfiler;
|
|
398
|
+
//# sourceMappingURL=UIProfiler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UIProfiler.js","sources":["../../../../../src/profiling/UIProfiler.ts"],"sourcesContent":["import type { Client, ContinuousProfiler, ProfileChunk, Span } from '@sentry/core';\nimport {\n type ProfileChunkEnvelope,\n createEnvelope,\n debug,\n dsnToString,\n getGlobalScope,\n getRootSpan,\n getSdkMetadataForEnvelopeHeader,\n uuid4,\n} from '@sentry/core';\nimport type { BrowserOptions } from '../client';\nimport { DEBUG_BUILD } from './../debug-build';\nimport type { JSSelfProfiler } from './jsSelfProfiling';\nimport { createProfileChunkPayload, shouldProfileSession, startJSSelfProfile, validateProfileChunk } from './utils';\n\nconst CHUNK_INTERVAL_MS = 60_000; // 1 minute\n// Maximum length for trace lifecycle profiling per root span (e.g. if spanEnd never fires)\nconst MAX_ROOT_SPAN_PROFILE_MS = 300_000; // 5 minutes max per root span in trace mode\n\n/**\n * UIProfiler (Profiling V2):\n * Supports two lifecycle modes:\n * - 'manual': controlled explicitly via start()/stop()\n * - 'trace': automatically runs while there are active sampled root spans\n *\n * Profiles are emitted as standalone `profile_chunk` envelopes either when:\n * - there are no more sampled root spans, or\n * - the 60s chunk timer elapses while profiling is running.\n */\nexport class UIProfiler implements ContinuousProfiler<Client> {\n private _client: Client | undefined;\n private _profiler: JSSelfProfiler | undefined;\n private _chunkTimer: ReturnType<typeof setTimeout> | undefined;\n\n // Manual + Trace\n private _profilerId: string | undefined; // one per Profiler session\n private _isRunning: boolean; // current profiler instance active flag\n private _sessionSampled: boolean; // sampling decision for entire session\n private _lifecycleMode: 'manual' | 'trace' | undefined;\n\n // Trace-only\n private _activeRootSpanIds: Set<string>;\n private _rootSpanTimeouts: Map<string, ReturnType<typeof setTimeout>>;\n\n public constructor() {\n this._client = undefined;\n this._profiler = undefined;\n this._chunkTimer = undefined;\n\n this._profilerId = undefined;\n this._isRunning = false;\n this._sessionSampled = false;\n this._lifecycleMode = undefined;\n\n this._activeRootSpanIds = new Set();\n this._rootSpanTimeouts = new Map();\n }\n\n /**\n * Initialize the profiler with client, session sampling and lifecycle mode.\n */\n public initialize(client: Client): void {\n const lifecycleMode = (client.getOptions() as BrowserOptions).profileLifecycle;\n const sessionSampled = shouldProfileSession(client.getOptions());\n\n DEBUG_BUILD && debug.log(`[Profiling] Initializing profiler (lifecycle='${lifecycleMode}').`);\n\n if (!sessionSampled) {\n DEBUG_BUILD && debug.log('[Profiling] Session not sampled. Skipping lifecycle profiler initialization.');\n }\n\n // One Profiler ID per profiling session (user session)\n this._profilerId = uuid4();\n this._client = client;\n this._sessionSampled = sessionSampled;\n this._lifecycleMode = lifecycleMode;\n\n if (lifecycleMode === 'trace') {\n this._setupTraceLifecycleListeners(client);\n }\n }\n\n /** Starts UI profiling (only effective in 'manual' mode and when sampled). */\n public start(): void {\n if (this._lifecycleMode === 'trace') {\n DEBUG_BUILD &&\n debug.warn(\n '[Profiling] `profileLifecycle` is set to \"trace\". Calls to `uiProfiler.start()` are ignored in trace mode.',\n );\n return;\n }\n\n if (this._isRunning) {\n DEBUG_BUILD && debug.warn('[Profiling] Profile session is already running, `uiProfiler.start()` is a no-op.');\n return;\n }\n\n if (!this._sessionSampled) {\n DEBUG_BUILD && debug.warn('[Profiling] Session is not sampled, `uiProfiler.start()` is a no-op.');\n return;\n }\n\n this._beginProfiling();\n }\n\n /** Stops UI profiling (only effective in 'manual' mode). */\n public stop(): void {\n if (this._lifecycleMode === 'trace') {\n DEBUG_BUILD &&\n debug.warn(\n '[Profiling] `profileLifecycle` is set to \"trace\". Calls to `uiProfiler.stop()` are ignored in trace mode.',\n );\n return;\n }\n\n if (!this._isRunning) {\n DEBUG_BUILD && debug.warn('[Profiling] Profiler is not running, `uiProfiler.stop()` is a no-op.');\n return;\n }\n\n this._endProfiling();\n }\n\n /** Handle an already-active root span at integration setup time (used only in trace mode). */\n public notifyRootSpanActive(rootSpan: Span): void {\n if (this._lifecycleMode !== 'trace' || !this._sessionSampled) {\n return;\n }\n\n const spanId = rootSpan.spanContext().spanId;\n if (!spanId || this._activeRootSpanIds.has(spanId)) {\n return;\n }\n\n this._registerTraceRootSpan(spanId);\n\n const rootSpanCount = this._activeRootSpanIds.size;\n\n if (rootSpanCount === 1) {\n DEBUG_BUILD &&\n debug.log('[Profiling] Detected already active root span during setup. Active root spans now:', rootSpanCount);\n\n this._beginProfiling();\n }\n }\n\n /**\n * Begin profiling if not already running.\n */\n private _beginProfiling(): void {\n if (this._isRunning) {\n return;\n }\n this._isRunning = true;\n\n DEBUG_BUILD && debug.log('[Profiling] Started profiling with profiler ID:', this._profilerId);\n\n // Expose profiler_id to match root spans with profiles\n getGlobalScope().setContext('profile', { profiler_id: this._profilerId });\n\n this._startProfilerInstance();\n\n if (!this._profiler) {\n DEBUG_BUILD && debug.log('[Profiling] Failed to start JS Profiler; stopping.');\n this._resetProfilerInfo();\n return;\n }\n\n this._startPeriodicChunking();\n }\n\n /** End profiling session; final chunk will be collected and sent. */\n private _endProfiling(): void {\n if (!this._isRunning) {\n return;\n }\n this._isRunning = false;\n\n if (this._chunkTimer) {\n clearTimeout(this._chunkTimer);\n this._chunkTimer = undefined;\n }\n\n this._clearAllRootSpanTimeouts();\n\n // Collect whatever was currently recording\n this._collectCurrentChunk().catch(e => {\n DEBUG_BUILD && debug.error('[Profiling] Failed to collect current profile chunk on `stop()`:', e);\n });\n\n // Manual: Clear profiling context so spans outside start()/stop() aren't marked as profiled\n // Trace: Profile context is kept for the whole session duration\n if (this._lifecycleMode === 'manual') {\n getGlobalScope().setContext('profile', {});\n }\n }\n\n /** Trace-mode: attach spanStart/spanEnd listeners. */\n private _setupTraceLifecycleListeners(client: Client): void {\n client.on('spanStart', span => {\n if (!this._sessionSampled) {\n DEBUG_BUILD && debug.log('[Profiling] Session not sampled because of negative sampling decision.');\n return;\n }\n if (span !== getRootSpan(span)) {\n return; // only care about root spans\n }\n // Only count sampled root spans\n if (!span.isRecording()) {\n DEBUG_BUILD && debug.log('[Profiling] Discarding profile because root span was not sampled.');\n return;\n }\n\n const spanId = span.spanContext().spanId;\n if (!spanId || this._activeRootSpanIds.has(spanId)) {\n return;\n }\n\n this._registerTraceRootSpan(spanId);\n\n const rootSpanCount = this._activeRootSpanIds.size;\n if (rootSpanCount === 1) {\n DEBUG_BUILD &&\n debug.log(\n `[Profiling] Root span ${spanId} started. Profiling active while there are active root spans (count=${rootSpanCount}).`,\n );\n this._beginProfiling();\n }\n });\n\n client.on('spanEnd', span => {\n if (!this._sessionSampled) {\n return;\n }\n const spanId = span.spanContext().spanId;\n if (!spanId || !this._activeRootSpanIds.has(spanId)) {\n return;\n }\n this._activeRootSpanIds.delete(spanId);\n const rootSpanCount = this._activeRootSpanIds.size;\n\n DEBUG_BUILD &&\n debug.log(\n `[Profiling] Root span with ID ${spanId} ended. Will continue profiling for as long as there are active root spans (currently: ${rootSpanCount}).`,\n );\n if (rootSpanCount === 0) {\n this._collectCurrentChunk().catch(e => {\n DEBUG_BUILD && debug.error('[Profiling] Failed to collect current profile chunk on last `spanEnd`:', e);\n });\n this._endProfiling();\n }\n });\n }\n\n /**\n * Resets profiling information from scope and resets running state (used on failure)\n */\n private _resetProfilerInfo(): void {\n this._isRunning = false;\n getGlobalScope().setContext('profile', {});\n }\n\n /**\n * Clear and reset all per-root-span timeouts.\n */\n private _clearAllRootSpanTimeouts(): void {\n this._rootSpanTimeouts.forEach(timeout => clearTimeout(timeout));\n this._rootSpanTimeouts.clear();\n }\n\n /** Keep track of root spans and schedule safeguard timeout (trace mode). */\n private _registerTraceRootSpan(spanId: string): void {\n this._activeRootSpanIds.add(spanId);\n const timeout = setTimeout(() => this._onRootSpanTimeout(spanId), MAX_ROOT_SPAN_PROFILE_MS);\n this._rootSpanTimeouts.set(spanId, timeout);\n }\n\n /**\n * Start a profiler instance if needed.\n */\n private _startProfilerInstance(): void {\n if (this._profiler?.stopped === false) {\n return; // already running\n }\n const profiler = startJSSelfProfile();\n if (!profiler) {\n DEBUG_BUILD && debug.log('[Profiling] Failed to start JS Profiler.');\n return;\n }\n this._profiler = profiler;\n }\n\n /**\n * Schedule the next 60s chunk while running.\n * Each tick collects a chunk and restarts the profiler.\n * A chunk should be closed when there are no active root spans anymore OR when the maximum chunk interval is reached.\n */\n private _startPeriodicChunking(): void {\n if (!this._isRunning) {\n return;\n }\n\n this._chunkTimer = setTimeout(() => {\n this._collectCurrentChunk().catch(e => {\n DEBUG_BUILD && debug.error('[Profiling] Failed to collect current profile chunk during periodic chunking:', e);\n });\n\n if (this._isRunning) {\n this._startProfilerInstance();\n\n if (!this._profiler) {\n // If restart failed, stop scheduling further chunks and reset context.\n this._resetProfilerInfo();\n return;\n }\n\n this._startPeriodicChunking();\n }\n }, CHUNK_INTERVAL_MS);\n }\n\n /**\n * Handle timeout for a specific root span ID to avoid indefinitely running profiler if `spanEnd` never fires.\n * If this was the last active root span, collect the current chunk and stop profiling.\n */\n private _onRootSpanTimeout(rootSpanId: string): void {\n // If span already ended, ignore\n if (!this._rootSpanTimeouts.has(rootSpanId)) {\n return;\n }\n this._rootSpanTimeouts.delete(rootSpanId);\n\n if (!this._activeRootSpanIds.has(rootSpanId)) {\n return;\n }\n\n DEBUG_BUILD &&\n debug.log(\n `[Profiling] Reached 5-minute timeout for root span ${rootSpanId}. You likely started a manual root span that never called \\`.end()\\`.`,\n );\n\n this._activeRootSpanIds.delete(rootSpanId);\n\n if (this._activeRootSpanIds.size === 0) {\n this._endProfiling();\n }\n }\n\n /**\n * Stop current profiler instance, convert profile to chunk & send.\n */\n private async _collectCurrentChunk(): Promise<void> {\n const prevProfiler = this._profiler;\n this._profiler = undefined;\n\n if (!prevProfiler) {\n return;\n }\n\n try {\n const profile = await prevProfiler.stop();\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const chunk = createProfileChunkPayload(profile, this._client!, this._profilerId);\n\n // Validate chunk before sending\n const validationReturn = validateProfileChunk(chunk);\n if ('reason' in validationReturn) {\n DEBUG_BUILD &&\n debug.log(\n '[Profiling] Discarding invalid profile chunk (this is probably a bug in the SDK):',\n validationReturn.reason,\n );\n return;\n }\n\n this._sendProfileChunk(chunk);\n\n DEBUG_BUILD && debug.log('[Profiling] Collected browser profile chunk.');\n } catch (e) {\n DEBUG_BUILD && debug.log('[Profiling] Error while stopping JS Profiler for chunk:', e);\n }\n }\n\n /**\n * Send a profile chunk as a standalone envelope.\n */\n private _sendProfileChunk(chunk: ProfileChunk): void {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const client = this._client!;\n\n const sdkInfo = getSdkMetadataForEnvelopeHeader(client.getSdkMetadata?.());\n const dsn = client.getDsn();\n const tunnel = client.getOptions().tunnel;\n\n const envelope = createEnvelope<ProfileChunkEnvelope>(\n {\n event_id: uuid4(),\n sent_at: new Date().toISOString(),\n ...(sdkInfo && { sdk: sdkInfo }),\n ...(!!tunnel && dsn && { dsn: dsnToString(dsn) }),\n },\n [[{ type: 'profile_chunk' }, chunk]],\n );\n\n client.sendEnvelope(envelope).then(null, reason => {\n DEBUG_BUILD && debug.error('Error while sending profile chunk envelope:', reason);\n });\n }\n}\n"],"names":["shouldProfileSession","DEBUG_BUILD","debug","uuid4","getGlobalScope","getRootSpan","startJSSelfProfile","createProfileChunkPayload","validateProfileChunk","getSdkMetadataForEnvelopeHeader","createEnvelope","dsnToString"],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const core = require('@sentry/core');
|
|
4
|
+
const debugBuild = require('../debug-build.js');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Starts the Sentry UI profiler.
|
|
8
|
+
* This mode is exclusive with the transaction profiler and will only work if the profilesSampleRate is set to a falsy value.
|
|
9
|
+
* In UI profiling mode, the profiler will keep reporting profile chunks to Sentry until it is stopped, which allows for continuous profiling of the application.
|
|
10
|
+
*/
|
|
11
|
+
function startProfiler() {
|
|
12
|
+
const client = core.getClient();
|
|
13
|
+
if (!client) {
|
|
14
|
+
debugBuild.DEBUG_BUILD && core.debug.warn('No Sentry client available, profiling is not started');
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const integration = client.getIntegrationByName('BrowserProfiling');
|
|
19
|
+
|
|
20
|
+
if (!integration) {
|
|
21
|
+
debugBuild.DEBUG_BUILD && core.debug.warn('BrowserProfiling integration is not available');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
client.emit('startUIProfiler');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Stops the Sentry UI profiler.
|
|
30
|
+
* Calls to stop will stop the profiler and flush the currently collected profile data to Sentry.
|
|
31
|
+
*/
|
|
32
|
+
function stopProfiler() {
|
|
33
|
+
const client = core.getClient();
|
|
34
|
+
if (!client) {
|
|
35
|
+
debugBuild.DEBUG_BUILD && core.debug.warn('No Sentry client available, profiling is not started');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const integration = client.getIntegrationByName('BrowserProfiling');
|
|
40
|
+
if (!integration) {
|
|
41
|
+
debugBuild.DEBUG_BUILD && core.debug.warn('ProfilingIntegration is not available');
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
client.emit('stopUIProfiler');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Profiler namespace for controlling the JS profiler in 'manual' mode.
|
|
50
|
+
*
|
|
51
|
+
* Requires the `browserProfilingIntegration` from the `@sentry/browser` package.
|
|
52
|
+
*/
|
|
53
|
+
const uiProfiler = {
|
|
54
|
+
startProfiler,
|
|
55
|
+
stopProfiler,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
exports.uiProfiler = uiProfiler;
|
|
59
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../src/profiling/index.ts"],"sourcesContent":["import type { Profiler } from '@sentry/core';\nimport { debug, getClient } from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\n\n/**\n * Starts the Sentry UI profiler.\n * This mode is exclusive with the transaction profiler and will only work if the profilesSampleRate is set to a falsy value.\n * In UI profiling mode, the profiler will keep reporting profile chunks to Sentry until it is stopped, which allows for continuous profiling of the application.\n */\nfunction startProfiler(): void {\n const client = getClient();\n if (!client) {\n DEBUG_BUILD && debug.warn('No Sentry client available, profiling is not started');\n return;\n }\n\n const integration = client.getIntegrationByName('BrowserProfiling');\n\n if (!integration) {\n DEBUG_BUILD && debug.warn('BrowserProfiling integration is not available');\n return;\n }\n\n client.emit('startUIProfiler');\n}\n\n/**\n * Stops the Sentry UI profiler.\n * Calls to stop will stop the profiler and flush the currently collected profile data to Sentry.\n */\nfunction stopProfiler(): void {\n const client = getClient();\n if (!client) {\n DEBUG_BUILD && debug.warn('No Sentry client available, profiling is not started');\n return;\n }\n\n const integration = client.getIntegrationByName('BrowserProfiling');\n if (!integration) {\n DEBUG_BUILD && debug.warn('ProfilingIntegration is not available');\n return;\n }\n\n client.emit('stopUIProfiler');\n}\n\n/**\n * Profiler namespace for controlling the JS profiler in 'manual' mode.\n *\n * Requires the `browserProfilingIntegration` from the `@sentry/browser` package.\n */\nexport const uiProfiler: Profiler = {\n startProfiler,\n stopProfiler,\n};\n"],"names":["getClient","DEBUG_BUILD","debug"],"mappings":";;;;;AAIA;AACA;AACA;AACA;AACA;AACA,SAAS,aAAa,GAAS;AAC/B,EAAE,MAAM,MAAA,GAASA,cAAS,EAAE;AAC5B,EAAE,IAAI,CAAC,MAAM,EAAE;AACf,IAAIC,0BAAeC,UAAK,CAAC,IAAI,CAAC,sDAAsD,CAAC;AACrF,IAAI;AACJ,EAAE;;AAEF,EAAE,MAAM,cAAc,MAAM,CAAC,oBAAoB,CAAC,kBAAkB,CAAC;;AAErE,EAAE,IAAI,CAAC,WAAW,EAAE;AACpB,IAAID,0BAAeC,UAAK,CAAC,IAAI,CAAC,+CAA+C,CAAC;AAC9E,IAAI;AACJ,EAAE;;AAEF,EAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC;AAChC;;AAEA;AACA;AACA;AACA;AACA,SAAS,YAAY,GAAS;AAC9B,EAAE,MAAM,MAAA,GAASF,cAAS,EAAE;AAC5B,EAAE,IAAI,CAAC,MAAM,EAAE;AACf,IAAIC,0BAAeC,UAAK,CAAC,IAAI,CAAC,sDAAsD,CAAC;AACrF,IAAI;AACJ,EAAE;;AAEF,EAAE,MAAM,cAAc,MAAM,CAAC,oBAAoB,CAAC,kBAAkB,CAAC;AACrE,EAAE,IAAI,CAAC,WAAW,EAAE;AACpB,IAAID,0BAAeC,UAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC;AACtE,IAAI;AACJ,EAAE;;AAEF,EAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC;AAC/B;;AAEA;AACA;AACA;AACA;AACA;AACO,MAAM,UAAU,GAAa;AACpC,EAAE,aAAa;AACf,EAAE,YAAY;AACd;;;;"}
|