@sentry/node 11.0.0-alpha.1 → 11.0.0-beta.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 (188) hide show
  1. package/README.md +19 -0
  2. package/build/cjs/bundler-plugin/esbuild.js.map +1 -1
  3. package/build/cjs/bundler-plugin/rollup.js.map +1 -1
  4. package/build/cjs/bundler-plugin/vite.js.map +1 -1
  5. package/build/cjs/bundler-plugin/webpack.js.map +1 -1
  6. package/build/cjs/index.js +56 -56
  7. package/build/cjs/integrations/anr/index.js +1 -1
  8. package/build/cjs/integrations/childProcess.js +0 -24
  9. package/build/cjs/integrations/childProcess.js.map +1 -1
  10. package/build/cjs/integrations/fs/vendored/instrumentation.js +4 -2
  11. package/build/cjs/integrations/fs/vendored/instrumentation.js.map +1 -1
  12. package/build/cjs/integrations/http/SentryHttpInstrumentation.js +7 -12
  13. package/build/cjs/integrations/http/SentryHttpInstrumentation.js.map +1 -1
  14. package/build/cjs/integrations/http/httpServerIntegration.js +4 -3
  15. package/build/cjs/integrations/http/httpServerIntegration.js.map +1 -1
  16. package/build/cjs/integrations/http/httpServerSpansIntegration.js +38 -92
  17. package/build/cjs/integrations/http/httpServerSpansIntegration.js.map +1 -1
  18. package/build/cjs/integrations/http/index.js +16 -30
  19. package/build/cjs/integrations/http/index.js.map +1 -1
  20. package/build/cjs/integrations/local-variables/local-variables-async.js +1 -1
  21. package/build/cjs/integrations/node-fetch/undici-instrumentation.js +15 -7
  22. package/build/cjs/integrations/node-fetch/undici-instrumentation.js.map +1 -1
  23. package/build/cjs/integrations/nodeRuntimeMetrics.js +2 -1
  24. package/build/cjs/integrations/nodeRuntimeMetrics.js.map +1 -1
  25. package/build/cjs/integrations/onunhandledrejection.js +5 -3
  26. package/build/cjs/integrations/onunhandledrejection.js.map +1 -1
  27. package/build/cjs/integrations/pino.js +2 -3
  28. package/build/cjs/integrations/pino.js.map +1 -1
  29. package/build/cjs/integrations/processSession.js +1 -1
  30. package/build/cjs/integrations/processSession.js.map +1 -1
  31. package/build/cjs/integrations/tracing/hapi.js +10 -0
  32. package/build/cjs/integrations/tracing/hapi.js.map +1 -0
  33. package/build/cjs/integrations/tracing/index.js +1 -34
  34. package/build/cjs/integrations/tracing/index.js.map +1 -1
  35. package/build/cjs/integrations/tracing/koa.js +10 -0
  36. package/build/cjs/integrations/tracing/koa.js.map +1 -0
  37. package/build/cjs/integrations/workerThreads.js +35 -0
  38. package/build/cjs/integrations/workerThreads.js.map +1 -0
  39. package/build/cjs/sdk/api.js +2 -1
  40. package/build/cjs/sdk/api.js.map +1 -1
  41. package/build/cjs/sdk/client.js +25 -14
  42. package/build/cjs/sdk/client.js.map +1 -1
  43. package/build/cjs/sdk/index.js +17 -30
  44. package/build/cjs/sdk/index.js.map +1 -1
  45. package/build/cjs/transports/http.js +10 -3
  46. package/build/cjs/transports/http.js.map +1 -1
  47. package/build/cjs/utils/outgoingFetchRequest.js +1 -1
  48. package/build/cjs/utils/outgoingFetchRequest.js.map +1 -1
  49. package/build/esm/bundler-plugin/esbuild.js.map +1 -1
  50. package/build/esm/bundler-plugin/rollup.js.map +1 -1
  51. package/build/esm/bundler-plugin/vite.js.map +1 -1
  52. package/build/esm/bundler-plugin/webpack.js.map +1 -1
  53. package/build/esm/index.js +7 -8
  54. package/build/esm/index.js.map +1 -1
  55. package/build/esm/integrations/anr/index.js +1 -1
  56. package/build/esm/integrations/anr/worker-script.js +2 -2
  57. package/build/esm/integrations/childProcess.js +1 -25
  58. package/build/esm/integrations/childProcess.js.map +1 -1
  59. package/build/esm/integrations/fs/vendored/instrumentation.js +4 -2
  60. package/build/esm/integrations/fs/vendored/instrumentation.js.map +1 -1
  61. package/build/esm/integrations/http/SentryHttpInstrumentation.js +5 -10
  62. package/build/esm/integrations/http/SentryHttpInstrumentation.js.map +1 -1
  63. package/build/esm/integrations/http/httpServerIntegration.js +3 -2
  64. package/build/esm/integrations/http/httpServerIntegration.js.map +1 -1
  65. package/build/esm/integrations/http/httpServerSpansIntegration.js +40 -94
  66. package/build/esm/integrations/http/httpServerSpansIntegration.js.map +1 -1
  67. package/build/esm/integrations/http/index.js +15 -29
  68. package/build/esm/integrations/http/index.js.map +1 -1
  69. package/build/esm/integrations/local-variables/local-variables-async.js +1 -1
  70. package/build/esm/integrations/local-variables/worker-script.js +1 -1
  71. package/build/esm/integrations/node-fetch/undici-instrumentation.js +17 -9
  72. package/build/esm/integrations/node-fetch/undici-instrumentation.js.map +1 -1
  73. package/build/esm/integrations/nodeRuntimeMetrics.js +2 -1
  74. package/build/esm/integrations/nodeRuntimeMetrics.js.map +1 -1
  75. package/build/esm/integrations/onunhandledrejection.js +5 -3
  76. package/build/esm/integrations/onunhandledrejection.js.map +1 -1
  77. package/build/esm/integrations/pino.js +2 -3
  78. package/build/esm/integrations/pino.js.map +1 -1
  79. package/build/esm/integrations/processSession.js +1 -1
  80. package/build/esm/integrations/processSession.js.map +1 -1
  81. package/build/esm/integrations/tracing/hapi.js +8 -0
  82. package/build/esm/integrations/tracing/hapi.js.map +1 -0
  83. package/build/esm/integrations/tracing/index.js +2 -35
  84. package/build/esm/integrations/tracing/index.js.map +1 -1
  85. package/build/esm/integrations/tracing/koa.js +8 -0
  86. package/build/esm/integrations/tracing/koa.js.map +1 -0
  87. package/build/esm/integrations/workerThreads.js +33 -0
  88. package/build/esm/integrations/workerThreads.js.map +1 -0
  89. package/build/esm/package.json +1 -1
  90. package/build/esm/sdk/api.js +2 -1
  91. package/build/esm/sdk/api.js.map +1 -1
  92. package/build/esm/sdk/client.js +25 -14
  93. package/build/esm/sdk/client.js.map +1 -1
  94. package/build/esm/sdk/index.js +11 -24
  95. package/build/esm/sdk/index.js.map +1 -1
  96. package/build/esm/transports/http.js +10 -3
  97. package/build/esm/transports/http.js.map +1 -1
  98. package/build/esm/utils/outgoingFetchRequest.js +2 -2
  99. package/build/esm/utils/outgoingFetchRequest.js.map +1 -1
  100. package/build/import-hook.mjs +1 -1
  101. package/build/types/bundler-plugin/esbuild.d.ts +3 -4
  102. package/build/types/bundler-plugin/esbuild.d.ts.map +1 -1
  103. package/build/types/bundler-plugin/rollup.d.ts +3 -4
  104. package/build/types/bundler-plugin/rollup.d.ts.map +1 -1
  105. package/build/types/bundler-plugin/vite.d.ts +3 -4
  106. package/build/types/bundler-plugin/vite.d.ts.map +1 -1
  107. package/build/types/bundler-plugin/webpack.d.ts +2 -2
  108. package/build/types/bundler-plugin/webpack.d.ts.map +1 -1
  109. package/build/types/index.d.ts +7 -6
  110. package/build/types/index.d.ts.map +1 -1
  111. package/build/types/integrations/childProcess.d.ts +2 -7
  112. package/build/types/integrations/childProcess.d.ts.map +1 -1
  113. package/build/types/integrations/fs/vendored/instrumentation.d.ts.map +1 -1
  114. package/build/types/integrations/http/SentryHttpInstrumentation.d.ts +8 -62
  115. package/build/types/integrations/http/SentryHttpInstrumentation.d.ts.map +1 -1
  116. package/build/types/integrations/http/httpServerIntegration.d.ts +4 -3
  117. package/build/types/integrations/http/httpServerIntegration.d.ts.map +1 -1
  118. package/build/types/integrations/http/httpServerSpansIntegration.d.ts +2 -9
  119. package/build/types/integrations/http/httpServerSpansIntegration.d.ts.map +1 -1
  120. package/build/types/integrations/http/index.d.ts +16 -74
  121. package/build/types/integrations/http/index.d.ts.map +1 -1
  122. package/build/types/integrations/node-fetch/undici-instrumentation.d.ts.map +1 -1
  123. package/build/types/integrations/nodeRuntimeMetrics.d.ts.map +1 -1
  124. package/build/types/integrations/pino.d.ts.map +1 -1
  125. package/build/types/integrations/tracing/hapi.d.ts +13 -0
  126. package/build/types/integrations/tracing/hapi.d.ts.map +1 -0
  127. package/build/types/integrations/tracing/index.d.ts.map +1 -1
  128. package/build/types/integrations/tracing/koa.d.ts +27 -0
  129. package/build/types/integrations/tracing/koa.d.ts.map +1 -0
  130. package/build/types/integrations/workerThreads.d.ts +8 -0
  131. package/build/types/integrations/workerThreads.d.ts.map +1 -0
  132. package/build/types/sdk/api.d.ts.map +1 -1
  133. package/build/types/sdk/client.d.ts +3 -1
  134. package/build/types/sdk/client.d.ts.map +1 -1
  135. package/build/types/sdk/index.d.ts.map +1 -1
  136. package/build/types/transports/http.d.ts +1 -1
  137. package/build/types/transports/http.d.ts.map +1 -1
  138. package/build/types/types.d.ts +13 -1
  139. package/build/types/types.d.ts.map +1 -1
  140. package/package.json +8 -6
  141. package/build/cjs/integrations/tracing/express.js +0 -11
  142. package/build/cjs/integrations/tracing/express.js.map +0 -1
  143. package/build/cjs/integrations/tracing/fastify/index.js +0 -40
  144. package/build/cjs/integrations/tracing/fastify/index.js.map +0 -1
  145. package/build/cjs/integrations/tracing/hapi/index.js +0 -44
  146. package/build/cjs/integrations/tracing/hapi/index.js.map +0 -1
  147. package/build/cjs/integrations/tracing/koa/index.js +0 -22
  148. package/build/cjs/integrations/tracing/koa/index.js.map +0 -1
  149. package/build/cjs/integrations/tracing/redis/cache.js +0 -43
  150. package/build/cjs/integrations/tracing/redis/cache.js.map +0 -1
  151. package/build/cjs/integrations/tracing/redis/index.js +0 -34
  152. package/build/cjs/integrations/tracing/redis/index.js.map +0 -1
  153. package/build/cjs/utils/redisCache.js +0 -98
  154. package/build/cjs/utils/redisCache.js.map +0 -1
  155. package/build/esm/integrations/tracing/express.js +0 -9
  156. package/build/esm/integrations/tracing/express.js.map +0 -1
  157. package/build/esm/integrations/tracing/fastify/index.js +0 -37
  158. package/build/esm/integrations/tracing/fastify/index.js.map +0 -1
  159. package/build/esm/integrations/tracing/hapi/index.js +0 -41
  160. package/build/esm/integrations/tracing/hapi/index.js.map +0 -1
  161. package/build/esm/integrations/tracing/koa/index.js +0 -20
  162. package/build/esm/integrations/tracing/koa/index.js.map +0 -1
  163. package/build/esm/integrations/tracing/redis/cache.js +0 -40
  164. package/build/esm/integrations/tracing/redis/cache.js.map +0 -1
  165. package/build/esm/integrations/tracing/redis/index.js +0 -28
  166. package/build/esm/integrations/tracing/redis/index.js.map +0 -1
  167. package/build/esm/utils/redisCache.js +0 -89
  168. package/build/esm/utils/redisCache.js.map +0 -1
  169. package/build/types/integrations/tracing/express.d.ts +0 -6
  170. package/build/types/integrations/tracing/express.d.ts.map +0 -1
  171. package/build/types/integrations/tracing/fastify/index.d.ts +0 -115
  172. package/build/types/integrations/tracing/fastify/index.d.ts.map +0 -1
  173. package/build/types/integrations/tracing/fastify/types.d.ts +0 -33
  174. package/build/types/integrations/tracing/fastify/types.d.ts.map +0 -1
  175. package/build/types/integrations/tracing/hapi/index.d.ts +0 -29
  176. package/build/types/integrations/tracing/hapi/index.d.ts.map +0 -1
  177. package/build/types/integrations/tracing/hapi/types.d.ts +0 -166
  178. package/build/types/integrations/tracing/hapi/types.d.ts.map +0 -1
  179. package/build/types/integrations/tracing/koa/index.d.ts +0 -26
  180. package/build/types/integrations/tracing/koa/index.d.ts.map +0 -1
  181. package/build/types/integrations/tracing/redis/cache.d.ts +0 -22
  182. package/build/types/integrations/tracing/redis/cache.d.ts.map +0 -1
  183. package/build/types/integrations/tracing/redis/index.d.ts +0 -21
  184. package/build/types/integrations/tracing/redis/index.d.ts.map +0 -1
  185. package/build/types/integrations/tracing/redis/vendored/types.d.ts +0 -9
  186. package/build/types/integrations/tracing/redis/vendored/types.d.ts.map +0 -1
  187. package/build/types/utils/redisCache.d.ts +0 -17
  188. package/build/types/utils/redisCache.d.ts.map +0 -1
@@ -1,6 +1,8 @@
1
1
  import { errorMonitor } from 'node:events';
