@sentry/browser 10.19.0 → 10.21.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.
Files changed (81) hide show
  1. package/build/npm/cjs/client.js +1 -35
  2. package/build/npm/cjs/client.js.map +1 -1
  3. package/build/npm/cjs/index.js +9 -2
  4. package/build/npm/cjs/index.js.map +1 -1
  5. package/build/npm/cjs/integrations/featureFlags/growthbook/integration.js +29 -0
  6. package/build/npm/cjs/integrations/featureFlags/growthbook/integration.js.map +1 -0
  7. package/build/npm/cjs/integrations/httpcontext.js +2 -0
  8. package/build/npm/cjs/integrations/httpcontext.js.map +1 -1
  9. package/build/npm/cjs/integrations/spanstreaming.js +252 -0
  10. package/build/npm/cjs/integrations/spanstreaming.js.map +1 -0
  11. package/build/npm/cjs/tracing/browserTracingIntegration.js +2 -0
  12. package/build/npm/cjs/tracing/browserTracingIntegration.js.map +1 -1
  13. package/build/npm/cjs/tracing/request.js +18 -36
  14. package/build/npm/cjs/tracing/request.js.map +1 -1
  15. package/build/npm/cjs/tracing/utils.js +54 -0
  16. package/build/npm/cjs/tracing/utils.js.map +1 -0
  17. package/build/npm/cjs/utils/lazyLoadIntegration.js +3 -0
  18. package/build/npm/cjs/utils/lazyLoadIntegration.js.map +1 -1
  19. package/build/npm/esm/client.js +1 -35
  20. package/build/npm/esm/client.js.map +1 -1
  21. package/build/npm/esm/index.js +3 -1
  22. package/build/npm/esm/index.js.map +1 -1
  23. package/build/npm/esm/integrations/featureFlags/growthbook/integration.js +27 -0
  24. package/build/npm/esm/integrations/featureFlags/growthbook/integration.js.map +1 -0
  25. package/build/npm/esm/integrations/httpcontext.js +2 -0
  26. package/build/npm/esm/integrations/httpcontext.js.map +1 -1
  27. package/build/npm/esm/integrations/spanstreaming.js +250 -0
  28. package/build/npm/esm/integrations/spanstreaming.js.map +1 -0
  29. package/build/npm/esm/package.json +1 -1
  30. package/build/npm/esm/tracing/browserTracingIntegration.js +2 -0
  31. package/build/npm/esm/tracing/browserTracingIntegration.js.map +1 -1
  32. package/build/npm/esm/tracing/request.js +15 -33
  33. package/build/npm/esm/tracing/request.js.map +1 -1
  34. package/build/npm/esm/tracing/utils.js +49 -0
  35. package/build/npm/esm/tracing/utils.js.map +1 -0
  36. package/build/npm/esm/utils/lazyLoadIntegration.js +3 -0
  37. package/build/npm/esm/utils/lazyLoadIntegration.js.map +1 -1
  38. package/build/npm/types/client.d.ts +0 -2
  39. package/build/npm/types/client.d.ts.map +1 -1
  40. package/build/npm/types/helpers.d.ts +1 -0
  41. package/build/npm/types/helpers.d.ts.map +1 -1
  42. package/build/npm/types/index.d.ts +3 -1
  43. package/build/npm/types/index.d.ts.map +1 -1
  44. package/build/npm/types/integrations/featureFlags/growthbook/index.d.ts +2 -0
  45. package/build/npm/types/integrations/featureFlags/growthbook/index.d.ts.map +1 -0
  46. package/build/npm/types/integrations/featureFlags/growthbook/integration.d.ts +25 -0
  47. package/build/npm/types/integrations/featureFlags/growthbook/integration.d.ts.map +1 -0
  48. package/build/npm/types/integrations/featureFlags/growthbook/types.d.ts +6 -0
  49. package/build/npm/types/integrations/featureFlags/growthbook/types.d.ts.map +1 -0
  50. package/build/npm/types/integrations/httpcontext.d.ts.map +1 -1
  51. package/build/npm/types/integrations/spanstreaming.d.ts +5 -0
  52. package/build/npm/types/integrations/spanstreaming.d.ts.map +1 -0
  53. package/build/npm/types/integrations-bundle/index.instrumentanthropicaiclient.d.ts +2 -0
  54. package/build/npm/types/integrations-bundle/index.instrumentanthropicaiclient.d.ts.map +1 -0
  55. package/build/npm/types/integrations-bundle/index.instrumentgooglegenaiclient.d.ts +2 -0
  56. package/build/npm/types/integrations-bundle/index.instrumentgooglegenaiclient.d.ts.map +1 -0
  57. package/build/npm/types/integrations-bundle/index.instrumentopenaiclient.d.ts +2 -0
  58. package/build/npm/types/integrations-bundle/index.instrumentopenaiclient.d.ts.map +1 -0
  59. package/build/npm/types/tracing/browserTracingIntegration.d.ts +6 -4
  60. package/build/npm/types/tracing/browserTracingIntegration.d.ts.map +1 -1
  61. package/build/npm/types/tracing/request.d.ts +6 -4
  62. package/build/npm/types/tracing/request.d.ts.map +1 -1
  63. package/build/npm/types/tracing/utils.d.ts +17 -0
  64. package/build/npm/types/tracing/utils.d.ts.map +1 -0
  65. package/build/npm/types/utils/lazyLoadIntegration.d.ts +3 -0
  66. package/build/npm/types/utils/lazyLoadIntegration.d.ts.map +1 -1
  67. package/build/npm/types-ts3.8/client.d.ts +0 -2
  68. package/build/npm/types-ts3.8/helpers.d.ts +1 -0
  69. package/build/npm/types-ts3.8/index.d.ts +3 -1
  70. package/build/npm/types-ts3.8/integrations/featureFlags/growthbook/index.d.ts +2 -0
  71. package/build/npm/types-ts3.8/integrations/featureFlags/growthbook/integration.d.ts +25 -0
  72. package/build/npm/types-ts3.8/integrations/featureFlags/growthbook/types.d.ts +6 -0
  73. package/build/npm/types-ts3.8/integrations/spanstreaming.d.ts +5 -0
  74. package/build/npm/types-ts3.8/integrations-bundle/index.instrumentanthropicaiclient.d.ts +2 -0
  75. package/build/npm/types-ts3.8/integrations-bundle/index.instrumentgooglegenaiclient.d.ts +2 -0
  76. package/build/npm/types-ts3.8/integrations-bundle/index.instrumentopenaiclient.d.ts +2 -0
  77. package/build/npm/types-ts3.8/tracing/browserTracingIntegration.d.ts +6 -4
  78. package/build/npm/types-ts3.8/tracing/request.d.ts +6 -4
  79. package/build/npm/types-ts3.8/tracing/utils.d.ts +17 -0
  80. package/build/npm/types-ts3.8/utils/lazyLoadIntegration.d.ts +3 -0
  81. package/package.json +7 -7
