@sentry/profiling-node 7.107.0 → 8.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -7,33 +7,26 @@ const nodeAbi = require('node-abi');
7
7
  const process$1 = require('process');
8
8
  const worker_threads = require('worker_threads');
9
9
 
10
- /******************************************************************************
11
- Copyright (c) Microsoft Corporation.
12
-
13
- Permission to use, copy, modify, and/or distribute this software for any
14
- purpose with or without fee is hereby granted.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
17
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
19
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22
- PERFORMANCE OF THIS SOFTWARE.
23
- ***************************************************************************** */
24
-
25
- function __awaiter(thisArg, _arguments, P, generator) {
26
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
- return new (P || (P = Promise))(function (resolve, reject) {
28
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
- step((generator = generator.apply(thisArg, _arguments || [])).next());
32
- });
33
- }
34
-
35
10
  // eslint-disable-next-line @typescript-eslint/unbound-method
36
11
  const objectToString = Object.prototype.toString;
12
+
13
+ /**
14
+ * Checks whether given value's type is one of a few Error or Error-like
15
+ * {@link isError}.
16
+ *
17
+ * @param wat A value to be checked.
18
+ * @returns A boolean representing the result.
19
+ */
20
+ function isError(wat) {
21
+ switch (objectToString.call(wat)) {
22
+ case '[object Error]':
23
+ case '[object Exception]':
24
+ case '[object DOMException]':
25
+ return true;
26
+ default:
27
+ return isInstanceOf(wat, Error);
28
+ }
29
+ }
37
30
  /**
38
31
  * Checks whether given value is an instance of the given built-in class.
39
32
  *
@@ -45,6 +38,17 @@ function isBuiltin(wat, className) {
45
38
  return objectToString.call(wat) === `[object ${className}]`;
46
39
  }
47
40
 
41
+ /**
42
+ * Checks whether given value's type is a string
43
+ * {@link isString}.
44
+ *
45
+ * @param wat A value to be checked.
46
+ * @returns A boolean representing the result.
47
+ */
48
+ function isString(wat) {
49
+ return isBuiltin(wat, 'String');
50
+ }
51
+
48
52
  /**
49
53
  * Checks whether given value's type is an object literal, or a class instance.
50
54
  * {@link isPlainObject}.
@@ -56,6 +60,28 @@ function isPlainObject(wat) {
56
60
  return isBuiltin(wat, 'Object');
57
61
  }
58
62
 
63
+ /**
64
+ * Checks whether given value's type is an Event instance
65
+ * {@link isEvent}.
66
+ *
67
+ * @param wat A value to be checked.
68
+ * @returns A boolean representing the result.
69
+ */
70
+ function isEvent(wat) {
71
+ return typeof Event !== 'undefined' && isInstanceOf(wat, Event);
72
+ }
73
+
74
+ /**
75
+ * Checks whether given value's type is an Element instance
76
+ * {@link isElement}.
77
+ *
78
+ * @param wat A value to be checked.
79
+ * @returns A boolean representing the result.
80
+ */
81
+ function isElement(wat) {
82
+ return typeof Element !== 'undefined' && isInstanceOf(wat, Element);
83
+ }
84
+
59
85
  /**
60
86
  * Checks whether given value has a then function.
61
87
  * @param wat A value to be checked.
@@ -65,6 +91,55 @@ function isThenable(wat) {
65
91
  return Boolean(wat && wat.then && typeof wat.then === 'function');
66
92
  }
67
93
 
94
+ /**
95
+ * Checks whether given value's type is a SyntheticEvent
96
+ * {@link isSyntheticEvent}.
97
+ *
98
+ * @param wat A value to be checked.
99
+ * @returns A boolean representing the result.
100
+ */
101
+ function isSyntheticEvent(wat) {
102
+ return isPlainObject(wat) && 'nativeEvent' in wat && 'preventDefault' in wat && 'stopPropagation' in wat;
103
+ }
104
+
105
+ /**
106
+ * Checks whether given value is NaN
107
+ * {@link isNaN}.
108
+ *
109
+ * @param wat A value to be checked.
110
+ * @returns A boolean representing the result.
111
+ */
112
+ function isNaN$1(wat) {
113
+ return typeof wat === 'number' && wat !== wat;
114
+ }
115
+
116
+ /**
117
+ * Checks whether given value's type is an instance of provided constructor.
118
+ * {@link isInstanceOf}.
119
+ *
120
+ * @param wat A value to be checked.
121
+ * @param base A constructor to be used in a check.
122
+ * @returns A boolean representing the result.
123
+ */
124
+ function isInstanceOf(wat, base) {
125
+ try {
126
+ return wat instanceof base;
127
+ } catch (_e) {
128
+ return false;
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Checks whether given value's type is a Vue ViewModel.
134
+ *
135
+ * @param wat A value to be checked.
136
+ * @returns A boolean representing the result.
137
+ */
138
+ function isVueViewModel(wat) {
139
+ // Not using Object.prototype.toString because in Vue 3 it would read the instance's Symbol(Symbol.toStringTag) property.
140
+ return !!(typeof wat === 'object' && wat !== null && ((wat ).__isVue || (wat )._isVue));
141
+ }
142
+
68
143
  /** Internal global with common properties and Sentry extensions */
69
144
 
70
145
  // The code below for 'isGlobalObj' and 'GLOBAL_OBJ' was copied from core-js before modification
@@ -108,6 +183,13 @@ const GLOBAL_OBJ =
108
183
  })() ||
109
184
  {};
110
185
 
