aggregate-errors.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import { isInstanceOf } from './is.js';
  2. import { truncate } from './string.js';
  3. /**
  4. * Creates exceptions inside `event.exception.values` for errors that are nested on properties based on the `key` parameter.
  5. */
  6. function applyAggregateErrorsToEvent(
  7. exceptionFromErrorImplementation,
  8. parser,
  9. maxValueLimit = 250,
  10. key,
  11. limit,
  12. event,
  13. hint,
  14. ) {
  15. if (!event.exception || !event.exception.values || !hint || !isInstanceOf(hint.originalException, Error)) {
  16. return;
  17. }
  18. // Generally speaking the last item in `event.exception.values` is the exception originating from the original Error
  19. const originalException =
  20. event.exception.values.length > 0 ? event.exception.values[event.exception.values.length - 1] : undefined;
  21. // We only create exception grouping if there is an exception in the event.
  22. if (originalException) {
  23. event.exception.values = truncateAggregateExceptions(
  24. aggregateExceptionsFromError(
  25. exceptionFromErrorImplementation,
  26. parser,
  27. limit,
  28. hint.originalException ,
  29. key,
  30. event.exception.values,
  31. originalException,
  32. 0,
  33. ),
  34. maxValueLimit,
  35. );
  36. }
  37. }
  38. function aggregateExceptionsFromError(
  39. exceptionFromErrorImplementation,
  40. parser,
  41. limit,
  42. error,
  43. key,
  44. prevExceptions,
  45. exception,
  46. exceptionId,
  47. ) {
  48. if (prevExceptions.length >= limit + 1) {
  49. return prevExceptions;
  50. }
  51. let newExceptions = [...prevExceptions];
  52. if (isInstanceOf(error[key], Error)) {
  53. applyExceptionGroupFieldsForParentException(exception, exceptionId);
  54. const newException = exceptionFromErrorImplementation(parser, error[key]);
  55. const newExceptionId = newExceptions.length;
  56. applyExceptionGroupFieldsForChildException(newException, key, newExceptionId, exceptionId);
  57. newExceptions = aggregateExceptionsFromError(
  58. exceptionFromErrorImplementation,
  59. parser,
  60. limit,
  61. error[key],
  62. key,
  63. [newException, ...newExceptions],
  64. newException,
  65. newExceptionId,
  66. );
  67. }
  68. // This will create exception grouping for AggregateErrors
  69. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError
  70. if (Array.isArray(error.errors)) {
  71. error.errors.forEach((childError, i) => {
  72. if (isInstanceOf(childError, Error)) {
  73. applyExceptionGroupFieldsForParentException(exception, exceptionId);
  74. const newException = exceptionFromErrorImplementation(parser, childError);
  75. const newExceptionId = newExceptions.length;
  76. applyExceptionGroupFieldsForChildException(newException, `errors[${i}]`, newExceptionId, exceptionId);
  77. newExceptions = aggregateExceptionsFromError(
  78. exceptionFromErrorImplementation,
  79. parser,
  80. limit,
  81. childError,
  82. key,
  83. [newException, ...newExceptions],
  84. newException,
  85. newExceptionId,
  86. );
  87. }
  88. });
  89. }
  90. return newExceptions;
  91. }
  92. function applyExceptionGroupFieldsForParentException(exception, exceptionId) {
  93. // Don't know if this default makes sense. The protocol requires us to set these values so we pick *some* default.
  94. exception.mechanism = exception.mechanism || { type: 'generic', handled: true };
  95. exception.mechanism = {
  96. ...exception.mechanism,
  97. is_exception_group: true,
  98. exception_id: exceptionId,
  99. };
  100. }
  101. function applyExceptionGroupFieldsForChildException(
  102. exception,
  103. source,
  104. exceptionId,
  105. parentId,
  106. ) {
  107. // Don't know if this default makes sense. The protocol requires us to set these values so we pick *some* default.
  108. exception.mechanism = exception.mechanism || { type: 'generic', handled: true };
  109. exception.mechanism = {
  110. ...exception.mechanism,
  111. type: 'chained',
  112. source,
  113. exception_id: exceptionId,
  114. parent_id: parentId,
  115. };
  116. }
  117. /**
  118. * Truncate the message (exception.value) of all exceptions in the event.
  119. * Because this event processor is ran after `applyClientOptions`,
  120. * we need to truncate the message of the added exceptions here.
  121. */
  122. function truncateAggregateExceptions(exceptions, maxValueLength) {
  123. return exceptions.map(exception => {
  124. if (exception.value) {
  125. exception.value = truncate(exception.value, maxValueLength);
  126. }
  127. return exception;
  128. });
  129. }
  130. export { applyAggregateErrorsToEvent };
  131. //# sourceMappingURL=aggregate-errors.js.map