@@ -8,8 +8,6 @@ const helpers = require('./helpers.js');
8
8
  * A magic string that build tooling can leverage in order to inject a release value into the SDK.
9
9
  */
10
10
 
11
- const DEFAULT_FLUSH_INTERVAL = 5000;
12
-
13
11
  /**
14
12
  * The Sentry Browser SDK Client.
15
13
  *
@@ -17,7 +15,6 @@ const DEFAULT_FLUSH_INTERVAL = 5000;
17
15
  * @see SentryClient for usage documentation.
18
16
  */
19
17
  class BrowserClient extends core.Client {
20
-
21
18
  /**
22
19
  * Creates a new Browser SDK instance.
23
20
  *
@@ -41,6 +38,7 @@ class BrowserClient extends core.Client {
41
38
 
42
39
  const { sendDefaultPii, sendClientReports, enableLogs, _experiments } = this._options;
43
40
 
41
+ // Flush logs and metrics when page becomes hidden (e.g., tab switch, navigation)
44
42
  if (helpers.WINDOW.document && (sendClientReports || enableLogs || _experiments?.enableMetrics)) {
45
43
  helpers.WINDOW.document.addEventListener('visibilitychange', () => {
46
44
  if (helpers.WINDOW.document.visibilityState === 'hidden') {
@@ -57,38 +55,6 @@ class BrowserClient extends core.Client {
57
55
  });
58
56
  }
59
57
 
60
- if (enableLogs) {
61
- this.on('flush', () => {
62
- core._INTERNAL_flushLogsBuffer(this);
63
- });
64
-
65
- this.on('afterCaptureLog', () => {
66
- if (this._logFlushIdleTimeout) {
67
- clearTimeout(this._logFlushIdleTimeout);
68
- }
69
-
70
- this._logFlushIdleTimeout = setTimeout(() => {
71
- core._INTERNAL_flushLogsBuffer(this);
72
- }, DEFAULT_FLUSH_INTERVAL);
73
- });
74
- }
75
-
76
- if (_experiments?.enableMetrics) {
77
- this.on('flush', () => {
78
- core._INTERNAL_flushMetricsBuffer(this);
79
- });
80
-
81
- this.on('afterCaptureMetric', () => {
82
- if (this._metricFlushIdleTimeout) {
83
- clearTimeout(this._metricFlushIdleTimeout);
84
- }
85
-
86
- this._metricFlushIdleTimeout = setTimeout(() => {
87
- core._INTERNAL_flushMetricsBuffer(this);
88
- }, DEFAULT_FLUSH_INTERVAL);
89
- });
90
- }
91
-
92
58
  if (sendDefaultPii) {
93
59
  this.on('beforeSendSession', core.addAutoIpAddressToSession);
94
60
  }
@@ -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\nconst DEFAULT_FLUSH_INTERVAL = 5000;\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 * 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 private _logFlushIdleTimeout: ReturnType<typeof setTimeout> | undefined;\n private _metricFlushIdleTimeout: ReturnType<typeof setTimeout> | undefined;\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 { sendDefaultPii, sendClientReports, enableLogs, _experiments } = this._options;\n\n if (WINDOW.document && (sendClientReports || enableLogs || _experiments?.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 if (_experiments?.enableMetrics) {\n _INTERNAL_flushMetricsBuffer(this);\n }\n }\n });\n }\n\n if (enableLogs) {\n this.on('flush', () => {\n _INTERNAL_flushLogsBuffer(this);\n });\n\n this.on('afterCaptureLog', () => {\n if (this._logFlushIdleTimeout) {\n clearTimeout(this._logFlushIdleTimeout);\n }\n\n this._logFlushIdleTimeout = setTimeout(() => {\n _INTERNAL_flushLogsBuffer(this);\n }, DEFAULT_FLUSH_INTERVAL);\n });\n }\n\n if (_experiments?.enableMetrics) {\n this.on('flush', () => {\n _INTERNAL_flushMetricsBuffer(this);\n });\n\n this.on('afterCaptureMetric', () => {\n if (this._metricFlushIdleTimeout) {\n clearTimeout(this._metricFlushIdleTimeout);\n }\n\n this._metricFlushIdleTimeout = setTimeout(() => {\n _INTERNAL_flushMetricsBuffer(this);\n }, DEFAULT_FLUSH_INTERVAL);\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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"}
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 * 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 { sendDefaultPii, sendClientReports, enableLogs, _experiments } = this._options;\n\n // Flush logs and metrics when page becomes hidden (e.g., tab switch, navigation)\n if (WINDOW.document && (sendClientReports || enableLogs || _experiments?.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 if (_experiments?.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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"}
@@ -35,9 +35,11 @@ const browsersession = require('./integrations/browsersession.js');
35
35
  const integration$1 = require('./integrations/featureFlags/launchdarkly/integration.js');
36
36
  const integration$2 = require('./integrations/featureFlags/openfeature/integration.js');
37
37
  const integration$3 = require('./integrations/featureFlags/unleash/integration.js');
38
- const integration$4 = require('./integrations/featureFlags/statsig/integration.js');
38
+ const integration$4 = require('./integrations/featureFlags/growthbook/integration.js');
39
+ const integration$5 = require('./integrations/featureFlags/statsig/integration.js');
39
40
  const diagnoseSdk = require('./diagnose-sdk.js');
40
41
  const webWorker = require('./integrations/webWorker.js');
42
+ const spanstreaming = require('./integrations/spanstreaming.js');
41
43
 
42
44
 
43
45
 
@@ -81,6 +83,9 @@ exports.getSpanDescendants = core.getSpanDescendants;
81
83
  exports.getSpanStatusFromHttpCode = core.getSpanStatusFromHttpCode;
82
84
  exports.getTraceData = core.getTraceData;
83
85
  exports.inboundFiltersIntegration = core.inboundFiltersIntegration;
86
+ exports.instrumentAnthropicAiClient = core.instrumentAnthropicAiClient;
87
+ exports.instrumentGoogleGenAIClient = core.instrumentGoogleGenAIClient;
88
+ exports.instrumentOpenAiClient = core.instrumentOpenAiClient;
84
89
  exports.instrumentSupabaseClient = core.instrumentSupabaseClient;
85
90
  exports.isEnabled = core.isEnabled;
86
91
  exports.isInitialized = core.isInitialized;
@@ -167,8 +172,10 @@ exports.launchDarklyIntegration = integration$1.launchDarklyIntegration;
167
172
  exports.OpenFeatureIntegrationHook = integration$2.OpenFeatureIntegrationHook;
168
173
  exports.openFeatureIntegration = integration$2.openFeatureIntegration;
169
174
  exports.unleashIntegration = integration$3.unleashIntegration;
170
- exports.statsigIntegration = integration$4.statsigIntegration;
175
+ exports.growthbookIntegration = integration$4.growthbookIntegration;
176
+ exports.statsigIntegration = integration$5.statsigIntegration;
171
177
  exports.diagnoseSdkConnectivity = diagnoseSdk.diagnoseSdkConnectivity;
172
178
  exports.registerWebWorker = webWorker.registerWebWorker;
173
179
  exports.webWorkerIntegration = webWorker.webWorkerIntegration;
180
+ exports.spanStreamingIntegration = spanstreaming.spanStreamingIntegration;
174
181
  //# 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,29 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const core = require('@sentry/core');
4
+
5
+ /**
6
+ * Sentry integration for capturing feature flag evaluations from GrowthBook.
7
+ *
8
+ * See the feature flag documentation: https://develop.sentry.dev/sdk/expected-features/#feature-flags
9
+ *
10
+ * @example
11
+ * ```
12
+ * import { GrowthBook } from '@growthbook/growthbook';
13
+ * import * as Sentry from '@sentry/browser';
14
+ *
15
+ * Sentry.init({
16
+ * dsn: '___PUBLIC_DSN___',
17
+ * integrations: [Sentry.growthbookIntegration({ growthbookClass: GrowthBook })],
18
+ * });
19
+ *
20
+ * const gb = new GrowthBook();
21
+ * gb.isOn('my-feature');
22
+ * Sentry.captureException(new Error('something went wrong'));
23
+ * ```
24
+ */
25
+ const growthbookIntegration = (({ growthbookClass }) =>
26
+ core.growthbookIntegration({ growthbookClass })) ;
27
+
28
+ exports.growthbookIntegration = growthbookIntegration;
29
+ //# sourceMappingURL=integration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.js","sources":["../../../../../../src/integrations/featureFlags/growthbook/integration.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport { growthbookIntegration as coreGrowthbookIntegration } from '@sentry/core';\nimport type { GrowthBookClass } from './types';\n\n/**\n * Sentry integration for capturing feature flag evaluations from GrowthBook.\n *\n * See the feature flag documentation: https://develop.sentry.dev/sdk/expected-features/#feature-flags\n *\n * @example\n * ```\n * import { GrowthBook } from '@growthbook/growthbook';\n * import * as Sentry from '@sentry/browser';\n *\n * Sentry.init({\n * dsn: '___PUBLIC_DSN___',\n * integrations: [Sentry.growthbookIntegration({ growthbookClass: GrowthBook })],\n * });\n *\n * const gb = new GrowthBook();\n * gb.isOn('my-feature');\n * Sentry.captureException(new Error('something went wrong'));\n * ```\n */\nexport const growthbookIntegration = (({ growthbookClass }: { growthbookClass: GrowthBookClass }) =>\n coreGrowthbookIntegration({ growthbookClass })) satisfies IntegrationFn;\n"],"names":["coreGrowthbookIntegration"],"mappings":";;;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,yBAAyB,CAAC,EAAE,eAAA,EAAiB;AAC1D,EAAEA,0BAAyB,CAAC,EAAE,eAAA,EAAiB,CAAC,CAAA;;;;"}
@@ -10,6 +10,8 @@ const helpers = require('../helpers.js');
10
10
  const httpContextIntegration = core.defineIntegration(() => {
11
11
  return {
12
12
  name: 'HttpContext',
13
+ // TODO (span-streaming): probably fine to omit this in favour of us globally
14
+ // already adding request context data but should double-check this
13
15
  preprocessEvent(event) {
14
16
  // if none of the information we want exists, don't bother
15
17
  if (!helpers.WINDOW.navigator && !helpers.WINDOW.location && !helpers.WINDOW.document) {
@@ -1 +1 @@
1
- {"version":3,"file":"httpcontext.js","sources":["../../../../src/integrations/httpcontext.ts"],"sourcesContent":["import { defineIntegration } from '@sentry/core';\nimport { getHttpRequestData, WINDOW } from '../helpers';\n\n/**\n * Collects information about HTTP request headers and\n * attaches them to the event.\n */\nexport const httpContextIntegration = defineIntegration(() => {\n return {\n name: 'HttpContext',\n preprocessEvent(event) {\n // if none of the information we want exists, don't bother\n if (!WINDOW.navigator && !WINDOW.location && !WINDOW.document) {\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","getHttpRequestData"],"mappings":";;;;;AAGA;AACA;AACA;AACA;MACa,sBAAA,GAAyBA,sBAAiB,CAAC,MAAM;AAC9D,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,aAAa;AACvB,IAAI,eAAe,CAAC,KAAK,EAAE;AAC3B;AACA,MAAM,IAAI,CAACC,cAAM,CAAC,aAAa,CAACA,cAAM,CAAC,YAAY,CAACA,cAAM,CAAC,QAAQ,EAAE;AACrE,QAAQ;AACR;;AAEA,MAAM,MAAM,OAAA,GAAUC,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,KAAK;AACL,GAAG;AACH,CAAC;;;;"}
1
+ {"version":3,"file":"httpcontext.js","sources":["../../../../src/integrations/httpcontext.ts"],"sourcesContent":["import { defineIntegration } from '@sentry/core';\nimport { getHttpRequestData, WINDOW } from '../helpers';\n\n/**\n * Collects information about HTTP request headers and\n * attaches them to the event.\n */\nexport const httpContextIntegration = defineIntegration(() => {\n return {\n name: 'HttpContext',\n // TODO (span-streaming): probably fine to omit this in favour of us globally\n // already adding request context data but should double-check this\n preprocessEvent(event) {\n // if none of the information we want exists, don't bother\n if (!WINDOW.navigator && !WINDOW.location && !WINDOW.document) {\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","getHttpRequestData"],"mappings":";;;;;AAGA;AACA;AACA;AACA;MACa,sBAAA,GAAyBA,sBAAiB,CAAC,MAAM;AAC9D,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,aAAa;AACvB;AACA;AACA,IAAI,eAAe,CAAC,KAAK,EAAE;AAC3B;AACA,MAAM,IAAI,CAACC,cAAM,CAAC,aAAa,CAACA,cAAM,CAAC,YAAY,CAACA,cAAM,CAAC,QAAQ,EAAE;AACrE,QAAQ;AACR;;AAEA,MAAM,MAAM,OAAA,GAAUC,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,KAAK;AACL,GAAG;AACH,CAAC;;;;"}
@@ -0,0 +1,252 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const core = require('@sentry/core');
4
+ const debugBuild = require('../debug-build.js');
5
+ const helpers = require('../helpers.js');
6
+
7
+ const spanStreamingIntegration = core.defineIntegration(((userOptions) => {
8
+ const validatedUserProvidedBatchLimit =
9
+ userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1
10
+ ? userOptions.batchLimit
11
+ : undefined;
12
+
13
+ if (debugBuild.DEBUG_BUILD && userOptions?.batchLimit && !validatedUserProvidedBatchLimit) {
14
+ core.debug.warn('SpanStreaming batchLimit must be between 1 and 1000, defaulting to 1000');
15
+ }
16
+
17
+ const options = {
18
+ ...userOptions,
19
+ batchLimit:
20
+ userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1
21
+ ? userOptions.batchLimit
22
+ : 1000,
23
+ };
24
+
25
+ // key: traceId-segmentSpanId
26
+ const spanTreeMap = new Map();
27
+
28
+ return {
29
+ name: 'SpanStreaming',
30
+ setup(client) {
31
+ const clientOptions = client.getOptions();
32
+ const beforeSendSpan = clientOptions.beforeSendSpan;
33
+
34
+ const initialMessage = 'spanStreamingIntegration requires';
35
+ const fallbackMsg = 'Falling back to static trace lifecycle.';
36
+
37
+ if (clientOptions.traceLifecycle !== 'stream') {
38
+ debugBuild.DEBUG_BUILD && core.debug.warn(`${initialMessage} \`traceLifecycle\` to be set to "stream"! ${fallbackMsg}`);
39
+ return;
40
+ }
41
+
42
+ if (beforeSendSpan && !core.isV2BeforeSendSpanCallback(beforeSendSpan)) {
43
+ client.getOptions().traceLifecycle = 'static';
44
+ core.debug.warn(`${initialMessage} a beforeSendSpan callback using \`withStreamSpan\`! ${fallbackMsg}`);
45
+ return;
46
+ }
47
+
48
+ client.on('spanEnd', span => {
49
+ const spanTreeMapKey = getSpanTreeMapKey(span);
50
+ const spanBuffer = spanTreeMap.get(spanTreeMapKey);
51
+ if (spanBuffer) {
52
+ spanBuffer.add(span);
53
+ } else {
54
+ spanTreeMap.set(spanTreeMapKey, new Set([span]));
55
+ }
56
+ });
57
+
58
+ // For now, we send all spans on local segment (root) span end.
59
+ // TODO: This will change once we have more concrete ideas about a universal SDK data buffer.
60
+ client.on('segmentSpanEnd', segmentSpan => {
61
+ processAndSendSpans(segmentSpan, {
62
+ spanTreeMap: spanTreeMap,
63
+ client,
64
+ batchLimit: options.batchLimit,
65
+ beforeSendSpan,
66
+ });
67
+ });
68
+ },
69
+ };
70
+ }) );
71
+
72
+ /**
73
+ * Just the traceid alone isn't enough because there can be multiple span trees with the same traceid.
74
+ */
75
+ function getSpanTreeMapKey(span) {
76
+ return `${span.spanContext().traceId}-${core.getRootSpan(span).spanContext().spanId}`;
77
+ }
78
+
79
+ function processAndSendSpans(
80
+ segmentSpan,
81
+ { client, spanTreeMap, batchLimit, beforeSendSpan },
82
+ ) {
83
+ const traceId = segmentSpan.spanContext().traceId;
84
+ const spanTreeMapKey = getSpanTreeMapKey(segmentSpan);
85
+ const spansOfTrace = spanTreeMap.get(spanTreeMapKey);
86
+
87
+ if (!spansOfTrace?.size) {
88
+ spanTreeMap.delete(spanTreeMapKey);
89
+ return;
90
+ }
91
+
92
+ const segmentSpanJson = core.spanToV2JSON(segmentSpan);
93
+
94
+ for (const span of spansOfTrace) {
95
+ applyCommonSpanAttributes(span, segmentSpanJson, client);
96
+ }
97
+
98
+ applyScopeToSegmentSpan(segmentSpan, segmentSpanJson, client);
99
+
100
+ // TODO: Apply scope data and contexts to segment span
101
+
102
+ const { ignoreSpans } = client.getOptions();
103
+
104
+ // 1. Check if the entire span tree is ignored by ignoreSpans
105
+ if (ignoreSpans?.length && core.shouldIgnoreSpan(segmentSpanJson, ignoreSpans)) {
106
+ client.recordDroppedEvent('before_send', 'span', spansOfTrace.size);
107
+ spanTreeMap.delete(spanTreeMapKey);
108
+ return;
109
+ }
110
+
111
+ const serializedSpans = Array.from(spansOfTrace ?? []).map(s => {
112
+ const serialized = core.spanToV2JSON(s);
113
+ // remove internal span attributes we don't need to send.
114
+ delete serialized.attributes?.[core.SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME];
115
+ return serialized;
116
+ });
117
+
118
+ const processedSpans = [];
119
+ let ignoredSpanCount = 0;
120
+
121
+ for (const span of serializedSpans) {
122
+ // 2. Check if child spans should be ignored
123
+ const isChildSpan = span.span_id !== segmentSpan.spanContext().spanId;
124
+ if (ignoreSpans?.length && isChildSpan && core.shouldIgnoreSpan(span, ignoreSpans)) {
125
+ core.reparentChildSpans(serializedSpans, span);
126
+ ignoredSpanCount++;
127
+ // drop this span by not adding it to the processedSpans array
128
+ continue;
129
+ }
130
+
131
+ // 3. Apply beforeSendSpan callback
132
+ const processedSpan = beforeSendSpan ? applyBeforeSendSpanCallback(span, beforeSendSpan) : span;
133
+ processedSpans.push(processedSpan);
134
+ }
135
+
136
+ if (ignoredSpanCount) {
137
+ client.recordDroppedEvent('before_send', 'span', ignoredSpanCount);
138
+ }
139
+
140
+ const batches = [];
141
+ for (let i = 0; i < processedSpans.length; i += batchLimit) {
142
+ batches.push(processedSpans.slice(i, i + batchLimit));
143
+ }
144
+
145
+ debugBuild.DEBUG_BUILD && core.debug.log(`Sending trace ${traceId} in ${batches.length} batch${batches.length === 1 ? '' : 'es'}`);
146
+
147
+ const dsc = core.getDynamicSamplingContextFromSpan(segmentSpan);
148
+
149
+ for (const batch of batches) {
150
+ const envelope = core.createSpanV2Envelope(batch, dsc, client);
151
+ // no need to handle client reports for network errors,
152
+ // buffer overflows or rate limiting here. All of this is handled
153
+ // by client and transport.
154
+ client.sendEnvelope(envelope).then(null, reason => {
155
+ debugBuild.DEBUG_BUILD && core.debug.error('Error while sending span stream envelope:', reason);
156
+ });
157
+ }
158
+
159
+ spanTreeMap.delete(spanTreeMapKey);
160
+ }
161
+
162
+ function applyCommonSpanAttributes(span, serializedSegmentSpan, client) {
163
+ const sdk = client.getSdkMetadata();
164
+ const { release, environment, sendDefaultPii } = client.getOptions();
165
+
166
+ const { isolationScope: spanIsolationScope, scope: spanScope } = core.getCapturedScopesOnSpan(span);
167
+
168
+ const originalAttributeKeys = Object.keys(core.spanToV2JSON(span).attributes ?? {});
169
+
170
+ const finalScopeData = getFinalScopeData(spanIsolationScope, spanScope);
171
+
172
+ // avoid overwriting any previously set attributes (from users or potentially our SDK instrumentation)
173
+ setAttributesIfNotPresent(span, originalAttributeKeys, {
174
+ [core.SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: release,
175
+ [core.SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: environment,
176
+ [core.SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME]: serializedSegmentSpan.name,
177
+ [core.SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME]: sdk?.sdk?.name,
178
+ [core.SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION]: sdk?.sdk?.version,
179
+ ...(sendDefaultPii
180
+ ? {
181
+ [core.SEMANTIC_ATTRIBUTE_USER_ID]: finalScopeData.user?.id,
182
+ [core.SEMANTIC_ATTRIBUTE_USER_EMAIL]: finalScopeData.user?.email,
183
+ [core.SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS]: finalScopeData.user?.ip_address ?? undefined,
184
+ [core.SEMANTIC_ATTRIBUTE_USER_USERNAME]: finalScopeData.user?.username,
185
+ }
186
+ : {}),
187
+ });
188
+ }
189
+
190
+ /**
191
+ * Adds span attributes from the scopes' contexts
192
+ * TODO: It's not set in stone yet if we actually want to flatmap contexts into span attributes.
193
+ * For now we do it but not yet extra or tags. It's still TBD how to proceed here.
194
+ */
195
+ function applyScopeToSegmentSpan(segmentSpan, serializedSegmentSpan, client) {
196
+ const { isolationScope, scope } = core.getCapturedScopesOnSpan(segmentSpan);
197
+ const finalScopeData = getFinalScopeData(isolationScope, scope);
198
+
199
+ const browserRequestData = helpers.getHttpRequestData();
200
+
201
+ const tags = finalScopeData.tags ?? {};
202
+
203
+ let contextAttributes = {};
204
+ Object.keys(finalScopeData.contexts).forEach(key => {
205
+ const context = finalScopeData.contexts[key];
206
+ if (context) {
207
+ contextAttributes = { ...contextAttributes, ...core.attributesFromObject(context) };
208
+ }
209
+ });
210
+
211
+ const extraAttributes = core.attributesFromObject(finalScopeData.extra);
212
+
213
+ setAttributesIfNotPresent(segmentSpan, Object.keys(serializedSegmentSpan.attributes ?? {}), {
214
+ [core.SEMANTIC_ATTRIBUTE_URL_FULL]: browserRequestData.url,
215
+ ...core.httpHeadersToSpanAttributes(browserRequestData.headers, client.getOptions().sendDefaultPii ?? false),
216
+ ...tags,
217
+ ...contextAttributes,
218
+ ...extraAttributes,
219
+ });
220
+ }
221
+
222
+ function applyBeforeSendSpanCallback(span, beforeSendSpan) {
223
+ const modifedSpan = beforeSendSpan(span);
224
+ if (!modifedSpan) {
225
+ core.showSpanDropWarning();
226
+ return span;
227
+ }
228
+ return modifedSpan;
229
+ }
230
+
231
+ function setAttributesIfNotPresent(span, originalAttributeKeys, newAttributes) {
232
+ Object.keys(newAttributes).forEach(key => {
233
+ if (!originalAttributeKeys.includes(key)) {
234
+ span.setAttribute(key, newAttributes[key]);
235
+ }
236
+ });
237
+ }
238
+
239
+ // TODO: Extract this to a helper in core. It's used in multiple places.
240
+ function getFinalScopeData(isolationScope, scope) {
241
+ const finalScopeData = core.getGlobalScope().getScopeData();
242
+ if (isolationScope) {
243
+ core.mergeScopeData(finalScopeData, isolationScope.getScopeData());
244
+ }
245
+ if (scope) {
246
+ core.mergeScopeData(finalScopeData, scope.getScopeData());
247
+ }
248
+ return finalScopeData;
249
+ }
250
+
251
+ exports.spanStreamingIntegration = spanStreamingIntegration;
252
+ //# sourceMappingURL=spanstreaming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spanstreaming.js","sources":["../../../../src/integrations/spanstreaming.ts"],"sourcesContent":["import type { Client, IntegrationFn, Scope, ScopeData, Span, SpanAttributes, SpanV2JSON } from '@sentry/core';\nimport {\n attributesFromObject,\n createSpanV2Envelope,\n debug,\n defineIntegration,\n getCapturedScopesOnSpan,\n getDynamicSamplingContextFromSpan,\n getGlobalScope,\n getRootSpan as getSegmentSpan,\n httpHeadersToSpanAttributes,\n isV2BeforeSendSpanCallback,\n mergeScopeData,\n reparentChildSpans,\n SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME,\n SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT,\n SEMANTIC_ATTRIBUTE_SENTRY_RELEASE,\n SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME,\n SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION,\n SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME,\n SEMANTIC_ATTRIBUTE_URL_FULL,\n SEMANTIC_ATTRIBUTE_USER_EMAIL,\n SEMANTIC_ATTRIBUTE_USER_ID,\n SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS,\n SEMANTIC_ATTRIBUTE_USER_USERNAME,\n shouldIgnoreSpan,\n showSpanDropWarning,\n spanToV2JSON,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { getHttpRequestData } from '../helpers';\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 const options: SpanStreamingOptions = {\n ...userOptions,\n batchLimit:\n userOptions?.batchLimit && userOptions.batchLimit <= 1000 && userOptions.batchLimit >= 1\n ? userOptions.batchLimit\n : 1000,\n };\n\n // key: traceId-segmentSpanId\n const spanTreeMap = new Map<string, Set<Span>>();\n\n return {\n name: 'SpanStreaming',\n setup(client) {\n const clientOptions = client.getOptions();\n const beforeSendSpan = clientOptions.beforeSendSpan;\n\n const initialMessage = 'spanStreamingIntegration requires';\n const fallbackMsg = 'Falling back to static trace lifecycle.';\n\n if (clientOptions.traceLifecycle !== 'stream') {\n DEBUG_BUILD && debug.warn(`${initialMessage} \\`traceLifecycle\\` to be set to \"stream\"! ${fallbackMsg}`);\n return;\n }\n\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 client.on('spanEnd', span => {\n const spanTreeMapKey = getSpanTreeMapKey(span);\n const spanBuffer = spanTreeMap.get(spanTreeMapKey);\n if (spanBuffer) {\n spanBuffer.add(span);\n } else {\n spanTreeMap.set(spanTreeMapKey, new Set([span]));\n }\n });\n\n // For now, we send all spans on local segment (root) span end.\n // TODO: This will change once we have more concrete ideas about a universal SDK data buffer.\n client.on('segmentSpanEnd', segmentSpan => {\n processAndSendSpans(segmentSpan, {\n spanTreeMap: spanTreeMap,\n client,\n batchLimit: options.batchLimit,\n beforeSendSpan,\n });\n });\n },\n };\n}) satisfies IntegrationFn);\n\ninterface SpanProcessingOptions {\n client: Client;\n spanTreeMap: Map<string, Set<Span>>;\n batchLimit: number;\n beforeSendSpan: ((span: SpanV2JSON) => SpanV2JSON) | undefined;\n}\n\n/**\n * Just the traceid alone isn't enough because there can be multiple span trees with the same traceid.\n */\nfunction getSpanTreeMapKey(span: Span): string {\n return `${span.spanContext().traceId}-${getSegmentSpan(span).spanContext().spanId}`;\n}\n\nfunction processAndSendSpans(\n segmentSpan: Span,\n { client, spanTreeMap, batchLimit, beforeSendSpan }: SpanProcessingOptions,\n): void {\n const traceId = segmentSpan.spanContext().traceId;\n const spanTreeMapKey = getSpanTreeMapKey(segmentSpan);\n const spansOfTrace = spanTreeMap.get(spanTreeMapKey);\n\n if (!spansOfTrace?.size) {\n spanTreeMap.delete(spanTreeMapKey);\n return;\n }\n\n const segmentSpanJson = spanToV2JSON(segmentSpan);\n\n for (const span of spansOfTrace) {\n applyCommonSpanAttributes(span, segmentSpanJson, client);\n }\n\n applyScopeToSegmentSpan(segmentSpan, segmentSpanJson, client);\n\n // TODO: Apply scope data and contexts to segment span\n\n const { ignoreSpans } = client.getOptions();\n\n // 1. Check if the entire span tree is ignored by ignoreSpans\n if (ignoreSpans?.length && shouldIgnoreSpan(segmentSpanJson, ignoreSpans)) {\n client.recordDroppedEvent('before_send', 'span', spansOfTrace.size);\n spanTreeMap.delete(spanTreeMapKey);\n return;\n }\n\n const serializedSpans = Array.from(spansOfTrace ?? []).map(s => {\n const serialized = spanToV2JSON(s);\n // remove internal span attributes we don't need to send.\n delete serialized.attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME];\n return serialized;\n });\n\n const processedSpans = [];\n let ignoredSpanCount = 0;\n\n for (const span of serializedSpans) {\n // 2. Check if child spans should be ignored\n const isChildSpan = span.span_id !== segmentSpan.spanContext().spanId;\n if (ignoreSpans?.length && isChildSpan && shouldIgnoreSpan(span, ignoreSpans)) {\n reparentChildSpans(serializedSpans, span);\n ignoredSpanCount++;\n // drop this span by not adding it to the processedSpans array\n continue;\n }\n\n // 3. Apply beforeSendSpan callback\n const processedSpan = beforeSendSpan ? applyBeforeSendSpanCallback(span, beforeSendSpan) : span;\n processedSpans.push(processedSpan);\n }\n\n if (ignoredSpanCount) {\n client.recordDroppedEvent('before_send', 'span', ignoredSpanCount);\n }\n\n const batches: SpanV2JSON[][] = [];\n for (let i = 0; i < processedSpans.length; i += batchLimit) {\n batches.push(processedSpans.slice(i, i + batchLimit));\n }\n\n DEBUG_BUILD && debug.log(`Sending trace ${traceId} in ${batches.length} batch${batches.length === 1 ? '' : 'es'}`);\n\n const dsc = getDynamicSamplingContextFromSpan(segmentSpan);\n\n for (const batch of batches) {\n const envelope = createSpanV2Envelope(batch, dsc, client);\n // no need to handle client reports for network errors,\n // buffer overflows or rate limiting here. All of this is handled\n // by client and transport.\n client.sendEnvelope(envelope).then(null, reason => {\n DEBUG_BUILD && debug.error('Error while sending span stream envelope:', reason);\n });\n }\n\n spanTreeMap.delete(spanTreeMapKey);\n}\n\nfunction applyCommonSpanAttributes(span: Span, serializedSegmentSpan: SpanV2JSON, client: Client): void {\n const sdk = client.getSdkMetadata();\n const { release, environment, sendDefaultPii } = client.getOptions();\n\n const { isolationScope: spanIsolationScope, scope: spanScope } = getCapturedScopesOnSpan(span);\n\n const originalAttributeKeys = Object.keys(spanToV2JSON(span).attributes ?? {});\n\n const finalScopeData = getFinalScopeData(spanIsolationScope, spanScope);\n\n // avoid overwriting any previously set attributes (from users or potentially our SDK instrumentation)\n setAttributesIfNotPresent(span, originalAttributeKeys, {\n [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: release,\n [SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: environment,\n [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME]: serializedSegmentSpan.name,\n [SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME]: sdk?.sdk?.name,\n [SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION]: sdk?.sdk?.version,\n ...(sendDefaultPii\n ? {\n [SEMANTIC_ATTRIBUTE_USER_ID]: finalScopeData.user?.id,\n [SEMANTIC_ATTRIBUTE_USER_EMAIL]: finalScopeData.user?.email,\n [SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS]: finalScopeData.user?.ip_address ?? undefined,\n [SEMANTIC_ATTRIBUTE_USER_USERNAME]: finalScopeData.user?.username,\n }\n : {}),\n });\n}\n\n/**\n * Adds span attributes from the scopes' contexts\n * TODO: It's not set in stone yet if we actually want to flatmap contexts into span attributes.\n * For now we do it but not yet extra or tags. It's still TBD how to proceed here.\n */\nfunction applyScopeToSegmentSpan(segmentSpan: Span, serializedSegmentSpan: SpanV2JSON, client: Client): void {\n const { isolationScope, scope } = getCapturedScopesOnSpan(segmentSpan);\n const finalScopeData = getFinalScopeData(isolationScope, scope);\n\n const browserRequestData = getHttpRequestData();\n\n const tags = finalScopeData.tags ?? {};\n\n let contextAttributes = {};\n Object.keys(finalScopeData.contexts).forEach(key => {\n const context = finalScopeData.contexts[key];\n if (context) {\n contextAttributes = { ...contextAttributes, ...attributesFromObject(context) };\n }\n });\n\n const extraAttributes = attributesFromObject(finalScopeData.extra);\n\n setAttributesIfNotPresent(segmentSpan, Object.keys(serializedSegmentSpan.attributes ?? {}), {\n [SEMANTIC_ATTRIBUTE_URL_FULL]: browserRequestData.url,\n ...httpHeadersToSpanAttributes(browserRequestData.headers, client.getOptions().sendDefaultPii ?? false),\n ...tags,\n ...contextAttributes,\n ...extraAttributes,\n });\n}\n\nfunction applyBeforeSendSpanCallback(span: SpanV2JSON, beforeSendSpan: (span: SpanV2JSON) => SpanV2JSON): SpanV2JSON {\n const modifedSpan = beforeSendSpan(span);\n if (!modifedSpan) {\n showSpanDropWarning();\n return span;\n }\n return modifedSpan;\n}\n\nfunction setAttributesIfNotPresent(span: Span, originalAttributeKeys: string[], newAttributes: SpanAttributes): void {\n Object.keys(newAttributes).forEach(key => {\n if (!originalAttributeKeys.includes(key)) {\n span.setAttribute(key, newAttributes[key]);\n }\n });\n}\n\n// TODO: Extract this to a helper in core. It's used in multiple places.\nfunction getFinalScopeData(isolationScope: Scope | undefined, scope: Scope | undefined): ScopeData {\n const finalScopeData = getGlobalScope().getScopeData();\n if (isolationScope) {\n mergeScopeData(finalScopeData, isolationScope.getScopeData());\n }\n if (scope) {\n mergeScopeData(finalScopeData, scope.getScopeData());\n }\n return finalScopeData;\n}\n"],"names":["defineIntegration","DEBUG_BUILD","debug","isV2BeforeSendSpanCallback","getSegmentSpan","spanToV2JSON","shouldIgnoreSpan","SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME","reparentChildSpans","getDynamicSamplingContextFromSpan","createSpanV2Envelope","getCapturedScopesOnSpan","SEMANTIC_ATTRIBUTE_SENTRY_RELEASE","SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT","SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME","SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME","SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION","SEMANTIC_ATTRIBUTE_USER_ID","SEMANTIC_ATTRIBUTE_USER_EMAIL","SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS","SEMANTIC_ATTRIBUTE_USER_USERNAME","getHttpRequestData","attributesFromObject","SEMANTIC_ATTRIBUTE_URL_FULL","httpHeadersToSpanAttributes","showSpanDropWarning","getGlobalScope","mergeScopeData"],"mappings":"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"}
@@ -75,6 +75,7 @@ const browserTracingIntegration = ((options = {}) => {
75
75
  consistentTraceSampling,
76
76
  enableReportPageLoaded,
77
77
  onRequestSpanStart,
78
+ onRequestSpanEnd,
78
79
  } = {
79
80
  ...DEFAULT_BROWSER_TRACING_OPTIONS,
80
81
  ...options,
@@ -402,6 +403,7 @@ const browserTracingIntegration = ((options = {}) => {
402
403
  shouldCreateSpanForRequest,
403
404
  enableHTTPTimings,
404
405
  onRequestSpanStart,
406
+ onRequestSpanEnd,
405
407
  });
406
408
  },
407
409
  };