@sentry/browser 6.19.0 → 6.19.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/bundles/bundle.debug.min.js +2 -2
- package/bundles/bundle.debug.min.js.map +1 -1
- package/bundles/bundle.es6.debug.min.js +2 -2
- package/bundles/bundle.es6.debug.min.js.map +1 -1
- package/bundles/bundle.es6.js +736 -558
- package/bundles/bundle.es6.js.map +1 -1
- package/bundles/bundle.es6.min.js +2 -2
- package/bundles/bundle.es6.min.js.map +1 -1
- package/bundles/bundle.js +776 -591
- package/bundles/bundle.js.map +1 -1
- package/bundles/bundle.min.js +2 -2
- package/bundles/bundle.min.js.map +1 -1
- package/dist/backend.d.ts.map +1 -1
- package/dist/backend.js +8 -0
- package/dist/backend.js.map +1 -1
- package/dist/eventbuilder.js.map +1 -1
- package/dist/transports/index.d.ts +2 -0
- package/dist/transports/index.d.ts.map +1 -1
- package/dist/transports/index.js +4 -0
- package/dist/transports/index.js.map +1 -1
- package/dist/transports/new-fetch.d.ts +10 -0
- package/dist/transports/new-fetch.d.ts.map +1 -0
- package/dist/transports/new-fetch.js +27 -0
- package/dist/transports/new-fetch.js.map +1 -0
- package/dist/transports/new-xhr.d.ts +11 -0
- package/dist/transports/new-xhr.d.ts.map +1 -0
- package/dist/transports/new-xhr.js +46 -0
- package/dist/transports/new-xhr.js.map +1 -0
- package/esm/backend.d.ts.map +1 -1
- package/esm/backend.js +10 -2
- package/esm/backend.js.map +1 -1
- package/esm/eventbuilder.js.map +1 -1
- package/esm/transports/index.d.ts +2 -0
- package/esm/transports/index.d.ts.map +1 -1
- package/esm/transports/index.js +2 -0
- package/esm/transports/index.js.map +1 -1
- package/esm/transports/new-fetch.d.ts +10 -0
- package/esm/transports/new-fetch.d.ts.map +1 -0
- package/esm/transports/new-fetch.js +25 -0
- package/esm/transports/new-fetch.js.map +1 -0
- package/esm/transports/new-xhr.d.ts +11 -0
- package/esm/transports/new-xhr.d.ts.map +1 -0
- package/esm/transports/new-xhr.js +44 -0
- package/esm/transports/new-xhr.js.map +1 -0
- package/package.json +6 -6
- package/types/backend.d.ts.map +1 -1
- package/types/transports/index.d.ts +2 -0
- package/types/transports/index.d.ts.map +1 -1
- package/types/transports/new-fetch.d.ts +10 -0
- package/types/transports/new-fetch.d.ts.map +1 -0
- package/types/transports/new-xhr.d.ts +11 -0
- package/types/transports/new-xhr.d.ts.map +1 -0
package/bundles/bundle.es6.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @sentry/browser 6.19.
|
|
1
|
+
/*! @sentry/browser 6.19.3 (fe6f7b3) | https://github.com/getsentry/sentry-javascript */
|
|
2
2
|
var Sentry = (function (exports) {
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -201,6 +201,16 @@ var Sentry = (function (exports) {
|
|
|
201
201
|
function isSyntheticEvent(wat) {
|
|
202
202
|
return isPlainObject(wat) && 'nativeEvent' in wat && 'preventDefault' in wat && 'stopPropagation' in wat;
|
|
203
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* Checks whether given value is NaN
|
|
206
|
+
* {@link isNaN}.
|
|
207
|
+
*
|
|
208
|
+
* @param wat A value to be checked.
|
|
209
|
+
* @returns A boolean representing the result.
|
|
210
|
+
*/
|
|
211
|
+
function isNaN$1(wat) {
|
|
212
|
+
return typeof wat === 'number' && wat !== wat;
|
|
213
|
+
}
|
|
204
214
|
/**
|
|
205
215
|
* Checks whether given value's type is an instance of provided constructor.
|
|
206
216
|
* {@link isInstanceOf}.
|
|
@@ -525,114 +535,6 @@ var Sentry = (function (exports) {
|
|
|
525
535
|
global$6.__SENTRY__ = sentryGlobal;
|
|
526
536
|
}
|
|
527
537
|
|
|
528
|
-
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
529
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
530
|
-
/**
|
|
531
|
-
* Helper to decycle json objects
|
|
532
|
-
*/
|
|
533
|
-
function memoBuilder() {
|
|
534
|
-
const hasWeakSet = typeof WeakSet === 'function';
|
|
535
|
-
const inner = hasWeakSet ? new WeakSet() : [];
|
|
536
|
-
function memoize(obj) {
|
|
537
|
-
if (hasWeakSet) {
|
|
538
|
-
if (inner.has(obj)) {
|
|
539
|
-
return true;
|
|
540
|
-
}
|
|
541
|
-
inner.add(obj);
|
|
542
|
-
return false;
|
|
543
|
-
}
|
|
544
|
-
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
545
|
-
for (let i = 0; i < inner.length; i++) {
|
|
546
|
-
const value = inner[i];
|
|
547
|
-
if (value === obj) {
|
|
548
|
-
return true;
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
inner.push(obj);
|
|
552
|
-
return false;
|
|
553
|
-
}
|
|
554
|
-
function unmemoize(obj) {
|
|
555
|
-
if (hasWeakSet) {
|
|
556
|
-
inner.delete(obj);
|
|
557
|
-
}
|
|
558
|
-
else {
|
|
559
|
-
for (let i = 0; i < inner.length; i++) {
|
|
560
|
-
if (inner[i] === obj) {
|
|
561
|
-
inner.splice(i, 1);
|
|
562
|
-
break;
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
return [memoize, unmemoize];
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
const STACKTRACE_LIMIT = 50;
|
|
571
|
-
/**
|
|
572
|
-
* Creates a stack parser with the supplied line parsers
|
|
573
|
-
*
|
|
574
|
-
* StackFrames are returned in the correct order for Sentry Exception
|
|
575
|
-
* frames and with Sentry SDK internal frames removed from the top and bottom
|
|
576
|
-
*
|
|
577
|
-
*/
|
|
578
|
-
function createStackParser(...parsers) {
|
|
579
|
-
const sortedParsers = parsers.sort((a, b) => a[0] - b[0]).map(p => p[1]);
|
|
580
|
-
return (stack, skipFirst = 0) => {
|
|
581
|
-
const frames = [];
|
|
582
|
-
for (const line of stack.split('\n').slice(skipFirst)) {
|
|
583
|
-
for (const parser of sortedParsers) {
|
|
584
|
-
const frame = parser(line);
|
|
585
|
-
if (frame) {
|
|
586
|
-
frames.push(frame);
|
|
587
|
-
break;
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
return stripSentryFramesAndReverse(frames);
|
|
592
|
-
};
|
|
593
|
-
}
|
|
594
|
-
/**
|
|
595
|
-
* @hidden
|
|
596
|
-
*/
|
|
597
|
-
function stripSentryFramesAndReverse(stack) {
|
|
598
|
-
if (!stack.length) {
|
|
599
|
-
return [];
|
|
600
|
-
}
|
|
601
|
-
let localStack = stack;
|
|
602
|
-
const firstFrameFunction = localStack[0].function || '';
|
|
603
|
-
const lastFrameFunction = localStack[localStack.length - 1].function || '';
|
|
604
|
-
// If stack starts with one of our API calls, remove it (starts, meaning it's the top of the stack - aka last call)
|
|
605
|
-
if (firstFrameFunction.indexOf('captureMessage') !== -1 || firstFrameFunction.indexOf('captureException') !== -1) {
|
|
606
|
-
localStack = localStack.slice(1);
|
|
607
|
-
}
|
|
608
|
-
// If stack ends with one of our internal API calls, remove it (ends, meaning it's the bottom of the stack - aka top-most call)
|
|
609
|
-
if (lastFrameFunction.indexOf('sentryWrapped') !== -1) {
|
|
610
|
-
localStack = localStack.slice(0, -1);
|
|
611
|
-
}
|
|
612
|
-
// The frame where the crash happened, should be the last entry in the array
|
|
613
|
-
return localStack
|
|
614
|
-
.slice(0, STACKTRACE_LIMIT)
|
|
615
|
-
.map(frame => (Object.assign(Object.assign({}, frame), { filename: frame.filename || localStack[0].filename, function: frame.function || '?' })))
|
|
616
|
-
.reverse();
|
|
617
|
-
}
|
|
618
|
-
const defaultFunctionName = '<anonymous>';
|
|
619
|
-
/**
|
|
620
|
-
* Safely extract function name from itself
|
|
621
|
-
*/
|
|
622
|
-
function getFunctionName(fn) {
|
|
623
|
-
try {
|
|
624
|
-
if (!fn || typeof fn !== 'function') {
|
|
625
|
-
return defaultFunctionName;
|
|
626
|
-
}
|
|
627
|
-
return fn.name || defaultFunctionName;
|
|
628
|
-
}
|
|
629
|
-
catch (e) {
|
|
630
|
-
// Just accessing custom props in some Selenium environments
|
|
631
|
-
// can cause a "Permission denied" exception (see raven-js#495).
|
|
632
|
-
return defaultFunctionName;
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
|
|
636
538
|
/**
|
|
637
539
|
* Truncates given string to the maximum characters count
|
|
638
540
|
*
|
|
@@ -772,235 +674,38 @@ var Sentry = (function (exports) {
|
|
|
772
674
|
*
|
|
773
675
|
* @param value Initial source that we have to transform in order for it to be usable by the serializer
|
|
774
676
|
*/
|
|
775
|
-
function
|
|
677
|
+
function convertToPlainObject(value) {
|
|
678
|
+
let newObj = value;
|
|
776
679
|
if (isError(value)) {
|
|
777
|
-
|
|
778
|
-
const err = {
|
|
779
|
-
message: error.message,
|
|
780
|
-
name: error.name,
|
|
781
|
-
stack: error.stack,
|
|
782
|
-
};
|
|
783
|
-
for (const i in error) {
|
|
784
|
-
if (Object.prototype.hasOwnProperty.call(error, i)) {
|
|
785
|
-
err[i] = error[i];
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
return err;
|
|
680
|
+
newObj = Object.assign({ message: value.message, name: value.name, stack: value.stack }, getOwnProperties(value));
|
|
789
681
|
}
|
|
790
|
-
if (isEvent(value)) {
|
|
682
|
+
else if (isEvent(value)) {
|
|
791
683
|
const event = value;
|
|
792
|
-
|
|
793
|
-
// Accessing event attributes can throw (see https://github.com/getsentry/sentry-javascript/issues/768 and
|
|
794
|
-
// https://github.com/getsentry/sentry-javascript/issues/838), but accessing `type` hasn't been wrapped in a
|
|
795
|
-
// try-catch in at least two years and no one's complained, so that's likely not an issue anymore
|
|
796
|
-
source.type = event.type;
|
|
797
|
-
try {
|
|
798
|
-
source.target = isElement(event.target)
|
|
799
|
-
? htmlTreeAsString(event.target)
|
|
800
|
-
: Object.prototype.toString.call(event.target);
|
|
801
|
-
}
|
|
802
|
-
catch (_oO) {
|
|
803
|
-
source.target = '<unknown>';
|
|
804
|
-
}
|
|
805
|
-
try {
|
|
806
|
-
source.currentTarget = isElement(event.currentTarget)
|
|
807
|
-
? htmlTreeAsString(event.currentTarget)
|
|
808
|
-
: Object.prototype.toString.call(event.currentTarget);
|
|
809
|
-
}
|
|
810
|
-
catch (_oO) {
|
|
811
|
-
source.currentTarget = '<unknown>';
|
|
812
|
-
}
|
|
684
|
+
newObj = Object.assign({ type: event.type, target: serializeEventTarget(event.target), currentTarget: serializeEventTarget(event.currentTarget) }, getOwnProperties(event));
|
|
813
685
|
if (typeof CustomEvent !== 'undefined' && isInstanceOf(value, CustomEvent)) {
|
|
814
|
-
|
|
815
|
-
}
|
|
816
|
-
for (const attr in event) {
|
|
817
|
-
if (Object.prototype.hasOwnProperty.call(event, attr)) {
|
|
818
|
-
source[attr] = event[attr];
|
|
819
|
-
}
|
|
686
|
+
newObj.detail = event.detail;
|
|
820
687
|
}
|
|
821
|
-
return source;
|
|
822
688
|
}
|
|
823
|
-
return
|
|
689
|
+
return newObj;
|
|
824
690
|
}
|
|
825
|
-
/**
|
|
826
|
-
function
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
}
|
|
830
|
-
/** Calculates bytes size of input object */
|
|
831
|
-
function jsonSize(value) {
|
|
832
|
-
return utf8Length(JSON.stringify(value));
|
|
833
|
-
}
|
|
834
|
-
/** JSDoc */
|
|
835
|
-
function normalizeToSize(object,
|
|
836
|
-
// Default Node.js REPL depth
|
|
837
|
-
depth = 3,
|
|
838
|
-
// 100kB, as 200kB is max payload size, so half sounds reasonable
|
|
839
|
-
maxSize = 100 * 1024) {
|
|
840
|
-
const serialized = normalize(object, depth);
|
|
841
|
-
if (jsonSize(serialized) > maxSize) {
|
|
842
|
-
return normalizeToSize(object, depth - 1, maxSize);
|
|
843
|
-
}
|
|
844
|
-
return serialized;
|
|
845
|
-
}
|
|
846
|
-
/**
|
|
847
|
-
* Transform any non-primitive, BigInt, or Symbol-type value into a string. Acts as a no-op on strings, numbers,
|
|
848
|
-
* booleans, null, and undefined.
|
|
849
|
-
*
|
|
850
|
-
* @param value The value to stringify
|
|
851
|
-
* @returns For non-primitive, BigInt, and Symbol-type values, a string denoting the value's type, type and value, or
|
|
852
|
-
* type and `description` property, respectively. For non-BigInt, non-Symbol primitives, returns the original value,
|
|
853
|
-
* unchanged.
|
|
854
|
-
*/
|
|
855
|
-
function serializeValue(value) {
|
|
856
|
-
// Node.js REPL notation
|
|
857
|
-
if (typeof value === 'string') {
|
|
858
|
-
return value;
|
|
859
|
-
}
|
|
860
|
-
const type = Object.prototype.toString.call(value);
|
|
861
|
-
if (type === '[object Object]') {
|
|
862
|
-
return '[Object]';
|
|
863
|
-
}
|
|
864
|
-
if (type === '[object Array]') {
|
|
865
|
-
return '[Array]';
|
|
866
|
-
}
|
|
867
|
-
// `makeSerializable` provides a string representation of certain non-serializable values. For all others, it's a
|
|
868
|
-
// pass-through.
|
|
869
|
-
const serializable = makeSerializable(value);
|
|
870
|
-
return isPrimitive(serializable) ? serializable : type;
|
|
871
|
-
}
|
|
872
|
-
/**
|
|
873
|
-
* makeSerializable()
|
|
874
|
-
*
|
|
875
|
-
* Takes unserializable input and make it serializer-friendly.
|
|
876
|
-
*
|
|
877
|
-
* Handles globals, functions, `undefined`, `NaN`, and other non-serializable values.
|
|
878
|
-
*/
|
|
879
|
-
function makeSerializable(value, key) {
|
|
880
|
-
if (key === 'domain' && value && typeof value === 'object' && value._events) {
|
|
881
|
-
return '[Domain]';
|
|
882
|
-
}
|
|
883
|
-
if (key === 'domainEmitter') {
|
|
884
|
-
return '[DomainEmitter]';
|
|
885
|
-
}
|
|
886
|
-
if (typeof global !== 'undefined' && value === global) {
|
|
887
|
-
return '[Global]';
|
|
888
|
-
}
|
|
889
|
-
// It's safe to use `window` and `document` here in this manner, as we are asserting using `typeof` first
|
|
890
|
-
// which won't throw if they are not present.
|
|
891
|
-
// eslint-disable-next-line no-restricted-globals
|
|
892
|
-
if (typeof window !== 'undefined' && value === window) {
|
|
893
|
-
return '[Window]';
|
|
894
|
-
}
|
|
895
|
-
// eslint-disable-next-line no-restricted-globals
|
|
896
|
-
if (typeof document !== 'undefined' && value === document) {
|
|
897
|
-
return '[Document]';
|
|
898
|
-
}
|
|
899
|
-
// React's SyntheticEvent thingy
|
|
900
|
-
if (isSyntheticEvent(value)) {
|
|
901
|
-
return '[SyntheticEvent]';
|
|
902
|
-
}
|
|
903
|
-
if (typeof value === 'number' && value !== value) {
|
|
904
|
-
return '[NaN]';
|
|
905
|
-
}
|
|
906
|
-
if (value === void 0) {
|
|
907
|
-
return '[undefined]';
|
|
908
|
-
}
|
|
909
|
-
if (typeof value === 'function') {
|
|
910
|
-
return `[Function: ${getFunctionName(value)}]`;
|
|
911
|
-
}
|
|
912
|
-
// symbols and bigints are considered primitives by TS, but aren't natively JSON-serilaizable
|
|
913
|
-
if (typeof value === 'symbol') {
|
|
914
|
-
return `[${String(value)}]`;
|
|
691
|
+
/** Creates a string representation of the target of an `Event` object */
|
|
692
|
+
function serializeEventTarget(target) {
|
|
693
|
+
try {
|
|
694
|
+
return isElement(target) ? htmlTreeAsString(target) : Object.prototype.toString.call(target);
|
|
915
695
|
}
|
|
916
|
-
|
|
917
|
-
return
|
|
696
|
+
catch (_oO) {
|
|
697
|
+
return '<unknown>';
|
|
918
698
|
}
|
|
919
|
-
return value;
|
|
920
699
|
}
|
|
921
|
-
/**
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
* @param maxProperties Optional maximum number of properties/elements included in any single object/array
|
|
928
|
-
* @param memo Optional Memo class handling decycling
|
|
929
|
-
*/
|
|
930
|
-
function walk(key, value, depth = +Infinity, maxProperties = +Infinity, memo = memoBuilder()) {
|
|
931
|
-
const [memoize, unmemoize] = memo;
|
|
932
|
-
// If we reach the maximum depth, serialize whatever is left
|
|
933
|
-
if (depth === 0) {
|
|
934
|
-
return serializeValue(value);
|
|
935
|
-
}
|
|
936
|
-
// If value implements `toJSON` method, call it and return early
|
|
937
|
-
if (value !== null && value !== undefined && typeof value.toJSON === 'function') {
|
|
938
|
-
return value.toJSON();
|
|
939
|
-
}
|
|
940
|
-
// `makeSerializable` provides a string representation of certain non-serializable values. For all others, it's a
|
|
941
|
-
// pass-through. If what comes back is a primitive (either because it's been stringified or because it was primitive
|
|
942
|
-
// all along), we're done.
|
|
943
|
-
const serializable = makeSerializable(value, key);
|
|
944
|
-
if (isPrimitive(serializable)) {
|
|
945
|
-
return serializable;
|
|
946
|
-
}
|
|
947
|
-
// Create source that we will use for the next iteration. It will either be an objectified error object (`Error` type
|
|
948
|
-
// with extracted key:value pairs) or the input itself.
|
|
949
|
-
const source = getWalkSource(value);
|
|
950
|
-
// Create an accumulator that will act as a parent for all future itterations of that branch
|
|
951
|
-
const acc = Array.isArray(value) ? [] : {};
|
|
952
|
-
// If we already walked that branch, bail out, as it's circular reference
|
|
953
|
-
if (memoize(value)) {
|
|
954
|
-
return '[Circular ~]';
|
|
955
|
-
}
|
|
956
|
-
let propertyCount = 0;
|
|
957
|
-
// Walk all keys of the source
|
|
958
|
-
for (const innerKey in source) {
|
|
959
|
-
// Avoid iterating over fields in the prototype if they've somehow been exposed to enumeration.
|
|
960
|
-
if (!Object.prototype.hasOwnProperty.call(source, innerKey)) {
|
|
961
|
-
continue;
|
|
962
|
-
}
|
|
963
|
-
if (propertyCount >= maxProperties) {
|
|
964
|
-
acc[innerKey] = '[MaxProperties ~]';
|
|
965
|
-
break;
|
|
700
|
+
/** Filters out all but an object's own properties */
|
|
701
|
+
function getOwnProperties(obj) {
|
|
702
|
+
const extractedProps = {};
|
|
703
|
+
for (const property in obj) {
|
|
704
|
+
if (Object.prototype.hasOwnProperty.call(obj, property)) {
|
|
705
|
+
extractedProps[property] = obj[property];
|
|
966
706
|
}
|
|
967
|
-
propertyCount += 1;
|
|
968
|
-
// Recursively walk through all the child nodes
|
|
969
|
-
const innerValue = source[innerKey];
|
|
970
|
-
acc[innerKey] = walk(innerKey, innerValue, depth - 1, maxProperties, memo);
|
|
971
|
-
}
|
|
972
|
-
// Once walked through all the branches, remove the parent from memo storage
|
|
973
|
-
unmemoize(value);
|
|
974
|
-
// Return accumulated values
|
|
975
|
-
return acc;
|
|
976
|
-
}
|
|
977
|
-
/**
|
|
978
|
-
* Recursively normalizes the given object.
|
|
979
|
-
*
|
|
980
|
-
* - Creates a copy to prevent original input mutation
|
|
981
|
-
* - Skips non-enumerable properties
|
|
982
|
-
* - When stringifying, calls `toJSON` if implemented
|
|
983
|
-
* - Removes circular references
|
|
984
|
-
* - Translates non-serializable values (`undefined`/`NaN`/functions) to serializable format
|
|
985
|
-
* - Translates known global objects/classes to a string representations
|
|
986
|
-
* - Takes care of `Error` object serialization
|
|
987
|
-
* - Optionally limits depth of final output
|
|
988
|
-
* - Optionally limits number of properties/elements included in any single object/array
|
|
989
|
-
*
|
|
990
|
-
* @param input The object to be normalized.
|
|
991
|
-
* @param depth The max depth to which to normalize the object. (Anything deeper stringified whole.)
|
|
992
|
-
* @param maxProperties The max number of elements or properties to be included in any single array or
|
|
993
|
-
* object in the normallized output..
|
|
994
|
-
* @returns A normalized version of the object, or `"**non-serializable**"` if any errors are thrown during normalization.
|
|
995
|
-
*/
|
|
996
|
-
function normalize(input, depth = +Infinity, maxProperties = +Infinity) {
|
|
997
|
-
try {
|
|
998
|
-
// since we're at the outermost level, there is no key
|
|
999
|
-
return walk('', input, depth, maxProperties);
|
|
1000
|
-
}
|
|
1001
|
-
catch (_oO) {
|
|
1002
|
-
return '**non-serializable**';
|
|
1003
707
|
}
|
|
708
|
+
return extractedProps;
|
|
1004
709
|
}
|
|
1005
710
|
/**
|
|
1006
711
|
* Given any captured exception, extract its keys and create a sorted
|
|
@@ -1009,7 +714,7 @@ var Sentry = (function (exports) {
|
|
|
1009
714
|
*/
|
|
1010
715
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
1011
716
|
function extractExceptionKeysForMessage(exception, maxLength = 40) {
|
|
1012
|
-
const keys = Object.keys(
|
|
717
|
+
const keys = Object.keys(convertToPlainObject(exception));
|
|
1013
718
|
keys.sort();
|
|
1014
719
|
if (!keys.length) {
|
|
1015
720
|
return '[object has no keys]';
|
|
@@ -1035,11 +740,10 @@ var Sentry = (function (exports) {
|
|
|
1035
740
|
*/
|
|
1036
741
|
function dropUndefinedKeys(val) {
|
|
1037
742
|
if (isPlainObject(val)) {
|
|
1038
|
-
const obj = val;
|
|
1039
743
|
const rv = {};
|
|
1040
|
-
for (const key of Object.keys(
|
|
1041
|
-
if (typeof
|
|
1042
|
-
rv[key] = dropUndefinedKeys(
|
|
744
|
+
for (const key of Object.keys(val)) {
|
|
745
|
+
if (typeof val[key] !== 'undefined') {
|
|
746
|
+
rv[key] = dropUndefinedKeys(val[key]);
|
|
1043
747
|
}
|
|
1044
748
|
}
|
|
1045
749
|
return rv;
|
|
@@ -1050,6 +754,72 @@ var Sentry = (function (exports) {
|
|
|
1050
754
|
return val;
|
|
1051
755
|
}
|
|
1052
756
|
|
|
757
|
+
const STACKTRACE_LIMIT = 50;
|
|
758
|
+
/**
|
|
759
|
+
* Creates a stack parser with the supplied line parsers
|
|
760
|
+
*
|
|
761
|
+
* StackFrames are returned in the correct order for Sentry Exception
|
|
762
|
+
* frames and with Sentry SDK internal frames removed from the top and bottom
|
|
763
|
+
*
|
|
764
|
+
*/
|
|
765
|
+
function createStackParser(...parsers) {
|
|
766
|
+
const sortedParsers = parsers.sort((a, b) => a[0] - b[0]).map(p => p[1]);
|
|
767
|
+
return (stack, skipFirst = 0) => {
|
|
768
|
+
const frames = [];
|
|
769
|
+
for (const line of stack.split('\n').slice(skipFirst)) {
|
|
770
|
+
for (const parser of sortedParsers) {
|
|
771
|
+
const frame = parser(line);
|
|
772
|
+
if (frame) {
|
|
773
|
+
frames.push(frame);
|
|
774
|
+
break;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
return stripSentryFramesAndReverse(frames);
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* @hidden
|
|
783
|
+
*/
|
|
784
|
+
function stripSentryFramesAndReverse(stack) {
|
|
785
|
+
if (!stack.length) {
|
|
786
|
+
return [];
|
|
787
|
+
}
|
|
788
|
+
let localStack = stack;
|
|
789
|
+
const firstFrameFunction = localStack[0].function || '';
|
|
790
|
+
const lastFrameFunction = localStack[localStack.length - 1].function || '';
|
|
791
|
+
// If stack starts with one of our API calls, remove it (starts, meaning it's the top of the stack - aka last call)
|
|
792
|
+
if (firstFrameFunction.indexOf('captureMessage') !== -1 || firstFrameFunction.indexOf('captureException') !== -1) {
|
|
793
|
+
localStack = localStack.slice(1);
|
|
794
|
+
}
|
|
795
|
+
// If stack ends with one of our internal API calls, remove it (ends, meaning it's the bottom of the stack - aka top-most call)
|
|
796
|
+
if (lastFrameFunction.indexOf('sentryWrapped') !== -1) {
|
|
797
|
+
localStack = localStack.slice(0, -1);
|
|
798
|
+
}
|
|
799
|
+
// The frame where the crash happened, should be the last entry in the array
|
|
800
|
+
return localStack
|
|
801
|
+
.slice(0, STACKTRACE_LIMIT)
|
|
802
|
+
.map(frame => (Object.assign(Object.assign({}, frame), { filename: frame.filename || localStack[0].filename, function: frame.function || '?' })))
|
|
803
|
+
.reverse();
|
|
804
|
+
}
|
|
805
|
+
const defaultFunctionName = '<anonymous>';
|
|
806
|
+
/**
|
|
807
|
+
* Safely extract function name from itself
|
|
808
|
+
*/
|
|
809
|
+
function getFunctionName(fn) {
|
|
810
|
+
try {
|
|
811
|
+
if (!fn || typeof fn !== 'function') {
|
|
812
|
+
return defaultFunctionName;
|
|
813
|
+
}
|
|
814
|
+
return fn.name || defaultFunctionName;
|
|
815
|
+
}
|
|
816
|
+
catch (e) {
|
|
817
|
+
// Just accessing custom props in some Selenium environments
|
|
818
|
+
// can cause a "Permission denied" exception (see raven-js#495).
|
|
819
|
+
return defaultFunctionName;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
|
|
1053
823
|
/**
|
|
1054
824
|
* Tells whether current environment supports Fetch API
|
|
1055
825
|
* {@link supportsFetch}.
|
|
@@ -1632,6 +1402,48 @@ var Sentry = (function (exports) {
|
|
|
1632
1402
|
};
|
|
1633
1403
|
}
|
|
1634
1404
|
|
|
1405
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
1406
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1407
|
+
/**
|
|
1408
|
+
* Helper to decycle json objects
|
|
1409
|
+
*/
|
|
1410
|
+
function memoBuilder() {
|
|
1411
|
+
const hasWeakSet = typeof WeakSet === 'function';
|
|
1412
|
+
const inner = hasWeakSet ? new WeakSet() : [];
|
|
1413
|
+
function memoize(obj) {
|
|
1414
|
+
if (hasWeakSet) {
|
|
1415
|
+
if (inner.has(obj)) {
|
|
1416
|
+
return true;
|
|
1417
|
+
}
|
|
1418
|
+
inner.add(obj);
|
|
1419
|
+
return false;
|
|
1420
|
+
}
|
|
1421
|
+
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
1422
|
+
for (let i = 0; i < inner.length; i++) {
|
|
1423
|
+
const value = inner[i];
|
|
1424
|
+
if (value === obj) {
|
|
1425
|
+
return true;
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
inner.push(obj);
|
|
1429
|
+
return false;
|
|
1430
|
+
}
|
|
1431
|
+
function unmemoize(obj) {
|
|
1432
|
+
if (hasWeakSet) {
|
|
1433
|
+
inner.delete(obj);
|
|
1434
|
+
}
|
|
1435
|
+
else {
|
|
1436
|
+
for (let i = 0; i < inner.length; i++) {
|
|
1437
|
+
if (inner[i] === obj) {
|
|
1438
|
+
inner.splice(i, 1);
|
|
1439
|
+
break;
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
return [memoize, unmemoize];
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1635
1447
|
/**
|
|
1636
1448
|
* UUID4 generator
|
|
1637
1449
|
*
|
|
@@ -1789,6 +1601,187 @@ var Sentry = (function (exports) {
|
|
|
1789
1601
|
return false;
|
|
1790
1602
|
}
|
|
1791
1603
|
|
|
1604
|
+
/**
|
|
1605
|
+
* Recursively normalizes the given object.
|
|
1606
|
+
*
|
|
1607
|
+
* - Creates a copy to prevent original input mutation
|
|
1608
|
+
* - Skips non-enumerable properties
|
|
1609
|
+
* - When stringifying, calls `toJSON` if implemented
|
|
1610
|
+
* - Removes circular references
|
|
1611
|
+
* - Translates non-serializable values (`undefined`/`NaN`/functions) to serializable format
|
|
1612
|
+
* - Translates known global objects/classes to a string representations
|
|
1613
|
+
* - Takes care of `Error` object serialization
|
|
1614
|
+
* - Optionally limits depth of final output
|
|
1615
|
+
* - Optionally limits number of properties/elements included in any single object/array
|
|
1616
|
+
*
|
|
1617
|
+
* @param input The object to be normalized.
|
|
1618
|
+
* @param depth The max depth to which to normalize the object. (Anything deeper stringified whole.)
|
|
1619
|
+
* @param maxProperties The max number of elements or properties to be included in any single array or
|
|
1620
|
+
* object in the normallized output..
|
|
1621
|
+
* @returns A normalized version of the object, or `"**non-serializable**"` if any errors are thrown during normalization.
|
|
1622
|
+
*/
|
|
1623
|
+
function normalize(input, depth = +Infinity, maxProperties = +Infinity) {
|
|
1624
|
+
try {
|
|
1625
|
+
// since we're at the outermost level, there is no key
|
|
1626
|
+
return visit('', input, depth, maxProperties);
|
|
1627
|
+
}
|
|
1628
|
+
catch (err) {
|
|
1629
|
+
return { ERROR: `**non-serializable** (${err})` };
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
/** JSDoc */
|
|
1633
|
+
function normalizeToSize(object,
|
|
1634
|
+
// Default Node.js REPL depth
|
|
1635
|
+
depth = 3,
|
|
1636
|
+
// 100kB, as 200kB is max payload size, so half sounds reasonable
|
|
1637
|
+
maxSize = 100 * 1024) {
|
|
1638
|
+
const normalized = normalize(object, depth);
|
|
1639
|
+
if (jsonSize(normalized) > maxSize) {
|
|
1640
|
+
return normalizeToSize(object, depth - 1, maxSize);
|
|
1641
|
+
}
|
|
1642
|
+
return normalized;
|
|
1643
|
+
}
|
|
1644
|
+
/**
|
|
1645
|
+
* Visits a node to perform normalization on it
|
|
1646
|
+
*
|
|
1647
|
+
* @param key The key corresponding to the given node
|
|
1648
|
+
* @param value The node to be visited
|
|
1649
|
+
* @param depth Optional number indicating the maximum recursion depth
|
|
1650
|
+
* @param maxProperties Optional maximum number of properties/elements included in any single object/array
|
|
1651
|
+
* @param memo Optional Memo class handling decycling
|
|
1652
|
+
*/
|
|
1653
|
+
function visit(key, value, depth = +Infinity, maxProperties = +Infinity, memo = memoBuilder()) {
|
|
1654
|
+
const [memoize, unmemoize] = memo;
|
|
1655
|
+
// If the value has a `toJSON` method, see if we can bail and let it do the work
|
|
1656
|
+
const valueWithToJSON = value;
|
|
1657
|
+
if (valueWithToJSON && typeof valueWithToJSON.toJSON === 'function') {
|
|
1658
|
+
try {
|
|
1659
|
+
return valueWithToJSON.toJSON();
|
|
1660
|
+
}
|
|
1661
|
+
catch (err) {
|
|
1662
|
+
// pass (The built-in `toJSON` failed, but we can still try to do it ourselves)
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
// Get the simple cases out of the way first
|
|
1666
|
+
if (value === null || (['number', 'boolean', 'string'].includes(typeof value) && !isNaN$1(value))) {
|
|
1667
|
+
return value;
|
|
1668
|
+
}
|
|
1669
|
+
const stringified = stringifyValue(key, value);
|
|
1670
|
+
// Anything we could potentially dig into more (objects or arrays) will have come back as `"[object XXXX]"`.
|
|
1671
|
+
// Everything else will have already been serialized, so if we don't see that pattern, we're done.
|
|
1672
|
+
if (!stringified.startsWith('[object ')) {
|
|
1673
|
+
return stringified;
|
|
1674
|
+
}
|
|
1675
|
+
// We're also done if we've reached the max depth
|
|
1676
|
+
if (depth === 0) {
|
|
1677
|
+
// At this point we know `serialized` is a string of the form `"[object XXXX]"`. Clean it up so it's just `"[XXXX]"`.
|
|
1678
|
+
return stringified.replace('object ', '');
|
|
1679
|
+
}
|
|
1680
|
+
// If we've already visited this branch, bail out, as it's circular reference. If not, note that we're seeing it now.
|
|
1681
|
+
if (memoize(value)) {
|
|
1682
|
+
return '[Circular ~]';
|
|
1683
|
+
}
|
|
1684
|
+
// 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
|
|
1685
|
+
// because we haven't yet reached the max depth. Create an accumulator to hold the results of visiting each
|
|
1686
|
+
// property/entry, and keep track of the number of items we add to it.
|
|
1687
|
+
const normalized = (Array.isArray(value) ? [] : {});
|
|
1688
|
+
let numAdded = 0;
|
|
1689
|
+
// Before we begin, convert`Error` and`Event` instances into plain objects, since some of each of their relevant
|
|
1690
|
+
// properties are non-enumerable and otherwise would get missed.
|
|
1691
|
+
const visitable = (isError(value) || isEvent(value) ? convertToPlainObject(value) : value);
|
|
1692
|
+
for (const visitKey in visitable) {
|
|
1693
|
+
// Avoid iterating over fields in the prototype if they've somehow been exposed to enumeration.
|
|
1694
|
+
if (!Object.prototype.hasOwnProperty.call(visitable, visitKey)) {
|
|
1695
|
+
continue;
|
|
1696
|
+
}
|
|
1697
|
+
if (numAdded >= maxProperties) {
|
|
1698
|
+
normalized[visitKey] = '[MaxProperties ~]';
|
|
1699
|
+
break;
|
|
1700
|
+
}
|
|
1701
|
+
// Recursively visit all the child nodes
|
|
1702
|
+
const visitValue = visitable[visitKey];
|
|
1703
|
+
normalized[visitKey] = visit(visitKey, visitValue, depth - 1, maxProperties, memo);
|
|
1704
|
+
numAdded += 1;
|
|
1705
|
+
}
|
|
1706
|
+
// Once we've visited all the branches, remove the parent from memo storage
|
|
1707
|
+
unmemoize(value);
|
|
1708
|
+
// Return accumulated values
|
|
1709
|
+
return normalized;
|
|
1710
|
+
}
|
|
1711
|
+
/**
|
|
1712
|
+
* Stringify the given value. Handles various known special values and types.
|
|
1713
|
+
*
|
|
1714
|
+
* Not meant to be used on simple primitives which already have a string representation, as it will, for example, turn
|
|
1715
|
+
* the number 1231 into "[Object Number]", nor on `null`, as it will throw.
|
|
1716
|
+
*
|
|
1717
|
+
* @param value The value to stringify
|
|
1718
|
+
* @returns A stringified representation of the given value
|
|
1719
|
+
*/
|
|
1720
|
+
function stringifyValue(key,
|
|
1721
|
+
// this type is a tiny bit of a cheat, since this function does handle NaN (which is technically a number), but for
|
|
1722
|
+
// our internal use, it'll do
|
|
1723
|
+
value) {
|
|
1724
|
+
try {
|
|
1725
|
+
if (key === 'domain' && value && typeof value === 'object' && value._events) {
|
|
1726
|
+
return '[Domain]';
|
|
1727
|
+
}
|
|
1728
|
+
if (key === 'domainEmitter') {
|
|
1729
|
+
return '[DomainEmitter]';
|
|
1730
|
+
}
|
|
1731
|
+
// It's safe to use `global`, `window`, and `document` here in this manner, as we are asserting using `typeof` first
|
|
1732
|
+
// which won't throw if they are not present.
|
|
1733
|
+
if (typeof global !== 'undefined' && value === global) {
|
|
1734
|
+
return '[Global]';
|
|
1735
|
+
}
|
|
1736
|
+
// eslint-disable-next-line no-restricted-globals
|
|
1737
|
+
if (typeof window !== 'undefined' && value === window) {
|
|
1738
|
+
return '[Window]';
|
|
1739
|
+
}
|
|
1740
|
+
// eslint-disable-next-line no-restricted-globals
|
|
1741
|
+
if (typeof document !== 'undefined' && value === document) {
|
|
1742
|
+
return '[Document]';
|
|
1743
|
+
}
|
|
1744
|
+
// React's SyntheticEvent thingy
|
|
1745
|
+
if (isSyntheticEvent(value)) {
|
|
1746
|
+
return '[SyntheticEvent]';
|
|
1747
|
+
}
|
|
1748
|
+
if (typeof value === 'number' && value !== value) {
|
|
1749
|
+
return '[NaN]';
|
|
1750
|
+
}
|
|
1751
|
+
// this catches `undefined` (but not `null`, which is a primitive and can be serialized on its own)
|
|
1752
|
+
if (value === void 0) {
|
|
1753
|
+
return '[undefined]';
|
|
1754
|
+
}
|
|
1755
|
+
if (typeof value === 'function') {
|
|
1756
|
+
return `[Function: ${getFunctionName(value)}]`;
|
|
1757
|
+
}
|
|
1758
|
+
if (typeof value === 'symbol') {
|
|
1759
|
+
return `[${String(value)}]`;
|
|
1760
|
+
}
|
|
1761
|
+
// stringified BigInts are indistinguishable from regular numbers, so we need to label them to avoid confusion
|
|
1762
|
+
if (typeof value === 'bigint') {
|
|
1763
|
+
return `[BigInt: ${String(value)}]`;
|
|
1764
|
+
}
|
|
1765
|
+
// Now that we've knocked out all the special cases and the primitives, all we have left are objects. Simply casting
|
|
1766
|
+
// them to strings means that instances of classes which haven't defined their `toStringTag` will just come out as
|
|
1767
|
+
// `"[object Object]"`. If we instead look at the constructor's name (which is the same as the name of the class),
|
|
1768
|
+
// we can make sure that only plain objects come out that way.
|
|
1769
|
+
return `[object ${Object.getPrototypeOf(value).constructor.name}]`;
|
|
1770
|
+
}
|
|
1771
|
+
catch (err) {
|
|
1772
|
+
return `**non-serializable** (${err})`;
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
/** Calculates bytes size of input string */
|
|
1776
|
+
function utf8Length(value) {
|
|
1777
|
+
// eslint-disable-next-line no-bitwise
|
|
1778
|
+
return ~-encodeURI(value).split(/%..|./).length;
|
|
1779
|
+
}
|
|
1780
|
+
/** Calculates bytes size of input object */
|
|
1781
|
+
function jsonSize(value) {
|
|
1782
|
+
return utf8Length(JSON.stringify(value));
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1792
1785
|
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
1793
1786
|
/**
|
|
1794
1787
|
* Creates a resolved sync promise.
|
|
@@ -2189,6 +2182,13 @@ var Sentry = (function (exports) {
|
|
|
2189
2182
|
function createEnvelope(headers, items = []) {
|
|
2190
2183
|
return [headers, items];
|
|
2191
2184
|
}
|
|
2185
|
+
/**
|
|
2186
|
+
* Get the type of the envelope. Grabs the type from the first envelope item.
|
|
2187
|
+
*/
|
|
2188
|
+
function getEnvelopeType(envelope) {
|
|
2189
|
+
const [, [[firstItemHeader]]] = envelope;
|
|
2190
|
+
return firstItemHeader.type;
|
|
2191
|
+
}
|
|
2192
2192
|
/**
|
|
2193
2193
|
* Serializes an envelope into a string.
|
|
2194
2194
|
*/
|
|
@@ -3931,7 +3931,7 @@ var Sentry = (function (exports) {
|
|
|
3931
3931
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
3932
3932
|
normalized.contexts.trace = event.contexts.trace;
|
|
3933
3933
|
}
|
|
3934
|
-
|
|
3934
|
+
normalized.sdkProcessingMetadata = Object.assign(Object.assign({}, normalized.sdkProcessingMetadata), { baseClientNormalized: true });
|
|
3935
3935
|
return normalized;
|
|
3936
3936
|
}
|
|
3937
3937
|
/**
|
|
@@ -4102,85 +4102,6 @@ var Sentry = (function (exports) {
|
|
|
4102
4102
|
return rv;
|
|
4103
4103
|
}
|
|
4104
4104
|
|
|
4105
|
-
/** Noop transport */
|
|
4106
|
-
class NoopTransport {
|
|
4107
|
-
/**
|
|
4108
|
-
* @inheritDoc
|
|
4109
|
-
*/
|
|
4110
|
-
sendEvent(_) {
|
|
4111
|
-
return resolvedSyncPromise({
|
|
4112
|
-
reason: 'NoopTransport: Event has been skipped because no Dsn is configured.',
|
|
4113
|
-
status: 'skipped',
|
|
4114
|
-
});
|
|
4115
|
-
}
|
|
4116
|
-
/**
|
|
4117
|
-
* @inheritDoc
|
|
4118
|
-
*/
|
|
4119
|
-
close(_) {
|
|
4120
|
-
return resolvedSyncPromise(true);
|
|
4121
|
-
}
|
|
4122
|
-
}
|
|
4123
|
-
|
|
4124
|
-
/**
|
|
4125
|
-
* This is the base implemention of a Backend.
|
|
4126
|
-
* @hidden
|
|
4127
|
-
*/
|
|
4128
|
-
class BaseBackend {
|
|
4129
|
-
/** Creates a new backend instance. */
|
|
4130
|
-
constructor(options) {
|
|
4131
|
-
this._options = options;
|
|
4132
|
-
if (!this._options.dsn) {
|
|
4133
|
-
logger.warn('No DSN provided, backend will not do anything.');
|
|
4134
|
-
}
|
|
4135
|
-
this._transport = this._setupTransport();
|
|
4136
|
-
}
|
|
4137
|
-
/**
|
|
4138
|
-
* @inheritDoc
|
|
4139
|
-
*/
|
|
4140
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
|
4141
|
-
eventFromException(_exception, _hint) {
|
|
4142
|
-
throw new SentryError('Backend has to implement `eventFromException` method');
|
|
4143
|
-
}
|
|
4144
|
-
/**
|
|
4145
|
-
* @inheritDoc
|
|
4146
|
-
*/
|
|
4147
|
-
eventFromMessage(_message, _level, _hint) {
|
|
4148
|
-
throw new SentryError('Backend has to implement `eventFromMessage` method');
|
|
4149
|
-
}
|
|
4150
|
-
/**
|
|
4151
|
-
* @inheritDoc
|
|
4152
|
-
*/
|
|
4153
|
-
sendEvent(event) {
|
|
4154
|
-
void this._transport.sendEvent(event).then(null, reason => {
|
|
4155
|
-
logger.error('Error while sending event:', reason);
|
|
4156
|
-
});
|
|
4157
|
-
}
|
|
4158
|
-
/**
|
|
4159
|
-
* @inheritDoc
|
|
4160
|
-
*/
|
|
4161
|
-
sendSession(session) {
|
|
4162
|
-
if (!this._transport.sendSession) {
|
|
4163
|
-
logger.warn("Dropping session because custom transport doesn't implement sendSession");
|
|
4164
|
-
return;
|
|
4165
|
-
}
|
|
4166
|
-
void this._transport.sendSession(session).then(null, reason => {
|
|
4167
|
-
logger.error('Error while sending session:', reason);
|
|
4168
|
-
});
|
|
4169
|
-
}
|
|
4170
|
-
/**
|
|
4171
|
-
* @inheritDoc
|
|
4172
|
-
*/
|
|
4173
|
-
getTransport() {
|
|
4174
|
-
return this._transport;
|
|
4175
|
-
}
|
|
4176
|
-
/**
|
|
4177
|
-
* Sets up the transport so it can be used later to send requests.
|
|
4178
|
-
*/
|
|
4179
|
-
_setupTransport() {
|
|
4180
|
-
return new NoopTransport();
|
|
4181
|
-
}
|
|
4182
|
-
}
|
|
4183
|
-
|
|
4184
4105
|
/** Extract sdk info from from the API metadata */
|
|
4185
4106
|
function getSdkMetadataForEnvelopeHeader(api) {
|
|
4186
4107
|
if (!api.metadata || !api.metadata.sdk) {
|
|
@@ -4204,8 +4125,8 @@ var Sentry = (function (exports) {
|
|
|
4204
4125
|
event.sdk.packages = [...(event.sdk.packages || []), ...(sdkInfo.packages || [])];
|
|
4205
4126
|
return event;
|
|
4206
4127
|
}
|
|
4207
|
-
/** Creates
|
|
4208
|
-
function
|
|
4128
|
+
/** Creates an envelope from a Session */
|
|
4129
|
+
function createSessionEnvelope(session, api) {
|
|
4209
4130
|
const sdkInfo = getSdkMetadataForEnvelopeHeader(api);
|
|
4210
4131
|
const envelopeHeaders = Object.assign(Object.assign({ sent_at: new Date().toISOString() }, (sdkInfo && { sdk: sdkInfo })), (!!api.tunnel && { dsn: dsnToString(api.dsn) }));
|
|
4211
4132
|
// I know this is hacky but we don't want to add `sessions` to request type since it's never rate limited
|
|
@@ -4213,12 +4134,62 @@ var Sentry = (function (exports) {
|
|
|
4213
4134
|
// TODO (v7) Have to cast type because envelope items do not accept a `SentryRequestType`
|
|
4214
4135
|
const envelopeItem = [{ type }, session];
|
|
4215
4136
|
const envelope = createEnvelope(envelopeHeaders, [envelopeItem]);
|
|
4137
|
+
return [envelope, type];
|
|
4138
|
+
}
|
|
4139
|
+
/** Creates a SentryRequest from a Session. */
|
|
4140
|
+
function sessionToSentryRequest(session, api) {
|
|
4141
|
+
const [envelope, type] = createSessionEnvelope(session, api);
|
|
4216
4142
|
return {
|
|
4217
4143
|
body: serializeEnvelope(envelope),
|
|
4218
4144
|
type,
|
|
4219
4145
|
url: getEnvelopeEndpointWithUrlEncodedAuth(api.dsn, api.tunnel),
|
|
4220
4146
|
};
|
|
4221
4147
|
}
|
|
4148
|
+
/**
|
|
4149
|
+
* Create an Envelope from an event. Note that this is duplicated from below,
|
|
4150
|
+
* but on purpose as this will be refactored in v7.
|
|
4151
|
+
*/
|
|
4152
|
+
function createEventEnvelope(event, api) {
|
|
4153
|
+
const sdkInfo = getSdkMetadataForEnvelopeHeader(api);
|
|
4154
|
+
const eventType = event.type || 'event';
|
|
4155
|
+
const { transactionSampling } = event.sdkProcessingMetadata || {};
|
|
4156
|
+
const { method: samplingMethod, rate: sampleRate } = transactionSampling || {};
|
|
4157
|
+
// TODO: Below is a temporary hack in order to debug a serialization error - see
|
|
4158
|
+
// https://github.com/getsentry/sentry-javascript/issues/2809,
|
|
4159
|
+
// https://github.com/getsentry/sentry-javascript/pull/4425, and
|
|
4160
|
+
// https://github.com/getsentry/sentry-javascript/pull/4574.
|
|
4161
|
+
//
|
|
4162
|
+
// TL; DR: even though we normalize all events (which should prevent this), something is causing `JSON.stringify` to
|
|
4163
|
+
// throw a circular reference error.
|
|
4164
|
+
//
|
|
4165
|
+
// When it's time to remove it:
|
|
4166
|
+
// 1. Delete everything between here and where the request object `req` is created, EXCEPT the line deleting
|
|
4167
|
+
// `sdkProcessingMetadata`
|
|
4168
|
+
// 2. Restore the original version of the request body, which is commented out
|
|
4169
|
+
// 3. Search for either of the PR URLs above and pull out the companion hacks in the browser playwright tests and the
|
|
4170
|
+
// baseClient tests in this package
|
|
4171
|
+
enhanceEventWithSdkInfo(event, api.metadata.sdk);
|
|
4172
|
+
event.tags = event.tags || {};
|
|
4173
|
+
event.extra = event.extra || {};
|
|
4174
|
+
// In theory, all events should be marked as having gone through normalization and so
|
|
4175
|
+
// we should never set this tag/extra data
|
|
4176
|
+
if (!(event.sdkProcessingMetadata && event.sdkProcessingMetadata.baseClientNormalized)) {
|
|
4177
|
+
event.tags.skippedNormalization = true;
|
|
4178
|
+
event.extra.normalizeDepth = event.sdkProcessingMetadata ? event.sdkProcessingMetadata.normalizeDepth : 'unset';
|
|
4179
|
+
}
|
|
4180
|
+
// prevent this data from being sent to sentry
|
|
4181
|
+
// TODO: This is NOT part of the hack - DO NOT DELETE
|
|
4182
|
+
delete event.sdkProcessingMetadata;
|
|
4183
|
+
const envelopeHeaders = Object.assign(Object.assign({ event_id: event.event_id, sent_at: new Date().toISOString() }, (sdkInfo && { sdk: sdkInfo })), (!!api.tunnel && { dsn: dsnToString(api.dsn) }));
|
|
4184
|
+
const eventItem = [
|
|
4185
|
+
{
|
|
4186
|
+
type: eventType,
|
|
4187
|
+
sample_rates: [{ id: samplingMethod, rate: sampleRate }],
|
|
4188
|
+
},
|
|
4189
|
+
event,
|
|
4190
|
+
];
|
|
4191
|
+
return createEnvelope(envelopeHeaders, [eventItem]);
|
|
4192
|
+
}
|
|
4222
4193
|
/** Creates a SentryRequest from an event. */
|
|
4223
4194
|
function eventToSentryRequest(event, api) {
|
|
4224
4195
|
const sdkInfo = getSdkMetadataForEnvelopeHeader(api);
|
|
@@ -4306,6 +4277,111 @@ var Sentry = (function (exports) {
|
|
|
4306
4277
|
return req;
|
|
4307
4278
|
}
|
|
4308
4279
|
|
|
4280
|
+
/** Noop transport */
|
|
4281
|
+
class NoopTransport {
|
|
4282
|
+
/**
|
|
4283
|
+
* @inheritDoc
|
|
4284
|
+
*/
|
|
4285
|
+
sendEvent(_) {
|
|
4286
|
+
return resolvedSyncPromise({
|
|
4287
|
+
reason: 'NoopTransport: Event has been skipped because no Dsn is configured.',
|
|
4288
|
+
status: 'skipped',
|
|
4289
|
+
});
|
|
4290
|
+
}
|
|
4291
|
+
/**
|
|
4292
|
+
* @inheritDoc
|
|
4293
|
+
*/
|
|
4294
|
+
close(_) {
|
|
4295
|
+
return resolvedSyncPromise(true);
|
|
4296
|
+
}
|
|
4297
|
+
}
|
|
4298
|
+
|
|
4299
|
+
/**
|
|
4300
|
+
* This is the base implemention of a Backend.
|
|
4301
|
+
* @hidden
|
|
4302
|
+
*/
|
|
4303
|
+
class BaseBackend {
|
|
4304
|
+
/** Creates a new backend instance. */
|
|
4305
|
+
constructor(options) {
|
|
4306
|
+
this._options = options;
|
|
4307
|
+
if (!this._options.dsn) {
|
|
4308
|
+
logger.warn('No DSN provided, backend will not do anything.');
|
|
4309
|
+
}
|
|
4310
|
+
this._transport = this._setupTransport();
|
|
4311
|
+
}
|
|
4312
|
+
/**
|
|
4313
|
+
* @inheritDoc
|
|
4314
|
+
*/
|
|
4315
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
|
4316
|
+
eventFromException(_exception, _hint) {
|
|
4317
|
+
throw new SentryError('Backend has to implement `eventFromException` method');
|
|
4318
|
+
}
|
|
4319
|
+
/**
|
|
4320
|
+
* @inheritDoc
|
|
4321
|
+
*/
|
|
4322
|
+
eventFromMessage(_message, _level, _hint) {
|
|
4323
|
+
throw new SentryError('Backend has to implement `eventFromMessage` method');
|
|
4324
|
+
}
|
|
4325
|
+
/**
|
|
4326
|
+
* @inheritDoc
|
|
4327
|
+
*/
|
|
4328
|
+
sendEvent(event) {
|
|
4329
|
+
// TODO(v7): Remove the if-else
|
|
4330
|
+
if (this._newTransport &&
|
|
4331
|
+
this._options.dsn &&
|
|
4332
|
+
this._options._experiments &&
|
|
4333
|
+
this._options._experiments.newTransport) {
|
|
4334
|
+
const api = initAPIDetails(this._options.dsn, this._options._metadata, this._options.tunnel);
|
|
4335
|
+
const env = createEventEnvelope(event, api);
|
|
4336
|
+
void this._newTransport.send(env).then(null, reason => {
|
|
4337
|
+
logger.error('Error while sending event:', reason);
|
|
4338
|
+
});
|
|
4339
|
+
}
|
|
4340
|
+
else {
|
|
4341
|
+
void this._transport.sendEvent(event).then(null, reason => {
|
|
4342
|
+
logger.error('Error while sending event:', reason);
|
|
4343
|
+
});
|
|
4344
|
+
}
|
|
4345
|
+
}
|
|
4346
|
+
/**
|
|
4347
|
+
* @inheritDoc
|
|
4348
|
+
*/
|
|
4349
|
+
sendSession(session) {
|
|
4350
|
+
if (!this._transport.sendSession) {
|
|
4351
|
+
logger.warn("Dropping session because custom transport doesn't implement sendSession");
|
|
4352
|
+
return;
|
|
4353
|
+
}
|
|
4354
|
+
// TODO(v7): Remove the if-else
|
|
4355
|
+
if (this._newTransport &&
|
|
4356
|
+
this._options.dsn &&
|
|
4357
|
+
this._options._experiments &&
|
|
4358
|
+
this._options._experiments.newTransport) {
|
|
4359
|
+
const api = initAPIDetails(this._options.dsn, this._options._metadata, this._options.tunnel);
|
|
4360
|
+
const [env] = createSessionEnvelope(session, api);
|
|
4361
|
+
void this._newTransport.send(env).then(null, reason => {
|
|
4362
|
+
logger.error('Error while sending session:', reason);
|
|
4363
|
+
});
|
|
4364
|
+
}
|
|
4365
|
+
else {
|
|
4366
|
+
void this._transport.sendSession(session).then(null, reason => {
|
|
4367
|
+
logger.error('Error while sending session:', reason);
|
|
4368
|
+
});
|
|
4369
|
+
}
|
|
4370
|
+
}
|
|
4371
|
+
/**
|
|
4372
|
+
* @inheritDoc
|
|
4373
|
+
*/
|
|
4374
|
+
getTransport() {
|
|
4375
|
+
return this._transport;
|
|
4376
|
+
}
|
|
4377
|
+
/**
|
|
4378
|
+
* Sets up the transport so it can be used later to send requests.
|
|
4379
|
+
*/
|
|
4380
|
+
_setupTransport() {
|
|
4381
|
+
return new NoopTransport();
|
|
4382
|
+
}
|
|
4383
|
+
}
|
|
4384
|
+
|
|
4309
4385
|
/**
|
|
4310
4386
|
* Internal function to create a new SDK client instance. The client is
|
|
4311
4387
|
* installed and then bound to the current scope.
|
|
@@ -4328,7 +4404,57 @@ var Sentry = (function (exports) {
|
|
|
4328
4404
|
hub.bindClient(client);
|
|
4329
4405
|
}
|
|
4330
4406
|
|
|
4331
|
-
const
|
|
4407
|
+
const DEFAULT_TRANSPORT_BUFFER_SIZE = 30;
|
|
4408
|
+
/**
|
|
4409
|
+
* Creates a `NewTransport`
|
|
4410
|
+
*
|
|
4411
|
+
* @param options
|
|
4412
|
+
* @param makeRequest
|
|
4413
|
+
*/
|
|
4414
|
+
function createTransport(options, makeRequest, buffer = makePromiseBuffer(options.bufferSize || DEFAULT_TRANSPORT_BUFFER_SIZE)) {
|
|
4415
|
+
let rateLimits = {};
|
|
4416
|
+
const flush = (timeout) => buffer.drain(timeout);
|
|
4417
|
+
function send(envelope) {
|
|
4418
|
+
const envCategory = getEnvelopeType(envelope);
|
|
4419
|
+
const category = envCategory === 'event' ? 'error' : envCategory;
|
|
4420
|
+
const request = {
|
|
4421
|
+
category,
|
|
4422
|
+
body: serializeEnvelope(envelope),
|
|
4423
|
+
};
|
|
4424
|
+
// Don't add to buffer if transport is already rate-limited
|
|
4425
|
+
if (isRateLimited(rateLimits, category)) {
|
|
4426
|
+
return rejectedSyncPromise({
|
|
4427
|
+
status: 'rate_limit',
|
|
4428
|
+
reason: getRateLimitReason(rateLimits, category),
|
|
4429
|
+
});
|
|
4430
|
+
}
|
|
4431
|
+
const requestTask = () => makeRequest(request).then(({ body, headers, reason, statusCode }) => {
|
|
4432
|
+
const status = eventStatusFromHttpCode(statusCode);
|
|
4433
|
+
if (headers) {
|
|
4434
|
+
rateLimits = updateRateLimits(rateLimits, headers);
|
|
4435
|
+
}
|
|
4436
|
+
if (status === 'success') {
|
|
4437
|
+
return resolvedSyncPromise({ status, reason });
|
|
4438
|
+
}
|
|
4439
|
+
return rejectedSyncPromise({
|
|
4440
|
+
status,
|
|
4441
|
+
reason: reason ||
|
|
4442
|
+
body ||
|
|
4443
|
+
(status === 'rate_limit' ? getRateLimitReason(rateLimits, category) : 'Unknown transport error'),
|
|
4444
|
+
});
|
|
4445
|
+
});
|
|
4446
|
+
return buffer.add(requestTask);
|
|
4447
|
+
}
|
|
4448
|
+
return {
|
|
4449
|
+
send,
|
|
4450
|
+
flush,
|
|
4451
|
+
};
|
|
4452
|
+
}
|
|
4453
|
+
function getRateLimitReason(rateLimits, category) {
|
|
4454
|
+
return `Too many ${category} requests, backing off until: ${new Date(disabledUntil(rateLimits, category)).toISOString()}`;
|
|
4455
|
+
}
|
|
4456
|
+
|
|
4457
|
+
const SDK_VERSION = '6.19.3';
|
|
4332
4458
|
|
|
4333
4459
|
let originalFunctionToString;
|
|
4334
4460
|
/** Patch toString calls to return proper name for wrapped functions */
|
|
@@ -4372,172 +4498,151 @@ var Sentry = (function (exports) {
|
|
|
4372
4498
|
/**
|
|
4373
4499
|
* @inheritDoc
|
|
4374
4500
|
*/
|
|
4375
|
-
setupOnce() {
|
|
4501
|
+
setupOnce(addGlobalEventProcessor, getCurrentHub) {
|
|
4376
4502
|
addGlobalEventProcessor((event) => {
|
|
4377
4503
|
const hub = getCurrentHub();
|
|
4378
|
-
if (
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
// This checks prevents most of the occurrences of the bug linked below:
|
|
4386
|
-
// https://github.com/getsentry/sentry-javascript/issues/2622
|
|
4387
|
-
// The bug is caused by multiple SDK instances, where one is minified and one is using non-mangled code.
|
|
4388
|
-
// Unfortunatelly we cannot fix it reliably (thus reserved property in rollup's terser config),
|
|
4389
|
-
// as we cannot force people using multiple instances in their apps to sync SDK versions.
|
|
4390
|
-
const options = typeof self._mergeOptions === 'function' ? self._mergeOptions(clientOptions) : {};
|
|
4391
|
-
if (typeof self._shouldDropEvent !== 'function') {
|
|
4392
|
-
return event;
|
|
4504
|
+
if (hub) {
|
|
4505
|
+
const self = hub.getIntegration(InboundFilters);
|
|
4506
|
+
if (self) {
|
|
4507
|
+
const client = hub.getClient();
|
|
4508
|
+
const clientOptions = client ? client.getOptions() : {};
|
|
4509
|
+
const options = _mergeOptions(self._options, clientOptions);
|
|
4510
|
+
return _shouldDropEvent$1(event, options) ? null : event;
|
|
4393
4511
|
}
|
|
4394
|
-
return self._shouldDropEvent(event, options) ? null : event;
|
|
4395
4512
|
}
|
|
4396
4513
|
return event;
|
|
4397
4514
|
});
|
|
4398
4515
|
}
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4516
|
+
}
|
|
4517
|
+
/**
|
|
4518
|
+
* @inheritDoc
|
|
4519
|
+
*/
|
|
4520
|
+
InboundFilters.id = 'InboundFilters';
|
|
4521
|
+
/** JSDoc */
|
|
4522
|
+
function _mergeOptions(internalOptions = {}, clientOptions = {}) {
|
|
4523
|
+
return {
|
|
4524
|
+
allowUrls: [
|
|
4525
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
4526
|
+
...(internalOptions.whitelistUrls || []),
|
|
4527
|
+
...(internalOptions.allowUrls || []),
|
|
4528
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
4529
|
+
...(clientOptions.whitelistUrls || []),
|
|
4530
|
+
...(clientOptions.allowUrls || []),
|
|
4531
|
+
],
|
|
4532
|
+
denyUrls: [
|
|
4533
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
4534
|
+
...(internalOptions.blacklistUrls || []),
|
|
4535
|
+
...(internalOptions.denyUrls || []),
|
|
4536
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
4537
|
+
...(clientOptions.blacklistUrls || []),
|
|
4538
|
+
...(clientOptions.denyUrls || []),
|
|
4539
|
+
],
|
|
4540
|
+
ignoreErrors: [
|
|
4541
|
+
...(internalOptions.ignoreErrors || []),
|
|
4542
|
+
...(clientOptions.ignoreErrors || []),
|
|
4543
|
+
...DEFAULT_IGNORE_ERRORS,
|
|
4544
|
+
],
|
|
4545
|
+
ignoreInternal: internalOptions.ignoreInternal !== undefined ? internalOptions.ignoreInternal : true,
|
|
4546
|
+
};
|
|
4547
|
+
}
|
|
4548
|
+
/** JSDoc */
|
|
4549
|
+
function _shouldDropEvent$1(event, options) {
|
|
4550
|
+
if (options.ignoreInternal && _isSentryError(event)) {
|
|
4551
|
+
logger.warn(`Event dropped due to being internal Sentry Error.\nEvent: ${getEventDescription(event)}`);
|
|
4552
|
+
return true;
|
|
4553
|
+
}
|
|
4554
|
+
if (_isIgnoredError(event, options.ignoreErrors)) {
|
|
4555
|
+
logger.warn(`Event dropped due to being matched by \`ignoreErrors\` option.\nEvent: ${getEventDescription(event)}`);
|
|
4556
|
+
return true;
|
|
4557
|
+
}
|
|
4558
|
+
if (_isDeniedUrl(event, options.denyUrls)) {
|
|
4559
|
+
logger.warn(`Event dropped due to being matched by \`denyUrls\` option.\nEvent: ${getEventDescription(event)}.\nUrl: ${_getEventFilterUrl(event)}`);
|
|
4560
|
+
return true;
|
|
4561
|
+
}
|
|
4562
|
+
if (!_isAllowedUrl(event, options.allowUrls)) {
|
|
4563
|
+
logger.warn(`Event dropped due to not being matched by \`allowUrls\` option.\nEvent: ${getEventDescription(event)}.\nUrl: ${_getEventFilterUrl(event)}`);
|
|
4564
|
+
return true;
|
|
4565
|
+
}
|
|
4566
|
+
return false;
|
|
4567
|
+
}
|
|
4568
|
+
function _isIgnoredError(event, ignoreErrors) {
|
|
4569
|
+
if (!ignoreErrors || !ignoreErrors.length) {
|
|
4417
4570
|
return false;
|
|
4418
4571
|
}
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
try {
|
|
4425
|
-
// @ts-ignore can't be a sentry error if undefined
|
|
4426
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
4427
|
-
return event.exception.values[0].type === 'SentryError';
|
|
4428
|
-
}
|
|
4429
|
-
catch (e) {
|
|
4430
|
-
// ignore
|
|
4431
|
-
}
|
|
4572
|
+
return _getPossibleEventMessages(event).some(message => ignoreErrors.some(pattern => isMatchingPattern(message, pattern)));
|
|
4573
|
+
}
|
|
4574
|
+
function _isDeniedUrl(event, denyUrls) {
|
|
4575
|
+
// TODO: Use Glob instead?
|
|
4576
|
+
if (!denyUrls || !denyUrls.length) {
|
|
4432
4577
|
return false;
|
|
4433
4578
|
}
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
options.ignoreErrors.some(pattern => isMatchingPattern(message, pattern)));
|
|
4579
|
+
const url = _getEventFilterUrl(event);
|
|
4580
|
+
return !url ? false : denyUrls.some(pattern => isMatchingPattern(url, pattern));
|
|
4581
|
+
}
|
|
4582
|
+
function _isAllowedUrl(event, allowUrls) {
|
|
4583
|
+
// TODO: Use Glob instead?
|
|
4584
|
+
if (!allowUrls || !allowUrls.length) {
|
|
4585
|
+
return true;
|
|
4442
4586
|
}
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
const url = this._getEventFilterUrl(event);
|
|
4450
|
-
return !url ? false : options.denyUrls.some(pattern => isMatchingPattern(url, pattern));
|
|
4587
|
+
const url = _getEventFilterUrl(event);
|
|
4588
|
+
return !url ? true : allowUrls.some(pattern => isMatchingPattern(url, pattern));
|
|
4589
|
+
}
|
|
4590
|
+
function _getPossibleEventMessages(event) {
|
|
4591
|
+
if (event.message) {
|
|
4592
|
+
return [event.message];
|
|
4451
4593
|
}
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4594
|
+
if (event.exception) {
|
|
4595
|
+
try {
|
|
4596
|
+
const { type = '', value = '' } = (event.exception.values && event.exception.values[0]) || {};
|
|
4597
|
+
return [`${value}`, `${type}: ${value}`];
|
|
4598
|
+
}
|
|
4599
|
+
catch (oO) {
|
|
4600
|
+
logger.error(`Cannot extract message for event ${getEventDescription(event)}`);
|
|
4601
|
+
return [];
|
|
4457
4602
|
}
|
|
4458
|
-
const url = this._getEventFilterUrl(event);
|
|
4459
|
-
return !url ? true : options.allowUrls.some(pattern => isMatchingPattern(url, pattern));
|
|
4460
4603
|
}
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
// eslint-disable-next-line deprecation/deprecation
|
|
4469
|
-
...(clientOptions.whitelistUrls || []),
|
|
4470
|
-
...(clientOptions.allowUrls || []),
|
|
4471
|
-
],
|
|
4472
|
-
denyUrls: [
|
|
4473
|
-
// eslint-disable-next-line deprecation/deprecation
|
|
4474
|
-
...(this._options.blacklistUrls || []),
|
|
4475
|
-
...(this._options.denyUrls || []),
|
|
4476
|
-
// eslint-disable-next-line deprecation/deprecation
|
|
4477
|
-
...(clientOptions.blacklistUrls || []),
|
|
4478
|
-
...(clientOptions.denyUrls || []),
|
|
4479
|
-
],
|
|
4480
|
-
ignoreErrors: [
|
|
4481
|
-
...(this._options.ignoreErrors || []),
|
|
4482
|
-
...(clientOptions.ignoreErrors || []),
|
|
4483
|
-
...DEFAULT_IGNORE_ERRORS,
|
|
4484
|
-
],
|
|
4485
|
-
ignoreInternal: typeof this._options.ignoreInternal !== 'undefined' ? this._options.ignoreInternal : true,
|
|
4486
|
-
};
|
|
4604
|
+
return [];
|
|
4605
|
+
}
|
|
4606
|
+
function _isSentryError(event) {
|
|
4607
|
+
try {
|
|
4608
|
+
// @ts-ignore can't be a sentry error if undefined
|
|
4609
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
4610
|
+
return event.exception.values[0].type === 'SentryError';
|
|
4487
4611
|
}
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
if (event.message) {
|
|
4491
|
-
return [event.message];
|
|
4492
|
-
}
|
|
4493
|
-
if (event.exception) {
|
|
4494
|
-
try {
|
|
4495
|
-
const { type = '', value = '' } = (event.exception.values && event.exception.values[0]) || {};
|
|
4496
|
-
return [`${value}`, `${type}: ${value}`];
|
|
4497
|
-
}
|
|
4498
|
-
catch (oO) {
|
|
4499
|
-
logger.error(`Cannot extract message for event ${getEventDescription(event)}`);
|
|
4500
|
-
return [];
|
|
4501
|
-
}
|
|
4502
|
-
}
|
|
4503
|
-
return [];
|
|
4612
|
+
catch (e) {
|
|
4613
|
+
// ignore
|
|
4504
4614
|
}
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4615
|
+
return false;
|
|
4616
|
+
}
|
|
4617
|
+
function _getLastValidUrl(frames = []) {
|
|
4618
|
+
for (let i = frames.length - 1; i >= 0; i--) {
|
|
4619
|
+
const frame = frames[i];
|
|
4620
|
+
if (frame && frame.filename !== '<anonymous>' && frame.filename !== '[native code]') {
|
|
4621
|
+
return frame.filename || null;
|
|
4512
4622
|
}
|
|
4513
|
-
return null;
|
|
4514
4623
|
}
|
|
4515
|
-
|
|
4516
|
-
|
|
4624
|
+
return null;
|
|
4625
|
+
}
|
|
4626
|
+
function _getEventFilterUrl(event) {
|
|
4627
|
+
try {
|
|
4628
|
+
if (event.stacktrace) {
|
|
4629
|
+
return _getLastValidUrl(event.stacktrace.frames);
|
|
4630
|
+
}
|
|
4631
|
+
let frames;
|
|
4517
4632
|
try {
|
|
4518
|
-
if
|
|
4519
|
-
|
|
4520
|
-
}
|
|
4521
|
-
let frames;
|
|
4522
|
-
try {
|
|
4523
|
-
// @ts-ignore we only care about frames if the whole thing here is defined
|
|
4524
|
-
frames = event.exception.values[0].stacktrace.frames;
|
|
4525
|
-
}
|
|
4526
|
-
catch (e) {
|
|
4527
|
-
// ignore
|
|
4528
|
-
}
|
|
4529
|
-
return frames ? this._getLastValidUrl(frames) : null;
|
|
4633
|
+
// @ts-ignore we only care about frames if the whole thing here is defined
|
|
4634
|
+
frames = event.exception.values[0].stacktrace.frames;
|
|
4530
4635
|
}
|
|
4531
|
-
catch (
|
|
4532
|
-
|
|
4533
|
-
return null;
|
|
4636
|
+
catch (e) {
|
|
4637
|
+
// ignore
|
|
4534
4638
|
}
|
|
4639
|
+
return frames ? _getLastValidUrl(frames) : null;
|
|
4535
4640
|
}
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4641
|
+
catch (oO) {
|
|
4642
|
+
logger.error(`Cannot extract url for event ${getEventDescription(event)}`);
|
|
4643
|
+
return null;
|
|
4644
|
+
}
|
|
4645
|
+
}
|
|
4541
4646
|
|
|
4542
4647
|
var CoreIntegrations = /*#__PURE__*/Object.freeze({
|
|
4543
4648
|
__proto__: null,
|
|
@@ -5218,11 +5323,76 @@ var Sentry = (function (exports) {
|
|
|
5218
5323
|
}
|
|
5219
5324
|
}
|
|
5220
5325
|
|
|
5326
|
+
/**
|
|
5327
|
+
* Creates a Transport that uses the Fetch API to send events to Sentry.
|
|
5328
|
+
*/
|
|
5329
|
+
function makeNewFetchTransport(options, nativeFetch = getNativeFetchImplementation()) {
|
|
5330
|
+
function makeRequest(request) {
|
|
5331
|
+
const requestOptions = Object.assign({ body: request.body, method: 'POST', referrerPolicy: 'origin' }, options.requestOptions);
|
|
5332
|
+
return nativeFetch(options.url, requestOptions).then(response => {
|
|
5333
|
+
return response.text().then(body => ({
|
|
5334
|
+
body,
|
|
5335
|
+
headers: {
|
|
5336
|
+
'x-sentry-rate-limits': response.headers.get('X-Sentry-Rate-Limits'),
|
|
5337
|
+
'retry-after': response.headers.get('Retry-After'),
|
|
5338
|
+
},
|
|
5339
|
+
reason: response.statusText,
|
|
5340
|
+
statusCode: response.status,
|
|
5341
|
+
}));
|
|
5342
|
+
});
|
|
5343
|
+
}
|
|
5344
|
+
return createTransport({ bufferSize: options.bufferSize }, makeRequest);
|
|
5345
|
+
}
|
|
5346
|
+
|
|
5347
|
+
/**
|
|
5348
|
+
* The DONE ready state for XmlHttpRequest
|
|
5349
|
+
*
|
|
5350
|
+
* Defining it here as a constant b/c XMLHttpRequest.DONE is not always defined
|
|
5351
|
+
* (e.g. during testing, it is `undefined`)
|
|
5352
|
+
*
|
|
5353
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState}
|
|
5354
|
+
*/
|
|
5355
|
+
const XHR_READYSTATE_DONE = 4;
|
|
5356
|
+
/**
|
|
5357
|
+
* Creates a Transport that uses the XMLHttpRequest API to send events to Sentry.
|
|
5358
|
+
*/
|
|
5359
|
+
function makeNewXHRTransport(options) {
|
|
5360
|
+
function makeRequest(request) {
|
|
5361
|
+
return new SyncPromise((resolve, _reject) => {
|
|
5362
|
+
const xhr = new XMLHttpRequest();
|
|
5363
|
+
xhr.onreadystatechange = () => {
|
|
5364
|
+
if (xhr.readyState === XHR_READYSTATE_DONE) {
|
|
5365
|
+
const response = {
|
|
5366
|
+
body: xhr.response,
|
|
5367
|
+
headers: {
|
|
5368
|
+
'x-sentry-rate-limits': xhr.getResponseHeader('X-Sentry-Rate-Limits'),
|
|
5369
|
+
'retry-after': xhr.getResponseHeader('Retry-After'),
|
|
5370
|
+
},
|
|
5371
|
+
reason: xhr.statusText,
|
|
5372
|
+
statusCode: xhr.status,
|
|
5373
|
+
};
|
|
5374
|
+
resolve(response);
|
|
5375
|
+
}
|
|
5376
|
+
};
|
|
5377
|
+
xhr.open('POST', options.url);
|
|
5378
|
+
for (const header in options.headers) {
|
|
5379
|
+
if (Object.prototype.hasOwnProperty.call(options.headers, header)) {
|
|
5380
|
+
xhr.setRequestHeader(header, options.headers[header]);
|
|
5381
|
+
}
|
|
5382
|
+
}
|
|
5383
|
+
xhr.send(request.body);
|
|
5384
|
+
});
|
|
5385
|
+
}
|
|
5386
|
+
return createTransport({ bufferSize: options.bufferSize }, makeRequest);
|
|
5387
|
+
}
|
|
5388
|
+
|
|
5221
5389
|
var index = /*#__PURE__*/Object.freeze({
|
|
5222
5390
|
__proto__: null,
|
|
5223
5391
|
BaseTransport: BaseTransport,
|
|
5224
5392
|
FetchTransport: FetchTransport,
|
|
5225
|
-
XHRTransport: XHRTransport
|
|
5393
|
+
XHRTransport: XHRTransport,
|
|
5394
|
+
makeNewFetchTransport: makeNewFetchTransport,
|
|
5395
|
+
makeNewXHRTransport: makeNewXHRTransport
|
|
5226
5396
|
});
|
|
5227
5397
|
|
|
5228
5398
|
/**
|
|
@@ -5251,12 +5421,20 @@ var Sentry = (function (exports) {
|
|
|
5251
5421
|
return super._setupTransport();
|
|
5252
5422
|
}
|
|
5253
5423
|
const transportOptions = Object.assign(Object.assign({}, this._options.transportOptions), { dsn: this._options.dsn, tunnel: this._options.tunnel, sendClientReports: this._options.sendClientReports, _metadata: this._options._metadata });
|
|
5424
|
+
const api = initAPIDetails(transportOptions.dsn, transportOptions._metadata, transportOptions.tunnel);
|
|
5425
|
+
const url = getEnvelopeEndpointWithUrlEncodedAuth(api.dsn, api.tunnel);
|
|
5254
5426
|
if (this._options.transport) {
|
|
5255
5427
|
return new this._options.transport(transportOptions);
|
|
5256
5428
|
}
|
|
5257
5429
|
if (supportsFetch()) {
|
|
5430
|
+
const requestOptions = Object.assign({}, transportOptions.fetchParameters);
|
|
5431
|
+
this._newTransport = makeNewFetchTransport({ requestOptions, url });
|
|
5258
5432
|
return new FetchTransport(transportOptions);
|
|
5259
5433
|
}
|
|
5434
|
+
this._newTransport = makeNewXHRTransport({
|
|
5435
|
+
url,
|
|
5436
|
+
headers: transportOptions.headers,
|
|
5437
|
+
});
|
|
5260
5438
|
return new XHRTransport(transportOptions);
|
|
5261
5439
|
}
|
|
5262
5440
|
}
|