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