186
+ /**
187
+ * @deprecated Use GLOBAL_OBJ instead or WINDOW from @sentry/browser. This will be removed in v8
188
+ */
189
+ function getGlobalObject() {
190
+ return GLOBAL_OBJ ;
191
+ }
192
+
111
193
  /**
112
194
  * Returns a global singleton contained in the global `__SENTRY__` object.
113
195
  *
@@ -126,6 +208,128 @@ function getGlobalSingleton(name, creator, obj) {
126
208
  return singleton;
127
209
  }
128
210
 
211
+ // eslint-disable-next-line deprecation/deprecation
212
+ const WINDOW$5 = getGlobalObject();
213
+
214
+ const DEFAULT_MAX_STRING_LENGTH = 80;
215
+
216
+ /**
217
+ * Given a child DOM element, returns a query-selector statement describing that
218
+ * and its ancestors
219
+ * e.g. [HTMLElement] => body > div > input#foo.btn[name=baz]
220
+ * @returns generated DOM path
221
+ */
222
+ function htmlTreeAsString(
223
+ elem,
224
+ options = {},
225
+ ) {
226
+ if (!elem) {
227
+ return '<unknown>';
228
+ }
229
+
230
+ // try/catch both:
231
+ // - accessing event.target (see getsentry/raven-js#838, #768)
232
+ // - `htmlTreeAsString` because it's complex, and just accessing the DOM incorrectly
233
+ // - can throw an exception in some circumstances.
234
+ try {
235
+ let currentElem = elem ;
236
+ const MAX_TRAVERSE_HEIGHT = 5;
237
+ const out = [];
238
+ let height = 0;
239
+ let len = 0;
240
+ const separator = ' > ';
241
+ const sepLength = separator.length;
242
+ let nextStr;
243
+ const keyAttrs = Array.isArray(options) ? options : options.keyAttrs;
244
+ const maxStringLength = (!Array.isArray(options) && options.maxStringLength) || DEFAULT_MAX_STRING_LENGTH;
245
+
246
+ while (currentElem && height++ < MAX_TRAVERSE_HEIGHT) {
247
+ nextStr = _htmlElementAsString(currentElem, keyAttrs);
248
+ // bail out if
249
+ // - nextStr is the 'html' element
250
+ // - the length of the string that would be created exceeds maxStringLength
251
+ // (ignore this limit if we are on the first iteration)
252
+ if (nextStr === 'html' || (height > 1 && len + out.length * sepLength + nextStr.length >= maxStringLength)) {
253
+ break;
254
+ }
255
+
256
+ out.push(nextStr);
257
+
258
+ len += nextStr.length;
259
+ currentElem = currentElem.parentNode;
260
+ }
261
+
262
+ return out.reverse().join(separator);
263
+ } catch (_oO) {
264
+ return '<unknown>';
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Returns a simple, query-selector representation of a DOM element
270
+ * e.g. [HTMLElement] => input#foo.btn[name=baz]
271
+ * @returns generated DOM path
272
+ */
273
+ function _htmlElementAsString(el, keyAttrs) {
274
+ const elem = el
275
+
276
+ ;
277
+
278
+ const out = [];
279
+ let className;
280
+ let classes;
281
+ let key;
282
+ let attr;
283
+ let i;
284
+
285
+ if (!elem || !elem.tagName) {
286
+ return '';
287
+ }
288
+
289
+ // @ts-expect-error WINDOW has HTMLElement
290
+ if (WINDOW$5.HTMLElement) {
291
+ // If using the component name annotation plugin, this value may be available on the DOM node
292
+ if (elem instanceof HTMLElement && elem.dataset && elem.dataset['sentryComponent']) {
293
+ return elem.dataset['sentryComponent'];
294
+ }
295
+ }
296
+
297
+ out.push(elem.tagName.toLowerCase());
298
+
299
+ // Pairs of attribute keys defined in `serializeAttribute` and their values on element.
300
+ const keyAttrPairs =
301
+ keyAttrs && keyAttrs.length
302
+ ? keyAttrs.filter(keyAttr => elem.getAttribute(keyAttr)).map(keyAttr => [keyAttr, elem.getAttribute(keyAttr)])
303
+ : null;
304
+
305
+ if (keyAttrPairs && keyAttrPairs.length) {
306
+ keyAttrPairs.forEach(keyAttrPair => {
307
+ out.push(`[${keyAttrPair[0]}="${keyAttrPair[1]}"]`);
308
+ });
309
+ } else {
310
+ if (elem.id) {
311
+ out.push(`#${elem.id}`);
312
+ }
313
+
314
+ className = elem.className;
315
+ if (className && isString(className)) {
316
+ classes = className.split(/\s+/);
317
+ for (i = 0; i < classes.length; i++) {
318
+ out.push(`.${classes[i]}`);
319
+ }
320
+ }
321
+ }
322
+ const allowedAttrs = ['aria-label', 'type', 'name', 'title', 'alt'];
323
+ for (i = 0; i < allowedAttrs.length; i++) {
324
+ key = allowedAttrs[i];
325
+ attr = elem.getAttribute(key);
326
+ if (attr) {
327
+ out.push(`[${key}="${attr}"]`);
328
+ }
329
+ }
330
+ return out.join('');
331
+ }
332
+
129
333
  /**
130
334
  * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code.
131
335
  *
@@ -220,21 +424,97 @@ function makeLogger() {
220
424
 
221
425
  const logger = makeLogger();
222
426
 
427
+ const defaultFunctionName = '<anonymous>';
428
+
429
+ /**
430
+ * Safely extract function name from itself
431
+ */
432
+ function getFunctionName(fn) {
433
+ try {
434
+ if (!fn || typeof fn !== 'function') {
435
+ return defaultFunctionName;
436
+ }
437
+ return fn.name || defaultFunctionName;
438
+ } catch (e) {
439
+ // Just accessing custom props in some Selenium environments
440
+ // can cause a "Permission denied" exception (see raven-js#495).
441
+ return defaultFunctionName;
442
+ }
443
+ }
444
+
223
445
  /**
224
- * Renders the string representation of this Dsn.
446
+ * This extracts the original function if available. See
447
+ * `markFunctionWrapped` for more information.
225
448
  *
226
- * By default, this will render the public representation without the password
227
- * component. To get the deprecated private representation, set `withPassword`
228
- * to true.
449
+ * @param func the function to unwrap
450
+ * @returns the unwrapped version of the function if available.
451
+ */
452
+ function getOriginalFunction(func) {
453
+ return func.__sentry_original__;
454
+ }
455
+
456
+ /**
457
+ * Transforms any `Error` or `Event` into a plain object with all of their enumerable properties, and some of their
458
+ * non-enumerable properties attached.
229
459
  *
230
- * @param withPassword When set to true, the password will be included.
460
+ * @param value Initial source that we have to transform in order for it to be usable by the serializer
461
+ * @returns An Event or Error turned into an object - or the value argurment itself, when value is neither an Event nor
462
+ * an Error.
231
463
  */
232
- function dsnToString(dsn, withPassword = false) {
233
- const { host, path, pass, port, projectId, protocol, publicKey } = dsn;
234
- return (
235
- `${protocol}://${publicKey}${withPassword && pass ? `:${pass}` : ''}` +
236
- `@${host}${port ? `:${port}` : ''}/${path ? `${path}/` : path}${projectId}`
237
- );
464
+ function convertToPlainObject(
465
+ value,
466
+ )
467
+
468
+ {
469
+ if (isError(value)) {
470
+ return {
471
+ message: value.message,
472
+ name: value.name,
473
+ stack: value.stack,
474
+ ...getOwnProperties(value),
475
+ };
476
+ } else if (isEvent(value)) {
477
+ const newObj
478
+
479
+ = {
480
+ type: value.type,
481
+ target: serializeEventTarget(value.target),
482
+ currentTarget: serializeEventTarget(value.currentTarget),
483
+ ...getOwnProperties(value),
484
+ };
485
+
486
+ if (typeof CustomEvent !== 'undefined' && isInstanceOf(value, CustomEvent)) {
487
+ newObj.detail = value.detail;
488
+ }
489
+
490
+ return newObj;
491
+ } else {
492
+ return value;
493
+ }
494
+ }
495
+
496
+ /** Creates a string representation of the target of an `Event` object */
497
+ function serializeEventTarget(target) {
498
+ try {
499
+ return isElement(target) ? htmlTreeAsString(target) : Object.prototype.toString.call(target);
500
+ } catch (_oO) {
501
+ return '<unknown>';
502
+ }
503
+ }
504
+
505
+ /** Filters out all but an object's own properties */
506
+ function getOwnProperties(obj) {
507
+ if (typeof obj === 'object' && obj !== null) {
508
+ const extractedProps = {};
509
+ for (const property in obj) {
510
+ if (Object.prototype.hasOwnProperty.call(obj, property)) {
511
+ extractedProps[property] = (obj )[property];
512
+ }
513
+ }
514
+ return extractedProps;
515
+ } else {
516
+ return {};
517
+ }
238
518
  }
239
519
 
240
520
  /**
@@ -346,200 +626,693 @@ function uuid4() {
346
626
  );
347
627
  }
348
628
 
629
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
630
+ /* eslint-disable @typescript-eslint/no-explicit-any */
631
+
349
632
  /**
350
- * Checks whether the given input is already an array, and if it isn't, wraps it in one.
351
- *
352
- * @param maybeArray Input to turn into an array, if necessary
353
- * @returns The input, if already an array, or an array with the input as the only element, if not
633
+ * Helper to decycle json objects
354
634
  */
355
- function arrayify(maybeArray) {
356
- return Array.isArray(maybeArray) ? maybeArray : [maybeArray];
357
- }
635
+ function memoBuilder() {
636
+ const hasWeakSet = typeof WeakSet === 'function';
637
+ const inner = hasWeakSet ? new WeakSet() : [];
638
+ function memoize(obj) {
639
+ if (hasWeakSet) {
640
+ if (inner.has(obj)) {
641
+ return true;
642
+ }
643
+ inner.add(obj);
644
+ return false;
645
+ }
646
+ // eslint-disable-next-line @typescript-eslint/prefer-for-of
647
+ for (let i = 0; i < inner.length; i++) {
648
+ const value = inner[i];
649
+ if (value === obj) {
650
+ return true;
651
+ }
652
+ }
653
+ inner.push(obj);
654
+ return false;
655
+ }
358
656
 
359
- /* eslint-disable @typescript-eslint/explicit-function-return-type */
657
+ function unmemoize(obj) {
658
+ if (hasWeakSet) {
659
+ inner.delete(obj);
660
+ } else {
661
+ for (let i = 0; i < inner.length; i++) {
662
+ if (inner[i] === obj) {
663
+ inner.splice(i, 1);
664
+ break;
665
+ }
666
+ }
667
+ }
668
+ }
669
+ return [memoize, unmemoize];
670
+ }
360
671
 
361
- /** SyncPromise internal states */
362
- var States; (function (States) {
363
- /** Pending */
364
- const PENDING = 0; States[States["PENDING"] = PENDING] = "PENDING";
365
- /** Resolved / OK */
366
- const RESOLVED = 1; States[States["RESOLVED"] = RESOLVED] = "RESOLVED";
367
- /** Rejected / Error */
368
- const REJECTED = 2; States[States["REJECTED"] = REJECTED] = "REJECTED";
369
- })(States || (States = {}));
672
+ /**
673
+ * Recursively normalizes the given object.
674
+ *
675
+ * - Creates a copy to prevent original input mutation
676
+ * - Skips non-enumerable properties
677
+ * - When stringifying, calls `toJSON` if implemented
678
+ * - Removes circular references
679
+ * - Translates non-serializable values (`undefined`/`NaN`/functions) to serializable format
680
+ * - Translates known global objects/classes to a string representations
681
+ * - Takes care of `Error` object serialization
682
+ * - Optionally limits depth of final output
683
+ * - Optionally limits number of properties/elements included in any single object/array
684
+ *
685
+ * @param input The object to be normalized.
686
+ * @param depth The max depth to which to normalize the object. (Anything deeper stringified whole.)
687
+ * @param maxProperties The max number of elements or properties to be included in any single array or
688
+ * object in the normallized output.
689
+ * @returns A normalized version of the object, or `"**non-serializable**"` if any errors are thrown during normalization.
690
+ */
691
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
692
+ function normalize(input, depth = 100, maxProperties = +Infinity) {
693
+ try {
694
+ // since we're at the outermost level, we don't provide a key
695
+ return visit('', input, depth, maxProperties);
696
+ } catch (err) {
697
+ return { ERROR: `**non-serializable** (${err})` };
698
+ }
699
+ }
370
700
 
371
701
  /**
372
- * Thenable class that behaves like a Promise and follows it's interface
373
- * but is not async internally
374
- */
375
- class SyncPromise {
702
+ * Visits a node to perform normalization on it
703
+ *
704
+ * @param key The key corresponding to the given node
705
+ * @param value The node to be visited
706
+ * @param depth Optional number indicating the maximum recursion depth
707
+ * @param maxProperties Optional maximum number of properties/elements included in any single object/array
708
+ * @param memo Optional Memo class handling decycling
709
+ */
710
+ function visit(
711
+ key,
712
+ value,
713
+ depth = +Infinity,
714
+ maxProperties = +Infinity,
715
+ memo = memoBuilder(),
716
+ ) {
717
+ const [memoize, unmemoize] = memo;
376
718
 
377
- constructor(
378
- executor,
379
- ) {SyncPromise.prototype.__init.call(this);SyncPromise.prototype.__init2.call(this);SyncPromise.prototype.__init3.call(this);SyncPromise.prototype.__init4.call(this);
380
- this._state = States.PENDING;
381
- this._handlers = [];
719
+ // Get the simple cases out of the way first
720
+ if (
721
+ value == null || // this matches null and undefined -> eqeq not eqeqeq
722
+ (['number', 'boolean', 'string'].includes(typeof value) && !isNaN$1(value))
723
+ ) {
724
+ return value ;
725
+ }
382
726
 
383
- try {
384
- executor(this._resolve, this._reject);
385
- } catch (e) {
386
- this._reject(e);
387
- }
727
+ const stringified = stringifyValue(key, value);
728
+
729
+ // Anything we could potentially dig into more (objects or arrays) will have come back as `"[object XXXX]"`.
730
+ // Everything else will have already been serialized, so if we don't see that pattern, we're done.
731
+ if (!stringified.startsWith('[object ')) {
732
+ return stringified;
388
733
  }
389
734
 
390
- /** JSDoc */
391
- then(
392
- onfulfilled,
393
- onrejected,
394
- ) {
395
- return new SyncPromise((resolve, reject) => {
396
- this._handlers.push([
397
- false,
398
- result => {
399
- if (!onfulfilled) {
400
- // TODO: ¯\_(ツ)_/¯
401
- // TODO: FIXME
402
- resolve(result );
403
- } else {
404
- try {
405
- resolve(onfulfilled(result));
406
- } catch (e) {
407
- reject(e);
408
- }
409
- }
410
- },
411
- reason => {
412
- if (!onrejected) {
413
- reject(reason);
414
- } else {
415
- try {
416
- resolve(onrejected(reason));
417
- } catch (e) {
418
- reject(e);
419
- }
420
- }
421
- },
422
- ]);
423
- this._executeHandlers();
424
- });
735
+ // From here on, we can assert that `value` is either an object or an array.
736
+
737
+ // Do not normalize objects that we know have already been normalized. As a general rule, the
738
+ // "__sentry_skip_normalization__" property should only be used sparingly and only should only be set on objects that
739
+ // have already been normalized.
740
+ if ((value )['__sentry_skip_normalization__']) {
741
+ return value ;
425
742
  }
426
743
 
427
- /** JSDoc */
428
- catch(
429
- onrejected,
430
- ) {
431
- return this.then(val => val, onrejected);
744
+ // We can set `__sentry_override_normalization_depth__` on an object to ensure that from there
745
+ // We keep a certain amount of depth.
746
+ // This should be used sparingly, e.g. we use it for the redux integration to ensure we get a certain amount of state.
747
+ const remainingDepth =
748
+ typeof (value )['__sentry_override_normalization_depth__'] === 'number'
749
+ ? ((value )['__sentry_override_normalization_depth__'] )
750
+ : depth;
751
+
752
+ // We're also done if we've reached the max depth
753
+ if (remainingDepth === 0) {
754
+ // At this point we know `serialized` is a string of the form `"[object XXXX]"`. Clean it up so it's just `"[XXXX]"`.
755
+ return stringified.replace('object ', '');
432
756
  }
433
757
 
434
- /** JSDoc */
435
- finally(onfinally) {
436
- return new SyncPromise((resolve, reject) => {
437
- let val;
438
- let isRejected;
758
+ // If we've already visited this branch, bail out, as it's circular reference. If not, note that we're seeing it now.
759
+ if (memoize(value)) {
760
+ return '[Circular ~]';
761
+ }
439
762
 
440
- return this.then(
441
- value => {
442
- isRejected = false;
443
- val = value;
444
- if (onfinally) {
445
- onfinally();
446
- }
447
- },
448
- reason => {
449
- isRejected = true;
450
- val = reason;
451
- if (onfinally) {
452
- onfinally();
453
- }
454
- },
455
- ).then(() => {
456
- if (isRejected) {
457
- reject(val);
458
- return;
459
- }
763
+ // If the value has a `toJSON` method, we call it to extract more information
764
+ const valueWithToJSON = value ;
765
+ if (valueWithToJSON && typeof valueWithToJSON.toJSON === 'function') {
766
+ try {
767
+ const jsonValue = valueWithToJSON.toJSON();
768
+ // We need to normalize the return value of `.toJSON()` in case it has circular references
769
+ return visit('', jsonValue, remainingDepth - 1, maxProperties, memo);
770
+ } catch (err) {
771
+ // pass (The built-in `toJSON` failed, but we can still try to do it ourselves)
772
+ }
773
+ }
460
774
 
461
- resolve(val );
462
- });
463
- });
775
+ // At this point we know we either have an object or an array, we haven't seen it before, and we're going to recurse
776
+ // because we haven't yet reached the max depth. Create an accumulator to hold the results of visiting each
777
+ // property/entry, and keep track of the number of items we add to it.
778
+ const normalized = (Array.isArray(value) ? [] : {}) ;
779
+ let numAdded = 0;
780
+
781
+ // Before we begin, convert`Error` and`Event` instances into plain objects, since some of each of their relevant
782
+ // properties are non-enumerable and otherwise would get missed.
783
+ const visitable = convertToPlainObject(value );
784
+
785
+ for (const visitKey in visitable) {
786
+ // Avoid iterating over fields in the prototype if they've somehow been exposed to enumeration.
787
+ if (!Object.prototype.hasOwnProperty.call(visitable, visitKey)) {
788
+ continue;
789
+ }
790
+
791
+ if (numAdded >= maxProperties) {
792
+ normalized[visitKey] = '[MaxProperties ~]';
793
+ break;
794
+ }
795
+
796
+ // Recursively visit all the child nodes
797
+ const visitValue = visitable[visitKey];
798
+ normalized[visitKey] = visit(visitKey, visitValue, remainingDepth - 1, maxProperties, memo);
799
+
800
+ numAdded++;
464
801
  }
465
802
 
466
- /** JSDoc */
467
- __init() {this._resolve = (value) => {
468
- this._setResult(States.RESOLVED, value);
469
- };}
803
+ // Once we've visited all the branches, remove the parent from memo storage
804
+ unmemoize(value);
470
805
 
471
- /** JSDoc */
472
- __init2() {this._reject = (reason) => {
473
- this._setResult(States.REJECTED, reason);
474
- };}
806
+ // Return accumulated values
807
+ return normalized;
808
+ }
475
809
 
476
- /** JSDoc */
477
- __init3() {this._setResult = (state, value) => {
478
- if (this._state !== States.PENDING) {
479
- return;
810
+ /* eslint-disable complexity */
811
+ /**
812
+ * Stringify the given value. Handles various known special values and types.
813
+ *
814
+ * Not meant to be used on simple primitives which already have a string representation, as it will, for example, turn
815
+ * the number 1231 into "[Object Number]", nor on `null`, as it will throw.
816
+ *
817
+ * @param value The value to stringify
818
+ * @returns A stringified representation of the given value
819
+ */
820
+ function stringifyValue(
821
+ key,
822
+ // this type is a tiny bit of a cheat, since this function does handle NaN (which is technically a number), but for
823
+ // our internal use, it'll do
824
+ value,
825
+ ) {
826
+ try {
827
+ if (key === 'domain' && value && typeof value === 'object' && (value )._events) {
828
+ return '[Domain]';
480
829
  }
481
830
 
482
- if (isThenable(value)) {
483
- void (value ).then(this._resolve, this._reject);
484
- return;
831
+ if (key === 'domainEmitter') {
832
+ return '[DomainEmitter]';
485
833
  }
486
834
 
487
- this._state = state;
488
- this._value = value;
835
+ // It's safe to use `global`, `window`, and `document` here in this manner, as we are asserting using `typeof` first
836
+ // which won't throw if they are not present.
489
837
 
490
- this._executeHandlers();
491
- };}
838
+ if (typeof global !== 'undefined' && value === global) {
839
+ return '[Global]';
840
+ }
492
841
 
493
- /** JSDoc */
494
- __init4() {this._executeHandlers = () => {
495
- if (this._state === States.PENDING) {
496
- return;
842
+ // eslint-disable-next-line no-restricted-globals
843
+ if (typeof window !== 'undefined' && value === window) {
844
+ return '[Window]';
497
845
  }
498
846
 
499
- const cachedHandlers = this._handlers.slice();
500
- this._handlers = [];
847
+ // eslint-disable-next-line no-restricted-globals
848
+ if (typeof document !== 'undefined' && value === document) {
849
+ return '[Document]';
850
+ }
501
851
 
502
- cachedHandlers.forEach(handler => {
503
- if (handler[0]) {
504
- return;
505
- }
852
+ if (isVueViewModel(value)) {
853
+ return '[VueViewModel]';
854
+ }
506
855
 
507
- if (this._state === States.RESOLVED) {
508
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
509
- handler[1](this._value );
510
- }
856
+ // React's SyntheticEvent thingy
857
+ if (isSyntheticEvent(value)) {
858
+ return '[SyntheticEvent]';
859
+ }
511
860
 
512
- if (this._state === States.REJECTED) {
513
- handler[2](this._value);
514
- }
861
+ if (typeof value === 'number' && value !== value) {
862
+ return '[NaN]';
863
+ }
515
864
 
516
- handler[0] = true;
517
- });
518
- };}
519
- }
865
+ if (typeof value === 'function') {
866
+ return `[Function: ${getFunctionName(value)}]`;
867
+ }
520
868
 
521
- const ONE_SECOND_IN_MS = 1000;
869
+ if (typeof value === 'symbol') {
870
+ return `[${String(value)}]`;
871
+ }
522
872
 
523
- /**
524
- * A partial definition of the [Performance Web API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Performance}
525
- * for accessing a high-resolution monotonic clock.
526
- */
873
+ // stringified BigInts are indistinguishable from regular numbers, so we need to label them to avoid confusion
874
+ if (typeof value === 'bigint') {
875
+ return `[BigInt: ${String(value)}]`;
876
+ }
527
877
 
528
- /**
529
- * Returns a timestamp in seconds since the UNIX epoch using the Date API.
530
- *
531
- * TODO(v8): Return type should be rounded.
532
- */
533
- function dateTimestampInSeconds() {
534
- return Date.now() / ONE_SECOND_IN_MS;
878
+ // Now that we've knocked out all the special cases and the primitives, all we have left are objects. Simply casting
879
+ // them to strings means that instances of classes which haven't defined their `toStringTag` will just come out as
880
+ // `"[object Object]"`. If we instead look at the constructor's name (which is the same as the name of the class),
881
+ // we can make sure that only plain objects come out that way.
882
+ const objName = getConstructorName(value);
883
+
884
+ // Handle HTML Elements
885
+ if (/^HTML(\w*)Element$/.test(objName)) {
886
+ return `[HTMLElement: ${objName}]`;
887
+ }
888
+
889
+ return `[object ${objName}]`;
890
+ } catch (err) {
891
+ return `**non-serializable** (${err})`;
892
+ }
535
893
  }
894
+ /* eslint-enable complexity */
536
895
 
537
- /**
538
- * Returns a wrapper around the native Performance API browser implementation, or undefined for browsers that do not
539
- * support the API.
540
- *
541
- * Wrapping the native API works around differences in behavior from different browsers.
542
- */
896
+ function getConstructorName(value) {
897
+ const prototype = Object.getPrototypeOf(value);
898
+
899
+ return prototype ? prototype.constructor.name : 'null prototype';
900
+ }
901
+
902
+ /* eslint-disable @typescript-eslint/explicit-function-return-type */
903
+ /* eslint-disable @typescript-eslint/no-explicit-any */
904
+
905
+ /** SyncPromise internal states */
906
+ var States; (function (States) {
907
+ /** Pending */
908
+ const PENDING = 0; States[States["PENDING"] = PENDING] = "PENDING";
909
+ /** Resolved / OK */
910
+ const RESOLVED = 1; States[States["RESOLVED"] = RESOLVED] = "RESOLVED";
911
+ /** Rejected / Error */
912
+ const REJECTED = 2; States[States["REJECTED"] = REJECTED] = "REJECTED";
913
+ })(States || (States = {}));
914
+
915
+ /**
916
+ * This code was originally copied from the 'cookie` module at v0.5.0 and was simplified for our use case.
917
+ * https://github.com/jshttp/cookie/blob/a0c84147aab6266bdb3996cf4062e93907c0b0fc/index.js
918
+ * It had the following license:
919
+ *
920
+ * (The MIT License)
921
+ *
922
+ * Copyright (c) 2012-2014 Roman Shtylman <shtylman@gmail.com>
923
+ * Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>
924
+ *
925
+ * Permission is hereby granted, free of charge, to any person obtaining
926
+ * a copy of this software and associated documentation files (the
927
+ * 'Software'), to deal in the Software without restriction, including
928
+ * without limitation the rights to use, copy, modify, merge, publish,
929
+ * distribute, sublicense, and/or sell copies of the Software, and to
930
+ * permit persons to whom the Software is furnished to do so, subject to
931
+ * the following conditions:
932
+ *
933
+ * The above copyright notice and this permission notice shall be
934
+ * included in all copies or substantial portions of the Software.
935
+ *
936
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
937
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
938
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
939
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
940
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
941
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
942
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
943
+ */
944
+
945
+ /**
946
+ * Parses a cookie string
947
+ */
948
+ function parseCookie(str) {
949
+ const obj = {};
950
+ let index = 0;
951
+
952
+ while (index < str.length) {
953
+ const eqIdx = str.indexOf('=', index);
954
+
955
+ // no more cookie pairs
956
+ if (eqIdx === -1) {
957
+ break;
958
+ }
959
+
960
+ let endIdx = str.indexOf(';', index);
961
+
962
+ if (endIdx === -1) {
963
+ endIdx = str.length;
964
+ } else if (endIdx < eqIdx) {
965
+ // backtrack on prior semicolon
966
+ index = str.lastIndexOf(';', eqIdx - 1) + 1;
967
+ continue;
968
+ }
969
+
970
+ const key = str.slice(index, eqIdx).trim();
971
+
972
+ // only assign once
973
+ if (undefined === obj[key]) {
974
+ let val = str.slice(eqIdx + 1, endIdx).trim();
975
+
976
+ // quoted values
977
+ if (val.charCodeAt(0) === 0x22) {
978
+ val = val.slice(1, -1);
979
+ }
980
+
981
+ try {
982
+ obj[key] = val.indexOf('%') !== -1 ? decodeURIComponent(val) : val;
983
+ } catch (e) {
984
+ obj[key] = val;
985
+ }
986
+ }
987
+
988
+ index = endIdx + 1;
989
+ }
990
+
991
+ return obj;
992
+ }
993
+
994
+ /**
995
+ * Strip the query string and fragment off of a given URL or path (if present)
996
+ *
997
+ * @param urlPath Full URL or path, including possible query string and/or fragment
998
+ * @returns URL or path without query string or fragment
999
+ */
1000
+ function stripUrlQueryAndFragment(urlPath) {
1001
+ // eslint-disable-next-line no-useless-escape
1002
+ return urlPath.split(/[\?#]/, 1)[0];
1003
+ }
1004
+
1005
+ const DEFAULT_INCLUDES = {
1006
+ ip: false,
1007
+ request: true,
1008
+ transaction: true,
1009
+ user: true,
1010
+ };
1011
+ const DEFAULT_REQUEST_INCLUDES = ['cookies', 'data', 'headers', 'method', 'query_string', 'url'];
1012
+ const DEFAULT_USER_INCLUDES = ['id', 'username', 'email'];
1013
+
1014
+ /**
1015
+ * Extracts a complete and parameterized path from the request object and uses it to construct transaction name.
1016
+ * If the parameterized transaction name cannot be extracted, we fall back to the raw URL.
1017
+ *
1018
+ * Additionally, this function determines and returns the transaction name source
1019
+ *
1020
+ * eg. GET /mountpoint/user/:id
1021
+ *
1022
+ * @param req A request object
1023
+ * @param options What to include in the transaction name (method, path, or a custom route name to be
1024
+ * used instead of the request's route)
1025
+ *
1026
+ * @returns A tuple of the fully constructed transaction name [0] and its source [1] (can be either 'route' or 'url')
1027
+ */
1028
+ function extractPathForTransaction(
1029
+ req,
1030
+ options = {},
1031
+ ) {
1032
+ const method = req.method && req.method.toUpperCase();
1033
+
1034
+ let path = '';
1035
+ let source = 'url';
1036
+
1037
+ // Check to see if there's a parameterized route we can use (as there is in Express)
1038
+ if (options.customRoute || req.route) {
1039
+ path = options.customRoute || `${req.baseUrl || ''}${req.route && req.route.path}`;
1040
+ source = 'route';
1041
+ }
1042
+
1043
+ // Otherwise, just take the original URL
1044
+ else if (req.originalUrl || req.url) {
1045
+ path = stripUrlQueryAndFragment(req.originalUrl || req.url || '');
1046
+ }
1047
+
1048
+ let name = '';
1049
+ if (options.method && method) {
1050
+ name += method;
1051
+ }
1052
+ if (options.method && options.path) {
1053
+ name += ' ';
1054
+ }
1055
+ if (options.path && path) {
1056
+ name += path;
1057
+ }
1058
+
1059
+ return [name, source];
1060
+ }
1061
+
1062
+ /** JSDoc */
1063
+ function extractTransaction(req, type) {
1064
+ switch (type) {
1065
+ case 'path': {
1066
+ return extractPathForTransaction(req, { path: true })[0];
1067
+ }
1068
+ case 'handler': {
1069
+ return (req.route && req.route.stack && req.route.stack[0] && req.route.stack[0].name) || '<anonymous>';
1070
+ }
1071
+ case 'methodPath':
1072
+ default: {
1073
+ // if exist _reconstructedRoute return that path instead of route.path
1074
+ const customRoute = req._reconstructedRoute ? req._reconstructedRoute : undefined;
1075
+ return extractPathForTransaction(req, { path: true, method: true, customRoute })[0];
1076
+ }
1077
+ }
1078
+ }
1079
+
1080
+ /** JSDoc */
1081
+ function extractUserData(
1082
+ user
1083
+
1084
+ ,
1085
+ keys,
1086
+ ) {
1087
+ const extractedUser = {};
1088
+ const attributes = Array.isArray(keys) ? keys : DEFAULT_USER_INCLUDES;
1089
+
1090
+ attributes.forEach(key => {
1091
+ if (user && key in user) {
1092
+ extractedUser[key] = user[key];
1093
+ }
1094
+ });
1095
+
1096
+ return extractedUser;
1097
+ }
1098
+
1099
+ /**
1100
+ * Normalize data from the request object, accounting for framework differences.
1101
+ *
1102
+ * @param req The request object from which to extract data
1103
+ * @param options.include An optional array of keys to include in the normalized data. Defaults to
1104
+ * DEFAULT_REQUEST_INCLUDES if not provided.
1105
+ * @param options.deps Injected, platform-specific dependencies
1106
+ * @returns An object containing normalized request data
1107
+ */
1108
+ function extractRequestData(
1109
+ req,
1110
+ options
1111
+
1112
+ ,
1113
+ ) {
1114
+ const { include = DEFAULT_REQUEST_INCLUDES } = options || {};
1115
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1116
+ const requestData = {};
1117
+
1118
+ // headers:
1119
+ // node, express, koa, nextjs: req.headers
1120
+ const headers = (req.headers || {})
1121
+
1122
+ ;
1123
+ // method:
1124
+ // node, express, koa, nextjs: req.method
1125
+ const method = req.method;
1126
+ // host:
1127
+ // express: req.hostname in > 4 and req.host in < 4
1128
+ // koa: req.host
1129
+ // node, nextjs: req.headers.host
1130
+ // Express 4 mistakenly strips off port number from req.host / req.hostname so we can't rely on them
1131
+ // See: https://github.com/expressjs/express/issues/3047#issuecomment-236653223
1132
+ // Also: https://github.com/getsentry/sentry-javascript/issues/1917
1133
+ const host = headers.host || req.hostname || req.host || '<no host>';
1134
+ // protocol:
1135
+ // node, nextjs: <n/a>
1136
+ // express, koa: req.protocol
1137
+ const protocol = req.protocol === 'https' || (req.socket && req.socket.encrypted) ? 'https' : 'http';
1138
+ // url (including path and query string):
1139
+ // node, express: req.originalUrl
1140
+ // koa, nextjs: req.url
1141
+ const originalUrl = req.originalUrl || req.url || '';
1142
+ // absolute url
1143
+ const absoluteUrl = originalUrl.startsWith(protocol) ? originalUrl : `${protocol}://${host}${originalUrl}`;
1144
+ include.forEach(key => {
1145
+ switch (key) {
1146
+ case 'headers': {
1147
+ requestData.headers = headers;
1148
+
1149
+ // Remove the Cookie header in case cookie data should not be included in the event
1150
+ if (!include.includes('cookies')) {
1151
+ delete (requestData.headers ).cookie;
1152
+ }
1153
+
1154
+ break;
1155
+ }
1156
+ case 'method': {
1157
+ requestData.method = method;
1158
+ break;
1159
+ }
1160
+ case 'url': {
1161
+ requestData.url = absoluteUrl;
1162
+ break;
1163
+ }
1164
+ case 'cookies': {
1165
+ // cookies:
1166
+ // node, express, koa: req.headers.cookie
1167
+ // vercel, sails.js, express (w/ cookie middleware), nextjs: req.cookies
1168
+ requestData.cookies =
1169
+ // TODO (v8 / #5257): We're only sending the empty object for backwards compatibility, so the last bit can
1170
+ // come off in v8
1171
+ req.cookies || (headers.cookie && parseCookie(headers.cookie)) || {};
1172
+ break;
1173
+ }
1174
+ case 'query_string': {
1175
+ // query string:
1176
+ // node: req.url (raw)
1177
+ // express, koa, nextjs: req.query
1178
+ requestData.query_string = extractQueryParams(req);
1179
+ break;
1180
+ }
1181
+ case 'data': {
1182
+ if (method === 'GET' || method === 'HEAD') {
1183
+ break;
1184
+ }
1185
+ // body data:
1186
+ // express, koa, nextjs: req.body
1187
+ //
1188
+ // when using node by itself, you have to read the incoming stream(see
1189
+ // https://nodejs.dev/learn/get-http-request-body-data-using-nodejs); if a user is doing that, we can't know
1190
+ // where they're going to store the final result, so they'll have to capture this data themselves
1191
+ if (req.body !== undefined) {
1192
+ requestData.data = isString(req.body) ? req.body : JSON.stringify(normalize(req.body));
1193
+ }
1194
+ break;
1195
+ }
1196
+ default: {
1197
+ if ({}.hasOwnProperty.call(req, key)) {
1198
+ requestData[key] = (req )[key];
1199
+ }
1200
+ }
1201
+ }
1202
+ });
1203
+
1204
+ return requestData;
1205
+ }
1206
+
1207
+ /**
1208
+ * Add data from the given request to the given event
1209
+ *
1210
+ * @param event The event to which the request data will be added
1211
+ * @param req Request object
1212
+ * @param options.include Flags to control what data is included
1213
+ * @param options.deps Injected platform-specific dependencies
1214
+ * @returns The mutated `Event` object
1215
+ */
1216
+ function addRequestDataToEvent(
1217
+ event,
1218
+ req,
1219
+ options,
1220
+ ) {
1221
+ const include = {
1222
+ ...DEFAULT_INCLUDES,
1223
+ ...(options && options.include),
1224
+ };
1225
+
1226
+ if (include.request) {
1227
+ const extractedRequestData = Array.isArray(include.request)
1228
+ ? extractRequestData(req, { include: include.request })
1229
+ : extractRequestData(req);
1230
+
1231
+ event.request = {
1232
+ ...event.request,
1233
+ ...extractedRequestData,
1234
+ };
1235
+ }
1236
+
1237
+ if (include.user) {
1238
+ const extractedUser = req.user && isPlainObject(req.user) ? extractUserData(req.user, include.user) : {};
1239
+
1240
+ if (Object.keys(extractedUser).length) {
1241
+ event.user = {
1242
+ ...event.user,
1243
+ ...extractedUser,
1244
+ };
1245
+ }
1246
+ }
1247
+
1248
+ // client ip:
1249
+ // node, nextjs: req.socket.remoteAddress
1250
+ // express, koa: req.ip
1251
+ if (include.ip) {
1252
+ const ip = req.ip || (req.socket && req.socket.remoteAddress);
1253
+ if (ip) {
1254
+ event.user = {
1255
+ ...event.user,
1256
+ ip_address: ip,
1257
+ };
1258
+ }
1259
+ }
1260
+
1261
+ if (include.transaction && !event.transaction) {
1262
+ // TODO do we even need this anymore?
1263
+ // TODO make this work for nextjs
1264
+ event.transaction = extractTransaction(req, include.transaction);
1265
+ }
1266
+
1267
+ return event;
1268
+ }
1269
+
1270
+ function extractQueryParams(req) {
1271
+ // url (including path and query string):
1272
+ // node, express: req.originalUrl
1273
+ // koa, nextjs: req.url
1274
+ let originalUrl = req.originalUrl || req.url || '';
1275
+
1276
+ if (!originalUrl) {
1277
+ return;
1278
+ }
1279
+
1280
+ // The `URL` constructor can't handle internal URLs of the form `/some/path/here`, so stick a dummy protocol and
1281
+ // hostname on the beginning. Since the point here is just to grab the query string, it doesn't matter what we use.
1282
+ if (originalUrl.startsWith('/')) {
1283
+ originalUrl = `http://dogs.are.great${originalUrl}`;
1284
+ }
1285
+
1286
+ try {
1287
+ const queryParams = req.query || new URL(originalUrl).search.slice(1);
1288
+ return queryParams.length ? queryParams : undefined;
1289
+ } catch (e2) {
1290
+ return undefined;
1291
+ }
1292
+ }
1293
+
1294
+ const ONE_SECOND_IN_MS = 1000;
1295
+
1296
+ /**
1297
+ * A partial definition of the [Performance Web API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Performance}
1298
+ * for accessing a high-resolution monotonic clock.
1299
+ */
1300
+
1301
+ /**
1302
+ * Returns a timestamp in seconds since the UNIX epoch using the Date API.
1303
+ *
1304
+ * TODO(v8): Return type should be rounded.
1305
+ */
1306
+ function dateTimestampInSeconds() {
1307
+ return Date.now() / ONE_SECOND_IN_MS;
1308
+ }
1309
+
1310
+ /**
1311
+ * Returns a wrapper around the native Performance API browser implementation, or undefined for browsers that do not
1312
+ * support the API.
1313
+ *
1314
+ * Wrapping the native API works around differences in behavior from different browsers.
1315
+ */
543
1316
  function createUnixTimestampInSecondsFunc() {
544
1317
  const { performance } = GLOBAL_OBJ ;
545
1318
  if (!performance || !performance.now) {
@@ -623,15 +1396,6 @@ const timestampInSeconds = createUnixTimestampInSecondsFunc();
623
1396
  return dateNow;
624
1397
  })();
625
1398
 
626
- /**
627
- * Creates an envelope.
628
- * Make sure to always explicitly provide the generic to this function
629
- * so that the envelope types resolve correctly.
630
- */
631
- function createEnvelope(headers, items = []) {
632
- return [headers, items] ;
633
- }
634
-
635
1399
  /**
636
1400
  * Convenience function to loop through the items and item types of an envelope.
637
1401
  * (This function was mostly created because working with envelope types is painful at the moment)
@@ -664,53 +1428,36 @@ function forEachEnvelopeItem(
664
1428
  const DEBUG_BUILD$1 = (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__);
665
1429
 
666
1430
  /**
667
- * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code.
1431
+ * @private Private API with no semver guarantees!
668
1432
  *
669
- * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking.
1433
+ * Strategy used to track async context.
670
1434
  */
671
- const DEBUG_BUILD = (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__);
672
-
673
- const DEFAULT_ENVIRONMENT = 'production';
674
1435
 
675
1436
  /**
676
- * Returns the global event processors.
677
- * @deprecated Global event processors will be removed in v8.
678
- */
679
- function getGlobalEventProcessors() {
680
- return getGlobalSingleton('globalEventProcessors', () => []);
1437
+ * Returns the global shim registry.
1438
+ *
1439
+ * FIXME: This function is problematic, because despite always returning a valid Carrier,
1440
+ * it has an optional `__SENTRY__` property, which then in turn requires us to always perform an unnecessary check
1441
+ * at the call-site. We always access the carrier through this function, so we can guarantee that `__SENTRY__` is there.
1442
+ **/
1443
+ function getMainCarrier() {
1444
+ // This ensures a Sentry carrier exists
1445
+ getSentryCarrier(GLOBAL_OBJ);
1446
+ return GLOBAL_OBJ;
681
1447
  }
682
1448
 
683
- /**
684
- * Process an array of event processors, returning the processed event (or `null` if the event was dropped).
685
- */
686
- function notifyEventProcessors(
687
- processors,
688
- event,
689
- hint,
690
- index = 0,
691
- ) {
692
- return new SyncPromise((resolve, reject) => {
693
- const processor = processors[index];
694
- if (event === null || typeof processor !== 'function') {
695
- resolve(event);
696
- } else {
697
- const result = processor({ ...event }, hint) ;
698
-
699
- DEBUG_BUILD && processor.id && result === null && logger.log(`Event processor "${processor.id}" dropped event`);
700
-
701
- if (isThenable(result)) {
702
- void result
703
- .then(final => notifyEventProcessors(processors, final, hint, index + 1).then(resolve))
704
- .then(null, reject);
705
- } else {
706
- void notifyEventProcessors(processors, result, hint, index + 1)
707
- .then(resolve)
708
- .then(null, reject);
709
- }
710
- }
711
- });
1449
+ /** Will either get the existing sentry carrier, or create a new one. */
1450
+ function getSentryCarrier(carrier) {
1451
+ if (!carrier.__SENTRY__) {
1452
+ carrier.__SENTRY__ = {
1453
+ extensions: {},
1454
+ };
1455
+ }
1456
+ return carrier.__SENTRY__;
712
1457
  }
713
1458
 
1459
+ const DEFAULT_ENVIRONMENT = 'production';
1460
+
714
1461
  /**
715
1462
  * Creates a new `Session` object by setting certain default parameters. If optional @param context
716
1463
  * is passed, the passed properties are applied to the session object.
@@ -867,320 +1614,28 @@ function sessionToJSON(session) {
867
1614
  });
868
1615
  }
869
1616
 
870
- const TRACE_FLAG_SAMPLED = 0x1;
871
-
872
1617
  /**
873
- * Convert a span to a trace context, which can be sent as the `trace` context in an event.
1618
+ * Default value for maximum number of breadcrumbs added to an event.
874
1619
  */
875
- function spanToTraceContext(span) {
876
- const { spanId: span_id, traceId: trace_id } = span.spanContext();
877
- const { data, op, parent_span_id, status, tags, origin } = spanToJSON(span);
878
-
879
- return dropUndefinedKeys({
880
- data,
881
- op,
882
- parent_span_id,
883
- span_id,
884
- status,
885
- tags,
886
- trace_id,
887
- origin,
888
- });
889
- }
1620
+ const DEFAULT_MAX_BREADCRUMBS = 100;
890
1621
 
891
1622
  /**
892
- * Convert a span to a JSON representation.
893
- * Note that all fields returned here are optional and need to be guarded against.
894
- *
895
- * Note: Because of this, we currently have a circular type dependency (which we opted out of in package.json).
896
- * This is not avoidable as we need `spanToJSON` in `spanUtils.ts`, which in turn is needed by `span.ts` for backwards compatibility.
897
- * And `spanToJSON` needs the Span class from `span.ts` to check here.
898
- * TODO v8: When we remove the deprecated stuff from `span.ts`, we can remove the circular dependency again.
1623
+ * Holds additional event information.
899
1624
  */
900
- function spanToJSON(span) {
901
- if (spanIsSpanClass(span)) {
902
- return span.getSpanJSON();
903
- }
1625
+ class Scope {
1626
+ /** Flag if notifying is happening. */
904
1627
 
905
- // Fallback: We also check for `.toJSON()` here...
906
- // eslint-disable-next-line deprecation/deprecation
907
- if (typeof span.toJSON === 'function') {
908
- // eslint-disable-next-line deprecation/deprecation
909
- return span.toJSON();
910
- }
1628
+ /** Callback for client to receive scope changes. */
911
1629
 
912
- return {};
913
- }
1630
+ /** Callback list that will be called during event processing. */
914
1631
 
915
- /**
916
- * Sadly, due to circular dependency checks we cannot actually import the Span class here and check for instanceof.
917
- * :( So instead we approximate this by checking if it has the `getSpanJSON` method.
918
- */
919
- function spanIsSpanClass(span) {
920
- return typeof (span ).getSpanJSON === 'function';
921
- }
1632
+ /** Array of breadcrumbs. */
922
1633
 
923
- /**
924
- * Returns true if a span is sampled.
925
- * In most cases, you should just use `span.isRecording()` instead.
926
- * However, this has a slightly different semantic, as it also returns false if the span is finished.
927
- * So in the case where this distinction is important, use this method.
928
- */
929
- function spanIsSampled(span) {
930
- // We align our trace flags with the ones OpenTelemetry use
931
- // So we also check for sampled the same way they do.
932
- const { traceFlags } = span.spanContext();
933
- // eslint-disable-next-line no-bitwise
934
- return Boolean(traceFlags & TRACE_FLAG_SAMPLED);
935
- }
1634
+ /** User */
936
1635
 
937
- /**
938
- * Get the currently active client.
939
- */
940
- function getClient() {
941
- // eslint-disable-next-line deprecation/deprecation
942
- return getCurrentHub().getClient();
943
- }
1636
+ /** Tags */
944
1637
 
945
- /**
946
- * Get the currently active scope.
947
- */
948
- function getCurrentScope() {
949
- // eslint-disable-next-line deprecation/deprecation
950
- return getCurrentHub().getScope();
951
- }
952
-
953
- /**
954
- * Returns the root span of a given span.
955
- *
956
- * As long as we use `Transaction`s internally, the returned root span
957
- * will be a `Transaction` but be aware that this might change in the future.
958
- *
959
- * If the given span has no root span or transaction, `undefined` is returned.
960
- */
961
- function getRootSpan(span) {
962
- // TODO (v8): Remove this check and just return span
963
- // eslint-disable-next-line deprecation/deprecation
964
- return span.transaction;
965
- }
966
-
967
- /**
968
- * Creates a dynamic sampling context from a client.
969
- *
970
- * Dispatches the `createDsc` lifecycle hook as a side effect.
971
- */
972
- function getDynamicSamplingContextFromClient(
973
- trace_id,
974
- client,
975
- scope,
976
- ) {
977
- const options = client.getOptions();
978
-
979
- const { publicKey: public_key } = client.getDsn() || {};
980
- // TODO(v8): Remove segment from User
981
- // eslint-disable-next-line deprecation/deprecation
982
- const { segment: user_segment } = (scope && scope.getUser()) || {};
983
-
984
- const dsc = dropUndefinedKeys({
985
- environment: options.environment || DEFAULT_ENVIRONMENT,
986
- release: options.release,
987
- user_segment,
988
- public_key,
989
- trace_id,
990
- }) ;
991
-
992
- client.emit && client.emit('createDsc', dsc);
993
-
994
- return dsc;
995
- }
996
-
997
- /**
998
- * A Span with a frozen dynamic sampling context.
999
- */
1000
-
1001
- /**
1002
- * Creates a dynamic sampling context from a span (and client and scope)
1003
- *
1004
- * @param span the span from which a few values like the root span name and sample rate are extracted.
1005
- *
1006
- * @returns a dynamic sampling context
1007
- */
1008
- function getDynamicSamplingContextFromSpan(span) {
1009
- const client = getClient();
1010
- if (!client) {
1011
- return {};
1012
- }
1013
-
1014
- // passing emit=false here to only emit later once the DSC is actually populated
1015
- const dsc = getDynamicSamplingContextFromClient(spanToJSON(span).trace_id || '', client, getCurrentScope());
1016
-
1017
- // TODO (v8): Remove v7FrozenDsc as a Transaction will no longer have _frozenDynamicSamplingContext
1018
- const txn = getRootSpan(span) ;
1019
- if (!txn) {
1020
- return dsc;
1021
- }
1022
-
1023
- // TODO (v8): Remove v7FrozenDsc as a Transaction will no longer have _frozenDynamicSamplingContext
1024
- // For now we need to avoid breaking users who directly created a txn with a DSC, where this field is still set.
1025
- // @see Transaction class constructor
1026
- const v7FrozenDsc = txn && txn._frozenDynamicSamplingContext;
1027
- if (v7FrozenDsc) {
1028
- return v7FrozenDsc;
1029
- }
1030
-
1031
- // TODO (v8): Replace txn.metadata with txn.attributes[]
1032
- // We can't do this yet because attributes aren't always set yet.
1033
- // eslint-disable-next-line deprecation/deprecation
1034
- const { sampleRate: maybeSampleRate, source } = txn.metadata;
1035
- if (maybeSampleRate != null) {
1036
- dsc.sample_rate = `${maybeSampleRate}`;
1037
- }
1038
-
1039
- // We don't want to have a transaction name in the DSC if the source is "url" because URLs might contain PII
1040
- const jsonSpan = spanToJSON(txn);
1041
-
1042
- // after JSON conversion, txn.name becomes jsonSpan.description
1043
- if (source && source !== 'url') {
1044
- dsc.transaction = jsonSpan.description;
1045
- }
1046
-
1047
- dsc.sampled = String(spanIsSampled(txn));
1048
-
1049
- client.emit && client.emit('createDsc', dsc);
1050
-
1051
- return dsc;
1052
- }
1053
-
1054
- /**
1055
- * Applies data from the scope to the event and runs all event processors on it.
1056
- */
1057
- function applyScopeDataToEvent(event, data) {
1058
- const { fingerprint, span, breadcrumbs, sdkProcessingMetadata } = data;
1059
-
1060
- // Apply general data
1061
- applyDataToEvent(event, data);
1062
-
1063
- // We want to set the trace context for normal events only if there isn't already
1064
- // a trace context on the event. There is a product feature in place where we link
1065
- // errors with transaction and it relies on that.
1066
- if (span) {
1067
- applySpanToEvent(event, span);
1068
- }
1069
-
1070
- applyFingerprintToEvent(event, fingerprint);
1071
- applyBreadcrumbsToEvent(event, breadcrumbs);
1072
- applySdkMetadataToEvent(event, sdkProcessingMetadata);
1073
- }
1074
-
1075
- function applyDataToEvent(event, data) {
1076
- const {
1077
- extra,
1078
- tags,
1079
- user,
1080
- contexts,
1081
- level,
1082
- // eslint-disable-next-line deprecation/deprecation
1083
- transactionName,
1084
- } = data;
1085
-
1086
- const cleanedExtra = dropUndefinedKeys(extra);
1087
- if (cleanedExtra && Object.keys(cleanedExtra).length) {
1088
- event.extra = { ...cleanedExtra, ...event.extra };
1089
- }
1090
-
1091
- const cleanedTags = dropUndefinedKeys(tags);
1092
- if (cleanedTags && Object.keys(cleanedTags).length) {
1093
- event.tags = { ...cleanedTags, ...event.tags };
1094
- }
1095
-
1096
- const cleanedUser = dropUndefinedKeys(user);
1097
- if (cleanedUser && Object.keys(cleanedUser).length) {
1098
- event.user = { ...cleanedUser, ...event.user };
1099
- }
1100
-
1101
- const cleanedContexts = dropUndefinedKeys(contexts);
1102
- if (cleanedContexts && Object.keys(cleanedContexts).length) {
1103
- event.contexts = { ...cleanedContexts, ...event.contexts };
1104
- }
1105
-
1106
- if (level) {
1107
- event.level = level;
1108
- }
1109
-
1110
- if (transactionName) {
1111
- event.transaction = transactionName;
1112
- }
1113
- }
1114
-
1115
- function applyBreadcrumbsToEvent(event, breadcrumbs) {
1116
- const mergedBreadcrumbs = [...(event.breadcrumbs || []), ...breadcrumbs];
1117
- event.breadcrumbs = mergedBreadcrumbs.length ? mergedBreadcrumbs : undefined;
1118
- }
1119
-
1120
- function applySdkMetadataToEvent(event, sdkProcessingMetadata) {
1121
- event.sdkProcessingMetadata = {
1122
- ...event.sdkProcessingMetadata,
1123
- ...sdkProcessingMetadata,
1124
- };
1125
- }
1126
-
1127
- function applySpanToEvent(event, span) {
1128
- event.contexts = { trace: spanToTraceContext(span), ...event.contexts };
1129
- const rootSpan = getRootSpan(span);
1130
- if (rootSpan) {
1131
- event.sdkProcessingMetadata = {
1132
- dynamicSamplingContext: getDynamicSamplingContextFromSpan(span),
1133
- ...event.sdkProcessingMetadata,
1134
- };
1135
- const transactionName = spanToJSON(rootSpan).description;
1136
- if (transactionName) {
1137
- event.tags = { transaction: transactionName, ...event.tags };
1138
- }
1139
- }
1140
- }
1141
-
1142
- /**
1143
- * Applies fingerprint from the scope to the event if there's one,
1144
- * uses message if there's one instead or get rid of empty fingerprint
1145
- */
1146
- function applyFingerprintToEvent(event, fingerprint) {
1147
- // Make sure it's an array first and we actually have something in place
1148
- event.fingerprint = event.fingerprint ? arrayify(event.fingerprint) : [];
1149
-
1150
- // If we have something on the scope, then merge it with event
1151
- if (fingerprint) {
1152
- event.fingerprint = event.fingerprint.concat(fingerprint);
1153
- }
1154
-
1155
- // If we have no data at all, remove empty array default
1156
- if (event.fingerprint && !event.fingerprint.length) {
1157
- delete event.fingerprint;
1158
- }
1159
- }
1160
-
1161
- /**
1162
- * Default value for maximum number of breadcrumbs added to an event.
1163
- */
1164
- const DEFAULT_MAX_BREADCRUMBS = 100;
1165
-
1166
- /**
1167
- * Holds additional event information. {@link Scope.applyToEvent} will be
1168
- * called by the client before an event will be sent.
1169
- */
1170
- class Scope {
1171
- /** Flag if notifying is happening. */
1172
-
1173
- /** Callback for client to receive scope changes. */
1174
-
1175
- /** Callback list that will be called after {@link applyToEvent}. */
1176
-
1177
- /** Array of breadcrumbs. */
1178
-
1179
- /** User */
1180
-
1181
- /** Tags */
1182
-
1183
- /** Extra */
1638
+ /** Extra */
1184
1639
 
1185
1640
  /** Contexts */
1186
1641
 
@@ -1196,10 +1651,12 @@ class Scope {
1196
1651
  /** Fingerprint */
1197
1652
 
1198
1653
  /** Severity */
1199
- // eslint-disable-next-line deprecation/deprecation
1200
1654
 
1201
1655
  /**
1202
1656
  * Transaction Name
1657
+ *
1658
+ * IMPORTANT: The transaction name on the scope has nothing to do with root spans/transaction objects.
1659
+ * It's purpose is to assign a transaction to the scope that's added to non-transaction events.
1203
1660
  */
1204
1661
 
1205
1662
  /** Span */
@@ -1235,7 +1692,7 @@ class Scope {
1235
1692
  }
1236
1693
 
1237
1694
  /**
1238
- * Clone this scope instance.
1695
+ * @inheritDoc
1239
1696
  */
1240
1697
  clone() {
1241
1698
  const newScope = new Scope();
@@ -1259,23 +1716,22 @@ class Scope {
1259
1716
  return newScope;
1260
1717
  }
1261
1718
 
1262
- /** Update the client on the scope. */
1719
+ /**
1720
+ * @inheritDoc
1721
+ */
1263
1722
  setClient(client) {
1264
1723
  this._client = client;
1265
1724
  }
1266
1725
 
1267
1726
  /**
1268
- * Get the client assigned to this scope.
1269
- *
1270
- * It is generally recommended to use the global function `Sentry.getClient()` instead, unless you know what you are doing.
1727
+ * @inheritDoc
1271
1728
  */
1272
1729
  getClient() {
1273
- return this._client;
1730
+ return this._client ;
1274
1731
  }
1275
1732
 
1276
1733
  /**
1277
- * Add internal on change listener. Used for sub SDKs that need to store the scope.
1278
- * @hidden
1734
+ * @inheritDoc
1279
1735
  */
1280
1736
  addScopeListener(callback) {
1281
1737
  this._scopeListeners.push(callback);
@@ -1299,7 +1755,6 @@ class Scope {
1299
1755
  email: undefined,
1300
1756
  id: undefined,
1301
1757
  ip_address: undefined,
1302
- segment: undefined,
1303
1758
  username: undefined,
1304
1759
  };
1305
1760
 
@@ -1387,17 +1842,14 @@ class Scope {
1387
1842
  /**
1388
1843
  * @inheritDoc
1389
1844
  */
1390
- setLevel(
1391
- // eslint-disable-next-line deprecation/deprecation
1392
- level,
1393
- ) {
1845
+ setLevel(level) {
1394
1846
  this._level = level;
1395
1847
  this._notifyScopeListeners();
1396
1848
  return this;
1397
1849
  }
1398
1850
 
1399
1851
  /**
1400
- * Sets the transaction name on the scope for future events.
1852
+ * @inheritDoc
1401
1853
  */
1402
1854
  setTransactionName(name) {
1403
1855
  this._transactionName = name;
@@ -1447,10 +1899,15 @@ class Scope {
1447
1899
  // Often, this span (if it exists at all) will be a transaction, but it's not guaranteed to be. Regardless, it will
1448
1900
  // have a pointer to the currently-active transaction.
1449
1901
  const span = this._span;
1902
+
1450
1903
  // Cannot replace with getRootSpan because getRootSpan returns a span, not a transaction
1451
1904
  // Also, this method will be removed anyway.
1452
1905
  // eslint-disable-next-line deprecation/deprecation
1453
- return span && span.transaction;
1906
+ if (span && (span ).transaction) {
1907
+ // eslint-disable-next-line deprecation/deprecation
1908
+ return (span ).transaction;
1909
+ }
1910
+ return undefined;
1454
1911
  }
1455
1912
 
1456
1913
  /**
@@ -1533,6 +1990,7 @@ class Scope {
1533
1990
  * @inheritDoc
1534
1991
  */
1535
1992
  clear() {
1993
+ // client is not cleared here on purpose!
1536
1994
  this._breadcrumbs = [];
1537
1995
  this._tags = {};
1538
1996
  this._extra = {};
@@ -1653,33 +2111,7 @@ class Scope {
1653
2111
  }
1654
2112
 
1655
2113
  /**
1656
- * Applies data from the scope to the event and runs all event processors on it.
1657
- *
1658
- * @param event Event
1659
- * @param hint Object containing additional information about the original exception, for use by the event processors.
1660
- * @hidden
1661
- * @deprecated Use `applyScopeDataToEvent()` directly
1662
- */
1663
- applyToEvent(
1664
- event,
1665
- hint = {},
1666
- additionalEventProcessors = [],
1667
- ) {
1668
- applyScopeDataToEvent(event, this.getScopeData());
1669
-
1670
- // TODO (v8): Update this order to be: Global > Client > Scope
1671
- const eventProcessors = [
1672
- ...additionalEventProcessors,
1673
- // eslint-disable-next-line deprecation/deprecation
1674
- ...getGlobalEventProcessors(),
1675
- ...this._eventProcessors,
1676
- ];
1677
-
1678
- return notifyEventProcessors(eventProcessors, event, hint);
1679
- }
1680
-
1681
- /**
1682
- * Add data which will be accessible during event processing but won't get sent to Sentry
2114
+ * @inheritDoc
1683
2115
  */
1684
2116
  setSDKProcessingMetadata(newData) {
1685
2117
  this._sdkProcessingMetadata = { ...this._sdkProcessingMetadata, ...newData };
@@ -1703,11 +2135,7 @@ class Scope {
1703
2135
  }
1704
2136
 
1705
2137
  /**
1706
- * Capture an exception for this scope.
1707
- *
1708
- * @param exception The exception to capture.
1709
- * @param hint Optinal additional data to attach to the Sentry event.
1710
- * @returns the id of the captured Sentry event.
2138
+ * @inheritDoc
1711
2139
  */
1712
2140
  captureException(exception, hint) {
1713
2141
  const eventId = hint && hint.event_id ? hint.event_id : uuid4();
@@ -1734,12 +2162,7 @@ class Scope {
1734
2162
  }
1735
2163
 
1736
2164
  /**
1737
- * Capture a message for this scope.
1738
- *
1739
- * @param message The message to capture.
1740
- * @param level An optional severity level to report the message with.
1741
- * @param hint Optional additional data to attach to the Sentry event.
1742
- * @returns the id of the captured message.
2165
+ * @inheritDoc
1743
2166
  */
1744
2167
  captureMessage(message, level, hint) {
1745
2168
  const eventId = hint && hint.event_id ? hint.event_id : uuid4();
@@ -1767,11 +2190,7 @@ class Scope {
1767
2190
  }
1768
2191
 
1769
2192
  /**
1770
- * Captures a manually created event for this scope and sends it to Sentry.
1771
- *
1772
- * @param exception The event to capture.
1773
- * @param hint Optional additional data to attach to the Sentry event.
1774
- * @returns the id of the captured event.
2193
+ * @inheritDoc
1775
2194
  */
1776
2195
  captureEvent(event, hint) {
1777
2196
  const eventId = hint && hint.event_id ? hint.event_id : uuid4();
@@ -1810,7 +2229,7 @@ function generatePropagationContext() {
1810
2229
  };
1811
2230
  }
1812
2231
 
1813
- const SDK_VERSION = '7.107.0';
2232
+ const SDK_VERSION = '8.0.0-alpha.3';
1814
2233
 
1815
2234
  /**
1816
2235
  * API compatibility version of this hub.
@@ -1826,7 +2245,12 @@ const API_VERSION = parseFloat(SDK_VERSION);
1826
2245
  * Default maximum number of breadcrumbs added to an event. Can be overwritten
1827
2246
  * with {@link Options.maxBreadcrumbs}.
1828
2247
  */
1829
- const DEFAULT_BREADCRUMBS = 100;
2248
+ const DEFAULT_BREADCRUMBS$1 = 100;
2249
+
2250
+ /**
2251
+ * A layer in the process stack.
2252
+ * @hidden
2253
+ */
1830
2254
 
1831
2255
  /**
1832
2256
  * @inheritDoc
@@ -1834,8 +2258,6 @@ const DEFAULT_BREADCRUMBS = 100;
1834
2258
  class Hub {
1835
2259
  /** Is a {@link Layer}[] containing the client and scope */
1836
2260
 
1837
- /** Contains the last event id of a captured event. */
1838
-
1839
2261
  /**
1840
2262
  * Creates a new instance of the hub, will push one {@link Layer} into the
1841
2263
  * internal stack on creation.
@@ -2064,7 +2486,7 @@ class Hub {
2064
2486
  * @deprecated Use `Sentry.captureException()` instead.
2065
2487
  */
2066
2488
  captureException(exception, hint) {
2067
- const eventId = (this._lastEventId = hint && hint.event_id ? hint.event_id : uuid4());
2489
+ const eventId = hint && hint.event_id ? hint.event_id : uuid4();
2068
2490
  const syntheticException = new Error('Sentry syntheticException');
2069
2491
  // eslint-disable-next-line deprecation/deprecation
2070
2492
  this.getScope().captureException(exception, {
@@ -2082,13 +2504,8 @@ class Hub {
2082
2504
  *
2083
2505
  * @deprecated Use `Sentry.captureMessage()` instead.
2084
2506
  */
2085
- captureMessage(
2086
- message,
2087
- // eslint-disable-next-line deprecation/deprecation
2088
- level,
2089
- hint,
2090
- ) {
2091
- const eventId = (this._lastEventId = hint && hint.event_id ? hint.event_id : uuid4());
2507
+ captureMessage(message, level, hint) {
2508
+ const eventId = hint && hint.event_id ? hint.event_id : uuid4();
2092
2509
  const syntheticException = new Error(message);
2093
2510
  // eslint-disable-next-line deprecation/deprecation
2094
2511
  this.getScope().captureMessage(message, level, {
@@ -2108,23 +2525,11 @@ class Hub {
2108
2525
  */
2109
2526
  captureEvent(event, hint) {
2110
2527
  const eventId = hint && hint.event_id ? hint.event_id : uuid4();
2111
- if (!event.type) {
2112
- this._lastEventId = eventId;
2113
- }
2114
2528
  // eslint-disable-next-line deprecation/deprecation
2115
2529
  this.getScope().captureEvent(event, { ...hint, event_id: eventId });
2116
2530
  return eventId;
2117
2531
  }
2118
2532
 
2119
- /**
2120
- * @inheritDoc
2121
- *
2122
- * @deprecated This will be removed in v8.
2123
- */
2124
- lastEventId() {
2125
- return this._lastEventId;
2126
- }
2127
-
2128
2533
  /**
2129
2534
  * @inheritDoc
2130
2535
  *
@@ -2132,11 +2537,11 @@ class Hub {
2132
2537
  */
2133
2538
  addBreadcrumb(breadcrumb, hint) {
2134
2539
  // eslint-disable-next-line deprecation/deprecation
2135
- const { scope, client } = this.getStackTop();
2540
+ const { client } = this.getStackTop();
2136
2541
 
2137
2542
  if (!client) return;
2138
2543
 
2139
- const { beforeBreadcrumb = null, maxBreadcrumbs = DEFAULT_BREADCRUMBS } =
2544
+ const { beforeBreadcrumb = null, maxBreadcrumbs = DEFAULT_BREADCRUMBS$1 } =
2140
2545
  (client.getOptions && client.getOptions()) || {};
2141
2546
 
2142
2547
  if (maxBreadcrumbs <= 0) return;
@@ -2149,19 +2554,10 @@ class Hub {
2149
2554
 
2150
2555
  if (finalBreadcrumb === null) return;
2151
2556
 
2152
- if (client.emit) {
2153
- client.emit('beforeAddBreadcrumb', finalBreadcrumb, hint);
2154
- }
2155
-
2156
- // TODO(v8): I know this comment doesn't make much sense because the hub will be deprecated but I still wanted to
2157
- // write it down. In theory, we would have to add the breadcrumbs to the isolation scope here, however, that would
2158
- // duplicate all of the breadcrumbs. There was the possibility of adding breadcrumbs to both, the isolation scope
2159
- // and the normal scope, and deduplicating it down the line in the event processing pipeline. However, that would
2160
- // have been very fragile, because the breadcrumb objects would have needed to keep their identity all throughout
2161
- // the event processing pipeline.
2162
- // In the new implementation, the top level `Sentry.addBreadcrumb()` should ONLY write to the isolation scope.
2557
+ client.emit('beforeAddBreadcrumb', finalBreadcrumb, hint);
2163
2558
 
2164
- scope.addBreadcrumb(finalBreadcrumb, maxBreadcrumbs);
2559
+ // eslint-disable-next-line deprecation/deprecation
2560
+ this.getIsolationScope().addBreadcrumb(finalBreadcrumb, maxBreadcrumbs);
2165
2561
  }
2166
2562
 
2167
2563
  /**
@@ -2169,9 +2565,6 @@ class Hub {
2169
2565
  * @deprecated Use `Sentry.setUser()` instead.
2170
2566
  */
2171
2567
  setUser(user) {
2172
- // TODO(v8): The top level `Sentry.setUser()` function should write ONLY to the isolation scope.
2173
- // eslint-disable-next-line deprecation/deprecation
2174
- this.getScope().setUser(user);
2175
2568
  // eslint-disable-next-line deprecation/deprecation
2176
2569
  this.getIsolationScope().setUser(user);
2177
2570
  }
@@ -2181,9 +2574,6 @@ class Hub {
2181
2574
  * @deprecated Use `Sentry.setTags()` instead.
2182
2575
  */
2183
2576
  setTags(tags) {
2184
- // TODO(v8): The top level `Sentry.setTags()` function should write ONLY to the isolation scope.
2185
- // eslint-disable-next-line deprecation/deprecation
2186
- this.getScope().setTags(tags);
2187
2577
  // eslint-disable-next-line deprecation/deprecation
2188
2578
  this.getIsolationScope().setTags(tags);
2189
2579
  }
@@ -2193,9 +2583,6 @@ class Hub {
2193
2583
  * @deprecated Use `Sentry.setExtras()` instead.
2194
2584
  */
2195
2585
  setExtras(extras) {
2196
- // TODO(v8): The top level `Sentry.setExtras()` function should write ONLY to the isolation scope.
2197
- // eslint-disable-next-line deprecation/deprecation
2198
- this.getScope().setExtras(extras);
2199
2586
  // eslint-disable-next-line deprecation/deprecation
2200
2587
  this.getIsolationScope().setExtras(extras);
2201
2588
  }
@@ -2205,9 +2592,6 @@ class Hub {
2205
2592
  * @deprecated Use `Sentry.setTag()` instead.
2206
2593
  */
2207
2594
  setTag(key, value) {
2208
- // TODO(v8): The top level `Sentry.setTag()` function should write ONLY to the isolation scope.
2209
- // eslint-disable-next-line deprecation/deprecation
2210
- this.getScope().setTag(key, value);
2211
2595
  // eslint-disable-next-line deprecation/deprecation
2212
2596
  this.getIsolationScope().setTag(key, value);
2213
2597
  }
@@ -2217,9 +2601,6 @@ class Hub {
2217
2601
  * @deprecated Use `Sentry.setExtra()` instead.
2218
2602
  */
2219
2603
  setExtra(key, extra) {
2220
- // TODO(v8): The top level `Sentry.setExtra()` function should write ONLY to the isolation scope.
2221
- // eslint-disable-next-line deprecation/deprecation
2222
- this.getScope().setExtra(key, extra);
2223
2604
  // eslint-disable-next-line deprecation/deprecation
2224
2605
  this.getIsolationScope().setExtra(key, extra);
2225
2606
  }
@@ -2230,40 +2611,10 @@ class Hub {
2230
2611
  */
2231
2612
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2232
2613
  setContext(name, context) {
2233
- // TODO(v8): The top level `Sentry.setContext()` function should write ONLY to the isolation scope.
2234
- // eslint-disable-next-line deprecation/deprecation
2235
- this.getScope().setContext(name, context);
2236
2614
  // eslint-disable-next-line deprecation/deprecation
2237
2615
  this.getIsolationScope().setContext(name, context);
2238
2616
  }
2239
2617
 
2240
- /**
2241
- * @inheritDoc
2242
- *
2243
- * @deprecated Use `getScope()` directly.
2244
- */
2245
- configureScope(callback) {
2246
- // eslint-disable-next-line deprecation/deprecation
2247
- const { scope, client } = this.getStackTop();
2248
- if (client) {
2249
- callback(scope);
2250
- }
2251
- }
2252
-
2253
- /**
2254
- * @inheritDoc
2255
- */
2256
- run(callback) {
2257
- // eslint-disable-next-line deprecation/deprecation
2258
- const oldHub = makeMain(this);
2259
- try {
2260
- callback(this);
2261
- } finally {
2262
- // eslint-disable-next-line deprecation/deprecation
2263
- makeMain(oldHub);
2264
- }
2265
- }
2266
-
2267
2618
  /**
2268
2619
  * @inheritDoc
2269
2620
  * @deprecated Use `Sentry.getClient().getIntegrationByName()` instead.
@@ -2276,59 +2627,11 @@ class Hub {
2276
2627
  // eslint-disable-next-line deprecation/deprecation
2277
2628
  return client.getIntegration(integration);
2278
2629
  } catch (_oO) {
2279
- DEBUG_BUILD && logger.warn(`Cannot retrieve integration ${integration.id} from the current Hub`);
2630
+ DEBUG_BUILD$1 && logger.warn(`Cannot retrieve integration ${integration.id} from the current Hub`);
2280
2631
  return null;
2281
2632
  }
2282
2633
  }
2283
2634
 
2284
- /**
2285
- * Starts a new `Transaction` and returns it. This is the entry point to manual tracing instrumentation.
2286
- *
2287
- * A tree structure can be built by adding child spans to the transaction, and child spans to other spans. To start a
2288
- * new child span within the transaction or any span, call the respective `.startChild()` method.
2289
- *
2290
- * Every child span must be finished before the transaction is finished, otherwise the unfinished spans are discarded.
2291
- *
2292
- * The transaction must be finished with a call to its `.end()` method, at which point the transaction with all its
2293
- * finished child spans will be sent to Sentry.
2294
- *
2295
- * @param context Properties of the new `Transaction`.
2296
- * @param customSamplingContext Information given to the transaction sampling function (along with context-dependent
2297
- * default values). See {@link Options.tracesSampler}.
2298
- *
2299
- * @returns The transaction which was just started
2300
- *
2301
- * @deprecated Use `startSpan()`, `startSpanManual()` or `startInactiveSpan()` instead.
2302
- */
2303
- startTransaction(context, customSamplingContext) {
2304
- const result = this._callExtensionMethod('startTransaction', context, customSamplingContext);
2305
-
2306
- if (DEBUG_BUILD && !result) {
2307
- // eslint-disable-next-line deprecation/deprecation
2308
- const client = this.getClient();
2309
- if (!client) {
2310
- logger.warn(
2311
- "Tracing extension 'startTransaction' is missing. You should 'init' the SDK before calling 'startTransaction'",
2312
- );
2313
- } else {
2314
- logger.warn(`Tracing extension 'startTransaction' has not been added. Call 'addTracingExtensions' before calling 'init':
2315
- Sentry.addTracingExtensions();
2316
- Sentry.init({...});
2317
- `);
2318
- }
2319
- }
2320
-
2321
- return result;
2322
- }
2323
-
2324
- /**
2325
- * @inheritDoc
2326
- * @deprecated Use `spanToTraceHeader()` instead.
2327
- */
2328
- traceHeaders() {
2329
- return this._callExtensionMethod('traceHeaders');
2330
- }
2331
-
2332
2635
  /**
2333
2636
  * @inheritDoc
2334
2637
  *
@@ -2394,152 +2697,704 @@ Sentry.init({...});
2394
2697
  // Afterwards we set the new session on the scope
2395
2698
  scope.setSession(session);
2396
2699
 
2397
- return session;
2398
- }
2700
+ return session;
2701
+ }
2702
+
2703
+ /**
2704
+ * Returns if default PII should be sent to Sentry and propagated in ourgoing requests
2705
+ * when Tracing is used.
2706
+ *
2707
+ * @deprecated Use top-level `getClient().getOptions().sendDefaultPii` instead. This function
2708
+ * only unnecessarily increased API surface but only wrapped accessing the option.
2709
+ */
2710
+ shouldSendDefaultPii() {
2711
+ // eslint-disable-next-line deprecation/deprecation
2712
+ const client = this.getClient();
2713
+ const options = client && client.getOptions();
2714
+ return Boolean(options && options.sendDefaultPii);
2715
+ }
2716
+
2717
+ /**
2718
+ * Sends the current Session on the scope
2719
+ */
2720
+ _sendSessionUpdate() {
2721
+ // eslint-disable-next-line deprecation/deprecation
2722
+ const { scope, client } = this.getStackTop();
2723
+
2724
+ const session = scope.getSession();
2725
+ if (session && client && client.captureSession) {
2726
+ client.captureSession(session);
2727
+ }
2728
+ }
2729
+
2730
+ /**
2731
+ * Calls global extension method and binding current instance to the function call
2732
+ */
2733
+ // @ts-expect-error Function lacks ending return statement and return type does not include 'undefined'. ts(2366)
2734
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2735
+ _callExtensionMethod(method, ...args) {
2736
+ const carrier = getMainCarrier();
2737
+ const sentry = getSentryCarrier(carrier);
2738
+ if (sentry.extensions && typeof sentry.extensions[method] === 'function') {
2739
+ return sentry.extensions[method].apply(this, args);
2740
+ }
2741
+ DEBUG_BUILD$1 && logger.warn(`Extension method ${method} couldn't be found, doing nothing.`);
2742
+ }
2743
+ }
2744
+
2745
+ /**
2746
+ * Returns the default hub instance.
2747
+ *
2748
+ * If a hub is already registered in the global carrier but this module
2749
+ * contains a more recent version, it replaces the registered version.
2750
+ * Otherwise, the currently registered hub will be returned.
2751
+ *
2752
+ * @deprecated Use the respective replacement method directly instead.
2753
+ */
2754
+ function getCurrentHub() {
2755
+ // Get main carrier (global for every environment)
2756
+ const carrier = getMainCarrier();
2757
+
2758
+ const acs = getAsyncContextStrategy(carrier);
2759
+ return acs.getCurrentHub() || getGlobalHub();
2760
+ }
2761
+
2762
+ /** Get the default current scope. */
2763
+ function getDefaultCurrentScope() {
2764
+ return getGlobalSingleton('defaultCurrentScope', () => new Scope());
2765
+ }
2766
+
2767
+ /** Get the default isolation scope. */
2768
+ function getDefaultIsolationScope() {
2769
+ return getGlobalSingleton('defaultIsolationScope', () => new Scope());
2770
+ }
2771
+
2772
+ /**
2773
+ * Get the global hub.
2774
+ * This will be removed during the v8 cycle and is only here to make migration easier.
2775
+ */
2776
+ function getGlobalHub() {
2777
+ const registry = getMainCarrier();
2778
+ const sentry = getSentryCarrier(registry) ;
2779
+
2780
+ // If there's no hub, or its an old API, assign a new one
2781
+ if (sentry.hub) {
2782
+ return sentry.hub;
2783
+ }
2784
+
2785
+ // eslint-disable-next-line deprecation/deprecation
2786
+ sentry.hub = new Hub(undefined, getDefaultCurrentScope(), getDefaultIsolationScope());
2787
+ return sentry.hub;
2788
+ }
2789
+
2790
+ /**
2791
+ * Get the current async context strategy.
2792
+ * If none has been setup, the default will be used.
2793
+ */
2794
+ function getAsyncContextStrategy(carrier) {
2795
+ const sentry = getSentryCarrier(carrier);
2796
+
2797
+ if (sentry.acs) {
2798
+ return sentry.acs;
2799
+ }
2800
+
2801
+ // Otherwise, use the default one
2802
+ return getHubStackAsyncContextStrategy();
2803
+ }
2804
+
2805
+ function withScope$1(callback) {
2806
+ // eslint-disable-next-line deprecation/deprecation
2807
+ return getGlobalHub().withScope(callback);
2808
+ }
2809
+
2810
+ function withSetScope(scope, callback) {
2811
+ const hub = getGlobalHub() ;
2812
+ // eslint-disable-next-line deprecation/deprecation
2813
+ return hub.withScope(() => {
2814
+ // eslint-disable-next-line deprecation/deprecation
2815
+ hub.getStackTop().scope = scope ;
2816
+ return callback(scope);
2817
+ });
2818
+ }
2819
+
2820
+ function withIsolationScope$1(callback) {
2821
+ // eslint-disable-next-line deprecation/deprecation
2822
+ return getGlobalHub().withScope(() => {
2823
+ // eslint-disable-next-line deprecation/deprecation
2824
+ return callback(getGlobalHub().getIsolationScope());
2825
+ });
2826
+ }
2827
+
2828
+ /* eslint-disable deprecation/deprecation */
2829
+ function getHubStackAsyncContextStrategy() {
2830
+ return {
2831
+ getCurrentHub: getGlobalHub,
2832
+ withIsolationScope: withIsolationScope$1,
2833
+ withScope: withScope$1,
2834
+ withSetScope,
2835
+ withSetIsolationScope: (_isolationScope, callback) => {
2836
+ return withIsolationScope$1(callback);
2837
+ },
2838
+ getCurrentScope: () => getGlobalHub().getScope(),
2839
+ getIsolationScope: () => getGlobalHub().getIsolationScope(),
2840
+ };
2841
+ }
2842
+ /* eslint-enable deprecation/deprecation */
2843
+
2844
+ /**
2845
+ * Get the currently active scope.
2846
+ */
2847
+ function getCurrentScope() {
2848
+ const carrier = getMainCarrier();
2849
+ const acs = getAsyncContextStrategy(carrier);
2850
+ return acs.getCurrentScope();
2851
+ }
2852
+
2853
+ /**
2854
+ * Get the currently active client.
2855
+ */
2856
+ function getClient() {
2857
+ return getCurrentScope().getClient();
2858
+ }
2859
+
2860
+ /**
2861
+ * Fetches the metric summary if it exists for the passed span
2862
+ */
2863
+ function getMetricSummaryJsonForSpan(span) {
2864
+
2865
+ {
2866
+ return undefined;
2867
+ }
2868
+ }
2869
+
2870
+ /**
2871
+ * Use this attribute to represent the operation of a span.
2872
+ */
2873
+ const SEMANTIC_ATTRIBUTE_SENTRY_OP = 'sentry.op';
2874
+
2875
+ /**
2876
+ * Use this attribute to represent the origin of a span.
2877
+ */
2878
+ const SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN = 'sentry.origin';
2879
+
2880
+ const SPAN_STATUS_UNSET = 0;
2881
+ const SPAN_STATUS_OK = 1;
2882
+ const TRACE_FLAG_SAMPLED = 0x1;
2883
+
2884
+ /**
2885
+ * Convert a span time input intp a timestamp in seconds.
2886
+ */
2887
+ function spanTimeInputToSeconds(input) {
2888
+ if (typeof input === 'number') {
2889
+ return ensureTimestampInSeconds(input);
2890
+ }
2891
+
2892
+ if (Array.isArray(input)) {
2893
+ // See {@link HrTime} for the array-based time format
2894
+ return input[0] + input[1] / 1e9;
2895
+ }
2896
+
2897
+ if (input instanceof Date) {
2898
+ return ensureTimestampInSeconds(input.getTime());
2899
+ }
2900
+
2901
+ return timestampInSeconds();
2902
+ }
2903
+
2904
+ /**
2905
+ * Converts a timestamp to second, if it was in milliseconds, or keeps it as second.
2906
+ */
2907
+ function ensureTimestampInSeconds(timestamp) {
2908
+ const isMs = timestamp > 9999999999;
2909
+ return isMs ? timestamp / 1000 : timestamp;
2910
+ }
2911
+
2912
+ /**
2913
+ * Convert a span to a JSON representation.
2914
+ * Note that all fields returned here are optional and need to be guarded against.
2915
+ *
2916
+ * Note: Because of this, we currently have a circular type dependency (which we opted out of in package.json).
2917
+ * This is not avoidable as we need `spanToJSON` in `spanUtils.ts`, which in turn is needed by `span.ts` for backwards compatibility.
2918
+ * And `spanToJSON` needs the Span class from `span.ts` to check here.
2919
+ */
2920
+ function spanToJSON(span) {
2921
+ if (spanIsSentrySpan(span)) {
2922
+ return span.getSpanJSON();
2923
+ }
2924
+
2925
+ try {
2926
+ const { spanId: span_id, traceId: trace_id } = span.spanContext();
2927
+
2928
+ // Handle a span from @opentelemetry/sdk-base-trace's `Span` class
2929
+ if (spanIsOpenTelemetrySdkTraceBaseSpan(span)) {
2930
+ const { attributes, startTime, name, endTime, parentSpanId, status } = span;
2931
+
2932
+ return dropUndefinedKeys({
2933
+ span_id,
2934
+ trace_id,
2935
+ data: attributes,
2936
+ description: name,
2937
+ parent_span_id: parentSpanId,
2938
+ start_timestamp: spanTimeInputToSeconds(startTime),
2939
+ // This is [0,0] by default in OTEL, in which case we want to interpret this as no end time
2940
+ timestamp: spanTimeInputToSeconds(endTime) || undefined,
2941
+ status: getStatusMessage(status),
2942
+ op: attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP],
2943
+ origin: attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] ,
2944
+ _metrics_summary: getMetricSummaryJsonForSpan(span),
2945
+ });
2946
+ }
2947
+
2948
+ // Finally, at least we have `spanContext()`....
2949
+ return {
2950
+ span_id,
2951
+ trace_id,
2952
+ };
2953
+ } catch (e) {
2954
+ return {};
2955
+ }
2956
+ }
2957
+
2958
+ function spanIsOpenTelemetrySdkTraceBaseSpan(span) {
2959
+ const castSpan = span ;
2960
+ return !!castSpan.attributes && !!castSpan.startTime && !!castSpan.name && !!castSpan.endTime && !!castSpan.status;
2961
+ }
2962
+
2963
+ /** Exported only for tests. */
2964
+
2965
+ /**
2966
+ * Sadly, due to circular dependency checks we cannot actually import the Span class here and check for instanceof.
2967
+ * :( So instead we approximate this by checking if it has the `getSpanJSON` method.
2968
+ */
2969
+ function spanIsSentrySpan(span) {
2970
+ return typeof (span ).getSpanJSON === 'function';
2971
+ }
2972
+
2973
+ /**
2974
+ * Returns true if a span is sampled.
2975
+ * In most cases, you should just use `span.isRecording()` instead.
2976
+ * However, this has a slightly different semantic, as it also returns false if the span is finished.
2977
+ * So in the case where this distinction is important, use this method.
2978
+ */
2979
+ function spanIsSampled(span) {
2980
+ // We align our trace flags with the ones OpenTelemetry use
2981
+ // So we also check for sampled the same way they do.
2982
+ const { traceFlags } = span.spanContext();
2983
+ return traceFlags === TRACE_FLAG_SAMPLED;
2984
+ }
2985
+
2986
+ /** Get the status message to use for a JSON representation of a span. */
2987
+ function getStatusMessage(status) {
2988
+ if (!status || status.code === SPAN_STATUS_UNSET) {
2989
+ return undefined;
2990
+ }
2991
+
2992
+ if (status.code === SPAN_STATUS_OK) {
2993
+ return 'ok';
2994
+ }
2995
+
2996
+ return status.message || 'unknown_error';
2997
+ }
2998
+ const ROOT_SPAN_FIELD = '_sentryRootSpan';
2999
+
3000
+ /**
3001
+ * Returns the root span of a given span.
3002
+ */
3003
+ function getRootSpan(span) {
3004
+ return span[ROOT_SPAN_FIELD] || span;
3005
+ }
3006
+
3007
+ /**
3008
+ * Convert a new integration function to the legacy class syntax.
3009
+ * In v8, we can remove this and instead export the integration functions directly.
3010
+ *
3011
+ * @deprecated This will be removed in v8!
3012
+ */
3013
+ function convertIntegrationFnToClass(
3014
+ name,
3015
+ fn,
3016
+ ) {
3017
+ return Object.assign(
3018
+ function ConvertedIntegration(...args) {
3019
+ return fn(...args);
3020
+ },
3021
+ { id: name },
3022
+ ) ;
3023
+ }
3024
+
3025
+ /**
3026
+ * Define an integration function that can be used to create an integration instance.
3027
+ * Note that this by design hides the implementation details of the integration, as they are considered internal.
3028
+ */
3029
+ function defineIntegration(fn) {
3030
+ return fn;
3031
+ }
3032
+
3033
+ /** Keys are source filename/url, values are metadata objects. */
3034
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3035
+ const filenameMetadataMap = new Map();
3036
+ /** Set of stack strings that have already been parsed. */
3037
+ const parsedStacks = new Set();
2399
3038
 
2400
- /**
2401
- * Returns if default PII should be sent to Sentry and propagated in ourgoing requests
2402
- * when Tracing is used.
2403
- *
2404
- * @deprecated Use top-level `getClient().getOptions().sendDefaultPii` instead. This function
2405
- * only unnecessarily increased API surface but only wrapped accessing the option.
2406
- */
2407
- shouldSendDefaultPii() {
2408
- // eslint-disable-next-line deprecation/deprecation
2409
- const client = this.getClient();
2410
- const options = client && client.getOptions();
2411
- return Boolean(options && options.sendDefaultPii);
3039
+ function ensureMetadataStacksAreParsed(parser) {
3040
+ if (!GLOBAL_OBJ._sentryModuleMetadata) {
3041
+ return;
2412
3042
  }
2413
3043
 
2414
- /**
2415
- * Sends the current Session on the scope
2416
- */
2417
- _sendSessionUpdate() {
2418
- // eslint-disable-next-line deprecation/deprecation
2419
- const { scope, client } = this.getStackTop();
3044
+ for (const stack of Object.keys(GLOBAL_OBJ._sentryModuleMetadata)) {
3045
+ const metadata = GLOBAL_OBJ._sentryModuleMetadata[stack];
2420
3046
 
2421
- const session = scope.getSession();
2422
- if (session && client && client.captureSession) {
2423
- client.captureSession(session);
3047
+ if (parsedStacks.has(stack)) {
3048
+ continue;
2424
3049
  }
2425
- }
2426
3050
 
2427
- /**
2428
- * Calls global extension method and binding current instance to the function call
2429
- */
2430
- // @ts-expect-error Function lacks ending return statement and return type does not include 'undefined'. ts(2366)
2431
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2432
- _callExtensionMethod(method, ...args) {
2433
- const carrier = getMainCarrier();
2434
- const sentry = carrier.__SENTRY__;
2435
- if (sentry && sentry.extensions && typeof sentry.extensions[method] === 'function') {
2436
- return sentry.extensions[method].apply(this, args);
3051
+ // Ensure this stack doesn't get parsed again
3052
+ parsedStacks.add(stack);
3053
+
3054
+ const frames = parser(stack);
3055
+
3056
+ // Go through the frames starting from the top of the stack and find the first one with a filename
3057
+ for (const frame of frames.reverse()) {
3058
+ if (frame.filename) {
3059
+ // Save the metadata for this filename
3060
+ filenameMetadataMap.set(frame.filename, metadata);
3061
+ break;
3062
+ }
2437
3063
  }
2438
- DEBUG_BUILD && logger.warn(`Extension method ${method} couldn't be found, doing nothing.`);
2439
3064
  }
2440
3065
  }
2441
3066
 
2442
3067
  /**
2443
- * Returns the global shim registry.
3068
+ * Retrieve metadata for a specific JavaScript file URL.
2444
3069
  *
2445
- * FIXME: This function is problematic, because despite always returning a valid Carrier,
2446
- * it has an optional `__SENTRY__` property, which then in turn requires us to always perform an unnecessary check
2447
- * at the call-site. We always access the carrier through this function, so we can guarantee that `__SENTRY__` is there.
2448
- **/
2449
- function getMainCarrier() {
2450
- GLOBAL_OBJ.__SENTRY__ = GLOBAL_OBJ.__SENTRY__ || {
2451
- extensions: {},
2452
- hub: undefined,
2453
- };
2454
- return GLOBAL_OBJ;
3070
+ * Metadata is injected by the Sentry bundler plugins using the `_experiments.moduleMetadata` config option.
3071
+ */
3072
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3073
+ function getMetadataForUrl(parser, filename) {
3074
+ ensureMetadataStacksAreParsed(parser);
3075
+ return filenameMetadataMap.get(filename);
2455
3076
  }
2456
3077
 
2457
3078
  /**
2458
- * Replaces the current main hub with the passed one on the global object
3079
+ * Adds metadata to stack frames.
2459
3080
  *
2460
- * @returns The old replaced hub
2461
- *
2462
- * @deprecated Use `setCurrentClient()` instead.
3081
+ * Metadata is injected by the Sentry bundler plugins using the `_experiments.moduleMetadata` config option.
2463
3082
  */
2464
- function makeMain(hub) {
2465
- const registry = getMainCarrier();
2466
- const oldHub = getHubFromCarrier(registry);
2467
- setHubOnCarrier(registry, hub);
2468
- return oldHub;
3083
+ function addMetadataToStackFrames(parser, event) {
3084
+ try {
3085
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
3086
+ event.exception.values.forEach(exception => {
3087
+ if (!exception.stacktrace) {
3088
+ return;
3089
+ }
3090
+
3091
+ for (const frame of exception.stacktrace.frames || []) {
3092
+ if (!frame.filename) {
3093
+ continue;
3094
+ }
3095
+
3096
+ const metadata = getMetadataForUrl(parser, frame.filename);
3097
+
3098
+ if (metadata) {
3099
+ frame.module_metadata = metadata;
3100
+ }
3101
+ }
3102
+ });
3103
+ } catch (_) {
3104
+ // To save bundle size we're just try catching here instead of checking for the existence of all the different objects.
3105
+ }
2469
3106
  }
2470
3107
 
2471
3108
  /**
2472
- * Returns the default hub instance.
3109
+ * Strips metadata from stack frames.
3110
+ */
3111
+ function stripMetadataFromStackFrames(event) {
3112
+ try {
3113
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
3114
+ event.exception.values.forEach(exception => {
3115
+ if (!exception.stacktrace) {
3116
+ return;
3117
+ }
3118
+
3119
+ for (const frame of exception.stacktrace.frames || []) {
3120
+ delete frame.module_metadata;
3121
+ }
3122
+ });
3123
+ } catch (_) {
3124
+ // To save bundle size we're just try catching here instead of checking for the existence of all the different objects.
3125
+ }
3126
+ }
3127
+
3128
+ const INTEGRATION_NAME$a = 'ModuleMetadata';
3129
+
3130
+ const _moduleMetadataIntegration = (() => {
3131
+ return {
3132
+ name: INTEGRATION_NAME$a,
3133
+ setup(client) {
3134
+ // We need to strip metadata from stack frames before sending them to Sentry since these are client side only.
3135
+ client.on('beforeEnvelope', envelope => {
3136
+ forEachEnvelopeItem(envelope, (item, type) => {
3137
+ if (type === 'event') {
3138
+ const event = Array.isArray(item) ? (item )[1] : undefined;
3139
+
3140
+ if (event) {
3141
+ stripMetadataFromStackFrames(event);
3142
+ item[1] = event;
3143
+ }
3144
+ }
3145
+ });
3146
+ });
3147
+ },
3148
+
3149
+ processEvent(event, _hint, client) {
3150
+ const stackParser = client.getOptions().stackParser;
3151
+ addMetadataToStackFrames(stackParser, event);
3152
+ return event;
3153
+ },
3154
+ };
3155
+ }) ;
3156
+
3157
+ const moduleMetadataIntegration = defineIntegration(_moduleMetadataIntegration);
3158
+
3159
+ /**
3160
+ * Adds module metadata to stack frames.
2473
3161
  *
2474
- * If a hub is already registered in the global carrier but this module
2475
- * contains a more recent version, it replaces the registered version.
2476
- * Otherwise, the currently registered hub will be returned.
3162
+ * Metadata can be injected by the Sentry bundler plugins using the `_experiments.moduleMetadata` config option.
2477
3163
  *
2478
- * @deprecated Use the respective replacement method directly instead.
3164
+ * When this integration is added, the metadata passed to the bundler plugin is added to the stack frames of all events
3165
+ * under the `module_metadata` property. This can be used to help in tagging or routing of events from different teams
3166
+ * our sources
3167
+ *
3168
+ * @deprecated Use `moduleMetadataIntegration()` instead.
3169
+ */
3170
+ // eslint-disable-next-line deprecation/deprecation
3171
+ convertIntegrationFnToClass(
3172
+ INTEGRATION_NAME$a,
3173
+ moduleMetadataIntegration,
3174
+ )
3175
+
3176
+ ;
3177
+
3178
+ const DEFAULT_OPTIONS = {
3179
+ include: {
3180
+ cookies: true,
3181
+ data: true,
3182
+ headers: true,
3183
+ ip: false,
3184
+ query_string: true,
3185
+ url: true,
3186
+ user: {
3187
+ id: true,
3188
+ username: true,
3189
+ email: true,
3190
+ },
3191
+ },
3192
+ transactionNamingScheme: 'methodPath' ,
3193
+ };
3194
+
3195
+ const INTEGRATION_NAME$9 = 'RequestData';
3196
+
3197
+ const _requestDataIntegration = ((options = {}) => {
3198
+ const _options = {
3199
+ ...DEFAULT_OPTIONS,
3200
+ ...options,
3201
+ include: {
3202
+ ...DEFAULT_OPTIONS.include,
3203
+ ...options.include,
3204
+ user:
3205
+ options.include && typeof options.include.user === 'boolean'
3206
+ ? options.include.user
3207
+ : {
3208
+ ...DEFAULT_OPTIONS.include.user,
3209
+ // Unclear why TS still thinks `options.include.user` could be a boolean at this point
3210
+ ...((options.include || {}).user ),
3211
+ },
3212
+ },
3213
+ };
3214
+
3215
+ return {
3216
+ name: INTEGRATION_NAME$9,
3217
+ processEvent(event, _hint, client) {
3218
+ // Note: In the long run, most of the logic here should probably move into the request data utility functions. For
3219
+ // the moment it lives here, though, until https://github.com/getsentry/sentry-javascript/issues/5718 is addressed.
3220
+ // (TL;DR: Those functions touch many parts of the repo in many different ways, and need to be clened up. Once
3221
+ // that's happened, it will be easier to add this logic in without worrying about unexpected side effects.)
3222
+ const { transactionNamingScheme } = _options;
3223
+
3224
+ const { sdkProcessingMetadata = {} } = event;
3225
+ const req = sdkProcessingMetadata.request;
3226
+
3227
+ if (!req) {
3228
+ return event;
3229
+ }
3230
+
3231
+ const addRequestDataOptions = convertReqDataIntegrationOptsToAddReqDataOpts(_options);
3232
+
3233
+ const processedEvent = addRequestDataToEvent(event, req, addRequestDataOptions);
3234
+
3235
+ // Transaction events already have the right `transaction` value
3236
+ if (event.type === 'transaction' || transactionNamingScheme === 'handler') {
3237
+ return processedEvent;
3238
+ }
3239
+
3240
+ // In all other cases, use the request's associated transaction (if any) to overwrite the event's `transaction`
3241
+ // value with a high-quality one
3242
+ const reqWithTransaction = req ;
3243
+ const transaction = reqWithTransaction._sentryTransaction;
3244
+ if (transaction) {
3245
+ const name = spanToJSON(transaction).description || '';
3246
+
3247
+ // TODO (v8): Remove the nextjs check and just base it on `transactionNamingScheme` for all SDKs. (We have to
3248
+ // keep it the way it is for the moment, because changing the names of transactions in Sentry has the potential
3249
+ // to break things like alert rules.)
3250
+ const shouldIncludeMethodInTransactionName =
3251
+ getSDKName(client) === 'sentry.javascript.nextjs'
3252
+ ? name.startsWith('/api')
3253
+ : transactionNamingScheme !== 'path';
3254
+
3255
+ const [transactionValue] = extractPathForTransaction(req, {
3256
+ path: true,
3257
+ method: shouldIncludeMethodInTransactionName,
3258
+ customRoute: name,
3259
+ });
3260
+
3261
+ processedEvent.transaction = transactionValue;
3262
+ }
3263
+
3264
+ return processedEvent;
3265
+ },
3266
+ };
3267
+ }) ;
3268
+
3269
+ const requestDataIntegration = defineIntegration(_requestDataIntegration);
3270
+
3271
+ /**
3272
+ * Add data about a request to an event. Primarily for use in Node-based SDKs, but included in `@sentry/core`
3273
+ * so it can be used in cross-platform SDKs like `@sentry/nextjs`.
3274
+ * @deprecated Use `requestDataIntegration()` instead.
2479
3275
  */
2480
- function getCurrentHub() {
2481
- // Get main carrier (global for every environment)
2482
- const registry = getMainCarrier();
3276
+ // eslint-disable-next-line deprecation/deprecation
3277
+ convertIntegrationFnToClass(INTEGRATION_NAME$9, requestDataIntegration)
3278
+
3279
+ ;
2483
3280
 
2484
- if (registry.__SENTRY__ && registry.__SENTRY__.acs) {
2485
- const hub = registry.__SENTRY__.acs.getCurrentHub();
3281
+ /** Convert this integration's options to match what `addRequestDataToEvent` expects */
3282
+ /** TODO: Can possibly be deleted once https://github.com/getsentry/sentry-javascript/issues/5718 is fixed */
3283
+ function convertReqDataIntegrationOptsToAddReqDataOpts(
3284
+ integrationOptions,
3285
+ ) {
3286
+ const {
3287
+ transactionNamingScheme,
3288
+ include: { ip, user, ...requestOptions },
3289
+ } = integrationOptions;
2486
3290
 
2487
- if (hub) {
2488
- return hub;
3291
+ const requestIncludeKeys = ['method'];
3292
+ for (const [key, value] of Object.entries(requestOptions)) {
3293
+ if (value) {
3294
+ requestIncludeKeys.push(key);
2489
3295
  }
2490
3296
  }
2491
3297
 
2492
- // Return hub that lives on a global object
2493
- return getGlobalHub(registry);
2494
- }
3298
+ let addReqDataUserOpt;
3299
+ if (user === undefined) {
3300
+ addReqDataUserOpt = true;
3301
+ } else if (typeof user === 'boolean') {
3302
+ addReqDataUserOpt = user;
3303
+ } else {
3304
+ const userIncludeKeys = [];
3305
+ for (const [key, value] of Object.entries(user)) {
3306
+ if (value) {
3307
+ userIncludeKeys.push(key);
3308
+ }
3309
+ }
3310
+ addReqDataUserOpt = userIncludeKeys;
3311
+ }
2495
3312
 
2496
- function getGlobalHub(registry = getMainCarrier()) {
2497
- // If there's no hub, or its an old API, assign a new one
3313
+ return {
3314
+ include: {
3315
+ ip,
3316
+ user: addReqDataUserOpt,
3317
+ request: requestIncludeKeys.length !== 0 ? requestIncludeKeys : undefined,
3318
+ transaction: transactionNamingScheme,
3319
+ },
3320
+ };
3321
+ }
2498
3322
 
2499
- if (
2500
- !hasHubOnCarrier(registry) ||
2501
- // eslint-disable-next-line deprecation/deprecation
2502
- getHubFromCarrier(registry).isOlderThan(API_VERSION)
2503
- ) {
2504
- // eslint-disable-next-line deprecation/deprecation
2505
- setHubOnCarrier(registry, new Hub());
3323
+ function getSDKName(client) {
3324
+ try {
3325
+ // For a long chain like this, it's fewer bytes to combine a try-catch with assuming everything is there than to
3326
+ // write out a long chain of `a && a.b && a.b.c && ...`
3327
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
3328
+ return client.getOptions()._metadata.sdk.name;
3329
+ } catch (err) {
3330
+ // In theory we should never get here
3331
+ return undefined;
2506
3332
  }
2507
-
2508
- // Return hub that lives on a global object
2509
- return getHubFromCarrier(registry);
2510
3333
  }
2511
3334
 
3335
+ let originalFunctionToString;
3336
+
3337
+ const INTEGRATION_NAME$8 = 'FunctionToString';
3338
+
3339
+ const SETUP_CLIENTS = new WeakMap();
3340
+
3341
+ const _functionToStringIntegration = (() => {
3342
+ return {
3343
+ name: INTEGRATION_NAME$8,
3344
+ setupOnce() {
3345
+ // eslint-disable-next-line @typescript-eslint/unbound-method
3346
+ originalFunctionToString = Function.prototype.toString;
3347
+
3348
+ // intrinsics (like Function.prototype) might be immutable in some environments
3349
+ // e.g. Node with --frozen-intrinsics, XS (an embedded JavaScript engine) or SES (a JavaScript proposal)
3350
+ try {
3351
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3352
+ Function.prototype.toString = function ( ...args) {
3353
+ const originalFunction = getOriginalFunction(this);
3354
+ const context =
3355
+ SETUP_CLIENTS.has(getClient() ) && originalFunction !== undefined ? originalFunction : this;
3356
+ return originalFunctionToString.apply(context, args);
3357
+ };
3358
+ } catch (e) {
3359
+ // ignore errors here, just don't patch this
3360
+ }
3361
+ },
3362
+ setup(client) {
3363
+ SETUP_CLIENTS.set(client, true);
3364
+ },
3365
+ };
3366
+ }) ;
3367
+
2512
3368
  /**
2513
- * This will tell whether a carrier has a hub on it or not
2514
- * @param carrier object
3369
+ * Patch toString calls to return proper name for wrapped functions.
3370
+ *
3371
+ * ```js
3372
+ * Sentry.init({
3373
+ * integrations: [
3374
+ * functionToStringIntegration(),
3375
+ * ],
3376
+ * });
3377
+ * ```
2515
3378
  */
2516
- function hasHubOnCarrier(carrier) {
2517
- return !!(carrier && carrier.__SENTRY__ && carrier.__SENTRY__.hub);
2518
- }
3379
+ const functionToStringIntegration = defineIntegration(_functionToStringIntegration);
2519
3380
 
2520
3381
  /**
2521
- * This will create a new {@link Hub} and add to the passed object on
2522
- * __SENTRY__.hub.
2523
- * @param carrier object
2524
- * @hidden
3382
+ * Patch toString calls to return proper name for wrapped functions.
3383
+ *
3384
+ * @deprecated Use `functionToStringIntegration()` instead.
2525
3385
  */
2526
- function getHubFromCarrier(carrier) {
2527
- // eslint-disable-next-line deprecation/deprecation
2528
- return getGlobalSingleton('hub', () => new Hub(), carrier);
2529
- }
3386
+ // eslint-disable-next-line deprecation/deprecation
3387
+ convertIntegrationFnToClass(
3388
+ INTEGRATION_NAME$8,
3389
+ functionToStringIntegration,
3390
+ ) ;
2530
3391
 
2531
3392
  /**
2532
- * This will set passed {@link Hub} on the passed object's __SENTRY__.hub attribute
2533
- * @param carrier object
2534
- * @param hub Hub
2535
- * @returns A boolean indicating success or failure
3393
+ * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code.
3394
+ *
3395
+ * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking.
2536
3396
  */
2537
- function setHubOnCarrier(carrier, hub) {
2538
- if (!carrier) return false;
2539
- const __SENTRY__ = (carrier.__SENTRY__ = carrier.__SENTRY__ || {});
2540
- __SENTRY__.hub = hub;
2541
- return true;
2542
- }
3397
+ const DEBUG_BUILD = (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__);
2543
3398
 
2544
3399
  const stdlib = detectLibc.familySync();
2545
3400
  const platform = process.env['BUILD_PLATFORM'] || os.platform();
@@ -2562,7 +3417,6 @@ function importCppBindingsModule() {
2562
3417
  const binaryPath = path.join(path.resolve(process$1.env['SENTRY_PROFILER_BINARY_DIR']), `sentry_cpu_profiler-${identifier}`);
2563
3418
  return require(`${binaryPath}.node`);
2564
3419
  }
2565
- /* eslint-disable no-fallthrough */
2566
3420
  // We need the fallthrough so that in the end, we can fallback to the require dynamice require.
2567
3421
  // This is for cases where precompiled binaries were not provided, but may have been compiled from source.
2568
3422
  if (platform === 'darwin') {
@@ -2658,14 +3512,14 @@ const PrivateCpuProfilerBindings = importCppBindingsModule();
2658
3512
  const CpuProfilerBindings = {
2659
3513
  startProfiling(name) {
2660
3514
  if (!PrivateCpuProfilerBindings) {
2661
- DEBUG_BUILD$1 && logger.log('[Profiling] Bindings not loaded, ignoring call to startProfiling.');
3515
+ DEBUG_BUILD && logger.log('[Profiling] Bindings not loaded, ignoring call to startProfiling.');
2662
3516
  return;
2663
3517
  }
2664
3518
  return PrivateCpuProfilerBindings.startProfiling(name);
2665
3519
  },
2666
3520
  stopProfiling(name) {
2667
3521
  if (!PrivateCpuProfilerBindings) {
2668
- DEBUG_BUILD$1 &&
3522
+ DEBUG_BUILD &&
2669
3523
  logger.log('[Profiling] Bindings not loaded or profile was never started, ignoring call to stopProfiling.');
2670
3524
  return null;
2671
3525
  }
@@ -2673,10 +3527,8 @@ const CpuProfilerBindings = {
2673
3527
  },
2674
3528
  };
2675
3529
 
2676
- /* eslint-disable max-lines */
2677
3530
  // We require the file because if we import it, it will be included in the bundle.
2678
3531
  // I guess tsc does not check file contents when it's imported.
2679
- // eslint-disable-next-line
2680
3532
  const THREAD_ID_STRING = String(worker_threads.threadId);
2681
3533
  const THREAD_NAME = worker_threads.isMainThread ? 'main' : 'worker';
2682
3534
  const FORMAT_VERSION = '1';
@@ -2720,84 +3572,6 @@ function enrichWithThreadInformation(profile) {
2720
3572
  },
2721
3573
  };
2722
3574
  }
2723
- /**
2724
- * Extract sdk info from from the API metadata
2725
- * @param {SdkMetadata | undefined} metadata
2726
- * @returns {SdkInfo | undefined}
2727
- */
2728
- function getSdkMetadataForEnvelopeHeader(metadata) {
2729
- if (!metadata || !metadata.sdk) {
2730
- return undefined;
2731
- }
2732
- return { name: metadata.sdk.name, version: metadata.sdk.version };
2733
- }
2734
- /**
2735
- * Apply SdkInfo (name, version, packages, integrations) to the corresponding event key.
2736
- * Merge with existing data if any.
2737
- *
2738
- * @param {Event} event
2739
- * @param {SdkInfo | undefined} sdkInfo
2740
- * @returns {Event}
2741
- */
2742
- function enhanceEventWithSdkInfo(event, sdkInfo) {
2743
- if (!sdkInfo) {
2744
- return event;
2745
- }
2746
- event.sdk = event.sdk || {};
2747
- event.sdk.name = event.sdk.name || sdkInfo.name || 'unknown sdk';
2748
- event.sdk.version = event.sdk.version || sdkInfo.version || 'unknown sdk version';
2749
- event.sdk.integrations = [...(event.sdk.integrations || []), ...(sdkInfo.integrations || [])];
2750
- event.sdk.packages = [...(event.sdk.packages || []), ...(sdkInfo.packages || [])];
2751
- return event;
2752
- }
2753
- /**
2754
- *
2755
- * @param {Event} event
2756
- * @param {SdkInfo | undefined} sdkInfo
2757
- * @param {string | undefined} tunnel
2758
- * @param {DsnComponents} dsn
2759
- * @returns {EventEnvelopeHeaders}
2760
- */
2761
- function createEventEnvelopeHeaders(event, sdkInfo, tunnel, dsn) {
2762
- const dynamicSamplingContext = event.sdkProcessingMetadata && event.sdkProcessingMetadata['dynamicSamplingContext'];
2763
- return Object.assign(Object.assign(Object.assign({ event_id: event.event_id, sent_at: new Date().toISOString() }, (sdkInfo && { sdk: sdkInfo })), (!!tunnel && { dsn: dsnToString(dsn) })), (event.type === 'transaction' &&
2764
- dynamicSamplingContext && {
2765
- trace: dropUndefinedKeys(Object.assign({}, dynamicSamplingContext)),
2766
- }));
2767
- }
2768
- /**
2769
- * Creates a profiling event envelope from a Sentry event. If profile does not pass
2770
- * validation, returns null.
2771
- * @param {Event}
2772
- * @returns {Profile | null}
2773
- */
2774
- function createProfilingEventFromTransaction(event) {
2775
- var _a, _b, _c, _d, _e, _f, _g;
2776
- if (event.type !== 'transaction') {
2777
- // createProfilingEventEnvelope should only be called for transactions,
2778
- // we type guard this behavior with isProfiledTransactionEvent.
2779
- throw new TypeError('Profiling events may only be attached to transactions, this should never occur.');
2780
- }
2781
- const rawProfile = event.sdkProcessingMetadata['profile'];
2782
- if (rawProfile === undefined || rawProfile === null) {
2783
- throw new TypeError(`Cannot construct profiling event envelope without a valid profile. Got ${rawProfile} instead.`);
2784
- }
2785
- if (!rawProfile.profile_id) {
2786
- throw new TypeError(`Cannot construct profiling event envelope without a valid profile id. Got ${rawProfile.profile_id} instead.`);
2787
- }
2788
- if (!isValidProfile(rawProfile)) {
2789
- return null;
2790
- }
2791
- return createProfilePayload(rawProfile, {
2792
- release: (_a = event.release) !== null && _a !== void 0 ? _a : '',
2793
- environment: (_b = event.environment) !== null && _b !== void 0 ? _b : '',
2794
- event_id: (_c = event.event_id) !== null && _c !== void 0 ? _c : '',
2795
- transaction: (_d = event.transaction) !== null && _d !== void 0 ? _d : '',
2796
- start_timestamp: event.start_timestamp ? event.start_timestamp * 1000 : Date.now(),
2797
- trace_id: (_g = (_f = (_e = event.contexts) === null || _e === void 0 ? void 0 : _e['trace']) === null || _f === void 0 ? void 0 : _f['trace_id']) !== null && _g !== void 0 ? _g : '',
2798
- profile_id: rawProfile.profile_id,
2799
- });
2800
- }
2801
3575
  /**
2802
3576
  * Creates a profiling envelope item, if the profile does not pass validation, returns null.
2803
3577
  * @param {RawThreadCpuProfile}
@@ -2830,7 +3604,7 @@ function createProfilePayload(cpuProfile, { release, environment, event_id, tran
2830
3604
  // All profiles and transactions are rejected if this is the case and we want to
2831
3605
  // warn users that this is happening if they enable debug flag
2832
3606
  if (trace_id && trace_id.length !== 32) {
2833
- DEBUG_BUILD$1 && logger.log(`[Profiling] Invalid traceId: ${trace_id} on profiled event`);
3607
+ DEBUG_BUILD && logger.log(`[Profiling] Invalid traceId: ${trace_id} on profiled event`);
2834
3608
  }
2835
3609
  const enrichedThreadProfile = enrichWithThreadInformation(cpuProfile);
2836
3610
  const profile = {
@@ -2870,54 +3644,6 @@ function createProfilePayload(cpuProfile, { release, environment, event_id, tran
2870
3644
  };
2871
3645
  return profile;
2872
3646
  }
2873
- /**
2874
- * Creates an envelope from a profiling event.
2875
- * @param {Event} Profile
2876
- * @param {DsnComponents} dsn
2877
- * @param {SdkMetadata} metadata
2878
- * @param {string|undefined} tunnel
2879
- * @returns {Envelope|null}
2880
- */
2881
- function createProfilingEventEnvelope(event, dsn, metadata, tunnel) {
2882
- const sdkInfo = getSdkMetadataForEnvelopeHeader(metadata);
2883
- enhanceEventWithSdkInfo(event, metadata && metadata.sdk);
2884
- const envelopeHeaders = createEventEnvelopeHeaders(event, sdkInfo, tunnel, dsn);
2885
- const profile = createProfilingEventFromTransaction(event);
2886
- if (!profile) {
2887
- return null;
2888
- }
2889
- const envelopeItem = [
2890
- {
2891
- type: 'profile',
2892
- },
2893
- // @ts-expect-error profile is not part of EventItem yet
2894
- profile,
2895
- ];
2896
- return createEnvelope(envelopeHeaders, [envelopeItem]);
2897
- }
2898
- /**
2899
- * Check if event metadata contains profile information
2900
- * @param {Event}
2901
- * @returns {boolean}
2902
- */
2903
- function isProfiledTransactionEvent(event) {
2904
- return !!(event.sdkProcessingMetadata && event.sdkProcessingMetadata['profile']);
2905
- }
2906
- /**
2907
- * Due to how profiles are attached to event metadata, we may sometimes want to remove them to ensure
2908
- * they are not processed by other Sentry integrations. This can be the case when we cannot construct a valid
2909
- * profile from the data we have or some of the mechanisms to send the event (Hub, Transport etc) are not available to us.
2910
- *
2911
- * @param {Event | ProfiledEvent} event
2912
- * @returns {Event}
2913
- */
2914
- function maybeRemoveProfileFromSdkMetadata(event) {
2915
- if (!isProfiledTransactionEvent(event)) {
2916
- return event;
2917
- }
2918
- delete event.sdkProcessingMetadata.profile;
2919
- return event;
2920
- }
2921
3647
  /**
2922
3648
  * Checks the given sample rate to make sure it is valid type and value (a boolean, or a number between 0 and 1).
2923
3649
  * @param {unknown} rate
@@ -2926,7 +3652,7 @@ function maybeRemoveProfileFromSdkMetadata(event) {
2926
3652
  function isValidSampleRate(rate) {
2927
3653
  // we need to check NaN explicitly because it's of type 'number' and therefore wouldn't get caught by this typecheck
2928
3654
  if ((typeof rate !== 'number' && typeof rate !== 'boolean') || (typeof rate === 'number' && isNaN(rate))) {
2929
- DEBUG_BUILD$1 &&
3655
+ DEBUG_BUILD &&
2930
3656
  logger.warn(`[Profiling] Invalid sample rate. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify(rate)} of type ${JSON.stringify(typeof rate)}.`);
2931
3657
  return false;
2932
3658
  }
@@ -2936,7 +3662,7 @@ function isValidSampleRate(rate) {
2936
3662
  }
2937
3663
  // in case sampleRate is a boolean, it will get automatically cast to 1 if it's true and 0 if it's false
2938
3664
  if (rate < 0 || rate > 1) {
2939
- DEBUG_BUILD$1 && logger.warn(`[Profiling] Invalid sample rate. Sample rate must be between 0 and 1. Got ${rate}.`);
3665
+ DEBUG_BUILD && logger.warn(`[Profiling] Invalid sample rate. Sample rate must be between 0 and 1. Got ${rate}.`);
2940
3666
  return false;
2941
3667
  }
2942
3668
  return true;
@@ -2948,7 +3674,7 @@ function isValidSampleRate(rate) {
2948
3674
  */
2949
3675
  function isValidProfile(profile) {
2950
3676
  if (profile.samples.length <= 1) {
2951
- DEBUG_BUILD$1 &&
3677
+ DEBUG_BUILD &&
2952
3678
  // Log a warning if the profile has less than 2 samples so users can know why
2953
3679
  // they are not seeing any profiling data and we cant avoid the back and forth
2954
3680
  // of asking them to provide us with a dump of the profile data.
@@ -3071,40 +3797,44 @@ const MAX_PROFILE_DURATION_MS = 30 * 1000;
3071
3797
  * Takes a transaction and determines if it should be profiled or not. If it should be profiled, it returns the
3072
3798
  * profile_id, otherwise returns undefined. Takes care of setting profile context on transaction as well
3073
3799
  */
3074
- function maybeProfileTransaction(client, transaction, customSamplingContext) {
3800
+ function maybeProfileSpan(client, span, customSamplingContext) {
3075
3801
  // profilesSampleRate is multiplied with tracesSampleRate to get the final sampling rate. We dont perform
3076
- // the actual multiplication to get the final rate, but we discard the profile if the transaction was sampled,
3077
- // so anything after this block from here is based on the transaction sampling.
3078
- // eslint-disable-next-line deprecation/deprecation
3079
- if (!transaction.sampled) {
3802
+ // the actual multiplication to get the final rate, but we discard the profile if the span was sampled,
3803
+ // so anything after this block from here is based on the span sampling.
3804
+ if (!spanIsSampled(span)) {
3080
3805
  return;
3081
3806
  }
3082
3807
  // Client and options are required for profiling
3083
3808
  if (!client) {
3084
- DEBUG_BUILD$1 && logger.log('[Profiling] Profiling disabled, no client found.');
3809
+ DEBUG_BUILD && logger.log('[Profiling] Profiling disabled, no client found.');
3085
3810
  return;
3086
3811
  }
3087
3812
  const options = client.getOptions();
3088
3813
  if (!options) {
3089
- DEBUG_BUILD$1 && logger.log('[Profiling] Profiling disabled, no options found.');
3814
+ DEBUG_BUILD && logger.log('[Profiling] Profiling disabled, no options found.');
3090
3815
  return;
3091
3816
  }
3092
3817
  const profilesSampler = options.profilesSampler;
3093
3818
  let profilesSampleRate = options.profilesSampleRate;
3094
3819
  // Prefer sampler to sample rate if both are provided.
3095
3820
  if (typeof profilesSampler === 'function') {
3096
- // eslint-disable-next-line deprecation/deprecation
3097
- profilesSampleRate = profilesSampler(Object.assign({ transactionContext: transaction.toContext() }, customSamplingContext));
3821
+ const { description: spanName = '<unknown>', data } = spanToJSON(span);
3822
+ // We bail out early if that is not the case
3823
+ const parentSampled = true;
3824
+ profilesSampleRate = profilesSampler(Object.assign({ name: spanName, attributes: data, transactionContext: {
3825
+ name: spanName,
3826
+ parentSampled,
3827
+ }, parentSampled }, customSamplingContext));
3098
3828
  }
3099
3829
  // Since this is coming from the user (or from a function provided by the user), who knows what we might get. (The
3100
3830
  // only valid values are booleans or numbers between 0 and 1.)
3101
3831
  if (!isValidSampleRate(profilesSampleRate)) {
3102
- DEBUG_BUILD$1 && logger.warn('[Profiling] Discarding profile because of invalid sample rate.');
3832
+ DEBUG_BUILD && logger.warn('[Profiling] Discarding profile because of invalid sample rate.');
3103
3833
  return;
3104
3834
  }
3105
3835
  // if the function returned 0 (or false), or if `profileSampleRate` is 0, it's a sign the profile should be dropped
3106
3836
  if (!profilesSampleRate) {
3107
- DEBUG_BUILD$1 &&
3837
+ DEBUG_BUILD &&
3108
3838
  logger.log(`[Profiling] Discarding profile because ${typeof profilesSampler === 'function'
3109
3839
  ? 'profileSampler returned 0 or false'
3110
3840
  : 'a negative sampling decision was inherited or profileSampleRate is set to 0'}`);
@@ -3115,15 +3845,13 @@ function maybeProfileTransaction(client, transaction, customSamplingContext) {
3115
3845
  const sampled = profilesSampleRate === true ? true : Math.random() < profilesSampleRate;
3116
3846
  // Check if we should sample this profile
3117
3847
  if (!sampled) {
3118
- DEBUG_BUILD$1 &&
3848
+ DEBUG_BUILD &&
3119
3849
  logger.log(`[Profiling] Discarding profile because it's not included in the random sample (sampling rate = ${Number(profilesSampleRate)})`);
3120
3850
  return;
3121
3851
  }
3122
3852
  const profile_id = uuid4();
3123
3853
  CpuProfilerBindings.startProfiling(profile_id);
3124
- DEBUG_BUILD$1 &&
3125
- // eslint-disable-next-line deprecation/deprecation
3126
- logger.log(`[Profiling] started profiling transaction: ${transaction.name}`);
3854
+ DEBUG_BUILD && logger.log(`[Profiling] started profiling transaction: ${spanToJSON(span).description}`);
3127
3855
  // set transaction context - do this regardless if profiling fails down the line
3128
3856
  // so that we can still see the profile_id in the transaction context
3129
3857
  return profile_id;
@@ -3134,120 +3862,23 @@ function maybeProfileTransaction(client, transaction, customSamplingContext) {
3134
3862
  * @param profile_id
3135
3863
  * @returns
3136
3864
  */
3137
- function stopTransactionProfile(transaction, profile_id) {
3865
+ function stopSpanProfile(span, profile_id) {
3138
3866
  // Should not happen, but satisfy the type checker and be safe regardless.
3139
3867
  if (!profile_id) {
3140
3868
  return null;
3141
3869
  }
3142
3870
  const profile = CpuProfilerBindings.stopProfiling(profile_id);
3143
- DEBUG_BUILD$1 &&
3144
- // eslint-disable-next-line deprecation/deprecation
3145
- logger.log(`[Profiling] stopped profiling of transaction: ${transaction.name}`);
3146
- // In case of an overlapping transaction, stopProfiling may return null and silently ignore the overlapping profile.
3871
+ DEBUG_BUILD && logger.log(`[Profiling] stopped profiling of transaction: ${spanToJSON(span).description}`);
3872
+ // In case of an overlapping span, stopProfiling may return null and silently ignore the overlapping profile.
3147
3873
  if (!profile) {
3148
- DEBUG_BUILD$1 &&
3149
- logger.log(
3150
- // eslint-disable-next-line deprecation/deprecation
3151
- `[Profiling] profiler returned null profile for: ${transaction.name}`, 'this may indicate an overlapping transaction or a call to stopProfiling with a profile title that was never started');
3874
+ DEBUG_BUILD &&
3875
+ logger.log(`[Profiling] profiler returned null profile for: ${spanToJSON(span).description}`, 'this may indicate an overlapping span or a call to stopProfiling with a profile title that was never started');
3152
3876
  return null;
3153
3877
  }
3154
3878
  // Assign profile_id to the profile
3155
3879
  profile.profile_id = profile_id;
3156
3880
  return profile;
3157
3881
  }
3158
- /**
3159
- * Wraps startTransaction and stopTransaction with profiling related logic.
3160
- * startProfiling is called after the call to startTransaction in order to avoid our own code from
3161
- * being profiled. Because of that same reason, stopProfiling is called before the call to stopTransaction.
3162
- */
3163
- function __PRIVATE__wrapStartTransactionWithProfiling(startTransaction) {
3164
- return function wrappedStartTransaction(transactionContext, customSamplingContext) {
3165
- const transaction = startTransaction.call(this, transactionContext, customSamplingContext);
3166
- // Client is required if we want to profile
3167
- // eslint-disable-next-line deprecation/deprecation
3168
- const client = this.getClient();
3169
- if (!client) {
3170
- return transaction;
3171
- }
3172
- // Check if we should profile this transaction. If a profile_id is returned, then profiling has been started.
3173
- const profile_id = maybeProfileTransaction(client, transaction, customSamplingContext);
3174
- if (!profile_id) {
3175
- return transaction;
3176
- }
3177
- // A couple of important things to note here:
3178
- // `CpuProfilerBindings.stopProfiling` will be scheduled to run in 30seconds in order to exceed max profile duration.
3179
- // Whichever of the two (transaction.finish/timeout) is first to run, the profiling will be stopped and the gathered profile
3180
- // will be processed when the original transaction is finished. Since onProfileHandler can be invoked multiple times in the
3181
- // event of an error or user mistake (calling transaction.finish multiple times), it is important that the behavior of onProfileHandler
3182
- // is idempotent as we do not want any timings or profiles to be overriden by the last call to onProfileHandler.
3183
- // After the original finish method is called, the event will be reported through the integration and delegated to transport.
3184
- let profile = null;
3185
- const options = client.getOptions();
3186
- // Not intended for external use, hence missing types, but we want to profile a couple of things at Sentry that
3187
- // currently exceed the default timeout set by the SDKs.
3188
- const maxProfileDurationMs = (options._experiments && options._experiments['maxProfileDurationMs']) || MAX_PROFILE_DURATION_MS;
3189
- // Enqueue a timeout to prevent profiles from running over max duration.
3190
- let maxDurationTimeoutID = global.setTimeout(() => {
3191
- DEBUG_BUILD$1 &&
3192
- // eslint-disable-next-line deprecation/deprecation
3193
- logger.log('[Profiling] max profile duration elapsed, stopping profiling for:', transaction.name);
3194
- profile = stopTransactionProfile(transaction, profile_id);
3195
- }, maxProfileDurationMs);
3196
- // We need to reference the original finish call to avoid creating an infinite loop
3197
- // eslint-disable-next-line deprecation/deprecation
3198
- const originalFinish = transaction.finish.bind(transaction);
3199
- // Wrap the transaction finish method to stop profiling and set the profile on the transaction.
3200
- function profilingWrappedTransactionFinish() {
3201
- if (!profile_id) {
3202
- return originalFinish();
3203
- }
3204
- // We stop the handler first to ensure that the timeout is cleared and the profile is stopped.
3205
- if (maxDurationTimeoutID) {
3206
- global.clearTimeout(maxDurationTimeoutID);
3207
- maxDurationTimeoutID = undefined;
3208
- }
3209
- // onProfileHandler should always return the same profile even if this is called multiple times.
3210
- // Always call onProfileHandler to ensure stopProfiling is called and the timeout is cleared.
3211
- if (!profile) {
3212
- profile = stopTransactionProfile(transaction, profile_id);
3213
- }
3214
- // @ts-expect-error profile is not part of metadata
3215
- // eslint-disable-next-line deprecation/deprecation
3216
- transaction.setMetadata({ profile });
3217
- return originalFinish();
3218
- }
3219
- // eslint-disable-next-line deprecation/deprecation
3220
- transaction.finish = profilingWrappedTransactionFinish;
3221
- return transaction;
3222
- };
3223
- }
3224
- /**
3225
- * Patches startTransaction and stopTransaction with profiling logic.
3226
- * This is used by the SDK's that do not support event hooks.
3227
- * @private
3228
- */
3229
- function _addProfilingExtensionMethods() {
3230
- const carrier = getMainCarrier();
3231
- if (!carrier.__SENTRY__) {
3232
- DEBUG_BUILD$1 && logger.log("[Profiling] Can't find main carrier, profiling won't work.");
3233
- return;
3234
- }
3235
- carrier.__SENTRY__.extensions = carrier.__SENTRY__.extensions || {};
3236
- if (!carrier.__SENTRY__.extensions['startTransaction']) {
3237
- DEBUG_BUILD$1 && logger.log('[Profiling] startTransaction does not exists, profiling will not work.');
3238
- return;
3239
- }
3240
- DEBUG_BUILD$1 && logger.log('[Profiling] startTransaction exists, patching it with profiling functionality...');
3241
- carrier.__SENTRY__.extensions['startTransaction'] = __PRIVATE__wrapStartTransactionWithProfiling(
3242
- // This is patched by sentry/tracing, we are going to re-patch it...
3243
- carrier.__SENTRY__.extensions['startTransaction']);
3244
- }
3245
- /**
3246
- * This patches the global object and injects the Profiling extensions methods
3247
- */
3248
- function addProfilingExtensionMethods() {
3249
- _addProfilingExtensionMethods();
3250
- }
3251
3882
 
3252
3883
  const MAX_PROFILE_QUEUE_LENGTH = 50;
3253
3884
  const PROFILE_QUEUE = [];
@@ -3259,28 +3890,17 @@ function addToProfileQueue(profile) {
3259
3890
  PROFILE_QUEUE.shift();
3260
3891
  }
3261
3892
  }
3262
- /**
3263
- * We need this integration in order to send data to Sentry. We hook into the event processor
3264
- * and inspect each event to see if it is a transaction event and if that transaction event
3265
- * contains a profile on it's metadata. If that is the case, we create a profiling event envelope
3266
- * and delete the profile from the transaction metadata.
3267
- *
3268
- * @deprecated Use `nodeProfilingIntegration` instead.
3269
- */
3270
- class ProfilingIntegration {
3271
- constructor() {
3272
- this.name = 'ProfilingIntegration';
3273
- }
3274
- /**
3275
- * @inheritDoc
3276
- */
3277
- setupOnce(addGlobalEventProcessor, getCurrentHub) {
3278
- this.getCurrentHub = getCurrentHub;
3279
- // eslint-disable-next-line deprecation/deprecation
3280
- const client = this.getCurrentHub().getClient();
3281
- if (client && typeof client.on === 'function') {
3282
- client.on('startTransaction', (transaction) => {
3283
- const profile_id = maybeProfileTransaction(client, transaction, undefined);
3893
+ /** Exported only for tests. */
3894
+ const _nodeProfilingIntegration = (() => {
3895
+ return {
3896
+ name: 'ProfilingIntegration',
3897
+ setup(client) {
3898
+ const spanToProfileIdMap = new WeakMap();
3899
+ client.on('spanStart', span => {
3900
+ if (span !== getRootSpan(span)) {
3901
+ return;
3902
+ }
3903
+ const profile_id = maybeProfileSpan(client, span, undefined);
3284
3904
  if (profile_id) {
3285
3905
  const options = client.getOptions();
3286
3906
  // Not intended for external use, hence missing types, but we want to profile a couple of things at Sentry that
@@ -3293,32 +3913,26 @@ class ProfilingIntegration {
3293
3913
  }
3294
3914
  // Enqueue a timeout to prevent profiles from running over max duration.
3295
3915
  PROFILE_TIMEOUTS[profile_id] = global.setTimeout(() => {
3296
- DEBUG_BUILD$1 &&
3297
- // eslint-disable-next-line deprecation/deprecation
3298
- logger.log('[Profiling] max profile duration elapsed, stopping profiling for:', transaction.name);
3299
- const profile = stopTransactionProfile(transaction, profile_id);
3916
+ DEBUG_BUILD &&
3917
+ logger.log('[Profiling] max profile duration elapsed, stopping profiling for:', spanToJSON(span).description);
3918
+ const profile = stopSpanProfile(span, profile_id);
3300
3919
  if (profile) {
3301
3920
  addToProfileQueue(profile);
3302
3921
  }
3303
3922
  }, maxProfileDurationMs);
3304
- // eslint-disable-next-line deprecation/deprecation
3305
- transaction.setContext('profile', { profile_id });
3306
- // @ts-expect-error profile_id is not part of the metadata type
3307
- // eslint-disable-next-line deprecation/deprecation
3308
- transaction.setMetadata({ profile_id: profile_id });
3923
+ getCurrentScope().setContext('profile', { profile_id });
3924
+ spanToProfileIdMap.set(span, profile_id);
3309
3925
  }
3310
3926
  });
3311
- client.on('finishTransaction', transaction => {
3312
- // @ts-expect-error profile_id is not part of the metadata type
3313
- // eslint-disable-next-line deprecation/deprecation
3314
- const profile_id = transaction.metadata.profile_id;
3315
- if (profile_id && typeof profile_id === 'string') {
3927
+ client.on('spanEnd', span => {
3928
+ const profile_id = spanToProfileIdMap.get(span);
3929
+ if (profile_id) {
3316
3930
  if (PROFILE_TIMEOUTS[profile_id]) {
3317
3931
  global.clearTimeout(PROFILE_TIMEOUTS[profile_id]);
3318
3932
  // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
3319
3933
  delete PROFILE_TIMEOUTS[profile_id];
3320
3934
  }
3321
- const profile = stopTransactionProfile(transaction, profile_id);
3935
+ const profile = stopSpanProfile(span, profile_id);
3322
3936
  if (profile) {
3323
3937
  addToProfileQueue(profile);
3324
3938
  }
@@ -3343,18 +3957,17 @@ class ProfilingIntegration {
3343
3957
  }
3344
3958
  // Remove the profile from the transaction context before sending, relay will take care of the rest.
3345
3959
  if (profileContext) {
3346
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
3347
3960
  (_b = profiledTransaction.contexts) === null || _b === void 0 ? true : delete _b['profile'];
3348
3961
  }
3349
3962
  // We need to find both a profile and a transaction event for the same profile_id.
3350
3963
  const profileIndex = PROFILE_QUEUE.findIndex(p => p.profile_id === profile_id);
3351
3964
  if (profileIndex === -1) {
3352
- DEBUG_BUILD$1 && logger.log(`[Profiling] Could not retrieve profile for transaction: ${profile_id}`);
3965
+ DEBUG_BUILD && logger.log(`[Profiling] Could not retrieve profile for transaction: ${profile_id}`);
3353
3966
  continue;
3354
3967
  }
3355
3968
  const cpuProfile = PROFILE_QUEUE[profileIndex];
3356
3969
  if (!cpuProfile) {
3357
- DEBUG_BUILD$1 && logger.log(`[Profiling] Could not retrieve profile for transaction: ${profile_id}`);
3970
+ DEBUG_BUILD && logger.log(`[Profiling] Could not retrieve profile for transaction: ${profile_id}`);
3358
3971
  continue;
3359
3972
  }
3360
3973
  // Remove the profile from the queue.
@@ -3376,70 +3989,16 @@ class ProfilingIntegration {
3376
3989
  }
3377
3990
  addProfilesToEnvelope(envelope, profilesToAddToEnvelope);
3378
3991
  });
3379
- }
3380
- else {
3381
- // Patch the carrier methods and add the event processor.
3382
- addProfilingExtensionMethods();
3383
- addGlobalEventProcessor(this.handleGlobalEvent.bind(this));
3384
- }
3385
- }
3386
- /**
3387
- * @inheritDoc
3388
- */
3389
- handleGlobalEvent(event) {
3390
- return __awaiter(this, void 0, void 0, function* () {
3391
- if (this.getCurrentHub === undefined) {
3392
- return maybeRemoveProfileFromSdkMetadata(event);
3393
- }
3394
- if (isProfiledTransactionEvent(event)) {
3395
- // Client, Dsn and Transport are all required to be able to send the profiling event to Sentry.
3396
- // If either of them is not available, we remove the profile from the transaction event.
3397
- // and forward it to the next event processor.
3398
- const hub = this.getCurrentHub();
3399
- // eslint-disable-next-line deprecation/deprecation
3400
- const client = hub.getClient();
3401
- if (!client) {
3402
- DEBUG_BUILD$1 &&
3403
- logger.log('[Profiling] getClient did not return a Client, removing profile from event and forwarding to next event processors.');
3404
- return maybeRemoveProfileFromSdkMetadata(event);
3405
- }
3406
- const dsn = client.getDsn();
3407
- if (!dsn) {
3408
- DEBUG_BUILD$1 &&
3409
- logger.log('[Profiling] getDsn did not return a Dsn, removing profile from event and forwarding to next event processors.');
3410
- return maybeRemoveProfileFromSdkMetadata(event);
3411
- }
3412
- const transport = client.getTransport();
3413
- if (!transport) {
3414
- DEBUG_BUILD$1 &&
3415
- logger.log('[Profiling] getTransport did not return a Transport, removing profile from event and forwarding to next event processors.');
3416
- return maybeRemoveProfileFromSdkMetadata(event);
3417
- }
3418
- // If all required components are available, we construct a profiling event envelope and send it to Sentry.
3419
- DEBUG_BUILD$1 && logger.log('[Profiling] Preparing envelope and sending a profiling event');
3420
- const envelope = createProfilingEventEnvelope(event, dsn);
3421
- if (envelope) {
3422
- // Fire and forget, we don't want to block the main event processing flow.
3423
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
3424
- transport.send(envelope);
3425
- }
3426
- }
3427
- // Ensure sdkProcessingMetadata["profile"] is removed from the event before forwarding it to the next event processor.
3428
- return maybeRemoveProfileFromSdkMetadata(event);
3429
- });
3430
- }
3431
- }
3992
+ },
3993
+ };
3994
+ });
3432
3995
  /**
3433
3996
  * We need this integration in order to send data to Sentry. We hook into the event processor
3434
3997
  * and inspect each event to see if it is a transaction event and if that transaction event
3435
3998
  * contains a profile on it's metadata. If that is the case, we create a profiling event envelope
3436
3999
  * and delete the profile from the transaction metadata.
3437
4000
  */
3438
- const nodeProfilingIntegration = (() => {
3439
- // eslint-disable-next-line deprecation/deprecation
3440
- return new ProfilingIntegration();
3441
- });
4001
+ const nodeProfilingIntegration = defineIntegration(_nodeProfilingIntegration);
3442
4002
 
3443
- exports.ProfilingIntegration = ProfilingIntegration;
3444
4003
  exports.nodeProfilingIntegration = nodeProfilingIntegration;
3445
4004
  //# sourceMappingURL=index.js.map