wintercg-fetch.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import { instrumentFetchRequest } from '@sentry-internal/tracing';
  2. import { defineIntegration, convertIntegrationFnToClass, getClient, isSentryRequestUrl, addBreadcrumb } from '@sentry/core';
  3. import { LRUMap, addFetchInstrumentationHandler, stringMatchesSomePattern } from '@sentry/utils';
  4. const INTEGRATION_NAME = 'WinterCGFetch';
  5. const HAS_CLIENT_MAP = new WeakMap();
  6. const _winterCGFetch = ((options = {}) => {
  7. const breadcrumbs = options.breadcrumbs === undefined ? true : options.breadcrumbs;
  8. const shouldCreateSpanForRequest = options.shouldCreateSpanForRequest;
  9. const _createSpanUrlMap = new LRUMap(100);
  10. const _headersUrlMap = new LRUMap(100);
  11. const spans = {};
  12. /** Decides whether to attach trace data to the outgoing fetch request */
  13. function _shouldAttachTraceData(url) {
  14. const client = getClient();
  15. if (!client) {
  16. return false;
  17. }
  18. const clientOptions = client.getOptions();
  19. if (clientOptions.tracePropagationTargets === undefined) {
  20. return true;
  21. }
  22. const cachedDecision = _headersUrlMap.get(url);
  23. if (cachedDecision !== undefined) {
  24. return cachedDecision;
  25. }
  26. const decision = stringMatchesSomePattern(url, clientOptions.tracePropagationTargets);
  27. _headersUrlMap.set(url, decision);
  28. return decision;
  29. }
  30. /** Helper that wraps shouldCreateSpanForRequest option */
  31. function _shouldCreateSpan(url) {
  32. if (shouldCreateSpanForRequest === undefined) {
  33. return true;
  34. }
  35. const cachedDecision = _createSpanUrlMap.get(url);
  36. if (cachedDecision !== undefined) {
  37. return cachedDecision;
  38. }
  39. const decision = shouldCreateSpanForRequest(url);
  40. _createSpanUrlMap.set(url, decision);
  41. return decision;
  42. }
  43. return {
  44. name: INTEGRATION_NAME,
  45. // TODO v8: Remove this again
  46. // eslint-disable-next-line @typescript-eslint/no-empty-function
  47. setupOnce() {
  48. addFetchInstrumentationHandler(handlerData => {
  49. const client = getClient();
  50. if (!client || !HAS_CLIENT_MAP.get(client)) {
  51. return;
  52. }
  53. if (isSentryRequestUrl(handlerData.fetchData.url, client)) {
  54. return;
  55. }
  56. instrumentFetchRequest(
  57. handlerData,
  58. _shouldCreateSpan,
  59. _shouldAttachTraceData,
  60. spans,
  61. 'auto.http.wintercg_fetch',
  62. );
  63. if (breadcrumbs) {
  64. createBreadcrumb(handlerData);
  65. }
  66. });
  67. },
  68. setup(client) {
  69. HAS_CLIENT_MAP.set(client, true);
  70. },
  71. };
  72. }) ;
  73. const winterCGFetchIntegration = defineIntegration(_winterCGFetch);
  74. /**
  75. * Creates spans and attaches tracing headers to fetch requests on WinterCG runtimes.
  76. *
  77. * @deprecated Use `winterCGFetchIntegration()` instead.
  78. */
  79. // eslint-disable-next-line deprecation/deprecation
  80. const WinterCGFetch = convertIntegrationFnToClass(
  81. INTEGRATION_NAME,
  82. winterCGFetchIntegration,
  83. )
  84. ;
  85. // eslint-disable-next-line deprecation/deprecation
  86. function createBreadcrumb(handlerData) {
  87. const { startTimestamp, endTimestamp } = handlerData;
  88. // We only capture complete fetch requests
  89. if (!endTimestamp) {
  90. return;
  91. }
  92. if (handlerData.error) {
  93. const data = handlerData.fetchData;
  94. const hint = {
  95. data: handlerData.error,
  96. input: handlerData.args,
  97. startTimestamp,
  98. endTimestamp,
  99. };
  100. addBreadcrumb(
  101. {
  102. category: 'fetch',
  103. data,
  104. level: 'error',
  105. type: 'http',
  106. },
  107. hint,
  108. );
  109. } else {
  110. const data = {
  111. ...handlerData.fetchData,
  112. status_code: handlerData.response && handlerData.response.status,
  113. };
  114. const hint = {
  115. input: handlerData.args,
  116. response: handlerData.response,
  117. startTimestamp,
  118. endTimestamp,
  119. };
  120. addBreadcrumb(
  121. {
  122. category: 'fetch',
  123. data,
  124. type: 'http',
  125. },
  126. hint,
  127. );
  128. }
  129. }
  130. export { WinterCGFetch, winterCGFetchIntegration };
  131. //# sourceMappingURL=wintercg-fetch.js.map