2
- import { NET_TRANSPORT, HTTP_FLAVOR, HTTP_SCHEME, HTTP_USER_AGENT, HTTP_CLIENT_IP, NET_HOST_NAME, HTTP_HOST, HTTP_TARGET, HTTP_METHOD, URL_FRAGMENT, URL_QUERY, URL_PATH, URL_FULL, SENTRY_HTTP_PREFETCH, SENTRY_KIND, NET_HOST_IP, NET_HOST_PORT, NET_PEER_IP, NET_PEER_PORT, HTTP_STATUS_CODE, HTTP_RESPONSE_STATUS_CODE } from '@sentry/conventions/attributes';
3
- import { debug, parseStringToURLObject, stripUrlQueryAndFragment, getUrlQuery, getUrlFragment, startInactiveSpan, httpHeadersToSpanAttributes, filterCollectedUrl, filterCollectedUrlQuery, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_OP, withActiveSpan, bindScopeToEmitter, getSpanStatusFromHttpCode, SPAN_STATUS_ERROR, isTracingSuppressed } from '@sentry/core';
2
+ import { NETWORK_TRANSPORT, NETWORK_PROTOCOL_VERSION, NETWORK_PROTOCOL_NAME, SERVER_ADDRESS, URL_SCHEME, USER_AGENT_ORIGINAL, HTTP_REQUEST_METHOD, URL_FRAGMENT, URL_QUERY, URL_PATH, URL_FULL, SENTRY_HTTP_PREFETCH, SENTRY_SEGMENT_NAME_SOURCE, SENTRY_OP, SENTRY_KIND, CLIENT_ADDRESS, SERVER_PORT, NETWORK_LOCAL_ADDRESS, NETWORK_LOCAL_PORT, CLIENT_PORT, NETWORK_PEER_ADDRESS, NETWORK_PEER_PORT, HTTP_RESPONSE_STATUS_CODE } from '@sentry/conventions/attributes';
3
+ import { HTTP_SERVER } from '@sentry/conventions/op';
4
+ import { DEFAULT_IGNORE_STATUS_CODES, processHttpServerTransactionEvent } from '@sentry/core/server';
5
+ import { debug, parseStringToURLObject, stripUrlQueryAndFragment, getUrlQuery, getUrlFragment, startInactiveSpan, HTTP_SPAN_NAME_FALLBACK, httpHeadersToSpanAttributes, getContentLengthFromHeaders, filterCollectedUrlQuery, filterCollectedUrl, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, hasSpanStreamingEnabled, withActiveSpan, bindScopeToEmitter, getSpanStatusFromHttpCode, SPAN_STATUS_ERROR, isTracingSuppressed } from '@sentry/core';
4
6
  import { DEBUG_BUILD } from '../../debug-build.js';
5
7
  import { addStartSpanCallback } from './httpServerIntegration.js';
6
8
 
