@sentry/core 10.51.0 → 10.52.0

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.
Files changed (195) hide show
  1. package/build/cjs/client.js +6 -2
  2. package/build/cjs/client.js.map +1 -1
  3. package/build/cjs/fetch.js +7 -4
  4. package/build/cjs/fetch.js.map +1 -1
  5. package/build/cjs/index.js +27 -8
  6. package/build/cjs/index.js.map +1 -1
  7. package/build/cjs/integrations/express/index.js +2 -4
  8. package/build/cjs/integrations/express/index.js.map +1 -1
  9. package/build/cjs/integrations/express/utils.js +0 -7
  10. package/build/cjs/integrations/express/utils.js.map +1 -1
  11. package/build/cjs/integrations/http/add-outgoing-request-breadcrumb.js +43 -0
  12. package/build/cjs/integrations/http/add-outgoing-request-breadcrumb.js.map +1 -0
  13. package/build/cjs/integrations/http/client-patch.js +113 -0
  14. package/build/cjs/integrations/http/client-patch.js.map +1 -0
  15. package/build/cjs/integrations/http/client-subscriptions.js +166 -0
  16. package/build/cjs/integrations/http/client-subscriptions.js.map +1 -0
  17. package/build/cjs/integrations/http/constants.js +10 -0
  18. package/build/cjs/integrations/http/constants.js.map +1 -0
  19. package/build/cjs/integrations/http/double-wrap-warning.js +29 -0
  20. package/build/cjs/integrations/http/double-wrap-warning.js.map +1 -0
  21. package/build/cjs/integrations/http/get-outgoing-span-data.js +88 -0
  22. package/build/cjs/integrations/http/get-outgoing-span-data.js.map +1 -0
  23. package/build/cjs/integrations/http/get-request-url.js +54 -0
  24. package/build/cjs/integrations/http/get-request-url.js.map +1 -0
  25. package/build/cjs/integrations/http/inject-trace-propagation-headers.js +81 -0
  26. package/build/cjs/integrations/http/inject-trace-propagation-headers.js.map +1 -0
  27. package/build/cjs/integrations/requestdata.js +85 -3
  28. package/build/cjs/integrations/requestdata.js.map +1 -1
  29. package/build/cjs/logs/envelope.js +12 -2
  30. package/build/cjs/logs/envelope.js.map +1 -1
  31. package/build/cjs/logs/internal.js +7 -1
  32. package/build/cjs/logs/internal.js.map +1 -1
  33. package/build/cjs/metrics/envelope.js +15 -2
  34. package/build/cjs/metrics/envelope.js.map +1 -1
  35. package/build/cjs/metrics/internal.js +7 -1
  36. package/build/cjs/metrics/internal.js.map +1 -1
  37. package/build/cjs/tracing/spans/captureSpan.js +58 -23
  38. package/build/cjs/tracing/spans/captureSpan.js.map +1 -1
  39. package/build/cjs/tracing/trace.js +1 -0
  40. package/build/cjs/tracing/trace.js.map +1 -1
  41. package/build/cjs/tracing/vercel-ai/constants.js +8 -0
  42. package/build/cjs/tracing/vercel-ai/constants.js.map +1 -1
  43. package/build/cjs/tracing/vercel-ai/index.js +93 -14
  44. package/build/cjs/tracing/vercel-ai/index.js.map +1 -1
  45. package/build/cjs/utils/baggage.js +73 -0
  46. package/build/cjs/utils/baggage.js.map +1 -1
  47. package/build/cjs/utils/chain-and-copy-promiselike.js +1 -0
  48. package/build/cjs/utils/chain-and-copy-promiselike.js.map +1 -1
  49. package/build/cjs/utils/get-default-export.js +32 -0
  50. package/build/cjs/utils/get-default-export.js.map +1 -0
  51. package/build/cjs/utils/request.js +129 -0
  52. package/build/cjs/utils/request.js.map +1 -1
  53. package/build/cjs/utils/spanUtils.js +1 -1
  54. package/build/cjs/utils/spanUtils.js.map +1 -1
  55. package/build/cjs/utils/version.js +1 -1
  56. package/build/esm/client.js +6 -2
  57. package/build/esm/client.js.map +1 -1
  58. package/build/esm/fetch.js +7 -4
  59. package/build/esm/fetch.js.map +1 -1
  60. package/build/esm/index.js +8 -3
  61. package/build/esm/index.js.map +1 -1
  62. package/build/esm/integrations/express/index.js +3 -5
  63. package/build/esm/integrations/express/index.js.map +1 -1
  64. package/build/esm/integrations/express/utils.js +1 -7
  65. package/build/esm/integrations/express/utils.js.map +1 -1
  66. package/build/esm/integrations/http/add-outgoing-request-breadcrumb.js +41 -0
  67. package/build/esm/integrations/http/add-outgoing-request-breadcrumb.js.map +1 -0
  68. package/build/esm/integrations/http/client-patch.js +111 -0
  69. package/build/esm/integrations/http/client-patch.js.map +1 -0
  70. package/build/esm/integrations/http/client-subscriptions.js +164 -0
  71. package/build/esm/integrations/http/client-subscriptions.js.map +1 -0
  72. package/build/esm/integrations/http/constants.js +6 -0
  73. package/build/esm/integrations/http/constants.js.map +1 -0
  74. package/build/esm/integrations/http/double-wrap-warning.js +26 -0
  75. package/build/esm/integrations/http/double-wrap-warning.js.map +1 -0
  76. package/build/esm/integrations/http/get-outgoing-span-data.js +85 -0
  77. package/build/esm/integrations/http/get-outgoing-span-data.js.map +1 -0
  78. package/build/esm/integrations/http/get-request-url.js +49 -0
  79. package/build/esm/integrations/http/get-request-url.js.map +1 -0
  80. package/build/esm/integrations/http/inject-trace-propagation-headers.js +79 -0
  81. package/build/esm/integrations/http/inject-trace-propagation-headers.js.map +1 -0
  82. package/build/esm/integrations/requestdata.js +85 -3
  83. package/build/esm/integrations/requestdata.js.map +1 -1
  84. package/build/esm/logs/envelope.js +12 -2
  85. package/build/esm/logs/envelope.js.map +1 -1
  86. package/build/esm/logs/internal.js +7 -1
  87. package/build/esm/logs/internal.js.map +1 -1
  88. package/build/esm/metrics/envelope.js +15 -2
  89. package/build/esm/metrics/envelope.js.map +1 -1
  90. package/build/esm/metrics/internal.js +7 -1
  91. package/build/esm/metrics/internal.js.map +1 -1
  92. package/build/esm/package.json +1 -1
  93. package/build/esm/tracing/spans/captureSpan.js +58 -23
  94. package/build/esm/tracing/spans/captureSpan.js.map +1 -1
  95. package/build/esm/tracing/trace.js +1 -1
  96. package/build/esm/tracing/trace.js.map +1 -1
  97. package/build/esm/tracing/vercel-ai/constants.js +8 -1
  98. package/build/esm/tracing/vercel-ai/constants.js.map +1 -1
  99. package/build/esm/tracing/vercel-ai/index.js +95 -17
  100. package/build/esm/tracing/vercel-ai/index.js.map +1 -1
  101. package/build/esm/utils/baggage.js +73 -1
  102. package/build/esm/utils/baggage.js.map +1 -1
  103. package/build/esm/utils/chain-and-copy-promiselike.js +1 -0
  104. package/build/esm/utils/chain-and-copy-promiselike.js.map +1 -1
  105. package/build/esm/utils/get-default-export.js +30 -0
  106. package/build/esm/utils/get-default-export.js.map +1 -0
  107. package/build/esm/utils/request.js +127 -1
  108. package/build/esm/utils/request.js.map +1 -1
  109. package/build/esm/utils/spanUtils.js +1 -1
  110. package/build/esm/utils/spanUtils.js.map +1 -1
  111. package/build/esm/utils/version.js +1 -1
  112. package/build/types/client.d.ts.map +1 -1
  113. package/build/types/fetch.d.ts.map +1 -1
  114. package/build/types/index.d.ts +13 -4
  115. package/build/types/index.d.ts.map +1 -1
  116. package/build/types/integrations/express/index.d.ts.map +1 -1
  117. package/build/types/integrations/express/utils.d.ts +1 -5
  118. package/build/types/integrations/express/utils.d.ts.map +1 -1
  119. package/build/types/integrations/http/add-outgoing-request-breadcrumb.d.ts +6 -0
  120. package/build/types/integrations/http/add-outgoing-request-breadcrumb.d.ts.map +1 -0
  121. package/build/types/integrations/http/client-patch.d.ts +46 -0
  122. package/build/types/integrations/http/client-patch.d.ts.map +1 -0
  123. package/build/types/integrations/http/client-subscriptions.d.ts +21 -0
  124. package/build/types/integrations/http/client-subscriptions.d.ts.map +1 -0
  125. package/build/types/integrations/http/constants.d.ts +6 -0
  126. package/build/types/integrations/http/constants.d.ts.map +1 -0
  127. package/build/types/integrations/http/double-wrap-warning.d.ts +4 -0
  128. package/build/types/integrations/http/double-wrap-warning.d.ts.map +1 -0
  129. package/build/types/integrations/http/get-outgoing-span-data.d.ts +13 -0
  130. package/build/types/integrations/http/get-outgoing-span-data.d.ts.map +1 -0
  131. package/build/types/integrations/http/get-request-url.d.ts +10 -0
  132. package/build/types/integrations/http/get-request-url.d.ts.map +1 -0
  133. package/build/types/integrations/http/index.d.ts +4 -0
  134. package/build/types/integrations/http/index.d.ts.map +1 -0
  135. package/build/types/integrations/http/inject-trace-propagation-headers.d.ts +12 -0
  136. package/build/types/integrations/http/inject-trace-propagation-headers.d.ts.map +1 -0
  137. package/build/types/integrations/http/types.d.ts +249 -0
  138. package/build/types/integrations/http/types.d.ts.map +1 -0
  139. package/build/types/integrations/requestdata.d.ts.map +1 -1
  140. package/build/types/logs/envelope.d.ts +5 -2
  141. package/build/types/logs/envelope.d.ts.map +1 -1
  142. package/build/types/logs/internal.d.ts.map +1 -1
  143. package/build/types/metrics/envelope.d.ts +5 -2
  144. package/build/types/metrics/envelope.d.ts.map +1 -1
  145. package/build/types/metrics/internal.d.ts.map +1 -1
  146. package/build/types/tracing/index.d.ts +1 -1
  147. package/build/types/tracing/index.d.ts.map +1 -1
  148. package/build/types/tracing/spans/captureSpan.d.ts +4 -4
  149. package/build/types/tracing/spans/captureSpan.d.ts.map +1 -1
  150. package/build/types/tracing/trace.d.ts +1 -0
  151. package/build/types/tracing/trace.d.ts.map +1 -1
  152. package/build/types/tracing/vercel-ai/constants.d.ts +1 -0
  153. package/build/types/tracing/vercel-ai/constants.d.ts.map +1 -1
  154. package/build/types/tracing/vercel-ai/index.d.ts +9 -0
  155. package/build/types/tracing/vercel-ai/index.d.ts.map +1 -1
  156. package/build/types/types-hoist/log.d.ts +5 -0
  157. package/build/types/types-hoist/log.d.ts.map +1 -1
  158. package/build/types/types-hoist/metric.d.ts +5 -0
  159. package/build/types/types-hoist/metric.d.ts.map +1 -1
  160. package/build/types/types-hoist/webfetchapi.d.ts +2 -0
  161. package/build/types/types-hoist/webfetchapi.d.ts.map +1 -1
  162. package/build/types/utils/baggage.d.ts +13 -0
  163. package/build/types/utils/baggage.d.ts.map +1 -1
  164. package/build/types/utils/get-default-export.d.ts +22 -0
  165. package/build/types/utils/get-default-export.d.ts.map +1 -0
  166. package/build/types/utils/request.d.ts +30 -0
  167. package/build/types/utils/request.d.ts.map +1 -1
  168. package/build/types/utils/spanUtils.d.ts +1 -1
  169. package/build/types-ts3.8/index.d.ts +13 -4
  170. package/build/types-ts3.8/integrations/express/utils.d.ts +1 -5
  171. package/build/types-ts3.8/integrations/http/add-outgoing-request-breadcrumb.d.ts +6 -0
  172. package/build/types-ts3.8/integrations/http/client-patch.d.ts +46 -0
  173. package/build/types-ts3.8/integrations/http/client-subscriptions.d.ts +21 -0
  174. package/build/types-ts3.8/integrations/http/constants.d.ts +6 -0
  175. package/build/types-ts3.8/integrations/http/double-wrap-warning.d.ts +4 -0
  176. package/build/types-ts3.8/integrations/http/get-outgoing-span-data.d.ts +13 -0
  177. package/build/types-ts3.8/integrations/http/get-request-url.d.ts +10 -0
  178. package/build/types-ts3.8/integrations/http/index.d.ts +4 -0
  179. package/build/types-ts3.8/integrations/http/inject-trace-propagation-headers.d.ts +12 -0
  180. package/build/types-ts3.8/integrations/http/types.d.ts +252 -0
  181. package/build/types-ts3.8/logs/envelope.d.ts +5 -2
  182. package/build/types-ts3.8/metrics/envelope.d.ts +5 -2
  183. package/build/types-ts3.8/tracing/index.d.ts +1 -1
  184. package/build/types-ts3.8/tracing/spans/captureSpan.d.ts +4 -4
  185. package/build/types-ts3.8/tracing/trace.d.ts +1 -0
  186. package/build/types-ts3.8/tracing/vercel-ai/constants.d.ts +1 -0
  187. package/build/types-ts3.8/tracing/vercel-ai/index.d.ts +9 -0
  188. package/build/types-ts3.8/types-hoist/log.d.ts +5 -0
  189. package/build/types-ts3.8/types-hoist/metric.d.ts +5 -0
  190. package/build/types-ts3.8/types-hoist/webfetchapi.d.ts +2 -0
  191. package/build/types-ts3.8/utils/baggage.d.ts +13 -0
  192. package/build/types-ts3.8/utils/get-default-export.d.ts +22 -0
  193. package/build/types-ts3.8/utils/request.d.ts +30 -0
  194. package/build/types-ts3.8/utils/spanUtils.d.ts +1 -1
  195. package/package.json +1 -1
