@sentry/browser 10.38.0 → 10.39.0-alpha.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 +7 -0
- package/build/npm/cjs/dev/client.js.map +1 -1
- package/build/npm/cjs/dev/index.js +7 -2
- package/build/npm/cjs/dev/index.js.map +1 -1
- package/build/npm/cjs/dev/integrations/browsersession.js +13 -9
- package/build/npm/cjs/dev/integrations/browsersession.js.map +1 -1
- package/build/npm/cjs/dev/integrations/culturecontext.js +64 -0
- package/build/npm/cjs/dev/integrations/culturecontext.js.map +1 -0
- package/build/npm/cjs/dev/integrations/httpcontext.js +25 -1
- package/build/npm/cjs/dev/integrations/httpcontext.js.map +1 -1
- package/build/npm/cjs/dev/integrations/spanstreaming.js +87 -0
- package/build/npm/cjs/dev/integrations/spanstreaming.js.map +1 -0
- package/build/npm/cjs/dev/integrations/spotlight.js +5 -4
- package/build/npm/cjs/dev/integrations/spotlight.js.map +1 -1
- package/build/npm/cjs/dev/profiling/UIProfiler.js +10 -0
- package/build/npm/cjs/dev/profiling/UIProfiler.js.map +1 -1
- package/build/npm/cjs/dev/profiling/integration.js +10 -0
- package/build/npm/cjs/dev/profiling/integration.js.map +1 -1
- package/build/npm/cjs/dev/sdk.js +2 -0
- package/build/npm/cjs/dev/sdk.js.map +1 -1
- package/build/npm/cjs/dev/tracing/browserTracingIntegration.js +18 -11
- package/build/npm/cjs/dev/tracing/browserTracingIntegration.js.map +1 -1
- package/build/npm/cjs/dev/tracing/linkedTraces.js +1 -0
- package/build/npm/cjs/dev/tracing/linkedTraces.js.map +1 -1
- package/build/npm/cjs/dev/tracing/request.js +1 -0
- package/build/npm/cjs/dev/tracing/request.js.map +1 -1
- package/build/npm/cjs/prod/client.js +7 -0
- package/build/npm/cjs/prod/client.js.map +1 -1
- package/build/npm/cjs/prod/index.js +7 -2
- package/build/npm/cjs/prod/index.js.map +1 -1
- package/build/npm/cjs/prod/integrations/browsersession.js +13 -9
- package/build/npm/cjs/prod/integrations/browsersession.js.map +1 -1
- package/build/npm/cjs/prod/integrations/culturecontext.js +64 -0
- package/build/npm/cjs/prod/integrations/culturecontext.js.map +1 -0
- package/build/npm/cjs/prod/integrations/httpcontext.js +25 -1
- package/build/npm/cjs/prod/integrations/httpcontext.js.map +1 -1
- package/build/npm/cjs/prod/integrations/spanstreaming.js +87 -0
- package/build/npm/cjs/prod/integrations/spanstreaming.js.map +1 -0
- package/build/npm/cjs/prod/integrations/spotlight.js +5 -4
- package/build/npm/cjs/prod/integrations/spotlight.js.map +1 -1
- package/build/npm/cjs/prod/profiling/UIProfiler.js +10 -0
- package/build/npm/cjs/prod/profiling/UIProfiler.js.map +1 -1
- package/build/npm/cjs/prod/profiling/integration.js +10 -0
- package/build/npm/cjs/prod/profiling/integration.js.map +1 -1
- package/build/npm/cjs/prod/sdk.js +2 -0
- package/build/npm/cjs/prod/sdk.js.map +1 -1
- package/build/npm/cjs/prod/tracing/browserTracingIntegration.js +18 -11
- package/build/npm/cjs/prod/tracing/browserTracingIntegration.js.map +1 -1
- package/build/npm/cjs/prod/tracing/linkedTraces.js +1 -0
- package/build/npm/cjs/prod/tracing/linkedTraces.js.map +1 -1
- package/build/npm/cjs/prod/tracing/request.js +1 -0
- package/build/npm/cjs/prod/tracing/request.js.map +1 -1
- package/build/npm/esm/dev/client.js +7 -0
- package/build/npm/esm/dev/client.js.map +1 -1
- package/build/npm/esm/dev/index.js +4 -2
- package/build/npm/esm/dev/index.js.map +1 -1
- package/build/npm/esm/dev/integrations/browsersession.js +13 -9
- package/build/npm/esm/dev/integrations/browsersession.js.map +1 -1
- package/build/npm/esm/dev/integrations/culturecontext.js +62 -0
- package/build/npm/esm/dev/integrations/culturecontext.js.map +1 -0
- package/build/npm/esm/dev/integrations/httpcontext.js +26 -2
- package/build/npm/esm/dev/integrations/httpcontext.js.map +1 -1
- package/build/npm/esm/dev/integrations/spanstreaming.js +85 -0
- package/build/npm/esm/dev/integrations/spanstreaming.js.map +1 -0
- package/build/npm/esm/dev/integrations/spotlight.js +5 -4
- package/build/npm/esm/dev/integrations/spotlight.js.map +1 -1
- package/build/npm/esm/dev/package.json +1 -1
- package/build/npm/esm/dev/profiling/UIProfiler.js +10 -0
- package/build/npm/esm/dev/profiling/UIProfiler.js.map +1 -1
- package/build/npm/esm/dev/profiling/integration.js +10 -0
- package/build/npm/esm/dev/profiling/integration.js.map +1 -1
- package/build/npm/esm/dev/sdk.js +2 -0
- package/build/npm/esm/dev/sdk.js.map +1 -1
- package/build/npm/esm/dev/tracing/browserTracingIntegration.js +19 -13
- package/build/npm/esm/dev/tracing/browserTracingIntegration.js.map +1 -1
- package/build/npm/esm/dev/tracing/linkedTraces.js +1 -0
- package/build/npm/esm/dev/tracing/linkedTraces.js.map +1 -1
- package/build/npm/esm/dev/tracing/request.js +1 -0
- package/build/npm/esm/dev/tracing/request.js.map +1 -1
- package/build/npm/esm/prod/client.js +7 -0
- package/build/npm/esm/prod/client.js.map +1 -1
- package/build/npm/esm/prod/index.js +4 -2
- package/build/npm/esm/prod/index.js.map +1 -1
- package/build/npm/esm/prod/integrations/browsersession.js +13 -9
- package/build/npm/esm/prod/integrations/browsersession.js.map +1 -1
- package/build/npm/esm/prod/integrations/culturecontext.js +62 -0
- package/build/npm/esm/prod/integrations/culturecontext.js.map +1 -0
- package/build/npm/esm/prod/integrations/httpcontext.js +26 -2
- package/build/npm/esm/prod/integrations/httpcontext.js.map +1 -1
- package/build/npm/esm/prod/integrations/spanstreaming.js +85 -0
- package/build/npm/esm/prod/integrations/spanstreaming.js.map +1 -0
- package/build/npm/esm/prod/integrations/spotlight.js +5 -4
- package/build/npm/esm/prod/integrations/spotlight.js.map +1 -1
- package/build/npm/esm/prod/package.json +1 -1
- package/build/npm/esm/prod/profiling/UIProfiler.js +10 -0
- package/build/npm/esm/prod/profiling/UIProfiler.js.map +1 -1
- package/build/npm/esm/prod/profiling/integration.js +10 -0
- package/build/npm/esm/prod/profiling/integration.js.map +1 -1
- package/build/npm/esm/prod/sdk.js +2 -0
- package/build/npm/esm/prod/sdk.js.map +1 -1
- package/build/npm/esm/prod/tracing/browserTracingIntegration.js +19 -13
- package/build/npm/esm/prod/tracing/browserTracingIntegration.js.map +1 -1
- package/build/npm/esm/prod/tracing/linkedTraces.js +1 -0
- package/build/npm/esm/prod/tracing/linkedTraces.js.map +1 -1
- package/build/npm/esm/prod/tracing/request.js +1 -0
- package/build/npm/esm/prod/tracing/request.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/index.bundle.tracing.d.ts +2 -1
- package/build/npm/types/index.bundle.tracing.d.ts.map +1 -1
- package/build/npm/types/index.bundle.tracing.logs.metrics.d.ts +2 -1
- package/build/npm/types/index.bundle.tracing.logs.metrics.d.ts.map +1 -1
- package/build/npm/types/index.bundle.tracing.replay.d.ts +2 -1
- package/build/npm/types/index.bundle.tracing.replay.d.ts.map +1 -1
- package/build/npm/types/index.bundle.tracing.replay.feedback.d.ts +2 -1
- package/build/npm/types/index.bundle.tracing.replay.feedback.d.ts.map +1 -1
- package/build/npm/types/index.bundle.tracing.replay.feedback.logs.metrics.d.ts +2 -1
- package/build/npm/types/index.bundle.tracing.replay.feedback.logs.metrics.d.ts.map +1 -1
- package/build/npm/types/index.bundle.tracing.replay.logs.metrics.d.ts +2 -1
- package/build/npm/types/index.bundle.tracing.replay.logs.metrics.d.ts.map +1 -1
- package/build/npm/types/index.d.ts +3 -2
- package/build/npm/types/index.d.ts.map +1 -1
- package/build/npm/types/integrations/browsersession.d.ts +16 -1
- package/build/npm/types/integrations/browsersession.d.ts.map +1 -1
- package/build/npm/types/integrations/culturecontext.d.ts +16 -0
- package/build/npm/types/integrations/culturecontext.d.ts.map +1 -0
- package/build/npm/types/integrations/httpcontext.d.ts.map +1 -1
- package/build/npm/types/integrations/spanstreaming.d.ts +5 -0
- package/build/npm/types/integrations/spanstreaming.d.ts.map +1 -0
- package/build/npm/types/integrations/spotlight.d.ts.map +1 -1
- package/build/npm/types/profiling/UIProfiler.d.ts +4 -0
- package/build/npm/types/profiling/UIProfiler.d.ts.map +1 -1
- package/build/npm/types/profiling/integration.d.ts.map +1 -1
- package/build/npm/types/sdk.d.ts.map +1 -1
- package/build/npm/types/tracing/browserTracingIntegration.d.ts +10 -0
- package/build/npm/types/tracing/browserTracingIntegration.d.ts.map +1 -1
- package/build/npm/types/tracing/request.d.ts.map +1 -1
- package/build/npm/types-ts3.8/exports.d.ts +1 -0
- package/build/npm/types-ts3.8/index.bundle.tracing.d.ts +2 -1
- package/build/npm/types-ts3.8/index.bundle.tracing.logs.metrics.d.ts +2 -1
- package/build/npm/types-ts3.8/index.bundle.tracing.replay.d.ts +2 -1
- package/build/npm/types-ts3.8/index.bundle.tracing.replay.feedback.d.ts +2 -1
- package/build/npm/types-ts3.8/index.bundle.tracing.replay.feedback.logs.metrics.d.ts +2 -1
- package/build/npm/types-ts3.8/index.bundle.tracing.replay.logs.metrics.d.ts +2 -1
- package/build/npm/types-ts3.8/index.d.ts +3 -2
- package/build/npm/types-ts3.8/integrations/browsersession.d.ts +16 -1
- package/build/npm/types-ts3.8/integrations/culturecontext.d.ts +16 -0
- package/build/npm/types-ts3.8/integrations/spanstreaming.d.ts +5 -0
- package/build/npm/types-ts3.8/profiling/UIProfiler.d.ts +4 -0
- package/build/npm/types-ts3.8/tracing/browserTracingIntegration.d.ts +10 -0
- package/package.json +7 -7
|
@@ -63,6 +63,13 @@ class BrowserClient extends core.Client {
|
|
|
63
63
|
if (enableMetrics) {
|
|
64
64
|
core._INTERNAL_flushMetricsBuffer(this);
|
|
65
65
|
}
|
|
66
|
+
|
|
67
|
+
// TODO: does anything speak against flushing here in general?
|
|
68
|
+
// this would also allow us to let the logs and metric buffers listen
|
|
69
|
+
// for client.on('flush'), meaning we don't have to explicitly call
|
|
70
|
+
// them like above (?)
|
|
71
|
+
// For now, this will flush the span buffer (besides errors, txns, etc).
|
|
72
|
+
this.flush(2000).then(null, () => {});
|
|
66
73
|
}
|
|
67
74
|
});
|
|
68
75
|
}
|
|
@@ -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 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":";;;;;;AAuBA;AACA;AACA;;AAmDA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,aAAA,SAAsBA,WAAM,CAAuB;AAChE;AACA;AACA;AACA;AACA;AACA,GAAS,WAAW,CAAC,OAAO,EAAwB;AACpD,IAAI,MAAM,IAAA,GAAO,mBAAmB,CAAC,OAAO,CAAC;AAC7C,IAAI,MAAM,YAAYC,cAAM,CAAC,iBAAA,IAAqBC,iBAAY,EAAE;AAChE,IAAIC,qBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;;AAE7D;AACA,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;AAC7B,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW;AACpC,QAAQ,QAAQ,EAAE,IAAI,CAAC,iBAAiB,MAAA,GAAS,OAAO;AACxD;AACA,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ;AACtC,OAAO;AACP,IAAI;;AAEJ,IAAI,KAAK,CAAC,IAAI,CAAC;;AAEf,IAAI,MAAM;AACV,MAAM,cAAc;AACpB,MAAM,iBAAiB;AACvB,MAAM,UAAU;AAChB,MAAM,YAAY;AAClB,MAAM,aAAa,EAAE,mBAAmB;AACxC,KAAI,GAAI,IAAI,CAAC,QAAQ;;AAErB;AACA;AACA,IAAI,MAAM,gBAAgB,mBAAA,IAAuB,YAAY,EAAE,aAAA,IAAiB,IAAI;;AAEpF;AACA;AACA,IAAI,IAAIF,cAAM,CAAC,QAAA,KAAa,iBAAA,IAAqB,UAAA,IAAc,aAAa,CAAC,EAAE;AAC/E,MAAMA,cAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,MAAM;AACjE,QAAQ,IAAIA,cAAM,CAAC,QAAQ,CAAC,eAAA,KAAoB,QAAQ,EAAE;AAC1D,UAAU,IAAI,iBAAiB,EAAE;AACjC,YAAY,IAAI,CAAC,cAAc,EAAE;AACjC,UAAU;AACV,UAAU,IAAI,UAAU,EAAE;AAC1B,YAAYG,8BAAyB,CAAC,IAAI,CAAC;AAC3C,UAAU;;AAEV,UAAU,IAAI,aAAa,EAAE;AAC7B,YAAYC,iCAA4B,CAAC,IAAI,CAAC;AAC9C,UAAU;
|
|
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 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 // TODO: does anything speak against flushing here in general?\n // this would also allow us to let the logs and metric buffers listen\n // for client.on('flush'), meaning we don't have to explicitly call\n // them like above (?)\n // For now, this will flush the span buffer (besides errors, txns, etc).\n this.flush(2000).then(null, () => {});\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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"}
|
|
@@ -17,6 +17,7 @@ const globalhandlers = require('./integrations/globalhandlers.js');
|
|
|
17
17
|
const httpcontext = require('./integrations/httpcontext.js');
|
|
18
18
|
const linkederrors = require('./integrations/linkederrors.js');
|
|
19
19
|
const browserapierrors = require('./integrations/browserapierrors.js');
|
|
20
|
+
const browsersession = require('./integrations/browsersession.js');
|
|
20
21
|
const lazyLoadIntegration = require('./utils/lazyLoadIntegration.js');
|
|
21
22
|
const reportingobserver = require('./integrations/reportingobserver.js');
|
|
22
23
|
const httpclient = require('./integrations/httpclient.js');
|
|
@@ -32,7 +33,7 @@ const setActiveSpan = require('./tracing/setActiveSpan.js');
|
|
|
32
33
|
const offline = require('./transports/offline.js');
|
|
33
34
|
const integration$1 = require('./profiling/integration.js');
|
|
34
35
|
const spotlight = require('./integrations/spotlight.js');
|
|
35
|
-
const
|
|
36
|
+
const culturecontext = require('./integrations/culturecontext.js');
|
|
36
37
|
const integration$2 = require('./integrations/featureFlags/launchdarkly/integration.js');
|
|
37
38
|
const integration = require('./integrations/featureFlags/openfeature/integration.js');
|
|
38
39
|
const integration$5 = require('./integrations/featureFlags/unleash/integration.js');
|
|
@@ -40,6 +41,7 @@ const integration$3 = require('./integrations/featureFlags/growthbook/integratio
|
|
|
40
41
|
const integration$4 = require('./integrations/featureFlags/statsig/integration.js');
|
|
41
42
|
const diagnoseSdk = require('./diagnose-sdk.js');
|
|
42
43
|
const webWorker = require('./integrations/webWorker.js');
|
|
44
|
+
const spanstreaming = require('./integrations/spanstreaming.js');
|
|
43
45
|
|
|
44
46
|
|
|
45
47
|
|
|
@@ -124,6 +126,7 @@ exports.updateSpanName = core.updateSpanName;
|
|
|
124
126
|
exports.withActiveSpan = core.withActiveSpan;
|
|
125
127
|
exports.withIsolationScope = core.withIsolationScope;
|
|
126
128
|
exports.withScope = core.withScope;
|
|
129
|
+
exports.withStreamSpan = core.withStreamSpan;
|
|
127
130
|
exports.zodErrorsIntegration = core.zodErrorsIntegration;
|
|
128
131
|
exports.WINDOW = helpers.WINDOW;
|
|
129
132
|
exports.BrowserClient = client.BrowserClient;
|
|
@@ -150,6 +153,7 @@ exports.globalHandlersIntegration = globalhandlers.globalHandlersIntegration;
|
|
|
150
153
|
exports.httpContextIntegration = httpcontext.httpContextIntegration;
|
|
151
154
|
exports.linkedErrorsIntegration = linkederrors.linkedErrorsIntegration;
|
|
152
155
|
exports.browserApiErrorsIntegration = browserapierrors.browserApiErrorsIntegration;
|
|
156
|
+
exports.browserSessionIntegration = browsersession.browserSessionIntegration;
|
|
153
157
|
exports.lazyLoadIntegration = lazyLoadIntegration.lazyLoadIntegration;
|
|
154
158
|
exports.reportingObserverIntegration = reportingobserver.reportingObserverIntegration;
|
|
155
159
|
exports.httpClientIntegration = httpclient.httpClientIntegration;
|
|
@@ -170,7 +174,7 @@ exports.setActiveSpanInBrowser = setActiveSpan.setActiveSpanInBrowser;
|
|
|
170
174
|
exports.makeBrowserOfflineTransport = offline.makeBrowserOfflineTransport;
|
|
171
175
|
exports.browserProfilingIntegration = integration$1.browserProfilingIntegration;
|
|
172
176
|
exports.spotlightBrowserIntegration = spotlight.spotlightBrowserIntegration;
|
|
173
|
-
exports.
|
|
177
|
+
exports.cultureContextIntegration = culturecontext.cultureContextIntegration;
|
|
174
178
|
exports.buildLaunchDarklyFlagUsedHandler = integration$2.buildLaunchDarklyFlagUsedHandler;
|
|
175
179
|
exports.launchDarklyIntegration = integration$2.launchDarklyIntegration;
|
|
176
180
|
exports.OpenFeatureIntegrationHook = integration.OpenFeatureIntegrationHook;
|
|
@@ -181,4 +185,5 @@ exports.statsigIntegration = integration$4.statsigIntegration;
|
|
|
181
185
|
exports.diagnoseSdkConnectivity = diagnoseSdk.diagnoseSdkConnectivity;
|
|
182
186
|
exports.registerWebWorker = webWorker.registerWebWorker;
|
|
183
187
|
exports.webWorkerIntegration = webWorker.webWorkerIntegration;
|
|
188
|
+
exports.spanStreamingIntegration = spanstreaming.spanStreamingIntegration;
|
|
184
189
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -11,7 +11,9 @@ const helpers = require('../helpers.js');
|
|
|
11
11
|
*
|
|
12
12
|
* Note: In order for session tracking to work, you need to set up Releases: https://docs.sentry.io/product/releases/
|
|
13
13
|
*/
|
|
14
|
-
const browserSessionIntegration = core.defineIntegration(() => {
|
|
14
|
+
const browserSessionIntegration = core.defineIntegration((options = {}) => {
|
|
15
|
+
const lifecycle = options.lifecycle ?? 'route';
|
|
16
|
+
|
|
15
17
|
return {
|
|
16
18
|
name: 'BrowserSession',
|
|
17
19
|
setupOnce() {
|
|
@@ -28,14 +30,16 @@ const browserSessionIntegration = core.defineIntegration(() => {
|
|
|
28
30
|
core.startSession({ ignoreDuration: true });
|
|
29
31
|
core.captureSession();
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
if (lifecycle === 'route') {
|
|
34
|
+
// We want to create a session for every navigation as well
|
|
35
|
+
browserUtils.addHistoryInstrumentationHandler(({ from, to }) => {
|
|
36
|
+
// Don't create an additional session for the initial route or if the location did not change
|
|
37
|
+
if (from !== undefined && from !== to) {
|
|
38
|
+
core.startSession({ ignoreDuration: true });
|
|
39
|
+
core.captureSession();
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
39
43
|
},
|
|
40
44
|
};
|
|
41
45
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browsersession.js","sources":["../../../../../src/integrations/browsersession.ts"],"sourcesContent":["import { captureSession, debug, defineIntegration, startSession } from '@sentry/core';\nimport { addHistoryInstrumentationHandler } from '@sentry-internal/browser-utils';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { WINDOW } from '../helpers';\n\n/**\n * When added, automatically creates sessions which allow you to track adoption and crashes (crash free rate) in your Releases in Sentry.\n * More information: https://docs.sentry.io/product/releases/health/\n *\n * Note: In order for session tracking to work, you need to set up Releases: https://docs.sentry.io/product/releases/\n */\nexport const browserSessionIntegration = defineIntegration(() => {\n return {\n name: 'BrowserSession',\n setupOnce() {\n if (typeof WINDOW.document === 'undefined') {\n DEBUG_BUILD &&\n debug.warn('Using the `browserSessionIntegration` in non-browser environments is not supported.');\n return;\n }\n\n // The session duration for browser sessions does not track a meaningful\n // concept that can be used as a metric.\n // Automatically captured sessions are akin to page views, and thus we\n // discard their duration.\n startSession({ ignoreDuration: true });\n captureSession();\n\n // We want to create a session for every navigation as well\n
|
|
1
|
+
{"version":3,"file":"browsersession.js","sources":["../../../../../src/integrations/browsersession.ts"],"sourcesContent":["import { captureSession, debug, defineIntegration, startSession } from '@sentry/core';\nimport { addHistoryInstrumentationHandler } from '@sentry-internal/browser-utils';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { WINDOW } from '../helpers';\n\ninterface BrowserSessionOptions {\n /**\n * Controls the session lifecycle - when new sessions are created.\n *\n * - `'route'`: A session is created on page load and on every navigation.\n * This is the default behavior.\n * - `'page'`: A session is created once when the page is loaded. Session is not\n * updated on navigation. This is useful for webviews or single-page apps where\n * URL changes should not trigger new sessions.\n *\n * @default 'route'\n */\n lifecycle?: 'route' | 'page';\n}\n\n/**\n * When added, automatically creates sessions which allow you to track adoption and crashes (crash free rate) in your Releases in Sentry.\n * More information: https://docs.sentry.io/product/releases/health/\n *\n * Note: In order for session tracking to work, you need to set up Releases: https://docs.sentry.io/product/releases/\n */\nexport const browserSessionIntegration = defineIntegration((options: BrowserSessionOptions = {}) => {\n const lifecycle = options.lifecycle ?? 'route';\n\n return {\n name: 'BrowserSession',\n setupOnce() {\n if (typeof WINDOW.document === 'undefined') {\n DEBUG_BUILD &&\n debug.warn('Using the `browserSessionIntegration` in non-browser environments is not supported.');\n return;\n }\n\n // The session duration for browser sessions does not track a meaningful\n // concept that can be used as a metric.\n // Automatically captured sessions are akin to page views, and thus we\n // discard their duration.\n startSession({ ignoreDuration: true });\n captureSession();\n\n if (lifecycle === 'route') {\n // We want to create a session for every navigation as well\n addHistoryInstrumentationHandler(({ from, to }) => {\n // Don't create an additional session for the initial route or if the location did not change\n if (from !== undefined && from !== to) {\n startSession({ ignoreDuration: true });\n captureSession();\n }\n });\n }\n },\n };\n});\n"],"names":["defineIntegration","WINDOW","DEBUG_BUILD","debug","startSession","captureSession","addHistoryInstrumentationHandler"],"mappings":";;;;;;;AAoBA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,yBAAA,GAA4BA,sBAAiB,CAAC,CAAC,OAAO,GAA0B,EAAE,KAAK;AACpG,EAAE,MAAM,SAAA,GAAY,OAAO,CAAC,SAAA,IAAa,OAAO;;AAEhD,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B,IAAI,SAAS,GAAG;AAChB,MAAM,IAAI,OAAOC,cAAM,CAAC,QAAA,KAAa,WAAW,EAAE;AAClD,QAAQC,sBAAA;AACR,UAAUC,UAAK,CAAC,IAAI,CAAC,qFAAqF,CAAC;AAC3G,QAAQ;AACR,MAAM;;AAEN;AACA;AACA;AACA;AACA,MAAMC,iBAAY,CAAC,EAAE,cAAc,EAAE,IAAA,EAAM,CAAC;AAC5C,MAAMC,mBAAc,EAAE;;AAEtB,MAAM,IAAI,SAAA,KAAc,OAAO,EAAE;AACjC;AACA,QAAQC,6CAAgC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAA,EAAI,KAAK;AAC3D;AACA,UAAU,IAAI,IAAA,KAAS,aAAa,IAAA,KAAS,EAAE,EAAE;AACjD,YAAYF,iBAAY,CAAC,EAAE,cAAc,EAAE,IAAA,EAAM,CAAC;AAClD,YAAYC,mBAAc,EAAE;AAC5B,UAAU;AACV,QAAQ,CAAC,CAAC;AACV,MAAM;AACN,IAAI,CAAC;AACL,GAAG;AACH,CAAC;;;;"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const core = require('@sentry/core');
|
|
4
|
+
const helpers = require('../helpers.js');
|
|
5
|
+
|
|
6
|
+
const INTEGRATION_NAME = 'CultureContext';
|
|
7
|
+
|
|
8
|
+
const _cultureContextIntegration = (() => {
|
|
9
|
+
return {
|
|
10
|
+
name: INTEGRATION_NAME,
|
|
11
|
+
preprocessEvent(event) {
|
|
12
|
+
const culture = getCultureContext();
|
|
13
|
+
|
|
14
|
+
if (culture) {
|
|
15
|
+
event.contexts = {
|
|
16
|
+
...event.contexts,
|
|
17
|
+
culture: { ...culture, ...event.contexts?.culture },
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}) ;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Captures culture context from the browser.
|
|
26
|
+
*
|
|
27
|
+
* Enabled by default.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```js
|
|
31
|
+
* import * as Sentry from '@sentry/browser';
|
|
32
|
+
*
|
|
33
|
+
* Sentry.init({
|
|
34
|
+
* integrations: [Sentry.cultureContextIntegration()],
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
const cultureContextIntegration = core.defineIntegration(_cultureContextIntegration);
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Returns the culture context from the browser's Intl API.
|
|
42
|
+
*/
|
|
43
|
+
function getCultureContext() {
|
|
44
|
+
try {
|
|
45
|
+
const intl = (helpers.WINDOW ).Intl;
|
|
46
|
+
if (!intl) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const options = intl.DateTimeFormat().resolvedOptions();
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
locale: options.locale,
|
|
54
|
+
timezone: options.timeZone,
|
|
55
|
+
calendar: options.calendar,
|
|
56
|
+
};
|
|
57
|
+
} catch {
|
|
58
|
+
// Ignore errors
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
exports.cultureContextIntegration = cultureContextIntegration;
|
|
64
|
+
//# sourceMappingURL=culturecontext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"culturecontext.js","sources":["../../../../../src/integrations/culturecontext.ts"],"sourcesContent":["import type { CultureContext, IntegrationFn } from '@sentry/core';\nimport { defineIntegration } from '@sentry/core';\nimport { WINDOW } from '../helpers';\n\nconst INTEGRATION_NAME = 'CultureContext';\n\nconst _cultureContextIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n preprocessEvent(event) {\n const culture = getCultureContext();\n\n if (culture) {\n event.contexts = {\n ...event.contexts,\n culture: { ...culture, ...event.contexts?.culture },\n };\n }\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Captures culture context from the browser.\n *\n * Enabled by default.\n *\n * @example\n * ```js\n * import * as Sentry from '@sentry/browser';\n *\n * Sentry.init({\n * integrations: [Sentry.cultureContextIntegration()],\n * });\n * ```\n */\nexport const cultureContextIntegration = defineIntegration(_cultureContextIntegration);\n\n/**\n * Returns the culture context from the browser's Intl API.\n */\nfunction getCultureContext(): CultureContext | undefined {\n try {\n const intl = (WINDOW as { Intl?: typeof Intl }).Intl;\n if (!intl) {\n return undefined;\n }\n\n const options = intl.DateTimeFormat().resolvedOptions();\n\n return {\n locale: options.locale,\n timezone: options.timeZone,\n calendar: options.calendar,\n };\n } catch {\n // Ignore errors\n return undefined;\n }\n}\n"],"names":["defineIntegration","WINDOW"],"mappings":";;;;;AAIA,MAAM,gBAAA,GAAmB,gBAAgB;;AAEzC,MAAM,0BAAA,IAA8B,MAAM;AAC1C,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B,IAAI,eAAe,CAAC,KAAK,EAAE;AAC3B,MAAM,MAAM,OAAA,GAAU,iBAAiB,EAAE;;AAEzC,MAAM,IAAI,OAAO,EAAE;AACnB,QAAQ,KAAK,CAAC,QAAA,GAAW;AACzB,UAAU,GAAG,KAAK,CAAC,QAAQ;AAC3B,UAAU,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,OAAA,EAAS;AAC7D,SAAS;AACT,MAAM;AACN,IAAI,CAAC;AACL,GAAG;AACH,CAAC,CAAA;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;MACa,yBAAA,GAA4BA,sBAAiB,CAAC,0BAA0B;;AAErF;AACA;AACA;AACA,SAAS,iBAAiB,GAA+B;AACzD,EAAE,IAAI;AACN,IAAI,MAAM,IAAA,GAAO,CAACC,cAAA,GAAkC,IAAI;AACxD,IAAI,IAAI,CAAC,IAAI,EAAE;AACf,MAAM,OAAO,SAAS;AACtB,IAAI;;AAEJ,IAAI,MAAM,OAAA,GAAU,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE;;AAE3D,IAAI,OAAO;AACX,MAAM,MAAM,EAAE,OAAO,CAAC,MAAM;AAC5B,MAAM,QAAQ,EAAE,OAAO,CAAC,QAAQ;AAChC,MAAM,QAAQ,EAAE,OAAO,CAAC,QAAQ;AAChC,KAAK;AACL,EAAE,EAAE,MAAM;AACV;AACA,IAAI,OAAO,SAAS;AACpB,EAAE;AACF;;;;"}
|
|
@@ -3,16 +3,40 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3
3
|
const core = require('@sentry/core');
|
|
4
4
|
const helpers = require('../helpers.js');
|
|
5
5
|
|
|
6
|
+
// Treeshakable guard to remove all code related to tracing
|
|
7
|
+
|
|
6
8
|
/**
|
|
7
9
|
* Collects information about HTTP request headers and
|
|
8
10
|
* attaches them to the event.
|
|
9
11
|
*/
|
|
10
12
|
const httpContextIntegration = core.defineIntegration(() => {
|
|
13
|
+
const inBrowserEnvironment = helpers.WINDOW.navigator || helpers.WINDOW.location || helpers.WINDOW.document;
|
|
14
|
+
|
|
11
15
|
return {
|
|
12
16
|
name: 'HttpContext',
|
|
17
|
+
setup(client) {
|
|
18
|
+
if (!inBrowserEnvironment) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (typeof __SENTRY_TRACING__ === 'undefined' || __SENTRY_TRACING__) {
|
|
23
|
+
if (core.hasSpanStreamingEnabled(client)) {
|
|
24
|
+
client.on('processSegmentSpan', spanJSON => {
|
|
25
|
+
const { url, headers } = helpers.getHttpRequestData();
|
|
26
|
+
|
|
27
|
+
const attributeHeaders = core.httpHeadersToSpanAttributes(headers);
|
|
28
|
+
|
|
29
|
+
core.safeSetSpanJSONAttributes(spanJSON, {
|
|
30
|
+
[core.SEMANTIC_ATTRIBUTE_URL_FULL]: url,
|
|
31
|
+
...attributeHeaders,
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
13
37
|
preprocessEvent(event) {
|
|
14
38
|
// if none of the information we want exists, don't bother
|
|
15
|
-
if (!
|
|
39
|
+
if (!inBrowserEnvironment) {
|
|
16
40
|
return;
|
|
17
41
|
}
|
|
18
42
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpcontext.js","sources":["../../../../../src/integrations/httpcontext.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"httpcontext.js","sources":["../../../../../src/integrations/httpcontext.ts"],"sourcesContent":["import {\n defineIntegration,\n hasSpanStreamingEnabled,\n httpHeadersToSpanAttributes,\n safeSetSpanJSONAttributes,\n SEMANTIC_ATTRIBUTE_URL_FULL,\n} from '@sentry/core';\nimport { getHttpRequestData, WINDOW } from '../helpers';\n\n// Treeshakable guard to remove all code related to tracing\ndeclare const __SENTRY_TRACING__: boolean | undefined;\n\n/**\n * Collects information about HTTP request headers and\n * attaches them to the event.\n */\nexport const httpContextIntegration = defineIntegration(() => {\n const inBrowserEnvironment = WINDOW.navigator || WINDOW.location || WINDOW.document;\n\n return {\n name: 'HttpContext',\n setup(client) {\n if (!inBrowserEnvironment) {\n return;\n }\n\n if (typeof __SENTRY_TRACING__ === 'undefined' || __SENTRY_TRACING__) {\n if (hasSpanStreamingEnabled(client)) {\n client.on('processSegmentSpan', spanJSON => {\n const { url, headers } = getHttpRequestData();\n\n const attributeHeaders = httpHeadersToSpanAttributes(headers);\n\n safeSetSpanJSONAttributes(spanJSON, {\n [SEMANTIC_ATTRIBUTE_URL_FULL]: url,\n ...attributeHeaders,\n });\n });\n }\n }\n },\n preprocessEvent(event) {\n // if none of the information we want exists, don't bother\n if (!inBrowserEnvironment) {\n return;\n }\n\n const reqData = getHttpRequestData();\n const headers = {\n ...reqData.headers,\n ...event.request?.headers,\n };\n\n event.request = {\n ...reqData,\n ...event.request,\n headers,\n };\n },\n };\n});\n"],"names":["defineIntegration","WINDOW","hasSpanStreamingEnabled","getHttpRequestData","httpHeadersToSpanAttributes","safeSetSpanJSONAttributes","SEMANTIC_ATTRIBUTE_URL_FULL"],"mappings":";;;;;AASA;;AAGA;AACA;AACA;AACA;MACa,sBAAA,GAAyBA,sBAAiB,CAAC,MAAM;AAC9D,EAAE,MAAM,oBAAA,GAAuBC,cAAM,CAAC,SAAA,IAAaA,cAAM,CAAC,QAAA,IAAYA,cAAM,CAAC,QAAQ;;AAErF,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,aAAa;AACvB,IAAI,KAAK,CAAC,MAAM,EAAE;AAClB,MAAM,IAAI,CAAC,oBAAoB,EAAE;AACjC,QAAQ;AACR,MAAM;;AAEN,MAAM,IAAI,OAAO,kBAAA,KAAuB,WAAA,IAAe,kBAAkB,EAAE;AAC3E,QAAQ,IAAIC,4BAAuB,CAAC,MAAM,CAAC,EAAE;AAC7C,UAAU,MAAM,CAAC,EAAE,CAAC,oBAAoB,EAAE,YAAY;AACtD,YAAY,MAAM,EAAE,GAAG,EAAE,SAAQ,GAAIC,0BAAkB,EAAE;;AAEzD,YAAY,MAAM,gBAAA,GAAmBC,gCAA2B,CAAC,OAAO,CAAC;;AAEzE,YAAYC,8BAAyB,CAAC,QAAQ,EAAE;AAChD,cAAc,CAACC,gCAA2B,GAAG,GAAG;AAChD,cAAc,GAAG,gBAAgB;AACjC,aAAa,CAAC;AACd,UAAU,CAAC,CAAC;AACZ,QAAQ;AACR,MAAM;AACN,IAAI,CAAC;AACL,IAAI,eAAe,CAAC,KAAK,EAAE;AAC3B;AACA,MAAM,IAAI,CAAC,oBAAoB,EAAE;AACjC,QAAQ;AACR,MAAM;;AAEN,MAAM,MAAM,OAAA,GAAUH,0BAAkB,EAAE;AAC1C,MAAM,MAAM,UAAU;AACtB,QAAQ,GAAG,OAAO,CAAC,OAAO;AAC1B,QAAQ,GAAG,KAAK,CAAC,OAAO,EAAE,OAAO;AACjC,OAAO;;AAEP,MAAM,KAAK,CAAC,OAAA,GAAU;AACtB,QAAQ,GAAG,OAAO;AAClB,QAAQ,GAAG,KAAK,CAAC,OAAO;AACxB,QAAQ,OAAO;AACf,OAAO;AACP,IAAI,CAAC;AACL,GAAG;AACH,CAAC;;;;"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const core = require('@sentry/core');
|
|
4
|
+
const debugBuild = require('../debug-build.js');
|
|
5
|
+
|
|
6
|
+
const spanStreamingIntegration = core.defineIntegration(((userOptions) => {
|
|
7
|
+
const validatedUserProvidedBatchLimit =
|
|
8
|
+
userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1
|
|
9
|
+
? userOptions.batchLimit
|
|
10
|
+
: undefined;
|
|
11
|
+
|
|
12
|
+
if (debugBuild.DEBUG_BUILD && userOptions?.batchLimit && !validatedUserProvidedBatchLimit) {
|
|
13
|
+
core.debug.warn('SpanStreaming batchLimit must be between 1 and 1000, defaulting to 1000');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let sdkConfigured = false;
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
name: 'SpanStreaming',
|
|
20
|
+
beforeSetup(client) {
|
|
21
|
+
const clientOptions = client.getOptions();
|
|
22
|
+
if (!clientOptions.traceLifecycle) {
|
|
23
|
+
client.getOptions().traceLifecycle = 'stream';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const initialMessage = 'spanStreamingIntegration requires';
|
|
27
|
+
const fallbackMsg = 'Falling back to static trace lifecycle.';
|
|
28
|
+
|
|
29
|
+
if (!clientOptions.traceLifecycle) {
|
|
30
|
+
// For browser, we auto-enable span streaming already if this integration is enabled
|
|
31
|
+
// This avoids requiring users to manually opt into span streaming via 2 mechanisms
|
|
32
|
+
// so we set `traceLifecycle` to `stream` if it's not set.
|
|
33
|
+
client.getOptions().traceLifecycle = 'stream';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (clientOptions.traceLifecycle !== 'stream') {
|
|
37
|
+
// If there's a conflict between this integration being added and `traceLifecycle` being set to `static`
|
|
38
|
+
// we prefer static (non-span-streaming) mode.
|
|
39
|
+
debugBuild.DEBUG_BUILD &&
|
|
40
|
+
core.debug.warn(
|
|
41
|
+
`${initialMessage} \`traceLifecycle\` is set to ${clientOptions.traceLifecycle}. ${fallbackMsg}. Either remove \`spanStreamingIntegration\` or set \`traceLifecycle\` to "stream".`,
|
|
42
|
+
);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const beforeSendSpan = clientOptions.beforeSendSpan;
|
|
47
|
+
if (beforeSendSpan && !core.isV2BeforeSendSpanCallback(beforeSendSpan)) {
|
|
48
|
+
client.getOptions().traceLifecycle = 'static';
|
|
49
|
+
core.debug.warn(`${initialMessage} a beforeSendSpan callback using \`withStreamSpan\`! ${fallbackMsg}`);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
sdkConfigured = true;
|
|
54
|
+
},
|
|
55
|
+
setup(client) {
|
|
56
|
+
if (!sdkConfigured) {
|
|
57
|
+
// options validation failed in beforeSetup, so we don't do anything here
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const buffer = new core.SpanBuffer(client);
|
|
62
|
+
|
|
63
|
+
client.on('enqueueSpan', spanJSON => {
|
|
64
|
+
buffer.addSpan(spanJSON);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
client.on('afterSpanEnd', span => {
|
|
68
|
+
core.captureSpan(span, client);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
client.on('processSpan', spanJSON => {
|
|
72
|
+
core.safeSetSpanJSONAttributes(spanJSON, {
|
|
73
|
+
// browser-only: tell Sentry to infer the IP address from the request
|
|
74
|
+
'client.address': client.getOptions().sendDefaultPii ? '{{auto}}' : undefined,
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// in addition to capturing the span, we also flush the trace when the segment
|
|
79
|
+
// span ends to ensure things are sent timely. We never know when the browser
|
|
80
|
+
// is closed, users navigate away, etc.
|
|
81
|
+
client.on('afterSegmentSpanEnd', segmentSpan => buffer.flushTrace(segmentSpan.spanContext().traceId));
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}) );
|
|
85
|
+
|
|
86
|
+
exports.spanStreamingIntegration = spanStreamingIntegration;
|
|
87
|
+
//# sourceMappingURL=spanstreaming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spanstreaming.js","sources":["../../../../../src/integrations/spanstreaming.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport {\n captureSpan,\n debug,\n defineIntegration,\n isV2BeforeSendSpanCallback,\n safeSetSpanJSONAttributes,\n SpanBuffer,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\n\nexport interface SpanStreamingOptions {\n batchLimit: number;\n}\n\nexport const spanStreamingIntegration = defineIntegration(((userOptions?: Partial<SpanStreamingOptions>) => {\n const validatedUserProvidedBatchLimit =\n userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1\n ? userOptions.batchLimit\n : undefined;\n\n if (DEBUG_BUILD && userOptions?.batchLimit && !validatedUserProvidedBatchLimit) {\n debug.warn('SpanStreaming batchLimit must be between 1 and 1000, defaulting to 1000');\n }\n\n let sdkConfigured = false;\n\n return {\n name: 'SpanStreaming',\n beforeSetup(client) {\n const clientOptions = client.getOptions();\n if (!clientOptions.traceLifecycle) {\n client.getOptions().traceLifecycle = 'stream';\n }\n\n const initialMessage = 'spanStreamingIntegration requires';\n const fallbackMsg = 'Falling back to static trace lifecycle.';\n\n if (!clientOptions.traceLifecycle) {\n // For browser, we auto-enable span streaming already if this integration is enabled\n // This avoids requiring users to manually opt into span streaming via 2 mechanisms\n // so we set `traceLifecycle` to `stream` if it's not set.\n client.getOptions().traceLifecycle = 'stream';\n }\n\n if (clientOptions.traceLifecycle !== 'stream') {\n // If there's a conflict between this integration being added and `traceLifecycle` being set to `static`\n // we prefer static (non-span-streaming) mode.\n DEBUG_BUILD &&\n debug.warn(\n `${initialMessage} \\`traceLifecycle\\` is set to ${clientOptions.traceLifecycle}. ${fallbackMsg}. Either remove \\`spanStreamingIntegration\\` or set \\`traceLifecycle\\` to \"stream\".`,\n );\n return;\n }\n\n const beforeSendSpan = clientOptions.beforeSendSpan;\n if (beforeSendSpan && !isV2BeforeSendSpanCallback(beforeSendSpan)) {\n client.getOptions().traceLifecycle = 'static';\n debug.warn(`${initialMessage} a beforeSendSpan callback using \\`withStreamSpan\\`! ${fallbackMsg}`);\n return;\n }\n\n sdkConfigured = true;\n },\n setup(client) {\n if (!sdkConfigured) {\n // options validation failed in beforeSetup, so we don't do anything here\n return;\n }\n\n const buffer = new SpanBuffer(client);\n\n client.on('enqueueSpan', spanJSON => {\n buffer.addSpan(spanJSON);\n });\n\n client.on('afterSpanEnd', span => {\n captureSpan(span, client);\n });\n\n client.on('processSpan', spanJSON => {\n safeSetSpanJSONAttributes(spanJSON, {\n // browser-only: tell Sentry to infer the IP address from the request\n 'client.address': client.getOptions().sendDefaultPii ? '{{auto}}' : undefined,\n });\n });\n\n // in addition to capturing the span, we also flush the trace when the segment\n // span ends to ensure things are sent timely. We never know when the browser\n // is closed, users navigate away, etc.\n client.on('afterSegmentSpanEnd', segmentSpan => buffer.flushTrace(segmentSpan.spanContext().traceId));\n },\n };\n}) satisfies IntegrationFn);\n"],"names":["defineIntegration","DEBUG_BUILD","debug","isV2BeforeSendSpanCallback","SpanBuffer","captureSpan","safeSetSpanJSONAttributes"],"mappings":";;;;;AAeO,MAAM,2BAA2BA,sBAAiB,EAAE,CAAC,WAAW,KAAqC;AAC5G,EAAE,MAAM,+BAAA;AACR,IAAI,WAAW,EAAE,UAAA,IAAc,WAAW,CAAC,UAAA,IAAc,IAAA,IAAQ,WAAW,CAAC,cAAc;AAC3F,QAAQ,WAAW,CAAC;AACpB,QAAQ,SAAS;;AAEjB,EAAE,IAAIC,sBAAA,IAAe,WAAW,EAAE,UAAA,IAAc,CAAC,+BAA+B,EAAE;AAClF,IAAIC,UAAK,CAAC,IAAI,CAAC,yEAAyE,CAAC;AACzF,EAAE;;AAEF,EAAE,IAAI,aAAA,GAAgB,KAAK;;AAE3B,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,eAAe;AACzB,IAAI,WAAW,CAAC,MAAM,EAAE;AACxB,MAAM,MAAM,aAAA,GAAgB,MAAM,CAAC,UAAU,EAAE;AAC/C,MAAM,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE;AACzC,QAAQ,MAAM,CAAC,UAAU,EAAE,CAAC,cAAA,GAAiB,QAAQ;AACrD,MAAM;;AAEN,MAAM,MAAM,cAAA,GAAiB,mCAAmC;AAChE,MAAM,MAAM,WAAA,GAAc,yCAAyC;;AAEnE,MAAM,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE;AACzC;AACA;AACA;AACA,QAAQ,MAAM,CAAC,UAAU,EAAE,CAAC,cAAA,GAAiB,QAAQ;AACrD,MAAM;;AAEN,MAAM,IAAI,aAAa,CAAC,cAAA,KAAmB,QAAQ,EAAE;AACrD;AACA;AACA,QAAQD,sBAAA;AACR,UAAUC,UAAK,CAAC,IAAI;AACpB,YAAY,CAAC,EAAA,cAAA,CAAA,8BAAA,EAAA,aAAA,CAAA,cAAA,CAAA,EAAA,EAAA,WAAA,CAAA,mFAAA,CAAA;AACA,WAAA;AACA,QAAA;AACA,MAAA;;AAEA,MAAA,MAAA,cAAA,GAAA,aAAA,CAAA,cAAA;AACA,MAAA,IAAA,cAAA,IAAA,CAAAC,+BAAA,CAAA,cAAA,CAAA,EAAA;AACA,QAAA,MAAA,CAAA,UAAA,EAAA,CAAA,cAAA,GAAA,QAAA;AACA,QAAAD,UAAA,CAAA,IAAA,CAAA,CAAA,EAAA,cAAA,CAAA,qDAAA,EAAA,WAAA,CAAA,CAAA,CAAA;AACA,QAAA;AACA,MAAA;;AAEA,MAAA,aAAA,GAAA,IAAA;AACA,IAAA,CAAA;AACA,IAAA,KAAA,CAAA,MAAA,EAAA;AACA,MAAA,IAAA,CAAA,aAAA,EAAA;AACA;AACA,QAAA;AACA,MAAA;;AAEA,MAAA,MAAA,MAAA,GAAA,IAAAE,eAAA,CAAA,MAAA,CAAA;;AAEA,MAAA,MAAA,CAAA,EAAA,CAAA,aAAA,EAAA,QAAA,IAAA;AACA,QAAA,MAAA,CAAA,OAAA,CAAA,QAAA,CAAA;AACA,MAAA,CAAA,CAAA;;AAEA,MAAA,MAAA,CAAA,EAAA,CAAA,cAAA,EAAA,IAAA,IAAA;AACA,QAAAC,gBAAA,CAAA,IAAA,EAAA,MAAA,CAAA;AACA,MAAA,CAAA,CAAA;;AAEA,MAAA,MAAA,CAAA,EAAA,CAAA,aAAA,EAAA,QAAA,IAAA;AACA,QAAAC,8BAAA,CAAA,QAAA,EAAA;AACA;AACA,UAAA,gBAAA,EAAA,MAAA,CAAA,UAAA,EAAA,CAAA,cAAA,GAAA,UAAA,GAAA,SAAA;AACA,SAAA,CAAA;AACA,MAAA,CAAA,CAAA;;AAEA;AACA;AACA;AACA,MAAA,MAAA,CAAA,EAAA,CAAA,qBAAA,EAAA,WAAA,IAAA,MAAA,CAAA,UAAA,CAAA,WAAA,CAAA,WAAA,EAAA,CAAA,OAAA,CAAA,CAAA;AACA,IAAA,CAAA;AACA,GAAA;AACA,CAAA;;;;"}
|
|
@@ -17,6 +17,7 @@ const _spotlightIntegration = ((options = {}) => {
|
|
|
17
17
|
// We don't want to send interaction transactions/root spans created from
|
|
18
18
|
// clicks within Spotlight to Sentry. Neither do we want them to be sent to
|
|
19
19
|
// spotlight.
|
|
20
|
+
// TODO (span-streaming): port this to what exactly?
|
|
20
21
|
processEvent: event => (isSpotlightInteraction(event) ? null : event),
|
|
21
22
|
afterAllSetup: (client) => {
|
|
22
23
|
setupSidecarForwarding(client, sidecarUrl);
|
|
@@ -72,10 +73,10 @@ const spotlightBrowserIntegration = core.defineIntegration(_spotlightIntegration
|
|
|
72
73
|
function isSpotlightInteraction(event) {
|
|
73
74
|
return Boolean(
|
|
74
75
|
event.type === 'transaction' &&
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
event.spans &&
|
|
77
|
+
event.contexts?.trace &&
|
|
78
|
+
event.contexts.trace.op === 'ui.action.click' &&
|
|
79
|
+
event.spans.some(({ description }) => description?.includes('#sentry-spotlight')),
|
|
79
80
|
);
|
|
80
81
|
}
|
|
81
82
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spotlight.js","sources":["../../../../../src/integrations/spotlight.ts"],"sourcesContent":["import type { Client, Envelope, Event, IntegrationFn } from '@sentry/core';\nimport { debug, defineIntegration, serializeEnvelope } from '@sentry/core';\nimport { getNativeImplementation } from '@sentry-internal/browser-utils';\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { WINDOW } from '../helpers';\n\nexport type SpotlightConnectionOptions = {\n /**\n * Set this if the Spotlight Sidecar is not running on localhost:8969\n * By default, the Url is set to http://localhost:8969/stream\n */\n sidecarUrl?: string;\n};\n\nexport const INTEGRATION_NAME = 'SpotlightBrowser';\n\nconst _spotlightIntegration = ((options: Partial<SpotlightConnectionOptions> = {}) => {\n const sidecarUrl = options.sidecarUrl || 'http://localhost:8969/stream';\n\n return {\n name: INTEGRATION_NAME,\n setup: () => {\n DEBUG_BUILD && debug.log('Using Sidecar URL', sidecarUrl);\n },\n // We don't want to send interaction transactions/root spans created from\n // clicks within Spotlight to Sentry. Neither do we want them to be sent to\n // spotlight.\n processEvent: event => (isSpotlightInteraction(event) ? null : event),\n afterAllSetup: (client: Client) => {\n setupSidecarForwarding(client, sidecarUrl);\n },\n };\n}) satisfies IntegrationFn;\n\nfunction setupSidecarForwarding(client: Client, sidecarUrl: string): void {\n const makeFetch: typeof WINDOW.fetch | undefined = getNativeImplementation('fetch');\n let failCount = 0;\n\n client.on('beforeEnvelope', (envelope: Envelope) => {\n if (failCount > 3) {\n debug.warn('[Spotlight] Disabled Sentry -> Spotlight integration due to too many failed requests:', failCount);\n return;\n }\n\n makeFetch(sidecarUrl, {\n method: 'POST',\n body: serializeEnvelope(envelope),\n headers: {\n 'Content-Type': 'application/x-sentry-envelope',\n },\n mode: 'cors',\n }).then(\n res => {\n if (res.status >= 200 && res.status < 400) {\n // Reset failed requests counter on success\n failCount = 0;\n }\n },\n err => {\n failCount++;\n debug.error(\n \"Sentry SDK can't connect to Sidecar is it running? See: https://spotlightjs.com/sidecar/npx/\",\n err,\n );\n },\n );\n });\n}\n\n/**\n * Use this integration to send errors and transactions to Spotlight.\n *\n * Learn more about spotlight at https://spotlightjs.com\n */\nexport const spotlightBrowserIntegration = defineIntegration(_spotlightIntegration);\n\n/**\n * Flags if the event is a transaction created from an interaction with the spotlight UI.\n */\nexport function isSpotlightInteraction(event: Event): boolean {\n return Boolean(\n event.type === 'transaction' &&\n
|
|
1
|
+
{"version":3,"file":"spotlight.js","sources":["../../../../../src/integrations/spotlight.ts"],"sourcesContent":["import type { Client, Envelope, Event, IntegrationFn } from '@sentry/core';\nimport { debug, defineIntegration, serializeEnvelope } from '@sentry/core';\nimport { getNativeImplementation } from '@sentry-internal/browser-utils';\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { WINDOW } from '../helpers';\n\nexport type SpotlightConnectionOptions = {\n /**\n * Set this if the Spotlight Sidecar is not running on localhost:8969\n * By default, the Url is set to http://localhost:8969/stream\n */\n sidecarUrl?: string;\n};\n\nexport const INTEGRATION_NAME = 'SpotlightBrowser';\n\nconst _spotlightIntegration = ((options: Partial<SpotlightConnectionOptions> = {}) => {\n const sidecarUrl = options.sidecarUrl || 'http://localhost:8969/stream';\n\n return {\n name: INTEGRATION_NAME,\n setup: () => {\n DEBUG_BUILD && debug.log('Using Sidecar URL', sidecarUrl);\n },\n // We don't want to send interaction transactions/root spans created from\n // clicks within Spotlight to Sentry. Neither do we want them to be sent to\n // spotlight.\n // TODO (span-streaming): port this to what exactly?\n processEvent: event => (isSpotlightInteraction(event) ? null : event),\n afterAllSetup: (client: Client) => {\n setupSidecarForwarding(client, sidecarUrl);\n },\n };\n}) satisfies IntegrationFn;\n\nfunction setupSidecarForwarding(client: Client, sidecarUrl: string): void {\n const makeFetch: typeof WINDOW.fetch | undefined = getNativeImplementation('fetch');\n let failCount = 0;\n\n client.on('beforeEnvelope', (envelope: Envelope) => {\n if (failCount > 3) {\n debug.warn('[Spotlight] Disabled Sentry -> Spotlight integration due to too many failed requests:', failCount);\n return;\n }\n\n makeFetch(sidecarUrl, {\n method: 'POST',\n body: serializeEnvelope(envelope),\n headers: {\n 'Content-Type': 'application/x-sentry-envelope',\n },\n mode: 'cors',\n }).then(\n res => {\n if (res.status >= 200 && res.status < 400) {\n // Reset failed requests counter on success\n failCount = 0;\n }\n },\n err => {\n failCount++;\n debug.error(\n \"Sentry SDK can't connect to Sidecar is it running? See: https://spotlightjs.com/sidecar/npx/\",\n err,\n );\n },\n );\n });\n}\n\n/**\n * Use this integration to send errors and transactions to Spotlight.\n *\n * Learn more about spotlight at https://spotlightjs.com\n */\nexport const spotlightBrowserIntegration = defineIntegration(_spotlightIntegration);\n\n/**\n * Flags if the event is a transaction created from an interaction with the spotlight UI.\n */\nexport function isSpotlightInteraction(event: Event): boolean {\n return Boolean(\n event.type === 'transaction' &&\n event.spans &&\n event.contexts?.trace &&\n event.contexts.trace.op === 'ui.action.click' &&\n event.spans.some(({ description }) => description?.includes('#sentry-spotlight')),\n );\n}\n"],"names":["DEBUG_BUILD","debug","getNativeImplementation","serializeEnvelope","defineIntegration"],"mappings":";;;;;;AAcO,MAAM,gBAAA,GAAmB;;AAEhC,MAAM,qBAAA,IAAyB,CAAC,OAAO,GAAwC,EAAE,KAAK;AACtF,EAAE,MAAM,UAAA,GAAa,OAAO,CAAC,UAAA,IAAc,8BAA8B;;AAEzE,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B,IAAI,KAAK,EAAE,MAAM;AACjB,MAAMA,sBAAA,IAAeC,UAAK,CAAC,GAAG,CAAC,mBAAmB,EAAE,UAAU,CAAC;AAC/D,IAAI,CAAC;AACL;AACA;AACA;AACA;AACA,IAAI,YAAY,EAAE,KAAA,KAAU,sBAAsB,CAAC,KAAK,CAAA,GAAI,IAAA,GAAO,KAAK,CAAC;AACzE,IAAI,aAAa,EAAE,CAAC,MAAM,KAAa;AACvC,MAAM,sBAAsB,CAAC,MAAM,EAAE,UAAU,CAAC;AAChD,IAAI,CAAC;AACL,GAAG;AACH,CAAC,CAAA;;AAED,SAAS,sBAAsB,CAAC,MAAM,EAAU,UAAU,EAAgB;AAC1E,EAAE,MAAM,SAAS,GAAoCC,oCAAuB,CAAC,OAAO,CAAC;AACrF,EAAE,IAAI,SAAA,GAAY,CAAC;;AAEnB,EAAE,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,QAAQ,KAAe;AACtD,IAAI,IAAI,SAAA,GAAY,CAAC,EAAE;AACvB,MAAMD,UAAK,CAAC,IAAI,CAAC,uFAAuF,EAAE,SAAS,CAAC;AACpH,MAAM;AACN,IAAI;;AAEJ,IAAI,SAAS,CAAC,UAAU,EAAE;AAC1B,MAAM,MAAM,EAAE,MAAM;AACpB,MAAM,IAAI,EAAEE,sBAAiB,CAAC,QAAQ,CAAC;AACvC,MAAM,OAAO,EAAE;AACf,QAAQ,cAAc,EAAE,+BAA+B;AACvD,OAAO;AACP,MAAM,IAAI,EAAE,MAAM;AAClB,KAAK,CAAC,CAAC,IAAI;AACX,MAAM,OAAO;AACb,QAAQ,IAAI,GAAG,CAAC,MAAA,IAAU,GAAA,IAAO,GAAG,CAAC,MAAA,GAAS,GAAG,EAAE;AACnD;AACA,UAAU,SAAA,GAAY,CAAC;AACvB,QAAQ;AACR,MAAM,CAAC;AACP,MAAM,OAAO;AACb,QAAQ,SAAS,EAAE;AACnB,QAAQF,UAAK,CAAC,KAAK;AACnB,UAAU,8FAA8F;AACxG,UAAU,GAAG;AACb,SAAS;AACT,MAAM,CAAC;AACP,KAAK;AACL,EAAE,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;MACa,2BAAA,GAA8BG,sBAAiB,CAAC,qBAAqB;;AAElF;AACA;AACA;AACO,SAAS,sBAAsB,CAAC,KAAK,EAAkB;AAC9D,EAAE,OAAO,OAAO;AAChB,IAAI,KAAK,CAAC,IAAA,KAAS,aAAA;AACnB,IAAI,KAAK,CAAC,KAAA;AACV,IAAI,KAAK,CAAC,QAAQ,EAAE,KAAA;AACpB,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAA,KAAO,iBAAA;AAChC,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,WAAA,EAAa,KAAK,WAAW,EAAE,QAAQ,CAAC,mBAAmB,CAAC,CAAC;AACrF,GAAG;AACH;;;;;;"}
|
|
@@ -106,6 +106,16 @@ class UIProfiler {
|
|
|
106
106
|
this._endProfiling();
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
/** Returns the current profiler session ID, or undefined if not initialized. */
|
|
110
|
+
getProfilerId() {
|
|
111
|
+
return this._profilerId;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Returns whether the profiler is currently running (recording). */
|
|
115
|
+
isRunning() {
|
|
116
|
+
return this._isRunning;
|
|
117
|
+
}
|
|
118
|
+
|
|
109
119
|
/** Handle an already-active root span at integration setup time (used only in trace mode). */
|
|
110
120
|
notifyRootSpanActive(rootSpan) {
|
|
111
121
|
if (this._lifecycleMode !== 'trace' || !this._sessionSampled) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UIProfiler.js","sources":["../../../../../src/profiling/UIProfiler.ts"],"sourcesContent":["import type { Client, ContinuousProfiler, ProfileChunk, ProfileChunkEnvelope, Span } from '@sentry/core';\nimport {\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 &&\n debug.log('[Profiling] Span not profiled because of negative sampling decision for user session.');\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', platform: 'javascript' }, 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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"}
|
|
1
|
+
{"version":3,"file":"UIProfiler.js","sources":["../../../../../src/profiling/UIProfiler.ts"],"sourcesContent":["import type { Client, ContinuousProfiler, ProfileChunk, ProfileChunkEnvelope, Span } from '@sentry/core';\nimport {\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 /** Returns the current profiler session ID, or undefined if not initialized. */\n public getProfilerId(): string | undefined {\n return this._profilerId;\n }\n\n /** Returns whether the profiler is currently running (recording). */\n public isRunning(): boolean {\n return this._isRunning;\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 &&\n debug.log('[Profiling] Span not profiled because of negative sampling decision for user session.');\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', platform: 'javascript' }, 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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"}
|
|
@@ -72,6 +72,16 @@ const _browserProfilingIntegration = (() => {
|
|
|
72
72
|
}
|
|
73
73
|
}, 0);
|
|
74
74
|
}
|
|
75
|
+
|
|
76
|
+
// Attach profilerId to every span when the profiler is active (for correlation with profile chunks)
|
|
77
|
+
client.on('spanStart', (span) => {
|
|
78
|
+
if (profiler.isRunning()) {
|
|
79
|
+
const profilerId = profiler.getProfilerId();
|
|
80
|
+
if (profilerId) {
|
|
81
|
+
span.setAttribute('sentry.profiler_id', profilerId);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
75
85
|
} else {
|
|
76
86
|
// LEGACY PROFILING (v1)
|
|
77
87
|
if (rootSpan && utils.isAutomatedPageLoadSpan(rootSpan)) {
|