index.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import { createTransport } from '@sentry/core';
  2. import { SentryError } from '@sentry/utils';
  3. const DEFAULT_TRANSPORT_BUFFER_SIZE = 30;
  4. /**
  5. * This is a modified promise buffer that collects tasks until drain is called.
  6. * We need this in the edge runtime because edge function invocations may not share I/O objects, like fetch requests
  7. * and responses, and the normal PromiseBuffer inherently buffers stuff inbetween incoming requests.
  8. *
  9. * A limitation we need to be aware of is that DEFAULT_TRANSPORT_BUFFER_SIZE is the maximum amount of payloads the
  10. * SDK can send for a given edge function invocation.
  11. */
  12. class IsolatedPromiseBuffer {
  13. // We just have this field because the promise buffer interface requires it.
  14. // If we ever remove it from the interface we should also remove it here.
  15. constructor(_bufferSize = DEFAULT_TRANSPORT_BUFFER_SIZE) {
  16. this.$ = [];
  17. this._taskProducers = [];
  18. this._bufferSize = _bufferSize;
  19. }
  20. /**
  21. * @inheritdoc
  22. */
  23. add(taskProducer) {
  24. if (this._taskProducers.length >= this._bufferSize) {
  25. return Promise.reject(new SentryError('Not adding Promise because buffer limit was reached.'));
  26. }
  27. this._taskProducers.push(taskProducer);
  28. return Promise.resolve();
  29. }
  30. /**
  31. * @inheritdoc
  32. */
  33. drain(timeout) {
  34. const oldTaskProducers = [...this._taskProducers];
  35. this._taskProducers = [];
  36. return new Promise(resolve => {
  37. const timer = setTimeout(() => {
  38. if (timeout && timeout > 0) {
  39. resolve(false);
  40. }
  41. }, timeout);
  42. // This cannot reject
  43. // eslint-disable-next-line @typescript-eslint/no-floating-promises
  44. Promise.all(
  45. oldTaskProducers.map(taskProducer =>
  46. taskProducer().then(null, () => {
  47. // catch all failed requests
  48. }),
  49. ),
  50. ).then(() => {
  51. // resolve to true if all fetch requests settled
  52. clearTimeout(timer);
  53. resolve(true);
  54. });
  55. });
  56. }
  57. }
  58. /**
  59. * Creates a Transport that uses the Edge Runtimes native fetch API to send events to Sentry.
  60. */
  61. function makeEdgeTransport(options) {
  62. function makeRequest(request) {
  63. const requestOptions = {
  64. body: request.body,
  65. method: 'POST',
  66. headers: options.headers,
  67. ...options.fetchOptions,
  68. };
  69. return fetch(options.url, requestOptions).then(response => {
  70. return {
  71. statusCode: response.status,
  72. headers: {
  73. 'x-sentry-rate-limits': response.headers.get('X-Sentry-Rate-Limits'),
  74. 'retry-after': response.headers.get('Retry-After'),
  75. },
  76. };
  77. });
  78. }
  79. return createTransport(options, makeRequest, new IsolatedPromiseBuffer(options.bufferSize));
  80. }
  81. export { IsolatedPromiseBuffer, makeEdgeTransport };
  82. //# sourceMappingURL=index.js.map