@@ -0,0 +1,166 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const addOutgoingRequestBreadcrumb = require('./add-outgoing-request-breadcrumb.js');
4
+ const debugBuild = require('../../debug-build.js');
5
+ const debugLogger = require('../../utils/debug-logger.js');
6
+ const currentScopes = require('../../currentScopes.js');
7
+ const spanstatus = require('../../tracing/spanstatus.js');
8
+ const hasSpansEnabled = require('../../utils/hasSpansEnabled.js');
9
+ const trace = require('../../tracing/trace.js');
10
+ const lru = require('../../utils/lru.js');
11
+ const getOutgoingSpanData = require('./get-outgoing-span-data.js');
12
+ const getRequestUrl = require('./get-request-url.js');
13
+ const injectTracePropagationHeaders = require('./inject-trace-propagation-headers.js');
14
+ const constants = require('./constants.js');
15
+ const doubleWrapWarning = require('./double-wrap-warning.js');
16
+
17
+ function getHttpClientSubscriptions(options) {
18
+ const propagationDecisionMap = new lru.LRUMap(100);
19
+ const getConfig = () => currentScopes.getClient()?.getOptions();
20
+
21
+ const onHttpClientRequestCreated = (data) => {
22
+ // Skip all instrumentation if tracing is suppressed
23
+ // (e.g., Sentry's own transport uses this to avoid self-instrumentation)
24
+ if (currentScopes.getCurrentScope().getScopeData().sdkProcessingMetadata[trace.SUPPRESS_TRACING_KEY] === true) {
25
+ return;
26
+ }
27
+
28
+ const clientOptions = getConfig();
29
+ const {
30
+ errorMonitor = 'error',
31
+ spans: createSpans = clientOptions ? hasSpansEnabled.hasSpansEnabled(clientOptions) : true,
32
+ propagateTrace = false,
33
+ breadcrumbs = true,
34
+ http,
35
+ https,
36
+ suppressOtelWarning = false,
37
+ } = options;
38
+
39
+ const { request } = data ;
40
+
41
+ // check if request is ignored. if so, we do nothing at all.
42
+ if (options.ignoreOutgoingRequests?.(getRequestUrl.getRequestUrlFromClientRequest(request), request)) {
43
+ return;
44
+ }
45
+
46
+ // guard against adding breadcrumbs multiple times, or when not enabled
47
+ let addedBreadcrumbs = false;
48
+ function addBreadcrumbs(request, response) {
49
+ if (!addedBreadcrumbs) {
50
+ addedBreadcrumbs = true;
51
+ addOutgoingRequestBreadcrumb.addOutgoingRequestBreadcrumb(request, response);
52
+ }
53
+ }
54
+
55
+ // called if spans and/or trace propagation are disabled
56
+ function breadcrumbsOnly(request) {
57
+ request.on(errorMonitor, () => addBreadcrumbs(request, undefined));
58
+ request.prependListener('response', response => {
59
+ if (request.listenerCount('response') <= 1) {
60
+ response.resume();
61
+ }
62
+ response.on('end', () => addBreadcrumbs(request, response));
63
+ response.on(errorMonitor, () => addBreadcrumbs(request, response));
64
+ });
65
+ }
66
+
67
+ if (!createSpans) {
68
+ // no spans, but maybe tracing and/or breadcrumbs
69
+ if (breadcrumbs) {
70
+ breadcrumbsOnly(request);
71
+ }
72
+ if (propagateTrace) {
73
+ injectTracePropagationHeaders.injectTracePropagationHeaders(request, propagationDecisionMap);
74
+ }
75
+ return;
76
+ }
77
+
78
+ // guard against OTel wrapping the same module and emitting double-spans
79
+ // this doesn't prevent it, just prints a debug warning for the user.
80
+ if (!suppressOtelWarning) {
81
+ if (http) doubleWrapWarning.doubleWrapWarning(http);
82
+ if (https) doubleWrapWarning.doubleWrapWarning(https);
83
+ }
84
+
85
+ // spans are enabled
86
+ const span = trace.startInactiveSpan(getOutgoingSpanData.getOutgoingRequestSpanData(request));
87
+ options.outgoingRequestHook?.(span, request);
88
+
89
+ // Inject trace headers after span creation so sentry-trace contains the
90
+ // outgoing span's ID (not the parent's), enabling downstream services to
91
+ // link to this span.
92
+ if (propagateTrace) {
93
+ if (span.isRecording()) {
94
+ trace.withActiveSpan(span, () => {
95
+ injectTracePropagationHeaders.injectTracePropagationHeaders(request, propagationDecisionMap);
96
+ });
97
+ } else {
98
+ injectTracePropagationHeaders.injectTracePropagationHeaders(request, propagationDecisionMap);
99
+ }
100
+ }
101
+
102
+ let spanEnded = false;
103
+ function endSpan(status) {
104
+ if (!spanEnded) {
105
+ spanEnded = true;
106
+ span.setStatus(status);
107
+ span.end();
108
+ }
109
+ }
110
+
111
+ // Fallback: end span if the connection closes before any response.
112
+ // This is removed if we do get a response, because in that case
113
+ // we want to only end the span when the response is finished.
114
+ const requestOnClose = () => endSpan({ code: spanstatus.SPAN_STATUS_UNSET });
115
+ request.on('close', requestOnClose);
116
+
117
+ request.on(errorMonitor, error => {
118
+ debugBuild.DEBUG_BUILD && debugLogger.debug.log(constants.LOG_PREFIX, 'outgoingRequest on request error()', error);
119
+ if (breadcrumbs) {
120
+ addBreadcrumbs(request, undefined);
121
+ }
122
+ endSpan({ code: spanstatus.SPAN_STATUS_ERROR });
123
+ });
124
+
125
+ request.prependListener('response', response => {
126
+ // no longer need this, listen on response now.
127
+ // do not end the span until the response finishes
128
+ request.removeListener('close', requestOnClose);
129
+ if (request.listenerCount('response') <= 1) {
130
+ response.resume();
131
+ }
132
+ getOutgoingSpanData.setIncomingResponseSpanData(response, span);
133
+ options.outgoingResponseHook?.(span, response);
134
+
135
+ let finished = false;
136
+ function finishWithResponse(error) {
137
+ if (!finished) {
138
+ finished = true;
139
+ if (error) {
140
+ debugBuild.DEBUG_BUILD && debugLogger.debug.log(constants.LOG_PREFIX, 'outgoingRequest on response error()', error);
141
+ }
142
+ if (breadcrumbs) {
143
+ addBreadcrumbs(request, response);
144
+ }
145
+ const aborted = response.aborted && !response.complete;
146
+ const status =
147
+ error || typeof response.statusCode !== 'number' || aborted
148
+ ? { code: spanstatus.SPAN_STATUS_ERROR }
149
+ : spanstatus.getSpanStatusFromHttpCode(response.statusCode);
150
+ options.applyCustomAttributesOnSpan?.(span, request, response);
151
+ endSpan(status);
152
+ }
153
+ }
154
+
155
+ response.on('end', () => finishWithResponse());
156
+ response.on(errorMonitor, finishWithResponse);
157
+ });
158
+ };
159
+
160
+ return {
161
+ [constants.HTTP_ON_CLIENT_REQUEST]: onHttpClientRequestCreated,
162
+ };
163
+ }
164
+
165
+ exports.getHttpClientSubscriptions = getHttpClientSubscriptions;
166
+ //# sourceMappingURL=client-subscriptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-subscriptions.js","sources":["../../../../src/integrations/http/client-subscriptions.ts"],"sourcesContent":["/**\n * Define the channels and subscription methods to subscribe to in order to\n * instrument the `node:http` module. Note that this does *not* actually\n * register the subscriptions, it simply returns a data object with the\n * channel names and the subscription handlers. Attach these to diagnostic\n * channels on Node versions where they are supported (ie, >=22.12.0).\n *\n * If any other platforms that do support diagnostic channels eventually add\n * channel coverage for the `node:http` client, then these methods can be\n * used on those platforms as well.\n *\n * This implementation is used in the client-patch strategy, by simply\n * calling the handlers with the relevant data at the appropriate time.\n */\n\nimport type { SpanStatus } from '../../types-hoist/spanStatus';\nimport { addOutgoingRequestBreadcrumb } from './add-outgoing-request-breadcrumb';\nimport {\n getSpanStatusFromHttpCode,\n SPAN_STATUS_ERROR,\n SPAN_STATUS_UNSET,\n startInactiveSpan,\n SUPPRESS_TRACING_KEY,\n withActiveSpan,\n} from '../../tracing';\nimport { debug } from '../../utils/debug-logger';\nimport { LRUMap } from '../../utils/lru';\nimport { getOutgoingRequestSpanData, setIncomingResponseSpanData } from './get-outgoing-span-data';\nimport { getRequestUrlFromClientRequest } from './get-request-url';\nimport { injectTracePropagationHeaders } from './inject-trace-propagation-headers';\nimport type { HttpInstrumentationOptions, HttpClientRequest, HttpIncomingMessage } from './types';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { LOG_PREFIX, HTTP_ON_CLIENT_REQUEST } from './constants';\nimport type { ClientSubscriptionName } from './constants';\nimport { getClient, getCurrentScope } from '../../currentScopes';\nimport { hasSpansEnabled } from '../../utils/hasSpansEnabled';\nimport { doubleWrapWarning } from './double-wrap-warning';\n\ntype ChannelListener = (message: unknown, name: string | symbol) => void;\n\nexport type HttpClientSubscriptions = Record<ClientSubscriptionName, ChannelListener>;\n\nexport function getHttpClientSubscriptions(options: HttpInstrumentationOptions): HttpClientSubscriptions {\n const propagationDecisionMap = new LRUMap<string, boolean>(100);\n const getConfig = () => getClient()?.getOptions();\n\n const onHttpClientRequestCreated: ChannelListener = (data: unknown): void => {\n // Skip all instrumentation if tracing is suppressed\n // (e.g., Sentry's own transport uses this to avoid self-instrumentation)\n if (getCurrentScope().getScopeData().sdkProcessingMetadata[SUPPRESS_TRACING_KEY] === true) {\n return;\n }\n\n const clientOptions = getConfig();\n const {\n errorMonitor = 'error',\n spans: createSpans = clientOptions ? hasSpansEnabled(clientOptions) : true,\n propagateTrace = false,\n breadcrumbs = true,\n http,\n https,\n suppressOtelWarning = false,\n } = options;\n\n const { request } = data as { request: HttpClientRequest };\n\n // check if request is ignored. if so, we do nothing at all.\n if (options.ignoreOutgoingRequests?.(getRequestUrlFromClientRequest(request), request)) {\n return;\n }\n\n // guard against adding breadcrumbs multiple times, or when not enabled\n let addedBreadcrumbs = false;\n function addBreadcrumbs(request: HttpClientRequest, response: HttpIncomingMessage | undefined) {\n if (!addedBreadcrumbs) {\n addedBreadcrumbs = true;\n addOutgoingRequestBreadcrumb(request, response);\n }\n }\n\n // called if spans and/or trace propagation are disabled\n function breadcrumbsOnly(request: HttpClientRequest) {\n request.on(errorMonitor, () => addBreadcrumbs(request, undefined));\n request.prependListener('response', response => {\n if (request.listenerCount('response') <= 1) {\n response.resume();\n }\n response.on('end', () => addBreadcrumbs(request, response));\n response.on(errorMonitor, () => addBreadcrumbs(request, response));\n });\n }\n\n if (!createSpans) {\n // no spans, but maybe tracing and/or breadcrumbs\n if (breadcrumbs) {\n breadcrumbsOnly(request);\n }\n if (propagateTrace) {\n injectTracePropagationHeaders(request, propagationDecisionMap);\n }\n return;\n }\n\n // guard against OTel wrapping the same module and emitting double-spans\n // this doesn't prevent it, just prints a debug warning for the user.\n if (!suppressOtelWarning) {\n if (http) doubleWrapWarning(http);\n if (https) doubleWrapWarning(https);\n }\n\n // spans are enabled\n const span = startInactiveSpan(getOutgoingRequestSpanData(request));\n options.outgoingRequestHook?.(span, request);\n\n // Inject trace headers after span creation so sentry-trace contains the\n // outgoing span's ID (not the parent's), enabling downstream services to\n // link to this span.\n if (propagateTrace) {\n if (span.isRecording()) {\n withActiveSpan(span, () => {\n injectTracePropagationHeaders(request, propagationDecisionMap);\n });\n } else {\n injectTracePropagationHeaders(request, propagationDecisionMap);\n }\n }\n\n let spanEnded = false;\n function endSpan(status: SpanStatus): void {\n if (!spanEnded) {\n spanEnded = true;\n span.setStatus(status);\n span.end();\n }\n }\n\n // Fallback: end span if the connection closes before any response.\n // This is removed if we do get a response, because in that case\n // we want to only end the span when the response is finished.\n const requestOnClose = () => endSpan({ code: SPAN_STATUS_UNSET });\n request.on('close', requestOnClose);\n\n request.on(errorMonitor, error => {\n DEBUG_BUILD && debug.log(LOG_PREFIX, 'outgoingRequest on request error()', error);\n if (breadcrumbs) {\n addBreadcrumbs(request, undefined);\n }\n endSpan({ code: SPAN_STATUS_ERROR });\n });\n\n request.prependListener('response', response => {\n // no longer need this, listen on response now.\n // do not end the span until the response finishes\n request.removeListener('close', requestOnClose);\n if (request.listenerCount('response') <= 1) {\n response.resume();\n }\n setIncomingResponseSpanData(response, span);\n options.outgoingResponseHook?.(span, response);\n\n let finished = false;\n function finishWithResponse(error?: unknown): void {\n if (!finished) {\n finished = true;\n if (error) {\n DEBUG_BUILD && debug.log(LOG_PREFIX, 'outgoingRequest on response error()', error);\n }\n if (breadcrumbs) {\n addBreadcrumbs(request, response);\n }\n const aborted = response.aborted && !response.complete;\n const status: SpanStatus =\n error || typeof response.statusCode !== 'number' || aborted\n ? { code: SPAN_STATUS_ERROR }\n : getSpanStatusFromHttpCode(response.statusCode);\n options.applyCustomAttributesOnSpan?.(span, request, response);\n endSpan(status);\n }\n }\n\n response.on('end', () => finishWithResponse());\n response.on(errorMonitor, finishWithResponse);\n });\n };\n\n return {\n [HTTP_ON_CLIENT_REQUEST]: onHttpClientRequestCreated,\n };\n}\n"],"names":["LRUMap","getClient","getCurrentScope","SUPPRESS_TRACING_KEY","hasSpansEnabled","getRequestUrlFromClientRequest","addOutgoingRequestBreadcrumb","injectTracePropagationHeaders","doubleWrapWarning","startInactiveSpan","getOutgoingRequestSpanData","withActiveSpan","SPAN_STATUS_UNSET","DEBUG_BUILD","debug","LOG_PREFIX","SPAN_STATUS_ERROR","setIncomingResponseSpanData","getSpanStatusFromHttpCode","HTTP_ON_CLIENT_REQUEST"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const LOG_PREFIX = '@sentry/instrumentation-http';
4
+ const HTTP_ON_CLIENT_REQUEST = 'http.client.request.created';
5
+ const HTTP_ON_SERVER_REQUEST = 'http.server.request.start';
6
+
7
+ exports.HTTP_ON_CLIENT_REQUEST = HTTP_ON_CLIENT_REQUEST;
8
+ exports.HTTP_ON_SERVER_REQUEST = HTTP_ON_SERVER_REQUEST;
9
+ exports.LOG_PREFIX = LOG_PREFIX;
10
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sources":["../../../../src/integrations/http/constants.ts"],"sourcesContent":["export const LOG_PREFIX = '@sentry/instrumentation-http';\nexport const HTTP_ON_CLIENT_REQUEST = 'http.client.request.created';\nexport const HTTP_ON_SERVER_REQUEST = 'http.server.request.start';\nexport type ClientSubscriptionName = typeof HTTP_ON_CLIENT_REQUEST;\nexport type ServerSubscriptionName = typeof HTTP_ON_SERVER_REQUEST;\n"],"names":[],"mappings":";;AAAO,MAAM,UAAA,GAAa;AACnB,MAAM,sBAAA,GAAyB;AAC/B,MAAM,sBAAA,GAAyB;;;;;;"}
@@ -0,0 +1,29 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const debugBuild = require('../../debug-build.js');
4
+ const debugLogger = require('../../utils/debug-logger.js');
5
+
6
+ const isOtelWrapped = (fn) =>
7
+ typeof fn.__unwrap === 'function';
8
+
9
+ // exported for tess
10
+ const warning =
11
+ 'Double-wrapped http.client detected. Either disable spans in Sentry.httpIntegration, or disable the OpenTelemetry HTTP instrumentation.';
12
+
13
+ let didDoubleWrapWarning = false;
14
+ // no-op in non-debug builds
15
+ const doubleWrapWarning = debugBuild.DEBUG_BUILD
16
+ ? (http) => {
17
+ if (!didDoubleWrapWarning) {
18
+ if (isOtelWrapped(http.request) || isOtelWrapped(http.get)) {
19
+ // TODO: add link to documentation
20
+ didDoubleWrapWarning = true;
21
+ debugLogger.debug.warn(warning);
22
+ }
23
+ }
24
+ }
25
+ : () => {};
26
+
27
+ exports.doubleWrapWarning = doubleWrapWarning;
28
+ exports.warning = warning;
29
+ //# sourceMappingURL=double-wrap-warning.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"double-wrap-warning.js","sources":["../../../../src/integrations/http/double-wrap-warning.ts"],"sourcesContent":["import { DEBUG_BUILD } from '../../debug-build';\nimport { debug } from '../../utils/debug-logger';\nimport type { HttpModuleExport } from './types';\n\nconst isOtelWrapped = (fn: Function & { __unwrap?: Function }): fn is Function & { __unwrap: Function } =>\n typeof fn.__unwrap === 'function';\n\n// exported for tess\nexport const warning =\n 'Double-wrapped http.client detected. Either disable spans in Sentry.httpIntegration, or disable the OpenTelemetry HTTP instrumentation.';\n\nlet didDoubleWrapWarning = false;\n// no-op in non-debug builds\nexport const doubleWrapWarning = DEBUG_BUILD\n ? (http: HttpModuleExport) => {\n if (!didDoubleWrapWarning) {\n if (isOtelWrapped(http.request) || isOtelWrapped(http.get)) {\n // TODO: add link to documentation\n didDoubleWrapWarning = true;\n debug.warn(warning);\n }\n }\n }\n : () => {};\n"],"names":["DEBUG_BUILD","debug"],"mappings":";;;;;AAIA,MAAM,aAAA,GAAgB,CAAC,EAAE;AACzB,EAAE,OAAO,EAAE,CAAC,QAAA,KAAa,UAAU;;AAEnC;MACa,OAAA;AACb,EAAE;;AAEF,IAAI,oBAAA,GAAuB,KAAK;AAChC;AACO,MAAM,oBAAoBA;AACjC,IAAI,CAAC,IAAI,KAAuB;AAChC,MAAM,IAAI,CAAC,oBAAoB,EAAE;AACjC,QAAQ,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAA,IAAK,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;AACpE;AACA,UAAU,oBAAA,GAAuB,IAAI;AACrC,UAAUC,iBAAK,CAAC,IAAI,CAAC,OAAO,CAAC;AAC7B,QAAQ;AACR,MAAM;AACN,IAAI;AACJ,IAAI,MAAM,CAAC;;;;;"}
@@ -0,0 +1,88 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const semanticAttributes = require('../../semanticAttributes.js');
4
+ const url = require('../../utils/url.js');
5
+ const getRequestUrl = require('./get-request-url.js');
6
+
7
+ /**
8
+ * Build the initial span name and attributes for an outgoing HTTP request.
9
+ * This is called before the span is created, to get the initial details.
10
+ */
11
+ function getOutgoingRequestSpanData(request) {
12
+ const url$1 = getRequestUrl.getRequestUrlFromClientRequest(request);
13
+ const [name, attributes] = url.getHttpSpanDetailsFromUrlObject(
14
+ url.parseStringToURLObject(url$1),
15
+ 'client',
16
+ 'auto.http.client',
17
+ request,
18
+ );
19
+
20
+ const userAgent = request.getHeader('user-agent');
21
+
22
+ return {
23
+ name,
24
+ attributes: {
25
+ // TODO(v11): Update these to the Sentry semantic attributes for urls.
26
+ // https://getsentry.github.io/sentry-conventions/attributes/
27
+ [semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.client',
28
+ 'otel.kind': 'CLIENT',
29
+ 'http.url': url$1,
30
+ 'http.method': request.method,
31
+ 'http.target': request.path || '/',
32
+ 'net.peer.name': request.host,
33
+ 'http.host': request.getHeader('host') ,
34
+ ...(userAgent ? { 'user_agent.original': userAgent } : {}),
35
+ ...attributes,
36
+ },
37
+ onlyIfParent: true,
38
+ };
39
+ }
40
+
41
+ /**
42
+ * Add span attributes once the response is received.
43
+ */
44
+ function setIncomingResponseSpanData(response, span) {
45
+ const { statusCode, statusMessage, httpVersion, socket } = response;
46
+ const transport = httpVersion?.toUpperCase() !== 'QUIC' ? 'ip_tcp' : 'ip_udp';
47
+
48
+ span.setAttributes({
49
+ 'http.response.status_code': statusCode,
50
+ 'network.protocol.version': httpVersion,
51
+ // TODO(v11): Update these to the Sentry semantic attributes for urls.
52
+ // https://getsentry.github.io/sentry-conventions/attributes/
53
+ 'http.flavor': httpVersion,
54
+ 'network.transport': transport,
55
+ 'net.transport': transport,
56
+ 'http.status_text': statusMessage?.toUpperCase(),
57
+ 'http.status_code': statusCode,
58
+ ...getResponseContentLengthAttributes(response),
59
+ ...getSocketAttrs(socket),
60
+ });
61
+ }
62
+
63
+ function getSocketAttrs(socket) {
64
+ if (!socket) return {};
65
+ const { remoteAddress, remotePort } = socket;
66
+ return {
67
+ 'network.peer.address': remoteAddress,
68
+ 'network.peer.port': remotePort,
69
+ 'net.peer.ip': remoteAddress,
70
+ 'net.peer.port': remotePort,
71
+ };
72
+ }
73
+
74
+ function getResponseContentLengthAttributes(response) {
75
+ const { headers } = response;
76
+ const contentLengthHeader = headers['content-length'];
77
+ const length = contentLengthHeader ? parseInt(String(contentLengthHeader), 10) : -1;
78
+ const encoding = headers['content-encoding'];
79
+ return length >= 0
80
+ ? encoding && encoding !== 'identity'
81
+ ? { 'http.response_content_length': length }
82
+ : { 'http.response_content_length_uncompressed': length }
83
+ : {};
84
+ }
85
+
86
+ exports.getOutgoingRequestSpanData = getOutgoingRequestSpanData;
87
+ exports.setIncomingResponseSpanData = setIncomingResponseSpanData;
88
+ //# sourceMappingURL=get-outgoing-span-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-outgoing-span-data.js","sources":["../../../../src/integrations/http/get-outgoing-span-data.ts"],"sourcesContent":["import type { Span, SpanAttributes } from '../../types-hoist/span';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP } from '../../semanticAttributes';\nimport { getHttpSpanDetailsFromUrlObject, parseStringToURLObject } from '../../utils/url';\nimport type { HttpClientRequest, HttpIncomingMessage } from './types';\nimport { getRequestUrlFromClientRequest } from './get-request-url';\nimport type { StartSpanOptions } from '../../types-hoist/startSpanOptions';\n\n/**\n * Build the initial span name and attributes for an outgoing HTTP request.\n * This is called before the span is created, to get the initial details.\n */\nexport function getOutgoingRequestSpanData(request: HttpClientRequest): StartSpanOptions {\n const url = getRequestUrlFromClientRequest(request);\n const [name, attributes] = getHttpSpanDetailsFromUrlObject(\n parseStringToURLObject(url),\n 'client',\n 'auto.http.client',\n request,\n );\n\n const userAgent = request.getHeader('user-agent');\n\n return {\n name,\n attributes: {\n // TODO(v11): Update these to the Sentry semantic attributes for urls.\n // https://getsentry.github.io/sentry-conventions/attributes/\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.client',\n 'otel.kind': 'CLIENT',\n 'http.url': url,\n 'http.method': request.method,\n 'http.target': request.path || '/',\n 'net.peer.name': request.host,\n 'http.host': request.getHeader('host') as string | undefined,\n ...(userAgent ? { 'user_agent.original': userAgent as string } : {}),\n ...attributes,\n },\n onlyIfParent: true,\n };\n}\n\n/**\n * Add span attributes once the response is received.\n */\nexport function setIncomingResponseSpanData(response: HttpIncomingMessage, span: Span): void {\n const { statusCode, statusMessage, httpVersion, socket } = response;\n const transport = httpVersion?.toUpperCase() !== 'QUIC' ? 'ip_tcp' : 'ip_udp';\n\n span.setAttributes({\n 'http.response.status_code': statusCode,\n 'network.protocol.version': httpVersion,\n // TODO(v11): Update these to the Sentry semantic attributes for urls.\n // https://getsentry.github.io/sentry-conventions/attributes/\n 'http.flavor': httpVersion,\n 'network.transport': transport,\n 'net.transport': transport,\n 'http.status_text': statusMessage?.toUpperCase(),\n 'http.status_code': statusCode,\n ...getResponseContentLengthAttributes(response),\n ...getSocketAttrs(socket),\n });\n}\n\nfunction getSocketAttrs(socket: HttpIncomingMessage['socket']): SpanAttributes {\n if (!socket) return {};\n const { remoteAddress, remotePort } = socket;\n return {\n 'network.peer.address': remoteAddress,\n 'network.peer.port': remotePort,\n 'net.peer.ip': remoteAddress,\n 'net.peer.port': remotePort,\n };\n}\n\nfunction getResponseContentLengthAttributes(response: HttpIncomingMessage): SpanAttributes {\n const { headers } = response;\n const contentLengthHeader = headers['content-length'];\n const length = contentLengthHeader ? parseInt(String(contentLengthHeader), 10) : -1;\n const encoding = headers['content-encoding'];\n return length >= 0\n ? encoding && encoding !== 'identity'\n ? { 'http.response_content_length': length }\n : { 'http.response_content_length_uncompressed': length }\n : {};\n}\n"],"names":["url","getRequestUrlFromClientRequest","getHttpSpanDetailsFromUrlObject","parseStringToURLObject","SEMANTIC_ATTRIBUTE_SENTRY_OP"],"mappings":";;;;;;AAOA;AACA;AACA;AACA;AACO,SAAS,0BAA0B,CAAC,OAAO,EAAuC;AACzF,EAAE,MAAMA,KAAA,GAAMC,4CAA8B,CAAC,OAAO,CAAC;AACrD,EAAE,MAAM,CAAC,IAAI,EAAE,UAAU,CAAA,GAAIC,mCAA+B;AAC5D,IAAIC,0BAAsB,CAACH,KAAG,CAAC;AAC/B,IAAI,QAAQ;AACZ,IAAI,kBAAkB;AACtB,IAAI,OAAO;AACX,GAAG;;AAEH,EAAE,MAAM,YAAY,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC;;AAEnD,EAAE,OAAO;AACT,IAAI,IAAI;AACR,IAAI,UAAU,EAAE;AAChB;AACA;AACA,MAAM,CAACI,+CAA4B,GAAG,aAAa;AACnD,MAAM,WAAW,EAAE,QAAQ;AAC3B,MAAM,UAAU,EAAEJ,KAAG;AACrB,MAAM,aAAa,EAAE,OAAO,CAAC,MAAM;AACnC,MAAM,aAAa,EAAE,OAAO,CAAC,IAAA,IAAQ,GAAG;AACxC,MAAM,eAAe,EAAE,OAAO,CAAC,IAAI;AACnC,MAAM,WAAW,EAAE,OAAO,CAAC,SAAS,CAAC,MAAM,CAAA;AAC3C,MAAM,IAAI,SAAA,GAAY,EAAE,qBAAqB,EAAE,SAAA,GAAoB,GAAI,EAAE,CAAC;AAC1E,MAAM,GAAG,UAAU;AACnB,KAAK;AACL,IAAI,YAAY,EAAE,IAAI;AACtB,GAAG;AACH;;AAEA;AACA;AACA;AACO,SAAS,2BAA2B,CAAC,QAAQ,EAAuB,IAAI,EAAc;AAC7F,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,MAAA,EAAO,GAAI,QAAQ;AACrE,EAAE,MAAM,SAAA,GAAY,WAAW,EAAE,WAAW,EAAC,KAAM,MAAA,GAAS,QAAA,GAAW,QAAQ;;AAE/E,EAAE,IAAI,CAAC,aAAa,CAAC;AACrB,IAAI,2BAA2B,EAAE,UAAU;AAC3C,IAAI,0BAA0B,EAAE,WAAW;AAC3C;AACA;AACA,IAAI,aAAa,EAAE,WAAW;AAC9B,IAAI,mBAAmB,EAAE,SAAS;AAClC,IAAI,eAAe,EAAE,SAAS;AAC9B,IAAI,kBAAkB,EAAE,aAAa,EAAE,WAAW,EAAE;AACpD,IAAI,kBAAkB,EAAE,UAAU;AAClC,IAAI,GAAG,kCAAkC,CAAC,QAAQ,CAAC;AACnD,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC;AAC7B,GAAG,CAAC;AACJ;;AAEA,SAAS,cAAc,CAAC,MAAM,EAAiD;AAC/E,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE;AACxB,EAAE,MAAM,EAAE,aAAa,EAAE,UAAA,EAAW,GAAI,MAAM;AAC9C,EAAE,OAAO;AACT,IAAI,sBAAsB,EAAE,aAAa;AACzC,IAAI,mBAAmB,EAAE,UAAU;AACnC,IAAI,aAAa,EAAE,aAAa;AAChC,IAAI,eAAe,EAAE,UAAU;AAC/B,GAAG;AACH;;AAEA,SAAS,kCAAkC,CAAC,QAAQ,EAAuC;AAC3F,EAAE,MAAM,EAAE,OAAA,EAAQ,GAAI,QAAQ;AAC9B,EAAE,MAAM,mBAAA,GAAsB,OAAO,CAAC,gBAAgB,CAAC;AACvD,EAAE,MAAM,MAAA,GAAS,mBAAA,GAAsB,QAAQ,CAAC,MAAM,CAAC,mBAAmB,CAAC,EAAE,EAAE,CAAA,GAAI,EAAE;AACrF,EAAE,MAAM,QAAA,GAAW,OAAO,CAAC,kBAAkB,CAAC;AAC9C,EAAE,OAAO,UAAU;AACnB,MAAM,QAAA,IAAY,QAAA,KAAa;AAC/B,QAAQ,EAAE,8BAA8B,EAAE,MAAA;AAC1C,QAAQ,EAAE,2CAA2C,EAAE,MAAA;AACvD,MAAM,EAAE;AACR;;;;;"}
@@ -0,0 +1,54 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ /** Convert an outgoing request to request options. */
4
+ function getRequestOptions(request) {
5
+ // request.host may be 'hostname:port' when the caller passed
6
+ // { host: 'hostname:port' } to http.request(). Split it so that
7
+ // `hostname` is always port-free (matching the http.RequestOptions contract)
8
+ // and the port is not lost when request.port is undefined.
9
+ const hostWithPort = request.host || '';
10
+ const portInHost = /^(.*):(\d+)$/.exec(hostWithPort);
11
+ const hostname = portInHost ? portInHost[1] : hostWithPort;
12
+ const port = request.port ?? (portInHost ? Number(portInHost[2]) : undefined);
13
+
14
+ return {
15
+ method: request.method,
16
+ port,
17
+ protocol: request.protocol,
18
+ host: request.host,
19
+ hostname,
20
+ path: request.path,
21
+ headers: request.getHeaders(),
22
+ };
23
+ }
24
+
25
+ function getRequestUrl(requestOptions) {
26
+ return String(getRequestUrlObject(requestOptions));
27
+ }
28
+
29
+ function getRequestUrlObject(requestOptions) {
30
+ const protocol = requestOptions.protocol || 'http:';
31
+ const hostHeader = requestOptions.headers?.host && String(requestOptions.headers?.host);
32
+ const hostname = hostHeader || requestOptions.hostname || requestOptions.host || '';
33
+ // Don't log standard :80 (http) and :443 (https) ports to reduce the noise
34
+ // Also don't add port if the hostname already includes a port
35
+ const port =
36
+ !requestOptions.port || requestOptions.port === 80 || requestOptions.port === 443 || /^(.*):(\d+)$/.test(hostname)
37
+ ? ''
38
+ : `:${requestOptions.port}`;
39
+ const path = requestOptions.path ? requestOptions.path : '/';
40
+ return new URL(path, `${protocol}//${hostname}${port}`);
41
+ }
42
+
43
+ /**
44
+ * Build the full URL string from a Node.js ClientRequest.
45
+ */
46
+ function getRequestUrlFromClientRequest(request) {
47
+ return String(getRequestUrl(getRequestOptions(request)));
48
+ }
49
+
50
+ exports.getRequestOptions = getRequestOptions;
51
+ exports.getRequestUrl = getRequestUrl;
52
+ exports.getRequestUrlFromClientRequest = getRequestUrlFromClientRequest;
53
+ exports.getRequestUrlObject = getRequestUrlObject;
54
+ //# sourceMappingURL=get-request-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-request-url.js","sources":["../../../../src/integrations/http/get-request-url.ts"],"sourcesContent":["import type { HttpClientRequest, HttpRequestOptions } from './types';\n\n/** Convert an outgoing request to request options. */\nexport function getRequestOptions(request: HttpClientRequest): HttpRequestOptions {\n // request.host may be 'hostname:port' when the caller passed\n // { host: 'hostname:port' } to http.request(). Split it so that\n // `hostname` is always port-free (matching the http.RequestOptions contract)\n // and the port is not lost when request.port is undefined.\n const hostWithPort = request.host || '';\n const portInHost = /^(.*):(\\d+)$/.exec(hostWithPort);\n const hostname = portInHost ? portInHost[1] : hostWithPort;\n const port = request.port ?? (portInHost ? Number(portInHost[2]) : undefined);\n\n return {\n method: request.method,\n port,\n protocol: request.protocol,\n host: request.host,\n hostname,\n path: request.path,\n headers: request.getHeaders(),\n };\n}\n\nexport function getRequestUrl(requestOptions: HttpRequestOptions): string {\n return String(getRequestUrlObject(requestOptions));\n}\n\nexport function getRequestUrlObject(requestOptions: HttpRequestOptions): URL {\n const protocol = requestOptions.protocol || 'http:';\n const hostHeader = requestOptions.headers?.host && String(requestOptions.headers?.host);\n const hostname = hostHeader || requestOptions.hostname || requestOptions.host || '';\n // Don't log standard :80 (http) and :443 (https) ports to reduce the noise\n // Also don't add port if the hostname already includes a port\n const port =\n !requestOptions.port || requestOptions.port === 80 || requestOptions.port === 443 || /^(.*):(\\d+)$/.test(hostname)\n ? ''\n : `:${requestOptions.port}`;\n const path = requestOptions.path ? requestOptions.path : '/';\n return new URL(path, `${protocol}//${hostname}${port}`);\n}\n\n/**\n * Build the full URL string from a Node.js ClientRequest.\n */\nexport function getRequestUrlFromClientRequest(request: HttpClientRequest): string {\n return String(getRequestUrl(getRequestOptions(request)));\n}\n"],"names":[],"mappings":";;AAEA;AACO,SAAS,iBAAiB,CAAC,OAAO,EAAyC;AAClF;AACA;AACA;AACA;AACA,EAAE,MAAM,YAAA,GAAe,OAAO,CAAC,IAAA,IAAQ,EAAE;AACzC,EAAE,MAAM,aAAa,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC;AACtD,EAAE,MAAM,QAAA,GAAW,UAAA,GAAa,UAAU,CAAC,CAAC,CAAA,GAAI,YAAY;AAC5D,EAAE,MAAM,IAAA,GAAO,OAAO,CAAC,IAAA,KAAS,UAAA,GAAa,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA,GAAI,SAAS,CAAC;;AAE/E,EAAE,OAAO;AACT,IAAI,MAAM,EAAE,OAAO,CAAC,MAAM;AAC1B,IAAI,IAAI;AACR,IAAI,QAAQ,EAAE,OAAO,CAAC,QAAQ;AAC9B,IAAI,IAAI,EAAE,OAAO,CAAC,IAAI;AACtB,IAAI,QAAQ;AACZ,IAAI,IAAI,EAAE,OAAO,CAAC,IAAI;AACtB,IAAI,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;AACjC,GAAG;AACH;;AAEO,SAAS,aAAa,CAAC,cAAc,EAA8B;AAC1E,EAAE,OAAO,MAAM,CAAC,mBAAmB,CAAC,cAAc,CAAC,CAAC;AACpD;;AAEO,SAAS,mBAAmB,CAAC,cAAc,EAA2B;AAC7E,EAAE,MAAM,QAAA,GAAW,cAAc,CAAC,QAAA,IAAY,OAAO;AACrD,EAAE,MAAM,UAAA,GAAa,cAAc,CAAC,OAAO,EAAE,IAAA,IAAQ,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC;AACzF,EAAE,MAAM,QAAA,GAAW,UAAA,IAAc,cAAc,CAAC,QAAA,IAAY,cAAc,CAAC,IAAA,IAAQ,EAAE;AACrF;AACA;AACA,EAAE,MAAM,IAAA;AACR,IAAI,CAAC,cAAc,CAAC,IAAA,IAAQ,cAAc,CAAC,SAAS,EAAA,IAAM,cAAc,CAAC,SAAS,GAAA,IAAO,cAAc,CAAC,IAAI,CAAC,QAAQ;AACrH,QAAQ;AACR,QAAQ,CAAC,CAAC,EAAE,cAAc,CAAC,IAAI,CAAC,CAAA;AACA,EAAA,MAAA,IAAA,GAAA,cAAA,CAAA,IAAA,GAAA,cAAA,CAAA,IAAA,GAAA,GAAA;AACA,EAAA,OAAA,IAAA,GAAA,CAAA,IAAA,EAAA,CAAA,EAAA,QAAA,CAAA,EAAA,EAAA,QAAA,CAAA,EAAA,IAAA,CAAA,CAAA,CAAA;AACA;;AAEA;AACA;AACA;AACA,SAAA,8BAAA,CAAA,OAAA,EAAA;AACA,EAAA,OAAA,MAAA,CAAA,aAAA,CAAA,iBAAA,CAAA,OAAA,CAAA,CAAA,CAAA;AACA;;;;;;;"}
@@ -0,0 +1,81 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const currentScopes = require('../../currentScopes.js');
4
+ const debugBuild = require('../../debug-build.js');
5
+ const debugLogger = require('../../utils/debug-logger.js');
6
+ const is = require('../../utils/is.js');
7
+ const traceData = require('../../utils/traceData.js');
8
+ const tracePropagationTargets = require('../../utils/tracePropagationTargets.js');
9
+ const constants = require('./constants.js');
10
+ const getRequestUrl = require('./get-request-url.js');
11
+ const baggage = require('../../utils/baggage.js');
12
+
13
+ /**
14
+ * Inject Sentry trace-propagation headers into an outgoing request if the
15
+ * target URL matches the configured `tracePropagationTargets`.
16
+ *
17
+ * Note: this must be called *before* calling `request.end()` (or firing the
18
+ * `http.client.request.start` diagnostics channel), because at that point,
19
+ * the headers have already been sent, and cannot be modified.
20
+ */
21
+ function injectTracePropagationHeaders(
22
+ request,
23
+ propagationDecisionMap,
24
+ ) {
25
+ const url = getRequestUrl.getRequestUrlFromClientRequest(request);
26
+ const clientOptions = currentScopes.getClient()?.getOptions();
27
+ const { tracePropagationTargets: tracePropagationTargets$1, propagateTraceparent } = clientOptions ?? {};
28
+
29
+ if (!tracePropagationTargets.shouldPropagateTraceForUrl(url, tracePropagationTargets$1, propagationDecisionMap)) {
30
+ return;
31
+ }
32
+
33
+ const hasExistingSentryTraceHeader = !!request.getHeader('sentry-trace');
34
+
35
+ if (hasExistingSentryTraceHeader) {
36
+ // add nothing if there's already a sentry-trace header,
37
+ // or else baggage can be sent twice.
38
+ return;
39
+ }
40
+
41
+ const traceData$1 = traceData.getTraceData({ propagateTraceparent });
42
+ if (!traceData$1) return;
43
+
44
+ const { 'sentry-trace': sentryTrace, baggage: baggage$1, traceparent } = traceData$1;
45
+
46
+ if (sentryTrace) {
47
+ try {
48
+ request.setHeader('sentry-trace', sentryTrace);
49
+ debugBuild.DEBUG_BUILD && debugLogger.debug.log(constants.LOG_PREFIX, 'Added sentry-trace header');
50
+ } catch (e) {
51
+ debugBuild.DEBUG_BUILD &&
52
+ debugLogger.debug.error(constants.LOG_PREFIX, 'Failed to set sentry-trace header:', is.isError(e) ? e.message : 'Unknown error');
53
+ }
54
+ }
55
+
56
+ if (traceparent && !request.getHeader('traceparent')) {
57
+ try {
58
+ request.setHeader('traceparent', traceparent);
59
+ debugBuild.DEBUG_BUILD && debugLogger.debug.log(constants.LOG_PREFIX, 'Added traceparent header');
60
+ } catch (e) {
61
+ debugBuild.DEBUG_BUILD &&
62
+ debugLogger.debug.error(constants.LOG_PREFIX, 'Failed to set traceparent header:', is.isError(e) ? e.message : 'Unknown error');
63
+ }
64
+ }
65
+
66
+ if (baggage$1) {
67
+ const merged = baggage.mergeBaggageHeaders(request.getHeader('baggage'), baggage$1);
68
+ if (merged) {
69
+ try {
70
+ request.setHeader('baggage', merged);
71
+ debugBuild.DEBUG_BUILD && debugLogger.debug.log(constants.LOG_PREFIX, 'Added baggage header');
72
+ } catch (e) {
73
+ debugBuild.DEBUG_BUILD &&
74
+ debugLogger.debug.error(constants.LOG_PREFIX, 'Failed to set baggage header:', is.isError(e) ? e.message : 'Unknown error');
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ exports.injectTracePropagationHeaders = injectTracePropagationHeaders;
81
+ //# sourceMappingURL=inject-trace-propagation-headers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inject-trace-propagation-headers.js","sources":["../../../../src/integrations/http/inject-trace-propagation-headers.ts"],"sourcesContent":["import type { LRUMap } from '../../utils/lru';\nimport { getClient } from '../../currentScopes';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { debug } from '../../utils/debug-logger';\nimport { isError } from '../../utils/is';\nimport { getTraceData } from '../../utils/traceData';\nimport { shouldPropagateTraceForUrl } from '../../utils/tracePropagationTargets';\nimport { LOG_PREFIX } from './constants';\nimport { getRequestUrlFromClientRequest } from './get-request-url';\nimport type { HttpClientRequest } from './types';\nimport { mergeBaggageHeaders } from '../../utils/baggage';\n\n/**\n * Inject Sentry trace-propagation headers into an outgoing request if the\n * target URL matches the configured `tracePropagationTargets`.\n *\n * Note: this must be called *before* calling `request.end()` (or firing the\n * `http.client.request.start` diagnostics channel), because at that point,\n * the headers have already been sent, and cannot be modified.\n */\nexport function injectTracePropagationHeaders(\n request: HttpClientRequest,\n propagationDecisionMap: LRUMap<string, boolean>,\n): void {\n const url = getRequestUrlFromClientRequest(request);\n const clientOptions = getClient()?.getOptions();\n const { tracePropagationTargets, propagateTraceparent } = clientOptions ?? {};\n\n if (!shouldPropagateTraceForUrl(url, tracePropagationTargets, propagationDecisionMap)) {\n return;\n }\n\n const hasExistingSentryTraceHeader = !!request.getHeader('sentry-trace');\n\n if (hasExistingSentryTraceHeader) {\n // add nothing if there's already a sentry-trace header,\n // or else baggage can be sent twice.\n return;\n }\n\n const traceData = getTraceData({ propagateTraceparent });\n if (!traceData) return;\n\n const { 'sentry-trace': sentryTrace, baggage, traceparent } = traceData;\n\n if (sentryTrace) {\n try {\n request.setHeader('sentry-trace', sentryTrace);\n DEBUG_BUILD && debug.log(LOG_PREFIX, 'Added sentry-trace header');\n } catch (e) {\n DEBUG_BUILD &&\n debug.error(LOG_PREFIX, 'Failed to set sentry-trace header:', isError(e) ? e.message : 'Unknown error');\n }\n }\n\n if (traceparent && !request.getHeader('traceparent')) {\n try {\n request.setHeader('traceparent', traceparent);\n DEBUG_BUILD && debug.log(LOG_PREFIX, 'Added traceparent header');\n } catch (e) {\n DEBUG_BUILD &&\n debug.error(LOG_PREFIX, 'Failed to set traceparent header:', isError(e) ? e.message : 'Unknown error');\n }\n }\n\n if (baggage) {\n const merged = mergeBaggageHeaders(request.getHeader('baggage'), baggage);\n if (merged) {\n try {\n request.setHeader('baggage', merged);\n DEBUG_BUILD && debug.log(LOG_PREFIX, 'Added baggage header');\n } catch (e) {\n DEBUG_BUILD &&\n debug.error(LOG_PREFIX, 'Failed to set baggage header:', isError(e) ? e.message : 'Unknown error');\n }\n }\n }\n}\n"],"names":["getRequestUrlFromClientRequest","getClient","tracePropagationTargets","shouldPropagateTraceForUrl","traceData","getTraceData","baggage","DEBUG_BUILD","debug","LOG_PREFIX","isError","mergeBaggageHeaders"],"mappings":";;;;;;;;;;;;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,6BAA6B;AAC7C,EAAE,OAAO;AACT,EAAE,sBAAsB;AACxB,EAAQ;AACR,EAAE,MAAM,GAAA,GAAMA,4CAA8B,CAAC,OAAO,CAAC;AACrD,EAAE,MAAM,gBAAgBC,uBAAS,EAAE,EAAE,UAAU,EAAE;AACjD,EAAE,MAAM,2BAAEC,yBAAuB,EAAE,oBAAA,KAAyB,aAAA,IAAiB,EAAE;;AAE/E,EAAE,IAAI,CAACC,kDAA0B,CAAC,GAAG,EAAED,yBAAuB,EAAE,sBAAsB,CAAC,EAAE;AACzF,IAAI;AACJ,EAAE;;AAEF,EAAE,MAAM,4BAAA,GAA+B,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,cAAc,CAAC;;AAE1E,EAAE,IAAI,4BAA4B,EAAE;AACpC;AACA;AACA,IAAI;AACJ,EAAE;;AAEF,EAAE,MAAME,cAAYC,sBAAY,CAAC,EAAE,oBAAA,EAAsB,CAAC;AAC1D,EAAE,IAAI,CAACD,WAAS,EAAE;;AAElB,EAAE,MAAM,EAAE,cAAc,EAAE,WAAW,WAAEE,SAAO,EAAE,WAAA,EAAY,GAAIF,WAAS;;AAEzE,EAAE,IAAI,WAAW,EAAE;AACnB,IAAI,IAAI;AACR,MAAM,OAAO,CAAC,SAAS,CAAC,cAAc,EAAE,WAAW,CAAC;AACpD,MAAMG,sBAAA,IAAeC,iBAAK,CAAC,GAAG,CAACC,oBAAU,EAAE,2BAA2B,CAAC;AACvE,IAAI,CAAA,CAAE,OAAO,CAAC,EAAE;AAChB,MAAMF,sBAAA;AACN,QAAQC,iBAAK,CAAC,KAAK,CAACC,oBAAU,EAAE,oCAAoC,EAAEC,UAAO,CAAC,CAAC,IAAI,CAAC,CAAC,OAAA,GAAU,eAAe,CAAC;AAC/G,IAAI;AACJ,EAAE;;AAEF,EAAE,IAAI,WAAA,IAAe,CAAC,OAAO,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE;AACxD,IAAI,IAAI;AACR,MAAM,OAAO,CAAC,SAAS,CAAC,aAAa,EAAE,WAAW,CAAC;AACnD,MAAMH,sBAAA,IAAeC,iBAAK,CAAC,GAAG,CAACC,oBAAU,EAAE,0BAA0B,CAAC;AACtE,IAAI,CAAA,CAAE,OAAO,CAAC,EAAE;AAChB,MAAMF,sBAAA;AACN,QAAQC,iBAAK,CAAC,KAAK,CAACC,oBAAU,EAAE,mCAAmC,EAAEC,UAAO,CAAC,CAAC,IAAI,CAAC,CAAC,OAAA,GAAU,eAAe,CAAC;AAC9G,IAAI;AACJ,EAAE;;AAEF,EAAE,IAAIJ,SAAO,EAAE;AACf,IAAI,MAAM,MAAA,GAASK,2BAAmB,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,EAAEL,SAAO,CAAC;AAC7E,IAAI,IAAI,MAAM,EAAE;AAChB,MAAM,IAAI;AACV,QAAQ,OAAO,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC;AAC5C,QAAQC,sBAAA,IAAeC,iBAAK,CAAC,GAAG,CAACC,oBAAU,EAAE,sBAAsB,CAAC;AACpE,MAAM,CAAA,CAAE,OAAO,CAAC,EAAE;AAClB,QAAQF,sBAAA;AACR,UAAUC,iBAAK,CAAC,KAAK,CAACC,oBAAU,EAAE,+BAA+B,EAAEC,UAAO,CAAC,CAAC,IAAI,CAAC,CAAC,OAAA,GAAU,eAAe,CAAC;AAC5G,MAAM;AACN,IAAI;AACJ,EAAE;AACF;;;;"}
@@ -1,8 +1,12 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
+ const currentScopes = require('../currentScopes.js');
3
4
  const integration = require('../integration.js');
5
+ const semanticAttributes = require('../semanticAttributes.js');
4
6
  const cookie = require('../utils/cookie.js');
7
+ const request = require('../utils/request.js');
5
8
  const getIpAddress = require('../vendor/getIpAddress.js');
9
+ const captureSpan = require('../tracing/spans/captureSpan.js');
6
10
 
7
11
  // TODO(v11): Change defaults based on `sendDefaultPii`
8
12
  const DEFAULT_INCLUDE = {
@@ -38,6 +42,22 @@ const _requestDataIntegration = ((options = {}) => {
38
42
 
39
43
  return event;
40
44
  },
45
+ processSegmentSpan(span, client) {
46
+ const { sdkProcessingMetadata = {} } = currentScopes.getIsolationScope().getScopeData();
47
+ const { normalizedRequest, ipAddress } = sdkProcessingMetadata;
48
+
49
+ if (!normalizedRequest) {
50
+ return;
51
+ }
52
+
53
+ const { sendDefaultPii } = client.getOptions();
54
+ const includeWithDefaultPiiApplied = {
55
+ ...include,
56
+ ip: include.ip ?? sendDefaultPii,
57
+ };
58
+
59
+ addNormalizedRequestDataToSpan(span, normalizedRequest, ipAddress, includeWithDefaultPiiApplied, sendDefaultPii);
60
+ },
41
61
  };
42
62
  }) ;
43
63
 
@@ -74,6 +94,60 @@ function addNormalizedRequestDataToEvent(
74
94
  }
75
95
  }
76
96
 
97
+ function addNormalizedRequestDataToSpan(
98
+ span,
99
+ normalizedRequest,
100
+ ipAddress,
101
+ include,
102
+ sendDefaultPii,
103
+ ) {
104
+ const requestData = extractNormalizedRequestData(normalizedRequest, include);
105
+ const attributes = {};
106
+
107
+ if (requestData.url) {
108
+ attributes['url.full'] = requestData.url;
109
+ }
110
+
111
+ if (requestData.method) {
112
+ attributes['http.request.method'] = requestData.method;
113
+ }
114
+
115
+ if (requestData.query_string) {
116
+ attributes['url.query'] = normalizeQueryString(requestData.query_string);
117
+ }
118
+
119
+ captureSpan.safeSetSpanJSONAttributes(span, attributes);
120
+
121
+ // Process cookies before headers so normalizedRequest.cookies takes precedence
122
+ // over the raw cookie header (matching the processEvent path).
123
+ if (requestData.cookies && Object.keys(requestData.cookies).length > 0) {
124
+ const cookieString = Object.entries(requestData.cookies)
125
+ .map(([name, value]) => `${name}=${value}`)
126
+ .join('; ');
127
+ const cookieAttributes = request.httpHeadersToSpanAttributes({ cookie: cookieString }, sendDefaultPii ?? false, 'request');
128
+ captureSpan.safeSetSpanJSONAttributes(span, cookieAttributes);
129
+ }
130
+
131
+ if (requestData.headers) {
132
+ const headerAttributes = request.httpHeadersToSpanAttributes(requestData.headers, sendDefaultPii ?? false, 'request');
133
+ captureSpan.safeSetSpanJSONAttributes(span, headerAttributes);
134
+ }
135
+
136
+ if (requestData.data != null) {
137
+ const serialized = typeof requestData.data === 'string' ? requestData.data : JSON.stringify(requestData.data);
138
+ if (serialized) {
139
+ captureSpan.safeSetSpanJSONAttributes(span, { 'http.request.body.data': serialized });
140
+ }
141
+ }
142
+
143
+ if (include.ip) {
144
+ const ip = (normalizedRequest.headers && getIpAddress.getClientIPAddress(normalizedRequest.headers)) || ipAddress || undefined;
145
+ if (ip) {
146
+ captureSpan.safeSetSpanJSONAttributes(span, { [semanticAttributes.SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS]: ip });
147
+ }
148
+ }
149
+ }
150
+
77
151
  function extractNormalizedRequestData(
78
152
  normalizedRequest,
79
153
  include,
@@ -84,13 +158,10 @@ function extractNormalizedRequestData(
84
158
  if (include.headers) {
85
159
  requestData.headers = headers;
86
160
 
87
- // Remove the Cookie header in case cookie data should not be included in the event
88
161
  if (!include.cookies) {
89
162
  delete (headers ).cookie;
90
163
  }
91
164
 
92
- // Remove IP headers in case IP data should not be included in the event.
93
- // Match case-insensitively — same as getClientIPAddress — so lowercase keys are stripped too.
94
165
  if (!include.ip) {
95
166
  const ipHeaderNamesLower = new Set(getIpAddress.ipHeaderNames.map(name => name.toLowerCase()));
96
167
  for (const key of Object.keys(headers)) {
@@ -124,5 +195,16 @@ function extractNormalizedRequestData(
124
195
  return requestData;
125
196
  }
126
197
 
198
+ function normalizeQueryString(queryString) {
199
+ if (typeof queryString === 'string') {
200
+ return queryString || undefined;
201
+ }
202
+
203
+ const pairs = Array.isArray(queryString) ? queryString : Object.entries(queryString);
204
+ const result = pairs.map(([key, value]) => `${key}=${value}`).join('&');
205
+
206
+ return result || undefined;
207
+ }
208
+
127
209
  exports.requestDataIntegration = requestDataIntegration;
128
210
  //# sourceMappingURL=requestdata.js.map