@@ -8,14 +10,8 @@ const INTEGRATION_NAME = "Http.ServerSpans";
8
10
  const _httpServerSpansIntegration = ((options = {}) => {
9
11
  const ignoreStaticAssets = options.ignoreStaticAssets ?? true;
10
12
  const ignoreIncomingRequests = options.ignoreIncomingRequests;
11
- const ignoreStatusCodes = options.ignoreStatusCodes ?? [
12
- [401, 404],
13
- // 300 and 304 are possibly valid status codes we do not want to filter
14
- [301, 303],
15
- [305, 399]
16
- ];
13
+ const ignoreStatusCodes = options.ignoreStatusCodes ?? DEFAULT_IGNORE_STATUS_CODES;
17
14
  const { onSpanCreated } = options;
18
- const { requestHook, responseHook, applyCustomAttributesOnSpan } = options.instrumentation ?? {};
19
15
  return {
20
16
  name: INTEGRATION_NAME,
21
17
  setup(client) {
@@ -37,51 +33,42 @@ const _httpServerSpansIntegration = ((options = {}) => {
37
33
  const urlObj = parseStringToURLObject(fullUrl);
38
34
  const headers = request.headers;
39
35
  const userAgent = headers["user-agent"];
40
- const ips = headers["x-forwarded-for"];
41
36
  const httpVersion = request.httpVersion;
42
37
  const host = headers.host;
43
38
  const hostname = host?.replace(/^(.*)(:[0-9]{1,5})/, "$1") || "localhost";
44
39
  const scheme = fullUrl.startsWith("https") ? "https" : "http";
45
- const method = normalizedRequest.method || request.method?.toUpperCase() || "GET";
40
+ const requestMethod = normalizedRequest.method || request.method?.toUpperCase();
41
+ const method = requestMethod || "GET";
46
42
  const httpTargetWithoutQueryFragment = urlObj ? urlObj.pathname : stripUrlQueryAndFragment(fullUrl);
47
43
  const bestEffortTransactionName = `${method} ${httpTargetWithoutQueryFragment}`;
48
44
  const query = getUrlQuery(urlObj?.search);
49
45
  const fragment = getUrlFragment(urlObj?.hash);
50
46
  const span = startInactiveSpan({
51
- name: bestEffortTransactionName,
47
+ // With span streaming, span names have to be low cardinality, so we can't fall back to the URL path.
48
+ // Route instrumentations rename the span to `${method} ${route}` once a route is known.
49
+ name: hasSpanStreamingEnabled(client) ? requestMethod || HTTP_SPAN_NAME_FALLBACK : bestEffortTransactionName,
52
50
  attributes: {
53
51
  // Sentry specific attributes
54
52
  [SENTRY_KIND]: "server",
55
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "http.server",
56
- [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
57
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.otel.http",
53
+ [SENTRY_OP]: HTTP_SERVER,
54
+ [SENTRY_SEGMENT_NAME_SOURCE]: "url",
55
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.http_server",
58
56
  [SENTRY_HTTP_PREFETCH]: isKnownPrefetchRequest(request) || void 0,
59
57
  [URL_FULL]: filterCollectedUrl(fullUrl, client),
60
58
  [URL_PATH]: urlObj?.pathname ?? httpTargetWithoutQueryFragment,
61
59
  [URL_QUERY]: filterCollectedUrlQuery(query, client),
62
60
  [URL_FRAGMENT]: fragment,
63
- // Old Semantic Conventions attributes - added for compatibility with what `@opentelemetry/instrumentation-http` output before
64
- /* eslint-disable typescript/no-deprecated */
65
- [HTTP_METHOD]: normalizedRequest.method,
66
- [HTTP_TARGET]: filterCollectedUrl(
67
- urlObj ? `${urlObj.pathname}${urlObj.search}` : httpTargetWithoutQueryFragment,
68
- client
69
- ),
70
- [HTTP_HOST]: host,
71
- [NET_HOST_NAME]: hostname,
72
- [HTTP_CLIENT_IP]: typeof ips === "string" ? ips.split(",")[0] : void 0,
73
- [HTTP_USER_AGENT]: userAgent,
74
- [HTTP_SCHEME]: scheme,
75
- [HTTP_FLAVOR]: httpVersion,
76
- [NET_TRANSPORT]: httpVersion?.toUpperCase() === "QUIC" ? "ip_udp" : "ip_tcp",
77
- /* eslint-enable typescript/no-deprecated */
78
- ...getRequestContentLengthAttribute(request),
61
+ [HTTP_REQUEST_METHOD]: normalizedRequest.method,
62
+ [USER_AGENT_ORIGINAL]: userAgent,
63
+ [URL_SCHEME]: scheme,
64
+ [SERVER_ADDRESS]: hostname,
65
+ [NETWORK_PROTOCOL_NAME]: "http",
66
+ [NETWORK_PROTOCOL_VERSION]: httpVersion,
67
+ [NETWORK_TRANSPORT]: httpVersion?.toUpperCase() === "QUIC" ? "udp" : "tcp",
68
+ "http.request.body.size": getContentLengthFromHeaders(request.headers),
79
69
  ...httpHeadersToSpanAttributes(normalizedRequest.headers || {}, client.getDataCollectionOptions())
80
70
  }
81
71
  });
82
- requestHook?.(span, request);
83
- responseHook?.(span, response);
84
- applyCustomAttributesOnSpan?.(span, request, response);
85
72
  onSpanCreated?.(span, request, response);
86
73
  return withActiveSpan(span, () => {
87
74
  bindScopeToEmitter(request);
@@ -92,7 +79,11 @@ const _httpServerSpansIntegration = ((options = {}) => {
92
79
  return;
93
80
  }
94
81
  isEnded = true;
95
- const newAttributes = getIncomingRequestAttributesOnResponse(request, response);
82
+ const newAttributes = getIncomingRequestAttributesOnResponse(
83
+ request,
84
+ response,
85
+ client.getDataCollectionOptions().userInfo
86
+ );
96
87
  span.setAttributes(newAttributes);
97
88
  span.setStatus(status);
98
89
  span.end();
@@ -111,23 +102,7 @@ const _httpServerSpansIntegration = ((options = {}) => {
111
102
  });
112
103
  },
113
104
  processEvent(event) {
114
- if (event.type === "transaction") {
115
- const statusCode = event.contexts?.trace?.data?.["http.response.status_code"];
116
- if (typeof statusCode === "number") {
117
- if (shouldFilterStatusCode(statusCode, ignoreStatusCodes)) {
118
- DEBUG_BUILD && debug.log("Dropping transaction due to status code", statusCode);
119
- return null;
120
- }
121
- event.contexts = {
122
- ...event.contexts,
123
- response: {
124
- ...event.contexts?.response,
125
- status_code: statusCode
126
- }
127
- };
128
- }
129
- }
130
- return event;
105
+ return processHttpServerTransactionEvent(event, ignoreStatusCodes);
131
106
  },
132
107
  afterAllSetup(client) {
133
108
  if (!DEBUG_BUILD) {
@@ -180,59 +155,30 @@ function shouldIgnoreSpansForIncomingRequest(request, {
180
155
  }
181
156
  return false;
182
157
  }
183
- function getRequestContentLengthAttribute(request) {
184
- const length = getContentLength(request.headers);
185
- if (length == null) {
186
- return {};
187
- }
188
- if (isCompressed(request.headers)) {
189
- return {
190
- ["http.request_content_length"]: length
191
- };
192
- } else {
193
- return {
194
- ["http.request_content_length_uncompressed"]: length
195
- };
196
- }
197
- }
198
- function getContentLength(headers) {
199
- const contentLengthHeader = headers["content-length"];
200
- if (contentLengthHeader === void 0) return null;
201
- const contentLength = parseInt(contentLengthHeader, 10);
202
- if (isNaN(contentLength)) return null;
203
- return contentLength;
204
- }
205
- function isCompressed(headers) {
206
- const encoding = headers["content-encoding"];
207
- return !!encoding && encoding !== "identity";
158
+ function getForwardedClientAddress(forwardedFor) {
159
+ return typeof forwardedFor === "string" ? forwardedFor.split(",")[0]?.trim() || void 0 : void 0;
208
160
  }
209
- function getIncomingRequestAttributesOnResponse(request, response) {
161
+ function getIncomingRequestAttributesOnResponse(request, response, collectClientAddress) {
210
162
  const { socket } = request;
211
163
  const { statusCode, statusMessage } = response;
212
164
  const newAttributes = {
213
165
  [HTTP_RESPONSE_STATUS_CODE]: statusCode,
214
- // eslint-disable-next-line typescript/no-deprecated
215
- [HTTP_STATUS_CODE]: statusCode,
216
- "http.status_text": statusMessage?.toUpperCase()
166
+ "http.response.status_text": statusMessage?.toUpperCase()
217
167
  };
168
+ if (collectClientAddress) {
169
+ newAttributes[CLIENT_ADDRESS] = getForwardedClientAddress(request.headers["x-forwarded-for"]) ?? socket?.remoteAddress;
170
+ }
218
171
  if (socket) {
219
172
  const { localAddress, localPort, remoteAddress, remotePort } = socket;
220
- newAttributes[NET_HOST_IP] = localAddress;
221
- newAttributes[NET_HOST_PORT] = localPort;
222
- newAttributes[NET_PEER_IP] = remoteAddress;
223
- newAttributes[NET_PEER_PORT] = remotePort;
173
+ newAttributes[SERVER_PORT] = localPort;
174
+ newAttributes[NETWORK_LOCAL_ADDRESS] = localAddress;
175
+ newAttributes[NETWORK_LOCAL_PORT] = localPort;
176
+ newAttributes[CLIENT_PORT] = remotePort;
177
+ newAttributes[NETWORK_PEER_ADDRESS] = collectClientAddress ? remoteAddress : void 0;
178
+ newAttributes[NETWORK_PEER_PORT] = remotePort;
224
179
  }
225
180
  return newAttributes;
226
181
  }
227
- function shouldFilterStatusCode(statusCode, dropForStatusCodes) {
228
- return dropForStatusCodes.some((code) => {
229
- if (typeof code === "number") {
230
- return code === statusCode;
231
- }
232
- const [min, max] = code;
233
- return statusCode >= min && statusCode <= max;
234
- });
235
- }
236
182
 
237
183
  export { httpServerSpansIntegration, isStaticAssetRequest };
238
184
  //# sourceMappingURL=httpServerSpansIntegration.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"httpServerSpansIntegration.js","sources":["../../../../src/integrations/http/httpServerSpansIntegration.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport { errorMonitor } from 'node:events';\nimport type { IncomingHttpHeaders } from 'node:http';\nimport {\n HTTP_CLIENT_IP,\n HTTP_FLAVOR,\n HTTP_HOST,\n HTTP_METHOD,\n HTTP_RESPONSE_STATUS_CODE,\n HTTP_SCHEME,\n HTTP_STATUS_CODE,\n HTTP_TARGET,\n HTTP_USER_AGENT,\n NET_HOST_IP,\n NET_HOST_NAME,\n NET_HOST_PORT,\n NET_PEER_IP,\n NET_PEER_PORT,\n NET_TRANSPORT,\n SENTRY_HTTP_PREFETCH,\n URL_FRAGMENT,\n URL_FULL,\n URL_PATH,\n URL_QUERY,\n SENTRY_KIND,\n} from '@sentry/conventions/attributes';\nimport type {\n Event,\n HttpClientRequest,\n HttpIncomingMessage,\n HttpServerResponse,\n Integration,\n IntegrationFn,\n Span,\n SpanAttributes,\n SpanStatus,\n} from '@sentry/core';\nimport {\n debug,\n getSpanStatusFromHttpCode,\n httpHeadersToSpanAttributes,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n SPAN_STATUS_ERROR,\n stripUrlQueryAndFragment,\n isTracingSuppressed,\n bindScopeToEmitter,\n startInactiveSpan,\n withActiveSpan,\n getUrlFragment,\n getUrlQuery,\n filterCollectedUrl,\n filterCollectedUrlQuery,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport type { NodeClient } from '../../sdk/client';\nimport { addStartSpanCallback } from './httpServerIntegration';\n\nconst INTEGRATION_NAME = 'Http.ServerSpans' as const;\n\n// Tree-shakable guard to remove all code related to tracing\ndeclare const __SENTRY_TRACING__: boolean;\n\nexport interface HttpServerSpansIntegrationOptions {\n /**\n * Do not capture spans for incoming HTTP requests to URLs where the given callback returns `true`.\n * Spans will be non recording if tracing is disabled.\n *\n * The `urlPath` param consists of the URL path and query string (if any) of the incoming request.\n * For example: `'/users/details?id=123'`\n *\n * The `request` param contains the original {@type IncomingMessage} object of the incoming request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreIncomingRequests?: (urlPath: string, request: HttpIncomingMessage) => boolean;\n\n /**\n * Whether to automatically ignore common static asset requests like favicon.ico, robots.txt, etc.\n * This helps reduce noise in your transactions.\n *\n * @default `true`\n */\n ignoreStaticAssets?: boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests with the given status codes.\n * By default, spans with some 3xx and 4xx status codes are ignored (see @default).\n * Expects an array of status codes or a range of status codes, e.g. [[300,399], 404] would ignore 3xx and 404 status codes.\n *\n * @default `[[401, 404], [301, 303], [305, 399]]`\n */\n ignoreStatusCodes?: (number | [number, number])[];\n\n /**\n * @deprecated This is deprecated in favor of `incomingRequestSpanHook`.\n */\n instrumentation?: {\n requestHook?: (span: Span, req: HttpClientRequest | HttpIncomingMessage) => void;\n responseHook?: (span: Span, response: HttpIncomingMessage | HttpServerResponse) => void;\n applyCustomAttributesOnSpan?: (\n span: Span,\n request: HttpClientRequest | HttpIncomingMessage,\n response: HttpIncomingMessage | HttpServerResponse,\n ) => void;\n };\n\n /**\n * A hook that can be used to mutate the span for incoming requests.\n * This is triggered after the span is created, but before it is recorded.\n */\n onSpanCreated?: (span: Span, request: HttpIncomingMessage, response: HttpServerResponse) => void;\n}\n\nconst _httpServerSpansIntegration = ((options: HttpServerSpansIntegrationOptions = {}) => {\n const ignoreStaticAssets = options.ignoreStaticAssets ?? true;\n const ignoreIncomingRequests = options.ignoreIncomingRequests;\n const ignoreStatusCodes = options.ignoreStatusCodes ?? [\n [401, 404],\n // 300 and 304 are possibly valid status codes we do not want to filter\n [301, 303],\n [305, 399],\n ];\n\n const { onSpanCreated } = options;\n // eslint-disable-next-line typescript/no-deprecated\n const { requestHook, responseHook, applyCustomAttributesOnSpan } = options.instrumentation ?? {};\n\n return {\n name: INTEGRATION_NAME,\n setup(client: NodeClient) {\n // If no tracing, we can just skip everything here\n if (typeof __SENTRY_TRACING__ !== 'undefined' && !__SENTRY_TRACING__) {\n return;\n }\n\n client.on('httpServerRequest', (_request, _response, normalizedRequest) => {\n // Type-casting this here because we do not want to put the node types into core\n const request = _request as HttpIncomingMessage;\n const response = _response as HttpServerResponse;\n\n const startSpan = (next: () => boolean): boolean => {\n if (\n shouldIgnoreSpansForIncomingRequest(request, {\n ignoreStaticAssets,\n ignoreIncomingRequests,\n })\n ) {\n DEBUG_BUILD && debug.log(INTEGRATION_NAME, 'Skipping span creation for incoming request', request.url);\n return next();\n }\n\n const fullUrl = normalizedRequest.url || request.url || '/';\n const urlObj = parseStringToURLObject(fullUrl);\n\n const headers = request.headers;\n const userAgent = headers['user-agent'];\n const ips = headers['x-forwarded-for'];\n const httpVersion = request.httpVersion;\n const host = headers.host as string | undefined;\n const hostname = host?.replace(/^(.*)(:[0-9]{1,5})/, '$1') || 'localhost';\n\n const scheme = fullUrl.startsWith('https') ? 'https' : 'http';\n\n const method = normalizedRequest.method || request.method?.toUpperCase() || 'GET';\n const httpTargetWithoutQueryFragment = urlObj ? urlObj.pathname : stripUrlQueryAndFragment(fullUrl);\n const bestEffortTransactionName = `${method} ${httpTargetWithoutQueryFragment}`;\n\n const query = getUrlQuery(urlObj?.search);\n const fragment = getUrlFragment(urlObj?.hash);\n\n const span = startInactiveSpan({\n name: bestEffortTransactionName,\n attributes: {\n // Sentry specific attributes\n [SENTRY_KIND]: 'server',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.http',\n [SENTRY_HTTP_PREFETCH]: isKnownPrefetchRequest(request) || undefined,\n [URL_FULL]: filterCollectedUrl(fullUrl, client),\n [URL_PATH]: urlObj?.pathname ?? httpTargetWithoutQueryFragment,\n [URL_QUERY]: filterCollectedUrlQuery(query, client),\n [URL_FRAGMENT]: fragment,\n // Old Semantic Conventions attributes - added for compatibility with what `@opentelemetry/instrumentation-http` output before\n /* eslint-disable typescript/no-deprecated */\n [HTTP_METHOD]: normalizedRequest.method,\n [HTTP_TARGET]: filterCollectedUrl(\n urlObj ? `${urlObj.pathname}${urlObj.search}` : httpTargetWithoutQueryFragment,\n client,\n ),\n [HTTP_HOST]: host,\n [NET_HOST_NAME]: hostname,\n [HTTP_CLIENT_IP]: typeof ips === 'string' ? ips.split(',')[0] : undefined,\n [HTTP_USER_AGENT]: userAgent,\n [HTTP_SCHEME]: scheme,\n [HTTP_FLAVOR]: httpVersion,\n [NET_TRANSPORT]: httpVersion?.toUpperCase() === 'QUIC' ? 'ip_udp' : 'ip_tcp',\n /* eslint-enable typescript/no-deprecated */\n ...getRequestContentLengthAttribute(request),\n ...httpHeadersToSpanAttributes(normalizedRequest.headers || {}, client.getDataCollectionOptions()),\n },\n });\n\n // TODO v11: Remove the following three hooks, only onSpanCreated should remain\n requestHook?.(span, request);\n responseHook?.(span, response);\n applyCustomAttributesOnSpan?.(span, request, response);\n onSpanCreated?.(span, request, response);\n\n return withActiveSpan(span, () => {\n bindScopeToEmitter(request);\n bindScopeToEmitter(response);\n\n // Ensure we only end the span once\n // E.g. error can be emitted before close is emitted\n let isEnded = false;\n function endSpan(status: SpanStatus): void {\n if (isEnded) {\n return;\n }\n\n isEnded = true;\n\n const newAttributes = getIncomingRequestAttributesOnResponse(request, response);\n span.setAttributes(newAttributes);\n span.setStatus(status);\n span.end();\n }\n\n response.on('close', () => {\n endSpan(getSpanStatusFromHttpCode(response.statusCode));\n });\n response.on(errorMonitor, () => {\n const httpStatus = getSpanStatusFromHttpCode(response.statusCode);\n // Ensure we def. have an error status here\n endSpan(httpStatus.code === SPAN_STATUS_ERROR ? httpStatus : { code: SPAN_STATUS_ERROR });\n });\n\n return next();\n });\n };\n\n addStartSpanCallback(request, startSpan);\n });\n },\n processEvent(event) {\n if (event.type === 'transaction') {\n const statusCode = event.contexts?.trace?.data?.['http.response.status_code'];\n if (typeof statusCode === 'number') {\n // Drop transaction if it has a status code that should be ignored\n if (shouldFilterStatusCode(statusCode, ignoreStatusCodes)) {\n DEBUG_BUILD && debug.log('Dropping transaction due to status code', statusCode);\n return null;\n }\n\n // Surface the HTTP status as the top-level `response` context. The OTel SDK span\n // exporter already does this on its path; doing it here covers transactions produced\n // by the `SentryTracerProvider`, which bypasses that exporter.\n event.contexts = {\n ...event.contexts,\n response: {\n ...event.contexts?.response,\n status_code: statusCode,\n },\n };\n }\n }\n\n return event;\n },\n afterAllSetup(client) {\n if (!DEBUG_BUILD) {\n return;\n }\n\n if (client.getIntegrationByName('Http')) {\n debug.warn(\n 'It seems that you have manually added `httpServerSpansIntegration` while `httpIntegration` is also present. Make sure to remove `httpIntegration` when adding `httpServerSpansIntegration`.',\n );\n }\n\n if (!client.getIntegrationByName('Http.Server')) {\n debug.error(\n 'It seems that you have manually added `httpServerSpansIntegration` without adding `httpServerIntegration`. This is a requiement for spans to be created - please add the `httpServerIntegration` integration.',\n );\n }\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * This integration emits spans for incoming requests handled via the node `http` module.\n * It requires the `httpServerIntegration` to be present.\n */\nexport const httpServerSpansIntegration = _httpServerSpansIntegration as (\n options?: HttpServerSpansIntegrationOptions,\n) => Integration & {\n name: 'Http.ServerSpans';\n setup: (client: NodeClient) => void;\n processEvent: (event: Event) => Event | null;\n};\n\nfunction isKnownPrefetchRequest(req: HttpIncomingMessage): boolean {\n // Currently only handles Next.js prefetch requests but may check other frameworks in the future.\n return req.headers['next-router-prefetch'] === '1';\n}\n\n/**\n * Check if a request is for a common static asset that should be ignored by default.\n *\n * Only exported for tests.\n */\nexport function isStaticAssetRequest(urlPath: string): boolean {\n const path = stripUrlQueryAndFragment(urlPath);\n // Common static file extensions\n if (path.match(/\\.(ico|png|jpg|jpeg|gif|svg|css|js|woff|woff2|ttf|eot|webp|avif)$/)) {\n return true;\n }\n\n // Common metadata files\n if (path.match(/^\\/(robots\\.txt|sitemap\\.xml|manifest\\.json|browserconfig\\.xml)$/)) {\n return true;\n }\n\n return false;\n}\n\nfunction shouldIgnoreSpansForIncomingRequest(\n request: HttpIncomingMessage,\n {\n ignoreStaticAssets,\n ignoreIncomingRequests,\n }: {\n ignoreStaticAssets?: boolean;\n ignoreIncomingRequests?: (urlPath: string, request: HttpIncomingMessage) => boolean;\n },\n): boolean {\n if (isTracingSuppressed()) {\n return true;\n }\n\n // request.url is the only property that holds any information about the url\n // it only consists of the URL path and query string (if any)\n const urlPath = request.url;\n\n const method = request.method?.toUpperCase();\n // We do not capture OPTIONS/HEAD requests as spans\n if (method === 'OPTIONS' || method === 'HEAD' || !urlPath) {\n return true;\n }\n\n // Default static asset filtering\n if (ignoreStaticAssets && method === 'GET' && isStaticAssetRequest(urlPath)) {\n return true;\n }\n\n if (ignoreIncomingRequests?.(urlPath, request)) {\n return true;\n }\n\n return false;\n}\n\nfunction getRequestContentLengthAttribute(request: HttpIncomingMessage): SpanAttributes {\n const length = getContentLength(request.headers);\n if (length == null) {\n return {};\n }\n\n if (isCompressed(request.headers)) {\n return {\n ['http.request_content_length']: length,\n };\n } else {\n return {\n ['http.request_content_length_uncompressed']: length,\n };\n }\n}\n\nfunction getContentLength(headers: IncomingHttpHeaders): number | null {\n const contentLengthHeader = headers['content-length'];\n if (contentLengthHeader === undefined) return null;\n\n const contentLength = parseInt(contentLengthHeader, 10);\n if (isNaN(contentLength)) return null;\n\n return contentLength;\n}\n\nfunction isCompressed(headers: IncomingHttpHeaders): boolean {\n const encoding = headers['content-encoding'];\n\n return !!encoding && encoding !== 'identity';\n}\n\nfunction getIncomingRequestAttributesOnResponse(\n request: HttpIncomingMessage,\n response: HttpServerResponse,\n): SpanAttributes {\n // take socket from the request,\n // since it may be detached from the response object in keep-alive mode\n const { socket } = request;\n const { statusCode, statusMessage } = response;\n\n const newAttributes: SpanAttributes = {\n [HTTP_RESPONSE_STATUS_CODE]: statusCode,\n // eslint-disable-next-line typescript/no-deprecated\n [HTTP_STATUS_CODE]: statusCode,\n 'http.status_text': statusMessage?.toUpperCase(),\n };\n\n if (socket) {\n const { localAddress, localPort, remoteAddress, remotePort } = socket;\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[NET_HOST_IP] = localAddress;\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[NET_HOST_PORT] = localPort;\n // eslint-disable-next-line typescript/no-deprecated\n newAttributes[NET_PEER_IP] = remoteAddress;\n // oxlint-disable-next-line typescript/no-deprecated\n newAttributes[NET_PEER_PORT] = remotePort;\n }\n\n return newAttributes;\n}\n\n/**\n * If the given status code should be filtered for the given list of status codes/ranges.\n */\nfunction shouldFilterStatusCode(statusCode: number, dropForStatusCodes: (number | [number, number])[]): boolean {\n return dropForStatusCodes.some(code => {\n if (typeof code === 'number') {\n return code === statusCode;\n }\n\n const [min, max] = code;\n return statusCode >= min && statusCode <= max;\n });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"httpServerSpansIntegration.js","sources":["../../../../src/integrations/http/httpServerSpansIntegration.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport { errorMonitor } from 'node:events';\nimport {\n CLIENT_ADDRESS,\n CLIENT_PORT,\n HTTP_REQUEST_METHOD,\n HTTP_RESPONSE_STATUS_CODE,\n NETWORK_LOCAL_ADDRESS,\n NETWORK_LOCAL_PORT,\n NETWORK_PEER_ADDRESS,\n NETWORK_PEER_PORT,\n NETWORK_PROTOCOL_NAME,\n NETWORK_PROTOCOL_VERSION,\n NETWORK_TRANSPORT,\n SENTRY_HTTP_PREFETCH,\n SENTRY_KIND,\n SENTRY_OP,\n SENTRY_SEGMENT_NAME_SOURCE,\n SERVER_ADDRESS,\n SERVER_PORT,\n URL_FRAGMENT,\n URL_FULL,\n URL_PATH,\n URL_QUERY,\n URL_SCHEME,\n USER_AGENT_ORIGINAL,\n} from '@sentry/conventions/attributes';\nimport { HTTP_SERVER } from '@sentry/conventions/op';\nimport type { Event, Integration, IntegrationFn, Span, SpanAttributes, SpanStatus } from '@sentry/core';\nimport type { HttpIncomingMessage, HttpServerResponse } from '@sentry/core/server';\nimport { DEFAULT_IGNORE_STATUS_CODES, processHttpServerTransactionEvent } from '@sentry/core/server';\nimport {\n debug,\n getSpanStatusFromHttpCode,\n httpHeadersToSpanAttributes,\n getContentLengthFromHeaders,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_STATUS_ERROR,\n stripUrlQueryAndFragment,\n isTracingSuppressed,\n bindScopeToEmitter,\n startInactiveSpan,\n withActiveSpan,\n getUrlFragment,\n getUrlQuery,\n filterCollectedUrl,\n filterCollectedUrlQuery,\n hasSpanStreamingEnabled,\n HTTP_SPAN_NAME_FALLBACK,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport type { NodeClient } from '../../sdk/client';\nimport { addStartSpanCallback } from './httpServerIntegration';\n\nconst INTEGRATION_NAME = 'Http.ServerSpans' as const;\n\n// Tree-shakable guard to remove all code related to tracing\ndeclare const __SENTRY_TRACING__: boolean;\n\nexport interface HttpServerSpansIntegrationOptions {\n /**\n * Do not capture spans for incoming HTTP requests to URLs where the given callback returns `true`.\n * Spans will be non recording if tracing is disabled.\n *\n * The `urlPath` param consists of the URL path and query string (if any) of the incoming request.\n * For example: `'/users/details?id=123'`\n *\n * The `request` param contains the original {@type IncomingMessage} object of the incoming request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreIncomingRequests?: (urlPath: string, request: HttpIncomingMessage) => boolean;\n\n /**\n * Whether to automatically ignore common static asset requests like favicon.ico, robots.txt, etc.\n * This helps reduce noise in your transactions.\n *\n * @default `true`\n */\n ignoreStaticAssets?: boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests with the given status codes.\n * By default, spans with some 3xx and 4xx status codes are ignored (see @default).\n * Expects an array of status codes or a range of status codes, e.g. [[300,399], 404] would ignore 3xx and 404 status codes.\n *\n * @default `[[401, 404], [301, 303], [305, 399]]`\n */\n ignoreStatusCodes?: (number | [number, number])[];\n\n /**\n * A hook that can be used to mutate the span for incoming requests.\n * This is triggered after the span is created, but before it is recorded.\n */\n onSpanCreated?: (span: Span, request: HttpIncomingMessage, response: HttpServerResponse) => void;\n}\n\nconst _httpServerSpansIntegration = ((options: HttpServerSpansIntegrationOptions = {}) => {\n const ignoreStaticAssets = options.ignoreStaticAssets ?? true;\n const ignoreIncomingRequests = options.ignoreIncomingRequests;\n const ignoreStatusCodes = options.ignoreStatusCodes ?? DEFAULT_IGNORE_STATUS_CODES;\n\n const { onSpanCreated } = options;\n\n return {\n name: INTEGRATION_NAME,\n setup(client: NodeClient) {\n // If no tracing, we can just skip everything here\n if (typeof __SENTRY_TRACING__ !== 'undefined' && !__SENTRY_TRACING__) {\n return;\n }\n\n client.on('httpServerRequest', (_request, _response, normalizedRequest) => {\n // Type-casting this here because we do not want to put the node types into core\n const request = _request as HttpIncomingMessage;\n const response = _response as HttpServerResponse;\n\n const startSpan = (next: () => boolean): boolean => {\n if (\n shouldIgnoreSpansForIncomingRequest(request, {\n ignoreStaticAssets,\n ignoreIncomingRequests,\n })\n ) {\n DEBUG_BUILD && debug.log(INTEGRATION_NAME, 'Skipping span creation for incoming request', request.url);\n return next();\n }\n\n const fullUrl = normalizedRequest.url || request.url || '/';\n const urlObj = parseStringToURLObject(fullUrl);\n\n const headers = request.headers;\n const userAgent = headers['user-agent'];\n const httpVersion = request.httpVersion;\n const host = headers.host as string | undefined;\n const hostname = host?.replace(/^(.*)(:[0-9]{1,5})/, '$1') || 'localhost';\n\n const scheme = fullUrl.startsWith('https') ? 'https' : 'http';\n\n const requestMethod = normalizedRequest.method || request.method?.toUpperCase();\n const method = requestMethod || 'GET';\n const httpTargetWithoutQueryFragment = urlObj ? urlObj.pathname : stripUrlQueryAndFragment(fullUrl);\n const bestEffortTransactionName = `${method} ${httpTargetWithoutQueryFragment}`;\n\n const query = getUrlQuery(urlObj?.search);\n const fragment = getUrlFragment(urlObj?.hash);\n\n const span = startInactiveSpan({\n // With span streaming, span names have to be low cardinality, so we can't fall back to the URL path.\n // Route instrumentations rename the span to `${method} ${route}` once a route is known.\n name: hasSpanStreamingEnabled(client)\n ? requestMethod || HTTP_SPAN_NAME_FALLBACK\n : bestEffortTransactionName,\n attributes: {\n // Sentry specific attributes\n [SENTRY_KIND]: 'server',\n [SENTRY_OP]: HTTP_SERVER,\n [SENTRY_SEGMENT_NAME_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.http_server',\n [SENTRY_HTTP_PREFETCH]: isKnownPrefetchRequest(request) || undefined,\n [URL_FULL]: filterCollectedUrl(fullUrl, client),\n [URL_PATH]: urlObj?.pathname ?? httpTargetWithoutQueryFragment,\n [URL_QUERY]: filterCollectedUrlQuery(query, client),\n [URL_FRAGMENT]: fragment,\n [HTTP_REQUEST_METHOD]: normalizedRequest.method,\n [USER_AGENT_ORIGINAL]: userAgent,\n [URL_SCHEME]: scheme,\n [SERVER_ADDRESS]: hostname,\n [NETWORK_PROTOCOL_NAME]: 'http',\n [NETWORK_PROTOCOL_VERSION]: httpVersion,\n [NETWORK_TRANSPORT]: httpVersion?.toUpperCase() === 'QUIC' ? 'udp' : 'tcp',\n 'http.request.body.size': getContentLengthFromHeaders(request.headers),\n ...httpHeadersToSpanAttributes(normalizedRequest.headers || {}, client.getDataCollectionOptions()),\n },\n });\n\n onSpanCreated?.(span, request, response);\n\n return withActiveSpan(span, () => {\n bindScopeToEmitter(request);\n bindScopeToEmitter(response);\n\n // Ensure we only end the span once\n // E.g. error can be emitted before close is emitted\n let isEnded = false;\n function endSpan(status: SpanStatus): void {\n if (isEnded) {\n return;\n }\n\n isEnded = true;\n\n const newAttributes = getIncomingRequestAttributesOnResponse(\n request,\n response,\n client.getDataCollectionOptions().userInfo,\n );\n span.setAttributes(newAttributes);\n span.setStatus(status);\n span.end();\n }\n\n response.on('close', () => {\n endSpan(getSpanStatusFromHttpCode(response.statusCode));\n });\n response.on(errorMonitor, () => {\n const httpStatus = getSpanStatusFromHttpCode(response.statusCode);\n // Ensure we def. have an error status here\n endSpan(httpStatus.code === SPAN_STATUS_ERROR ? httpStatus : { code: SPAN_STATUS_ERROR });\n });\n\n return next();\n });\n };\n\n addStartSpanCallback(request, startSpan);\n });\n },\n processEvent(event) {\n return processHttpServerTransactionEvent(event, ignoreStatusCodes);\n },\n afterAllSetup(client) {\n if (!DEBUG_BUILD) {\n return;\n }\n\n if (client.getIntegrationByName('Http')) {\n debug.warn(\n 'It seems that you have manually added `httpServerSpansIntegration` while `httpIntegration` is also present. Make sure to remove `httpIntegration` when adding `httpServerSpansIntegration`.',\n );\n }\n\n if (!client.getIntegrationByName('Http.Server')) {\n debug.error(\n 'It seems that you have manually added `httpServerSpansIntegration` without adding `httpServerIntegration`. This is a requiement for spans to be created - please add the `httpServerIntegration` integration.',\n );\n }\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * This integration emits spans for incoming requests handled via the node `http` module.\n * It requires the `httpServerIntegration` to be present.\n */\nexport const httpServerSpansIntegration = _httpServerSpansIntegration as (\n options?: HttpServerSpansIntegrationOptions,\n) => Integration & {\n name: 'Http.ServerSpans';\n setup: (client: NodeClient) => void;\n processEvent: (event: Event) => Event | null;\n};\n\nfunction isKnownPrefetchRequest(req: HttpIncomingMessage): boolean {\n // Currently only handles Next.js prefetch requests but may check other frameworks in the future.\n return req.headers['next-router-prefetch'] === '1';\n}\n\n/**\n * Check if a request is for a common static asset that should be ignored by default.\n *\n * Only exported for tests.\n */\nexport function isStaticAssetRequest(urlPath: string): boolean {\n const path = stripUrlQueryAndFragment(urlPath);\n // Common static file extensions\n if (path.match(/\\.(ico|png|jpg|jpeg|gif|svg|css|js|woff|woff2|ttf|eot|webp|avif)$/)) {\n return true;\n }\n\n // Common metadata files\n if (path.match(/^\\/(robots\\.txt|sitemap\\.xml|manifest\\.json|browserconfig\\.xml)$/)) {\n return true;\n }\n\n return false;\n}\n\nfunction shouldIgnoreSpansForIncomingRequest(\n request: HttpIncomingMessage,\n {\n ignoreStaticAssets,\n ignoreIncomingRequests,\n }: {\n ignoreStaticAssets?: boolean;\n ignoreIncomingRequests?: (urlPath: string, request: HttpIncomingMessage) => boolean;\n },\n): boolean {\n if (isTracingSuppressed()) {\n return true;\n }\n\n // request.url is the only property that holds any information about the url\n // it only consists of the URL path and query string (if any)\n const urlPath = request.url;\n\n const method = request.method?.toUpperCase();\n // We do not capture OPTIONS/HEAD requests as spans\n if (method === 'OPTIONS' || method === 'HEAD' || !urlPath) {\n return true;\n }\n\n // Default static asset filtering\n if (ignoreStaticAssets && method === 'GET' && isStaticAssetRequest(urlPath)) {\n return true;\n }\n\n if (ignoreIncomingRequests?.(urlPath, request)) {\n return true;\n }\n\n return false;\n}\n\n/**\n * First entry of `X-Forwarded-For`: the client as seen by the outermost proxy.\n * https://opentelemetry.io/docs/specs/semconv/registry/attributes/client/#client-address\n */\nfunction getForwardedClientAddress(forwardedFor: string | string[] | undefined): string | undefined {\n return typeof forwardedFor === 'string' ? forwardedFor.split(',')[0]?.trim() || undefined : undefined;\n}\n\nfunction getIncomingRequestAttributesOnResponse(\n request: HttpIncomingMessage,\n response: HttpServerResponse,\n collectClientAddress: boolean,\n): SpanAttributes {\n // take socket from the request,\n // since it may be detached from the response object in keep-alive mode\n const { socket } = request;\n const { statusCode, statusMessage } = response;\n\n const newAttributes: SpanAttributes = {\n [HTTP_RESPONSE_STATUS_CODE]: statusCode,\n 'http.response.status_text': statusMessage?.toUpperCase(),\n };\n\n if (collectClientAddress) {\n // `client.address` is the originating client, so a forwarding header wins over the socket, which\n // behind a proxy holds the proxy's address. `network.peer.address` below keeps the socket value.\n newAttributes[CLIENT_ADDRESS] =\n getForwardedClientAddress(request.headers['x-forwarded-for']) ?? socket?.remoteAddress;\n }\n\n if (socket) {\n const { localAddress, localPort, remoteAddress, remotePort } = socket;\n newAttributes[SERVER_PORT] = localPort;\n newAttributes[NETWORK_LOCAL_ADDRESS] = localAddress;\n newAttributes[NETWORK_LOCAL_PORT] = localPort;\n newAttributes[CLIENT_PORT] = remotePort;\n newAttributes[NETWORK_PEER_ADDRESS] = collectClientAddress ? remoteAddress : undefined;\n newAttributes[NETWORK_PEER_PORT] = remotePort;\n }\n\n return newAttributes;\n}\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { URL_FULL } from '@sentry/conventions/attributes';
2
- import { defineIntegration, hasSpansEnabled, getRequestUrlFromClientRequest, stripDataUrlContent, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core';
2
+ import { defineIntegration, hasSpansEnabled, stripDataUrlContent, getClient, hasSpanStreamingEnabled } from '@sentry/core';
3
+ import { getRequestUrlFromClientRequest } from '@sentry/core/server';
3
4
  import { httpServerIntegration } from './httpServerIntegration.js';
4
5
  import { httpServerSpansIntegration } from './httpServerSpansIntegration.js';
5
6
  import { instrumentHttpOutgoingRequests } from './SentryHttpInstrumentation.js';
@@ -7,24 +8,9 @@ import { instrumentHttpOutgoingRequests } from './SentryHttpInstrumentation.js';
7
8
  const INTEGRATION_NAME = "Http";
8
9
  const httpIntegration = defineIntegration((options = {}) => {
9
10
  const spans = options.spans ?? true;
10
- const disableIncomingRequestSpans = options.disableIncomingRequestSpans;
11
- const enableServerSpans = spans && !disableIncomingRequestSpans;
12
- const serverOptions = {
13
- sessions: options.trackIncomingRequestsAsSessions,
14
- sessionFlushingDelayMS: options.sessionFlushingDelayMS,
15
- ignoreRequestBody: options.ignoreIncomingRequestBody,
16
- maxRequestBodySize: options.maxIncomingRequestBodySize
17
- };
18
- const serverSpansOptions = {
19
- ignoreIncomingRequests: options.ignoreIncomingRequests,
20
- ignoreStaticAssets: options.ignoreStaticAssets,
21
- ignoreStatusCodes: options.dropSpansForIncomingRequestStatusCodes,
22
- // oxlint-disable-next-line typescript/no-deprecated -- pass through the deprecated option for back-compat
23
- instrumentation: options.instrumentation,
24
- onSpanCreated: options.incomingRequestSpanHook
25
- };
26
- const server = httpServerIntegration(serverOptions);
27
- const serverSpans = httpServerSpansIntegration(serverSpansOptions);
11
+ const enableServerSpans = spans && !options.disableIncomingRequestSpans;
12
+ const server = httpServerIntegration(options);
13
+ const serverSpans = httpServerSpansIntegration(options);
28
14
  return {
29
15
  name: INTEGRATION_NAME,
30
16
  setup(client) {
@@ -35,29 +21,29 @@ const httpIntegration = defineIntegration((options = {}) => {
35
21
  },
36
22
  setupOnce() {
37
23
  server.setupOnce();
38
- const sentryHttpInstrumentationOptions = {
24
+ const outgoingRequestOptions = {
39
25
  breadcrumbs: options.breadcrumbs,
40
26
  spans,
41
- propagateTraceInOutgoingRequests: options.tracePropagation ?? true,
42
- // oxlint-disable-next-line typescript/no-deprecated -- deprecated alias kept until removal
43
- createSpansForOutgoingRequests: spans,
27
+ tracePropagation: options.tracePropagation ?? true,
44
28
  ignoreOutgoingRequests: options.ignoreOutgoingRequests,
45
29
  outgoingRequestHook: (span, request) => {
46
30
  const url = getRequestUrlFromClientRequest(request);
47
31
  if (url.startsWith("data:")) {
48
32
  const sanitizedUrl = stripDataUrlContent(url);
49
- span.updateName(`${request.method || "GET"} ${sanitizedUrl}`);
33
+ const client = getClient();
34
+ if (!client || !hasSpanStreamingEnabled(client)) {
35
+ span.updateName(`${request.method || "GET"} ${sanitizedUrl}`);
36
+ }
50
37
  span.setAttributes({
51
- [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
52
38
  [URL_FULL]: sanitizedUrl
53
39
  });
54
40
  }
55
- options.instrumentation?.requestHook?.(span, request);
41
+ options.outgoingRequestHook?.(span, request);
56
42
  },
57
- outgoingResponseHook: options.instrumentation?.responseHook,
58
- outgoingRequestApplyCustomAttributes: options.instrumentation?.applyCustomAttributesOnSpan
43
+ outgoingResponseHook: options.outgoingResponseHook,
44
+ outgoingRequestApplyCustomAttributes: options.outgoingRequestApplyCustomAttributes
59
45
  };
60
- instrumentHttpOutgoingRequests(sentryHttpInstrumentationOptions);
46
+ instrumentHttpOutgoingRequests(outgoingRequestOptions);
61
47
  },
62
48
  processEvent(event) {
63
49
  return serverSpans.processEvent(event);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../src/integrations/http/index.ts"],"sourcesContent":["import type { RequestOptions } from 'node:http';\nimport type { HttpClientRequest, HttpIncomingMessage, HttpServerResponse, Span } from '@sentry/core';\nimport { URL_FULL } from '@sentry/conventions/attributes';\nimport {\n defineIntegration,\n getRequestUrlFromClientRequest,\n hasSpansEnabled,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n stripDataUrlContent,\n} from '@sentry/core';\nimport type { NodeClient } from '../../sdk/client';\nimport type { HttpServerIntegrationOptions } from './httpServerIntegration';\nimport { httpServerIntegration } from './httpServerIntegration';\nimport type { HttpServerSpansIntegrationOptions } from './httpServerSpansIntegration';\nimport { httpServerSpansIntegration } from './httpServerSpansIntegration';\nimport type { SentryHttpInstrumentationOptions } from './SentryHttpInstrumentation';\nimport { instrumentHttpOutgoingRequests } from './SentryHttpInstrumentation';\n\nconst INTEGRATION_NAME = 'Http' as const;\n\n// TODO(v11): Consolidate all the various HTTP integration options into one,\n// and deprecate the duplicated and aliased options.\ninterface HttpOptions {\n /**\n * Whether breadcrumbs should be recorded for outgoing requests.\n * Defaults to true\n */\n breadcrumbs?: boolean;\n\n /**\n * If set to false, do not emit any spans.\n * This will ensure that the default HttpInstrumentation from OpenTelemetry is not setup,\n * only the Sentry-specific instrumentation for request isolation is applied.\n *\n * Defaults to `true` when tracing is enabled.\n */\n spans?: boolean;\n\n /**\n * Whether the integration should create [Sessions](https://docs.sentry.io/product/releases/health/#sessions) for incoming requests to track the health and crash-free rate of your releases in Sentry.\n * Read more about Release Health: https://docs.sentry.io/product/releases/health/\n *\n * Defaults to `true`.\n */\n trackIncomingRequestsAsSessions?: boolean;\n\n /**\n * Number of milliseconds until sessions tracked with `trackIncomingRequestsAsSessions` will be flushed as a session aggregate.\n *\n * Defaults to `60000` (60s).\n */\n sessionFlushingDelayMS?: number;\n\n /**\n * Whether to inject trace propagation headers (sentry-trace, baggage, traceparent) into outgoing HTTP requests.\n *\n * When set to `false`, Sentry will not inject any trace propagation headers, but will still create breadcrumbs\n * (if `breadcrumbs` is enabled). This is useful when you run your own OpenTelemetry `HttpInstrumentation` and\n * want to avoid duplicate trace headers being injected by both Sentry and OpenTelemetry.\n *\n * @default `true`\n */\n tracePropagation?: boolean;\n\n /**\n * Do not capture spans or breadcrumbs for outgoing HTTP requests to URLs where the given callback returns `true`.\n * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled.\n *\n * The `url` param contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n * For example: `'https://someService.com/users/details?id=123'`\n *\n * The `request` param contains the original {@type RequestOptions} object used to make the outgoing request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreOutgoingRequests?: (url: string, request: RequestOptions) => boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests to URLs where the given callback returns `true`.\n * Spans will be non recording if tracing is disabled.\n *\n * The `urlPath` param consists of the URL path and query string (if any) of the incoming request.\n * For example: `'/users/details?id=123'`\n *\n * The `request` param contains the original {@type IncomingMessage} object of the incoming request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreIncomingRequests?: (urlPath: string, request: HttpIncomingMessage) => boolean;\n\n /**\n * A hook that can be used to mutate the span for incoming requests.\n * This is triggered after the span is created, but before it is recorded.\n */\n incomingRequestSpanHook?: (span: Span, request: HttpIncomingMessage, response: HttpServerResponse) => void;\n\n /**\n * Whether to automatically ignore common static asset requests like favicon.ico, robots.txt, etc.\n * This helps reduce noise in your transactions.\n *\n * @default `true`\n */\n ignoreStaticAssets?: boolean;\n\n /**\n * Do not capture spans for incoming HTTP requests with the given status codes.\n * By default, spans with some 3xx and 4xx status codes are ignored (see @default).\n * Expects an array of status codes or a range of status codes, e.g. [[300,399], 404] would ignore 3xx and 404 status codes.\n *\n * @default `[[401, 404], [301, 303], [305, 399]]`\n */\n dropSpansForIncomingRequestStatusCodes?: (number | [number, number])[];\n\n /**\n * Do not capture the request body for incoming HTTP requests to URLs where the given callback returns `true`.\n * This can be useful for long running requests where the body is not needed and we want to avoid capturing it.\n *\n * @param url Contains the entire URL, including query string (if any), protocol, host, etc. of the incoming request.\n * @param request Contains the {@type RequestOptions} object used to make the incoming request.\n */\n ignoreIncomingRequestBody?: (url: string, request: RequestOptions) => boolean;\n\n /**\n * Controls the maximum size of incoming HTTP request bodies attached to events.\n *\n * Available options:\n * - 'none': No request bodies will be attached\n * - 'small': Request bodies up to 1,000 bytes will be attached\n * - 'medium': Request bodies up to 10,000 bytes will be attached (default)\n * - 'always': Request bodies will always be attached\n *\n * Note that even with 'always' setting, bodies exceeding 1MB will never be attached\n * for performance and security reasons.\n *\n * @default 'medium'\n */\n maxIncomingRequestBodySize?: 'none' | 'small' | 'medium' | 'always';\n\n /**\n * If true, do not generate spans for incoming requests at all.\n * This is used by Remix to avoid generating spans for incoming requests, as it generates its own spans.\n */\n disableIncomingRequestSpans?: boolean;\n\n /**\n * Additional instrumentation options that are passed to the underlying HttpInstrumentation.\n */\n instrumentation?: {\n requestHook?: (span: Span, req: HttpIncomingMessage | HttpClientRequest) => void;\n responseHook?: (span: Span, response: HttpIncomingMessage | HttpServerResponse) => void;\n applyCustomAttributesOnSpan?: (\n span: Span,\n request: HttpIncomingMessage | HttpClientRequest,\n response: HttpIncomingMessage | HttpServerResponse,\n ) => void;\n };\n}\n\n/**\n * The http integration instruments Node's internal http and https modules.\n * It creates breadcrumbs and spans for outgoing HTTP requests which will be attached to the currently active span.\n */\nexport const httpIntegration = defineIntegration((options: HttpOptions = {}) => {\n const spans = options.spans ?? true;\n const disableIncomingRequestSpans = options.disableIncomingRequestSpans;\n const enableServerSpans = spans && !disableIncomingRequestSpans;\n\n const serverOptions = {\n sessions: options.trackIncomingRequestsAsSessions,\n sessionFlushingDelayMS: options.sessionFlushingDelayMS,\n ignoreRequestBody: options.ignoreIncomingRequestBody,\n maxRequestBodySize: options.maxIncomingRequestBodySize,\n } satisfies HttpServerIntegrationOptions;\n\n const serverSpansOptions: HttpServerSpansIntegrationOptions = {\n ignoreIncomingRequests: options.ignoreIncomingRequests,\n ignoreStaticAssets: options.ignoreStaticAssets,\n ignoreStatusCodes: options.dropSpansForIncomingRequestStatusCodes,\n // oxlint-disable-next-line typescript/no-deprecated -- pass through the deprecated option for back-compat\n instrumentation: options.instrumentation,\n onSpanCreated: options.incomingRequestSpanHook,\n };\n\n const server = httpServerIntegration(serverOptions);\n const serverSpans = httpServerSpansIntegration(serverSpansOptions);\n\n return {\n name: INTEGRATION_NAME,\n setup(client: NodeClient) {\n const clientOptions = client.getOptions();\n\n if (enableServerSpans && hasSpansEnabled(clientOptions)) {\n serverSpans.setup(client);\n }\n },\n setupOnce() {\n server.setupOnce();\n\n const sentryHttpInstrumentationOptions: SentryHttpInstrumentationOptions = {\n breadcrumbs: options.breadcrumbs,\n spans,\n propagateTraceInOutgoingRequests: options.tracePropagation ?? true,\n // oxlint-disable-next-line typescript/no-deprecated -- deprecated alias kept until removal\n createSpansForOutgoingRequests: spans,\n ignoreOutgoingRequests: options.ignoreOutgoingRequests,\n outgoingRequestHook: (span: Span, request: HttpClientRequest) => {\n // Sanitize data URLs to prevent long base64 strings in span attributes\n const url = getRequestUrlFromClientRequest(request);\n if (url.startsWith('data:')) {\n const sanitizedUrl = stripDataUrlContent(url);\n span.updateName(`${request.method || 'GET'} ${sanitizedUrl}`);\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [URL_FULL]: sanitizedUrl,\n });\n }\n options.instrumentation?.requestHook?.(span, request);\n },\n outgoingResponseHook: options.instrumentation?.responseHook,\n outgoingRequestApplyCustomAttributes: options.instrumentation?.applyCustomAttributesOnSpan,\n };\n\n // This is Sentry-specific instrumentation for outgoing request\n // breadcrumbs & trace propagation. It uses the diagnostic channels on\n // node versions that support it, falling back to monkey-patching when\n // needed.\n instrumentHttpOutgoingRequests(sentryHttpInstrumentationOptions);\n },\n processEvent(event) {\n // Always run this, even if spans are disabled\n // The reason being that e.g. the remix integration disables span\n // creation here but still wants to use the ignore status codes option\n return serverSpans.processEvent(event);\n },\n };\n});\n"],"names":[],"mappings":";;;;;;AAkBA,MAAM,gBAAA,GAAmB,MAAA;AA8IlB,MAAM,eAAA,GAAkB,iBAAA,CAAkB,CAAC,OAAA,GAAuB,EAAC,KAAM;AAC9E,EAAA,MAAM,KAAA,GAAQ,QAAQ,KAAA,IAAS,IAAA;AAC/B,EAAA,MAAM,8BAA8B,OAAA,CAAQ,2BAAA;AAC5C,EAAA,MAAM,iBAAA,GAAoB,SAAS,CAAC,2BAAA;AAEpC,EAAA,MAAM,aAAA,GAAgB;AAAA,IACpB,UAAU,OAAA,CAAQ,+BAAA;AAAA,IAClB,wBAAwB,OAAA,CAAQ,sBAAA;AAAA,IAChC,mBAAmB,OAAA,CAAQ,yBAAA;AAAA,IAC3B,oBAAoB,OAAA,CAAQ;AAAA,GAC9B;AAEA,EAAA,MAAM,kBAAA,GAAwD;AAAA,IAC5D,wBAAwB,OAAA,CAAQ,sBAAA;AAAA,IAChC,oBAAoB,OAAA,CAAQ,kBAAA;AAAA,IAC5B,mBAAmB,OAAA,CAAQ,sCAAA;AAAA;AAAA,IAE3B,iBAAiB,OAAA,CAAQ,eAAA;AAAA,IACzB,eAAe,OAAA,CAAQ;AAAA,GACzB;AAEA,EAAA,MAAM,MAAA,GAAS,sBAAsB,aAAa,CAAA;AAClD,EAAA,MAAM,WAAA,GAAc,2BAA2B,kBAAkB,CAAA;AAEjE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,MAAM,MAAA,EAAoB;AACxB,MAAA,MAAM,aAAA,GAAgB,OAAO,UAAA,EAAW;AAExC,MAAA,IAAI,iBAAA,IAAqB,eAAA,CAAgB,aAAa,CAAA,EAAG;AACvD,QAAA,WAAA,CAAY,MAAM,MAAM,CAAA;AAAA,MAC1B;AAAA,IACF,CAAA;AAAA,IACA,SAAA,GAAY;AACV,MAAA,MAAA,CAAO,SAAA,EAAU;AAEjB,MAAA,MAAM,gCAAA,GAAqE;AAAA,QACzE,aAAa,OAAA,CAAQ,WAAA;AAAA,QACrB,KAAA;AAAA,QACA,gCAAA,EAAkC,QAAQ,gBAAA,IAAoB,IAAA;AAAA;AAAA,QAE9D,8BAAA,EAAgC,KAAA;AAAA,QAChC,wBAAwB,OAAA,CAAQ,sBAAA;AAAA,QAChC,mBAAA,EAAqB,CAAC,IAAA,EAAY,OAAA,KAA+B;AAE/D,UAAA,MAAM,GAAA,GAAM,+BAA+B,OAAO,CAAA;AAClD,UAAA,IAAI,GAAA,CAAI,UAAA,CAAW,OAAO,CAAA,EAAG;AAC3B,YAAA,MAAM,YAAA,GAAe,oBAAoB,GAAG,CAAA;AAC5C,YAAA,IAAA,CAAK,WAAW,CAAA,EAAG,OAAA,CAAQ,UAAU,KAAK,CAAA,CAAA,EAAI,YAAY,CAAA,CAAE,CAAA;AAC5D,YAAA,IAAA,CAAK,aAAA,CAAc;AAAA,cACjB,CAAC,gCAAgC,GAAG,KAAA;AAAA,cACpC,CAAC,QAAQ,GAAG;AAAA,aACb,CAAA;AAAA,UACH;AACA,UAAA,OAAA,CAAQ,eAAA,EAAiB,WAAA,GAAc,IAAA,EAAM,OAAO,CAAA;AAAA,QACtD,CAAA;AAAA,QACA,oBAAA,EAAsB,QAAQ,eAAA,EAAiB,YAAA;AAAA,QAC/C,oCAAA,EAAsC,QAAQ,eAAA,EAAiB;AAAA,OACjE;AAMA,MAAA,8BAAA,CAA+B,gCAAgC,CAAA;AAAA,IACjE,CAAA;AAAA,IACA,aAAa,KAAA,EAAO;AAIlB,MAAA,OAAO,WAAA,CAAY,aAAa,KAAK,CAAA;AAAA,IACvC;AAAA,GACF;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../../src/integrations/http/index.ts"],"sourcesContent":["import type { ClientRequest, RequestOptions } from 'node:http';\nimport type { Span } from '@sentry/core';\nimport { URL_FULL } from '@sentry/conventions/attributes';\nimport {\n defineIntegration,\n getClient,\n hasSpansEnabled,\n hasSpanStreamingEnabled,\n stripDataUrlContent,\n} from '@sentry/core';\nimport { getRequestUrlFromClientRequest } from '@sentry/core/server';\nimport type { NodeClient } from '../../sdk/client';\nimport type { HttpServerIntegrationOptions } from './httpServerIntegration';\nimport { httpServerIntegration } from './httpServerIntegration';\nimport type { HttpServerSpansIntegrationOptions } from './httpServerSpansIntegration';\nimport { httpServerSpansIntegration } from './httpServerSpansIntegration';\nimport type { OutgoingHttpRequestInstrumentationOptions } from './SentryHttpInstrumentation';\nimport { instrumentHttpOutgoingRequests } from './SentryHttpInstrumentation';\n\nconst INTEGRATION_NAME = 'Http' as const;\n\ninterface HttpOptions extends HttpServerIntegrationOptions, HttpServerSpansIntegrationOptions {\n /**\n * Whether breadcrumbs should be recorded for outgoing requests.\n * Defaults to true\n */\n breadcrumbs?: boolean;\n\n /**\n * If set to false, do not emit any spans.\n * This will ensure that the default HttpInstrumentation from OpenTelemetry is not setup,\n * only the Sentry-specific instrumentation for request isolation is applied.\n *\n * Defaults to `true` when tracing is enabled.\n */\n spans?: boolean;\n\n /**\n * Whether to inject trace propagation headers (sentry-trace, baggage, traceparent) into outgoing HTTP requests.\n *\n * When set to `false`, Sentry will not inject any trace propagation headers, but will still create breadcrumbs\n * (if `breadcrumbs` is enabled). This is useful when you run your own OpenTelemetry `HttpInstrumentation` and\n * want to avoid duplicate trace headers being injected by both Sentry and OpenTelemetry.\n *\n * @default `true`\n */\n tracePropagation?: boolean;\n\n /**\n * Do not capture spans or breadcrumbs for outgoing HTTP requests to URLs where the given callback returns `true`.\n * This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled.\n *\n * The `url` param contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n * For example: `'https://someService.com/users/details?id=123'`\n *\n * The `request` param contains the original {@type RequestOptions} object used to make the outgoing request.\n * You can use it to filter on additional properties like method, headers, etc.\n */\n ignoreOutgoingRequests?: (url: string, request: RequestOptions) => boolean;\n\n /**\n * If true, do not generate spans for incoming requests at all.\n * This is used by Remix to avoid generating spans for incoming requests, as it generates its own spans.\n */\n disableIncomingRequestSpans?: boolean;\n\n /**\n * Called after an outgoing request span is created.\n * Only invoked when spans are created for outgoing requests.\n */\n outgoingRequestHook?: OutgoingHttpRequestInstrumentationOptions['outgoingRequestHook'];\n\n /**\n * Called when the outgoing request receives a response.\n * Only invoked when spans are created for outgoing requests.\n */\n outgoingResponseHook?: OutgoingHttpRequestInstrumentationOptions['outgoingResponseHook'];\n\n /**\n * Called when both the outgoing request and response are available.\n * Only invoked when spans are created for outgoing requests.\n */\n outgoingRequestApplyCustomAttributes?: OutgoingHttpRequestInstrumentationOptions['outgoingRequestApplyCustomAttributes'];\n}\n\n/**\n * The http integration instruments Node's internal http and https modules.\n * It creates breadcrumbs and spans for outgoing HTTP requests which will be attached to the currently active span.\n */\nexport const httpIntegration = defineIntegration((options: HttpOptions = {}) => {\n const spans = options.spans ?? true;\n const enableServerSpans = spans && !options.disableIncomingRequestSpans;\n\n const server = httpServerIntegration(options);\n const serverSpans = httpServerSpansIntegration(options);\n\n return {\n name: INTEGRATION_NAME,\n setup(client: NodeClient) {\n const clientOptions = client.getOptions();\n\n if (enableServerSpans && hasSpansEnabled(clientOptions)) {\n serverSpans.setup(client);\n }\n },\n setupOnce() {\n server.setupOnce();\n\n const outgoingRequestOptions: OutgoingHttpRequestInstrumentationOptions = {\n breadcrumbs: options.breadcrumbs,\n spans,\n tracePropagation: options.tracePropagation ?? true,\n ignoreOutgoingRequests: options.ignoreOutgoingRequests,\n outgoingRequestHook: (span: Span, request: ClientRequest) => {\n // Sanitize data URLs to prevent long base64 strings in span attributes\n const url = getRequestUrlFromClientRequest(request);\n if (url.startsWith('data:')) {\n const sanitizedUrl = stripDataUrlContent(url);\n // With span streaming the span already carries a low-cardinality name, so it must not be\n // renamed back to something containing the URL.\n const client = getClient();\n if (!client || !hasSpanStreamingEnabled(client)) {\n span.updateName(`${request.method || 'GET'} ${sanitizedUrl}`);\n }\n span.setAttributes({\n [URL_FULL]: sanitizedUrl,\n });\n }\n options.outgoingRequestHook?.(span, request);\n },\n outgoingResponseHook: options.outgoingResponseHook,\n outgoingRequestApplyCustomAttributes: options.outgoingRequestApplyCustomAttributes,\n };\n\n // This is Sentry-specific instrumentation for outgoing request\n // breadcrumbs & trace propagation. It uses the diagnostic channels on\n // node versions that support it, falling back to monkey-patching when\n // needed.\n instrumentHttpOutgoingRequests(outgoingRequestOptions);\n },\n processEvent(event) {\n // Always run this, even if spans are disabled\n // The reason being that e.g. the remix integration disables span\n // creation here but still wants to use the ignore status codes option\n return serverSpans.processEvent(event);\n },\n };\n});\n"],"names":[],"mappings":";;;;;;;AAmBA,MAAM,gBAAA,GAAmB,MAAA;AAsElB,MAAM,eAAA,GAAkB,iBAAA,CAAkB,CAAC,OAAA,GAAuB,EAAC,KAAM;AAC9E,EAAA,MAAM,KAAA,GAAQ,QAAQ,KAAA,IAAS,IAAA;AAC/B,EAAA,MAAM,iBAAA,GAAoB,KAAA,IAAS,CAAC,OAAA,CAAQ,2BAAA;AAE5C,EAAA,MAAM,MAAA,GAAS,sBAAsB,OAAO,CAAA;AAC5C,EAAA,MAAM,WAAA,GAAc,2BAA2B,OAAO,CAAA;AAEtD,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,MAAM,MAAA,EAAoB;AACxB,MAAA,MAAM,aAAA,GAAgB,OAAO,UAAA,EAAW;AAExC,MAAA,IAAI,iBAAA,IAAqB,eAAA,CAAgB,aAAa,CAAA,EAAG;AACvD,QAAA,WAAA,CAAY,MAAM,MAAM,CAAA;AAAA,MAC1B;AAAA,IACF,CAAA;AAAA,IACA,SAAA,GAAY;AACV,MAAA,MAAA,CAAO,SAAA,EAAU;AAEjB,MAAA,MAAM,sBAAA,GAAoE;AAAA,QACxE,aAAa,OAAA,CAAQ,WAAA;AAAA,QACrB,KAAA;AAAA,QACA,gBAAA,EAAkB,QAAQ,gBAAA,IAAoB,IAAA;AAAA,QAC9C,wBAAwB,OAAA,CAAQ,sBAAA;AAAA,QAChC,mBAAA,EAAqB,CAAC,IAAA,EAAY,OAAA,KAA2B;AAE3D,UAAA,MAAM,GAAA,GAAM,+BAA+B,OAAO,CAAA;AAClD,UAAA,IAAI,GAAA,CAAI,UAAA,CAAW,OAAO,CAAA,EAAG;AAC3B,YAAA,MAAM,YAAA,GAAe,oBAAoB,GAAG,CAAA;AAG5C,YAAA,MAAM,SAAS,SAAA,EAAU;AACzB,YAAA,IAAI,CAAC,MAAA,IAAU,CAAC,uBAAA,CAAwB,MAAM,CAAA,EAAG;AAC/C,cAAA,IAAA,CAAK,WAAW,CAAA,EAAG,OAAA,CAAQ,UAAU,KAAK,CAAA,CAAA,EAAI,YAAY,CAAA,CAAE,CAAA;AAAA,YAC9D;AACA,YAAA,IAAA,CAAK,aAAA,CAAc;AAAA,cACjB,CAAC,QAAQ,GAAG;AAAA,aACb,CAAA;AAAA,UACH;AACA,UAAA,OAAA,CAAQ,mBAAA,GAAsB,MAAM,OAAO,CAAA;AAAA,QAC7C,CAAA;AAAA,QACA,sBAAsB,OAAA,CAAQ,oBAAA;AAAA,QAC9B,sCAAsC,OAAA,CAAQ;AAAA,OAChD;AAMA,MAAA,8BAAA,CAA+B,sBAAsB,CAAA;AAAA,IACvD,CAAA;AAAA,IACA,aAAa,KAAA,EAAO;AAIlB,MAAA,OAAO,WAAA,CAAY,aAAa,KAAK,CAAA;AAAA,IACvC;AAAA,GACF;AACF,CAAC;;;;"}
@@ -3,7 +3,7 @@ import { defineIntegration, debug, getClient } from '@sentry/core';
3
3
  import { isDebuggerEnabled } from '../../utils/debug.js';
4
4
  import { LOCAL_VARIABLES_KEY, functionNamesMatch, filterFrameVariables } from './common.js';
5
5
 
6
- const base64WorkerScript = "LyohIEBzZW50cnkvbm9kZSAxMS4wLjAtYWxwaGEuMSAoNmFiN2VmZCkgfCBodHRwczovL2dpdGh1Yi5jb20vZ2V0c2VudHJ5L3NlbnRyeS1qYXZhc2NyaXB0ICovCmltcG9ydHtTZXNzaW9uIGFzIGV9ZnJvbSJub2RlOmluc3BlY3Rvci9wcm9taXNlcyI7aW1wb3J0e3dvcmtlckRhdGEgYXMgdH1mcm9tIm5vZGU6d29ya2VyX3RocmVhZHMiO2NvbnN0IG49Z2xvYmFsVGhpcyxpPXt9O2NvbnN0IG89Il9fU0VOVFJZX0VSUk9SX0xPQ0FMX1ZBUklBQkxFU19fIjtjb25zdCBhPXQ7ZnVuY3Rpb24gcyguLi5lKXthLmRlYnVnJiZmdW5jdGlvbihlKXtpZighKCJjb25zb2xlImluIG4pKXJldHVybiBlKCk7Y29uc3QgdD1uLmNvbnNvbGUsbz17fSxhPU9iamVjdC5rZXlzKGkpO2EuZm9yRWFjaChlPT57Y29uc3Qgbj1pW2VdO29bZV09dFtlXSx0W2VdPW59KTt0cnl7cmV0dXJuIGUoKX1maW5hbGx5e2EuZm9yRWFjaChlPT57dFtlXT1vW2VdfSl9fSgoKT0+Y29uc29sZS5sb2coIltMb2NhbFZhcmlhYmxlcyBXb3JrZXJdIiwuLi5lKSl9YXN5bmMgZnVuY3Rpb24gYyhlLHQsbixpKXtjb25zdCBvPWF3YWl0IGUucG9zdCgiUnVudGltZS5nZXRQcm9wZXJ0aWVzIix7b2JqZWN0SWQ6dCxvd25Qcm9wZXJ0aWVzOiEwfSk7aVtuXT1vLnJlc3VsdC5maWx0ZXIoZT0+Imxlbmd0aCIhPT1lLm5hbWUmJiFpc05hTihwYXJzZUludChlLm5hbWUsMTApKSkuc29ydCgoZSx0KT0+cGFyc2VJbnQoZS5uYW1lLDEwKS1wYXJzZUludCh0Lm5hbWUsMTApKS5tYXAoZT0+ZS52YWx1ZT8udmFsdWUpfWFzeW5jIGZ1bmN0aW9uIHIoZSx0LG4saSl7Y29uc3Qgbz1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuZ2V0UHJvcGVydGllcyIse29iamVjdElkOnQsb3duUHJvcGVydGllczohMH0pO2lbbl09by5yZXN1bHQubWFwKGU9PltlLm5hbWUsZS52YWx1ZT8udmFsdWVdKS5yZWR1Y2UoKGUsW3Qsbl0pPT4oZVt0XT1uLGUpLHt9KX1mdW5jdGlvbiB1KGUsdCl7ZS52YWx1ZSYmKCJ2YWx1ZSJpbiBlLnZhbHVlP3ZvaWQgMD09PWUudmFsdWUudmFsdWV8fG51bGw9PT1lLnZhbHVlLnZhbHVlP3RbZS5uYW1lXT1gPCR7ZS52YWx1ZS52YWx1ZX0+YDp0W2UubmFtZV09ZS52YWx1ZS52YWx1ZToiZGVzY3JpcHRpb24iaW4gZS52YWx1ZSYmImZ1bmN0aW9uIiE9PWUudmFsdWUudHlwZT90W2UubmFtZV09YDwke2UudmFsdWUuZGVzY3JpcHRpb259PmA6InVuZGVmaW5lZCI9PT1lLnZhbHVlLnR5cGUmJih0W2UubmFtZV09Ijx1bmRlZmluZWQ+IikpfWFzeW5jIGZ1bmN0aW9uIGwoZSx0KXtjb25zdCBuPWF3YWl0IGUucG9zdCgiUnVudGltZS5nZXRQcm9wZXJ0aWVzIix7b2JqZWN0SWQ6dCxvd25Qcm9wZXJ0aWVzOiEwfSksaT17fTtmb3IoY29uc3QgdCBvZiBuLnJlc3VsdClpZih0LnZhbHVlPy5vYmplY3RJZCYmIkFycmF5Ij09PXQudmFsdWUuY2xhc3NOYW1lKXtjb25zdCBuPXQudmFsdWUub2JqZWN0SWQ7YXdhaXQgYyhlLG4sdC5uYW1lLGkpfWVsc2UgaWYodC52YWx1ZT8ub2JqZWN0SWQmJiJPYmplY3QiPT09dC52YWx1ZS5jbGFzc05hbWUpe2NvbnN0IG49dC52YWx1ZS5vYmplY3RJZDthd2FpdCByKGUsbix0Lm5hbWUsaSl9ZWxzZSB0LnZhbHVlJiZ1KHQsaSk7cmV0dXJuIGl9bGV0IGY7KGFzeW5jIGZ1bmN0aW9uKCl7Y29uc3QgdD1uZXcgZTt0LmNvbm5lY3RUb01haW5UaHJlYWQoKSxzKCJDb25uZWN0ZWQgdG8gbWFpbiB0aHJlYWQiKTtsZXQgbj0hMTt0Lm9uKCJEZWJ1Z2dlci5yZXN1bWVkIiwoKT0+e249ITF9KSx0Lm9uKCJEZWJ1Z2dlci5wYXVzZWQiLGU9PntuPSEwLGFzeW5jIGZ1bmN0aW9uKGUse3JlYXNvbjp0LGRhdGE6e29iamVjdElkOm59LGNhbGxGcmFtZXM6aX0pe2lmKCJleGNlcHRpb24iIT09dCYmInByb21pc2VSZWplY3Rpb24iIT09dClyZXR1cm47aWYoZj8uKCksbnVsbD09bilyZXR1cm47Y29uc3QgYT1bXTtmb3IobGV0IHQ9MDt0PGkubGVuZ3RoO3QrKyl7Y29uc3R7c2NvcGVDaGFpbjpuLGZ1bmN0aW9uTmFtZTpvLHRoaXM6c309aVt0XSxjPW4uZmluZChlPT4ibG9jYWwiPT09ZS50eXBlKSxyPSJnbG9iYWwiIT09cy5jbGFzc05hbWUmJnMuY2xhc3NOYW1lP2Ake3MuY2xhc3NOYW1lfS4ke299YDpvO2lmKHZvaWQgMD09PWM/Lm9iamVjdC5vYmplY3RJZClhW3RdPXtmdW5jdGlvbjpyfTtlbHNle2NvbnN0IG49YXdhaXQgbChlLGMub2JqZWN0Lm9iamVjdElkKTthW3RdPXtmdW5jdGlvbjpyLHZhcnM6bn19fWF3YWl0IGUucG9zdCgiUnVudGltZS5jYWxsRnVuY3Rpb25PbiIse2Z1bmN0aW9uRGVjbGFyYXRpb246YGZ1bmN0aW9uKCkgeyB0aGlzLiR7b30gPSB0aGlzLiR7b30gfHwgJHtKU09OLnN0cmluZ2lmeShhKX07IH1gLHNpbGVudDohMCxvYmplY3RJZDpufSksYXdhaXQgZS5wb3N0KCJSdW50aW1lLnJlbGVhc2VPYmplY3QiLHtvYmplY3RJZDpufSl9KHQsZS5wYXJhbXMpLnRoZW4oYXN5bmMoKT0+e24mJmF3YWl0IHQucG9zdCgiRGVidWdnZXIucmVzdW1lIil9LGFzeW5jIGU9PntuJiZhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpfSl9KSxhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLmVuYWJsZSIpO2NvbnN0IGk9ITEhPT1hLmNhcHR1cmVBbGxFeGNlcHRpb25zO2lmKGF3YWl0IHQucG9zdCgiRGVidWdnZXIuc2V0UGF1c2VPbkV4Y2VwdGlvbnMiLHtzdGF0ZTppPyJhbGwiOiJ1bmNhdWdodCJ9KSxpKXtjb25zdCBlPWEubWF4RXhjZXB0aW9uc1BlclNlY29uZHx8NTA7Zj1mdW5jdGlvbihlLHQsbil7bGV0IGk9MCxvPTUsYT0wO3JldHVybiBzZXRJbnRlcnZhbCgoKT0+ezA9PT1hP2k+ZSYmKG8qPTIsbihvKSxvPjg2NDAwJiYobz04NjQwMCksYT1vKTooYS09MSwwPT09YSYmdCgpKSxpPTB9LDFlMykudW5yZWYoKSwoKT0+e2krPTF9fShlLGFzeW5jKCk9PntzKCJSYXRlLWxpbWl0IGxpZnRlZC4iKSxhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnNldFBhdXNlT25FeGNlcHRpb25zIix7c3RhdGU6ImFsbCJ9KX0sYXN5bmMgZT0+e3MoYFJhdGUtbGltaXQgZXhjZWVkZWQuIERpc2FibGluZyBjYXB0dXJpbmcgb2YgY2F1Z2h0IGV4Y2VwdGlvbnMgZm9yICR7ZX0gc2Vjb25kcy5gKSxhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnNldFBhdXNlT25FeGNlcHRpb25zIix7c3RhdGU6InVuY2F1Z2h0In0pfSl9fSkoKS5jYXRjaChlPT57cygiRmFpbGVkIHRvIHN0YXJ0IGRlYnVnZ2VyIixlKX0pLHNldEludGVydmFsKCgpPT57fSwxZTQpOw==";
6
+ const base64WorkerScript = "LyohIEBzZW50cnkvbm9kZSAxMS4wLjAtYmV0YS4wICg1NGJiYWU5KSB8IGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvc2VudHJ5LWphdmFzY3JpcHQgKi8KaW1wb3J0e1Nlc3Npb24gYXMgZX1mcm9tIm5vZGU6aW5zcGVjdG9yL3Byb21pc2VzIjtpbXBvcnR7d29ya2VyRGF0YSBhcyB0fWZyb20ibm9kZTp3b3JrZXJfdGhyZWFkcyI7Y29uc3Qgbj1nbG9iYWxUaGlzLGk9e307Y29uc3Qgbz0iX19TRU5UUllfRVJST1JfTE9DQUxfVkFSSUFCTEVTX18iO2NvbnN0IGE9dDtmdW5jdGlvbiBzKC4uLmUpe2EuZGVidWcmJmZ1bmN0aW9uKGUpe2lmKCEoImNvbnNvbGUiaW4gbikpcmV0dXJuIGUoKTtjb25zdCB0PW4uY29uc29sZSxvPXt9LGE9T2JqZWN0LmtleXMoaSk7YS5mb3JFYWNoKGU9Pntjb25zdCBuPWlbZV07b1tlXT10W2VdLHRbZV09bn0pO3RyeXtyZXR1cm4gZSgpfWZpbmFsbHl7YS5mb3JFYWNoKGU9Pnt0W2VdPW9bZV19KX19KCgpPT5jb25zb2xlLmxvZygiW0xvY2FsVmFyaWFibGVzIFdvcmtlcl0iLC4uLmUpKX1hc3luYyBmdW5jdGlvbiBjKGUsdCxuLGkpe2NvbnN0IG89YXdhaXQgZS5wb3N0KCJSdW50aW1lLmdldFByb3BlcnRpZXMiLHtvYmplY3RJZDp0LG93blByb3BlcnRpZXM6ITB9KTtpW25dPW8ucmVzdWx0LmZpbHRlcihlPT4ibGVuZ3RoIiE9PWUubmFtZSYmIWlzTmFOKHBhcnNlSW50KGUubmFtZSwxMCkpKS5zb3J0KChlLHQpPT5wYXJzZUludChlLm5hbWUsMTApLXBhcnNlSW50KHQubmFtZSwxMCkpLm1hcChlPT5lLnZhbHVlPy52YWx1ZSl9YXN5bmMgZnVuY3Rpb24gcihlLHQsbixpKXtjb25zdCBvPWF3YWl0IGUucG9zdCgiUnVudGltZS5nZXRQcm9wZXJ0aWVzIix7b2JqZWN0SWQ6dCxvd25Qcm9wZXJ0aWVzOiEwfSk7aVtuXT1vLnJlc3VsdC5tYXAoZT0+W2UubmFtZSxlLnZhbHVlPy52YWx1ZV0pLnJlZHVjZSgoZSxbdCxuXSk9PihlW3RdPW4sZSkse30pfWZ1bmN0aW9uIHUoZSx0KXtlLnZhbHVlJiYoInZhbHVlImluIGUudmFsdWU/dm9pZCAwPT09ZS52YWx1ZS52YWx1ZXx8bnVsbD09PWUudmFsdWUudmFsdWU/dFtlLm5hbWVdPWA8JHtlLnZhbHVlLnZhbHVlfT5gOnRbZS5uYW1lXT1lLnZhbHVlLnZhbHVlOiJkZXNjcmlwdGlvbiJpbiBlLnZhbHVlJiYiZnVuY3Rpb24iIT09ZS52YWx1ZS50eXBlP3RbZS5uYW1lXT1gPCR7ZS52YWx1ZS5kZXNjcmlwdGlvbn0+YDoidW5kZWZpbmVkIj09PWUudmFsdWUudHlwZSYmKHRbZS5uYW1lXT0iPHVuZGVmaW5lZD4iKSl9YXN5bmMgZnVuY3Rpb24gbChlLHQpe2NvbnN0IG49YXdhaXQgZS5wb3N0KCJSdW50aW1lLmdldFByb3BlcnRpZXMiLHtvYmplY3RJZDp0LG93blByb3BlcnRpZXM6ITB9KSxpPXt9O2Zvcihjb25zdCB0IG9mIG4ucmVzdWx0KWlmKHQudmFsdWU/Lm9iamVjdElkJiYiQXJyYXkiPT09dC52YWx1ZS5jbGFzc05hbWUpe2NvbnN0IG49dC52YWx1ZS5vYmplY3RJZDthd2FpdCBjKGUsbix0Lm5hbWUsaSl9ZWxzZSBpZih0LnZhbHVlPy5vYmplY3RJZCYmIk9iamVjdCI9PT10LnZhbHVlLmNsYXNzTmFtZSl7Y29uc3Qgbj10LnZhbHVlLm9iamVjdElkO2F3YWl0IHIoZSxuLHQubmFtZSxpKX1lbHNlIHQudmFsdWUmJnUodCxpKTtyZXR1cm4gaX1sZXQgZjsoYXN5bmMgZnVuY3Rpb24oKXtjb25zdCB0PW5ldyBlO3QuY29ubmVjdFRvTWFpblRocmVhZCgpLHMoIkNvbm5lY3RlZCB0byBtYWluIHRocmVhZCIpO2xldCBuPSExO3Qub24oIkRlYnVnZ2VyLnJlc3VtZWQiLCgpPT57bj0hMX0pLHQub24oIkRlYnVnZ2VyLnBhdXNlZCIsZT0+e249ITAsYXN5bmMgZnVuY3Rpb24oZSx7cmVhc29uOnQsZGF0YTp7b2JqZWN0SWQ6bn0sY2FsbEZyYW1lczppfSl7aWYoImV4Y2VwdGlvbiIhPT10JiYicHJvbWlzZVJlamVjdGlvbiIhPT10KXJldHVybjtpZihmPy4oKSxudWxsPT1uKXJldHVybjtjb25zdCBhPVtdO2ZvcihsZXQgdD0wO3Q8aS5sZW5ndGg7dCsrKXtjb25zdHtzY29wZUNoYWluOm4sZnVuY3Rpb25OYW1lOm8sdGhpczpzfT1pW3RdLGM9bi5maW5kKGU9PiJsb2NhbCI9PT1lLnR5cGUpLHI9Imdsb2JhbCIhPT1zLmNsYXNzTmFtZSYmcy5jbGFzc05hbWU/YCR7cy5jbGFzc05hbWV9LiR7b31gOm87aWYodm9pZCAwPT09Yz8ub2JqZWN0Lm9iamVjdElkKWFbdF09e2Z1bmN0aW9uOnJ9O2Vsc2V7Y29uc3Qgbj1hd2FpdCBsKGUsYy5vYmplY3Qub2JqZWN0SWQpO2FbdF09e2Z1bmN0aW9uOnIsdmFyczpufX19YXdhaXQgZS5wb3N0KCJSdW50aW1lLmNhbGxGdW5jdGlvbk9uIix7ZnVuY3Rpb25EZWNsYXJhdGlvbjpgZnVuY3Rpb24oKSB7IHRoaXMuJHtvfSA9IHRoaXMuJHtvfSB8fCAke0pTT04uc3RyaW5naWZ5KGEpfTsgfWAsc2lsZW50OiEwLG9iamVjdElkOm59KSxhd2FpdCBlLnBvc3QoIlJ1bnRpbWUucmVsZWFzZU9iamVjdCIse29iamVjdElkOm59KX0odCxlLnBhcmFtcykudGhlbihhc3luYygpPT57biYmYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKX0sYXN5bmMgZT0+e24mJmF3YWl0IHQucG9zdCgiRGVidWdnZXIucmVzdW1lIil9KX0pLGF3YWl0IHQucG9zdCgiRGVidWdnZXIuZW5hYmxlIik7Y29uc3QgaT0hMSE9PWEuY2FwdHVyZUFsbEV4Y2VwdGlvbnM7aWYoYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIse3N0YXRlOmk/ImFsbCI6InVuY2F1Z2h0In0pLGkpe2NvbnN0IGU9YS5tYXhFeGNlcHRpb25zUGVyU2Vjb25kfHw1MDtmPWZ1bmN0aW9uKGUsdCxuKXtsZXQgaT0wLG89NSxhPTA7cmV0dXJuIHNldEludGVydmFsKCgpPT57MD09PWE/aT5lJiYobyo9MixuKG8pLG8+ODY0MDAmJihvPTg2NDAwKSxhPW8pOihhLT0xLDA9PT1hJiZ0KCkpLGk9MH0sMWUzKS51bnJlZigpLCgpPT57aSs9MX19KGUsYXN5bmMoKT0+e3MoIlJhdGUtbGltaXQgbGlmdGVkLiIpLGF3YWl0IHQucG9zdCgiRGVidWdnZXIuc2V0UGF1c2VPbkV4Y2VwdGlvbnMiLHtzdGF0ZToiYWxsIn0pfSxhc3luYyBlPT57cyhgUmF0ZS1saW1pdCBleGNlZWRlZC4gRGlzYWJsaW5nIGNhcHR1cmluZyBvZiBjYXVnaHQgZXhjZXB0aW9ucyBmb3IgJHtlfSBzZWNvbmRzLmApLGF3YWl0IHQucG9zdCgiRGVidWdnZXIuc2V0UGF1c2VPbkV4Y2VwdGlvbnMiLHtzdGF0ZToidW5jYXVnaHQifSl9KX19KSgpLmNhdGNoKGU9PntzKCJGYWlsZWQgdG8gc3RhcnQgZGVidWdnZXIiLGUpfSksc2V0SW50ZXJ2YWwoKCk9Pnt9LDFlNCk7";
7
7
  function log(...args) {
8
8
  debug.log("[LocalVariables]", ...args);
9
9
  }
@@ -1,2 +1,2 @@
1
- /*! @sentry/node 11.0.0-alpha.1 (6ab7efd) | https://github.com/getsentry/sentry-javascript */
1
+ /*! @sentry/node 11.0.0-beta.0 (54bbae9) | https://github.com/getsentry/sentry-javascript */
2
2
  import{Session as e}from"node:inspector/promises";import{workerData as t}from"node:worker_threads";const n=globalThis,i={};const o="__SENTRY_ERROR_LOCAL_VARIABLES__";const a=t;function s(...e){a.debug&&function(e){if(!("console"in n))return e();const t=n.console,o={},a=Object.keys(i);a.forEach(e=>{const n=i[e];o[e]=t[e],t[e]=n});try{return e()}finally{a.forEach(e=>{t[e]=o[e]})}}(()=>console.log("[LocalVariables Worker]",...e))}async function c(e,t,n,i){const o=await e.post("Runtime.getProperties",{objectId:t,ownProperties:!0});i[n]=o.result.filter(e=>"length"!==e.name&&!isNaN(parseInt(e.name,10))).sort((e,t)=>parseInt(e.name,10)-parseInt(t.name,10)).map(e=>e.value?.value)}async function r(e,t,n,i){const o=await e.post("Runtime.getProperties",{objectId:t,ownProperties:!0});i[n]=o.result.map(e=>[e.name,e.value?.value]).reduce((e,[t,n])=>(e[t]=n,e),{})}function u(e,t){e.value&&("value"in e.value?void 0===e.value.value||null===e.value.value?t[e.name]=`<${e.value.value}>`:t[e.name]=e.value.value:"description"in e.value&&"function"!==e.value.type?t[e.name]=`<${e.value.description}>`:"undefined"===e.value.type&&(t[e.name]="<undefined>"))}async function l(e,t){const n=await e.post("Runtime.getProperties",{objectId:t,ownProperties:!0}),i={};for(const t of n.result)if(t.value?.objectId&&"Array"===t.value.className){const n=t.value.objectId;await c(e,n,t.name,i)}else if(t.value?.objectId&&"Object"===t.value.className){const n=t.value.objectId;await r(e,n,t.name,i)}else t.value&&u(t,i);return i}let f;(async function(){const t=new e;t.connectToMainThread(),s("Connected to main thread");let n=!1;t.on("Debugger.resumed",()=>{n=!1}),t.on("Debugger.paused",e=>{n=!0,async function(e,{reason:t,data:{objectId:n},callFrames:i}){if("exception"!==t&&"promiseRejection"!==t)return;if(f?.(),null==n)return;const a=[];for(let t=0;t<i.length;t++){const{scopeChain:n,functionName:o,this:s}=i[t],c=n.find(e=>"local"===e.type),r="global"!==s.className&&s.className?`${s.className}.${o}`:o;if(void 0===c?.object.objectId)a[t]={function:r};else{const n=await l(e,c.object.objectId);a[t]={function:r,vars:n}}}await e.post("Runtime.callFunctionOn",{functionDeclaration:`function() { this.${o} = this.${o} || ${JSON.stringify(a)}; }`,silent:!0,objectId:n}),await e.post("Runtime.releaseObject",{objectId:n})}(t,e.params).then(async()=>{n&&await t.post("Debugger.resume")},async e=>{n&&await t.post("Debugger.resume")})}),await t.post("Debugger.enable");const i=!1!==a.captureAllExceptions;if(await t.post("Debugger.setPauseOnExceptions",{state:i?"all":"uncaught"}),i){const e=a.maxExceptionsPerSecond||50;f=function(e,t,n){let i=0,o=5,a=0;return setInterval(()=>{0===a?i>e&&(o*=2,n(o),o>86400&&(o=86400),a=o):(a-=1,0===a&&t()),i=0},1e3).unref(),()=>{i+=1}}(e,async()=>{s("Rate-limit lifted."),await t.post("Debugger.setPauseOnExceptions",{state:"all"})},async e=>{s(`Rate-limit exceeded. Disabling capturing of caught exceptions for ${e} seconds.`),await t.post("Debugger.setPauseOnExceptions",{state:"uncaught"})})}})().catch(e=>{s("Failed to start debugger",e)}),setInterval(()=>{},1e4);
@@ -1,8 +1,9 @@
1
1
  import * as diagch from 'diagnostics_channel';
2
2
  import { URL } from 'url';
3
- import { LRUMap, isTracingSuppressed, debug, getUrlFragment, filterCollectedUrlQuery, getUrlQuery, filterCollectedUrl, stripDataUrlContent, getSanitizedUrlString, parseUrl, getClient, startInactiveSpan, hasSpanStreamingEnabled, getSpanStatusFromHttpCode, SPAN_STATUS_ERROR, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core';
3
+ import { LRUMap, isTracingSuppressed, debug, getUrlFragment, filterCollectedUrlQuery, getUrlQuery, filterCollectedUrl, stripDataUrlContent, getClient, hasSpanStreamingEnabled, getSanitizedUrlString, parseUrl, startInactiveSpan, getSpanStatusFromHttpCode, SPAN_STATUS_ERROR, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME, HTTP_SPAN_NAME_FALLBACK } from '@sentry/core';
4
4
  import { addTracePropagationHeadersToFetchRequest, addFetchRequestBreadcrumb } from '../../utils/outgoingFetchRequest.js';
5
- import { URL_FRAGMENT, URL_QUERY, URL_PATH, URL_FULL, HTTP_RESPONSE_STATUS_CODE, URL_SCHEME, HTTP_REQUEST_METHOD, SENTRY_OP, SENTRY_KIND, SERVER_ADDRESS, SERVER_PORT, USER_AGENT_ORIGINAL, NETWORK_PEER_PORT, NETWORK_PEER_ADDRESS } from '@sentry/conventions/attributes';
5
+ import { URL_FRAGMENT, URL_QUERY, URL_PATH, URL_DOMAIN, URL_FULL, HTTP_RESPONSE_STATUS_CODE, URL_SCHEME, HTTP_REQUEST_METHOD, SENTRY_OP, SENTRY_KIND, SERVER_ADDRESS, SERVER_PORT, USER_AGENT_ORIGINAL, NETWORK_PEER_PORT, NETWORK_PEER_ADDRESS } from '@sentry/conventions/attributes';
6
+ import { HTTP_CLIENT } from '@sentry/conventions/op';
6
7
  import { DEBUG_BUILD } from '../../debug-build.js';
7
8
 
8
9
  const ATTR_HTTP_REQUEST_METHOD_ORIGINAL = "http.request.method_original";
@@ -96,15 +97,16 @@ function onRequestCreated(config, { request }) {
96
97
  const requestMethod = getRequestMethod(request.method);
97
98
  const attributes = {
98
99
  [SENTRY_KIND]: "client",
99
- [SENTRY_OP]: "http.client",
100
+ [SENTRY_OP]: HTTP_CLIENT,
100
101
  [HTTP_REQUEST_METHOD]: requestMethod,
101
102
  [ATTR_HTTP_REQUEST_METHOD_ORIGINAL]: request.method,
102
103
  [URL_FULL]: filterCollectedUrl(requestUrl.toString()),
104
+ [URL_DOMAIN]: requestUrl.hostname || void 0,
103
105
  [URL_PATH]: requestUrl.pathname,
104
106
  [URL_QUERY]: filterCollectedUrlQuery(getUrlQuery(requestUrl.search)),
105
107
  [URL_FRAGMENT]: getUrlFragment(requestUrl.hash),
106
108
  [URL_SCHEME]: urlScheme,
107
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.otel.node_fetch"
109
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.node_fetch"
108
110
  };
109
111
  if (url.startsWith("data:")) {
110
112
  const sanitizedUrl = stripDataUrlContent(url);
@@ -125,11 +127,17 @@ function onRequestCreated(config, { request }) {
125
127
  attributes[USER_AGENT_ORIGINAL] = userAgent;
126
128
  }
127
129
  const isDataUrl = url.startsWith("data:");
128
- if (!isDataUrl) {
129
- attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] = "url";
130
- }
131
- const spanName = requestMethod === "_OTHER" ? "HTTP" : isDataUrl ? `${request.method || "GET"} ${stripDataUrlContent(url)}` : `${requestMethod} ${getSanitizedUrlString(parseUrl(requestUrl.toString()))}`;
132
130
  const client = getClient();
131
+ let spanName;
132
+ if (requestMethod === "_OTHER") {
133
+ spanName = HTTP_SPAN_NAME_FALLBACK;
134
+ } else if (!!client && hasSpanStreamingEnabled(client)) {
135
+ spanName = requestUrl.hostname ? `${requestMethod} ${requestUrl.hostname}` : requestMethod;
136
+ } else if (isDataUrl) {
137
+ spanName = `${request.method || "GET"} ${stripDataUrlContent(url)}`;
138
+ } else {
139
+ spanName = `${requestMethod} ${getSanitizedUrlString(parseUrl(requestUrl.toString()))}`;
140
+ }
133
141
  const span = startInactiveSpan({
134
142
  name: spanName,
135
143
  attributes,
@@ -237,7 +245,7 @@ function getRequestMethod(original) {
237
245
  PATCH: true,
238
246
  DELETE: true,
239
247
  TRACE: true,
240
- // QUERY from https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/
248
+ // QUERY from https://datatracker.ietf.org/doc/rfc10008/
241
249
  QUERY: true
242
250
  };
243
251
  if (original.toUpperCase() in knownMethods) {