@sentry/core 10.47.0 → 10.48.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 (316) hide show
  1. package/build/cjs/attributes.js +43 -0
  2. package/build/cjs/attributes.js.map +1 -1
  3. package/build/cjs/client.js +13 -6
  4. package/build/cjs/client.js.map +1 -1
  5. package/build/cjs/envelope.js +4 -3
  6. package/build/cjs/envelope.js.map +1 -1
  7. package/build/cjs/index.js +44 -13
  8. package/build/cjs/index.js.map +1 -1
  9. package/build/cjs/integration.js +6 -0
  10. package/build/cjs/integration.js.map +1 -1
  11. package/build/cjs/integrations/express/index.js +206 -0
  12. package/build/cjs/integrations/express/index.js.map +1 -0
  13. package/build/cjs/integrations/express/patch-layer.js +251 -0
  14. package/build/cjs/integrations/express/patch-layer.js.map +1 -0
  15. package/build/cjs/integrations/express/request-layer-store.js +25 -0
  16. package/build/cjs/integrations/express/request-layer-store.js.map +1 -0
  17. package/build/cjs/integrations/express/set-sdk-processing-metadata.js +17 -0
  18. package/build/cjs/integrations/express/set-sdk-processing-metadata.js.map +1 -0
  19. package/build/cjs/integrations/express/types.js +17 -0
  20. package/build/cjs/integrations/express/types.js.map +1 -0
  21. package/build/cjs/integrations/express/utils.js +238 -0
  22. package/build/cjs/integrations/express/utils.js.map +1 -0
  23. package/build/cjs/integrations/mcp-server/correlation.js +5 -1
  24. package/build/cjs/integrations/mcp-server/correlation.js.map +1 -1
  25. package/build/cjs/integrations/mcp-server/handlers.js +18 -10
  26. package/build/cjs/integrations/mcp-server/handlers.js.map +1 -1
  27. package/build/cjs/integrations/mcp-server/index.js +2 -1
  28. package/build/cjs/integrations/mcp-server/index.js.map +1 -1
  29. package/build/cjs/integrations/mcp-server/transport.js +1 -1
  30. package/build/cjs/integrations/mcp-server/transport.js.map +1 -1
  31. package/build/cjs/integrations/mcp-server/validation.js +7 -5
  32. package/build/cjs/integrations/mcp-server/validation.js.map +1 -1
  33. package/build/cjs/integrations/spanStreaming.js +48 -0
  34. package/build/cjs/integrations/spanStreaming.js.map +1 -0
  35. package/build/cjs/semanticAttributes.js +35 -3
  36. package/build/cjs/semanticAttributes.js.map +1 -1
  37. package/build/cjs/tracing/ai/gen-ai-attributes.js +9 -65
  38. package/build/cjs/tracing/ai/gen-ai-attributes.js.map +1 -1
  39. package/build/cjs/tracing/ai/utils.js +50 -0
  40. package/build/cjs/tracing/ai/utils.js.map +1 -1
  41. package/build/cjs/tracing/anthropic-ai/index.js +1 -12
  42. package/build/cjs/tracing/anthropic-ai/index.js.map +1 -1
  43. package/build/cjs/tracing/anthropic-ai/streaming.js +2 -100
  44. package/build/cjs/tracing/anthropic-ai/streaming.js.map +1 -1
  45. package/build/cjs/tracing/dynamicSamplingContext.js +2 -1
  46. package/build/cjs/tracing/dynamicSamplingContext.js.map +1 -1
  47. package/build/cjs/tracing/google-genai/constants.js +1 -6
  48. package/build/cjs/tracing/google-genai/constants.js.map +1 -1
  49. package/build/cjs/tracing/google-genai/index.js +24 -30
  50. package/build/cjs/tracing/google-genai/index.js.map +1 -1
  51. package/build/cjs/tracing/google-genai/streaming.js +2 -23
  52. package/build/cjs/tracing/google-genai/streaming.js.map +1 -1
  53. package/build/cjs/tracing/langchain/embeddings.js +132 -0
  54. package/build/cjs/tracing/langchain/embeddings.js.map +1 -0
  55. package/build/cjs/tracing/langchain/index.js.map +1 -1
  56. package/build/cjs/tracing/openai/index.js +2 -29
  57. package/build/cjs/tracing/openai/index.js.map +1 -1
  58. package/build/cjs/tracing/openai/streaming.js +3 -34
  59. package/build/cjs/tracing/openai/streaming.js.map +1 -1
  60. package/build/cjs/tracing/openai/utils.js +78 -204
  61. package/build/cjs/tracing/openai/utils.js.map +1 -1
  62. package/build/cjs/tracing/sentryNonRecordingSpan.js +7 -0
  63. package/build/cjs/tracing/sentryNonRecordingSpan.js.map +1 -1
  64. package/build/cjs/tracing/sentrySpan.js +39 -0
  65. package/build/cjs/tracing/sentrySpan.js.map +1 -1
  66. package/build/cjs/tracing/spans/beforeSendSpan.js +43 -0
  67. package/build/cjs/tracing/spans/beforeSendSpan.js.map +1 -0
  68. package/build/cjs/tracing/spans/captureSpan.js +126 -0
  69. package/build/cjs/tracing/spans/captureSpan.js.map +1 -0
  70. package/build/cjs/tracing/spans/envelope.js +38 -0
  71. package/build/cjs/tracing/spans/envelope.js.map +1 -0
  72. package/build/cjs/tracing/spans/estimateSize.js +41 -0
  73. package/build/cjs/tracing/spans/estimateSize.js.map +1 -0
  74. package/build/cjs/tracing/spans/hasSpanStreamingEnabled.js +11 -0
  75. package/build/cjs/tracing/spans/hasSpanStreamingEnabled.js.map +1 -0
  76. package/build/cjs/tracing/spans/spanBuffer.js +158 -0
  77. package/build/cjs/tracing/spans/spanBuffer.js.map +1 -0
  78. package/build/cjs/tracing/trace.js +83 -13
  79. package/build/cjs/tracing/trace.js.map +1 -1
  80. package/build/cjs/tracing/vercel-ai/utils.js +1 -4
  81. package/build/cjs/tracing/vercel-ai/utils.js.map +1 -1
  82. package/build/cjs/utils/featureFlags.js +6 -0
  83. package/build/cjs/utils/featureFlags.js.map +1 -1
  84. package/build/cjs/utils/object.js +33 -0
  85. package/build/cjs/utils/object.js.map +1 -1
  86. package/build/cjs/utils/spanUtils.js +116 -13
  87. package/build/cjs/utils/spanUtils.js.map +1 -1
  88. package/build/cjs/utils/stacktrace.js +3 -1
  89. package/build/cjs/utils/stacktrace.js.map +1 -1
  90. package/build/cjs/utils/string.js +3 -0
  91. package/build/cjs/utils/string.js.map +1 -1
  92. package/build/cjs/utils/version.js +1 -1
  93. package/build/esm/attributes.js +43 -1
  94. package/build/esm/attributes.js.map +1 -1
  95. package/build/esm/client.js +8 -1
  96. package/build/esm/client.js.map +1 -1
  97. package/build/esm/envelope.js +2 -1
  98. package/build/esm/envelope.js.map +1 -1
  99. package/build/esm/index.js +10 -2
  100. package/build/esm/index.js.map +1 -1
  101. package/build/esm/integration.js +6 -0
  102. package/build/esm/integration.js.map +1 -1
  103. package/build/esm/integrations/express/index.js +202 -0
  104. package/build/esm/integrations/express/index.js.map +1 -0
  105. package/build/esm/integrations/express/patch-layer.js +249 -0
  106. package/build/esm/integrations/express/patch-layer.js.map +1 -0
  107. package/build/esm/integrations/express/request-layer-store.js +22 -0
  108. package/build/esm/integrations/express/request-layer-store.js.map +1 -0
  109. package/build/esm/integrations/express/set-sdk-processing-metadata.js +15 -0
  110. package/build/esm/integrations/express/set-sdk-processing-metadata.js.map +1 -0
  111. package/build/esm/integrations/express/types.js +10 -0
  112. package/build/esm/integrations/express/types.js.map +1 -0
  113. package/build/esm/integrations/express/utils.js +225 -0
  114. package/build/esm/integrations/express/utils.js.map +1 -0
  115. package/build/esm/integrations/mcp-server/correlation.js +5 -1
  116. package/build/esm/integrations/mcp-server/correlation.js.map +1 -1
  117. package/build/esm/integrations/mcp-server/handlers.js +18 -10
  118. package/build/esm/integrations/mcp-server/handlers.js.map +1 -1
  119. package/build/esm/integrations/mcp-server/index.js +2 -1
  120. package/build/esm/integrations/mcp-server/index.js.map +1 -1
  121. package/build/esm/integrations/mcp-server/transport.js +1 -1
  122. package/build/esm/integrations/mcp-server/transport.js.map +1 -1
  123. package/build/esm/integrations/mcp-server/validation.js +7 -5
  124. package/build/esm/integrations/mcp-server/validation.js.map +1 -1
  125. package/build/esm/integrations/spanStreaming.js +46 -0
  126. package/build/esm/integrations/spanStreaming.js.map +1 -0
  127. package/build/esm/package.json +1 -1
  128. package/build/esm/semanticAttributes.js +26 -4
  129. package/build/esm/semanticAttributes.js.map +1 -1
  130. package/build/esm/tracing/ai/gen-ai-attributes.js +8 -56
  131. package/build/esm/tracing/ai/gen-ai-attributes.js.map +1 -1
  132. package/build/esm/tracing/ai/utils.js +51 -2
  133. package/build/esm/tracing/ai/utils.js.map +1 -1
  134. package/build/esm/tracing/anthropic-ai/index.js +2 -13
  135. package/build/esm/tracing/anthropic-ai/index.js.map +1 -1
  136. package/build/esm/tracing/anthropic-ai/streaming.js +3 -101
  137. package/build/esm/tracing/anthropic-ai/streaming.js.map +1 -1
  138. package/build/esm/tracing/dynamicSamplingContext.js +2 -1
  139. package/build/esm/tracing/dynamicSamplingContext.js.map +1 -1
  140. package/build/esm/tracing/google-genai/constants.js +2 -5
  141. package/build/esm/tracing/google-genai/constants.js.map +1 -1
  142. package/build/esm/tracing/google-genai/index.js +25 -31
  143. package/build/esm/tracing/google-genai/index.js.map +1 -1
  144. package/build/esm/tracing/google-genai/streaming.js +2 -23
  145. package/build/esm/tracing/google-genai/streaming.js.map +1 -1
  146. package/build/esm/tracing/langchain/embeddings.js +129 -0
  147. package/build/esm/tracing/langchain/embeddings.js.map +1 -0
  148. package/build/esm/tracing/langchain/index.js.map +1 -1
  149. package/build/esm/tracing/openai/index.js +3 -30
  150. package/build/esm/tracing/openai/index.js.map +1 -1
  151. package/build/esm/tracing/openai/streaming.js +4 -35
  152. package/build/esm/tracing/openai/streaming.js.map +1 -1
  153. package/build/esm/tracing/openai/utils.js +79 -196
  154. package/build/esm/tracing/openai/utils.js.map +1 -1
  155. package/build/esm/tracing/sentryNonRecordingSpan.js +7 -0
  156. package/build/esm/tracing/sentryNonRecordingSpan.js.map +1 -1
  157. package/build/esm/tracing/sentrySpan.js +40 -1
  158. package/build/esm/tracing/sentrySpan.js.map +1 -1
  159. package/build/esm/tracing/spans/beforeSendSpan.js +40 -0
  160. package/build/esm/tracing/spans/beforeSendSpan.js.map +1 -0
  161. package/build/esm/tracing/spans/captureSpan.js +122 -0
  162. package/build/esm/tracing/spans/captureSpan.js.map +1 -0
  163. package/build/esm/tracing/spans/envelope.js +36 -0
  164. package/build/esm/tracing/spans/envelope.js.map +1 -0
  165. package/build/esm/tracing/spans/estimateSize.js +39 -0
  166. package/build/esm/tracing/spans/estimateSize.js.map +1 -0
  167. package/build/esm/tracing/spans/hasSpanStreamingEnabled.js +9 -0
  168. package/build/esm/tracing/spans/hasSpanStreamingEnabled.js.map +1 -0
  169. package/build/esm/tracing/spans/spanBuffer.js +156 -0
  170. package/build/esm/tracing/spans/spanBuffer.js.map +1 -0
  171. package/build/esm/tracing/trace.js +84 -14
  172. package/build/esm/tracing/trace.js.map +1 -1
  173. package/build/esm/tracing/vercel-ai/utils.js +2 -5
  174. package/build/esm/tracing/vercel-ai/utils.js.map +1 -1
  175. package/build/esm/utils/featureFlags.js +6 -0
  176. package/build/esm/utils/featureFlags.js.map +1 -1
  177. package/build/esm/utils/object.js +33 -1
  178. package/build/esm/utils/object.js.map +1 -1
  179. package/build/esm/utils/spanUtils.js +112 -14
  180. package/build/esm/utils/spanUtils.js.map +1 -1
  181. package/build/esm/utils/stacktrace.js +3 -1
  182. package/build/esm/utils/stacktrace.js.map +1 -1
  183. package/build/esm/utils/string.js +3 -0
  184. package/build/esm/utils/string.js.map +1 -1
  185. package/build/esm/utils/version.js +1 -1
  186. package/build/types/attributes.d.ts +5 -0
  187. package/build/types/attributes.d.ts.map +1 -1
  188. package/build/types/client.d.ts +35 -1
  189. package/build/types/client.d.ts.map +1 -1
  190. package/build/types/envelope.d.ts.map +1 -1
  191. package/build/types/index.d.ts +12 -4
  192. package/build/types/index.d.ts.map +1 -1
  193. package/build/types/integration.d.ts.map +1 -1
  194. package/build/types/integrations/express/index.d.ts +75 -0
  195. package/build/types/integrations/express/index.d.ts.map +1 -0
  196. package/build/types/integrations/express/patch-layer.d.ts +32 -0
  197. package/build/types/integrations/express/patch-layer.d.ts.map +1 -0
  198. package/build/types/integrations/express/request-layer-store.d.ts +32 -0
  199. package/build/types/integrations/express/request-layer-store.d.ts.map +1 -0
  200. package/build/types/integrations/express/set-sdk-processing-metadata.d.ts +35 -0
  201. package/build/types/integrations/express/set-sdk-processing-metadata.d.ts.map +1 -0
  202. package/build/types/integrations/express/types.d.ts +154 -0
  203. package/build/types/integrations/express/types.d.ts.map +1 -0
  204. package/build/types/integrations/express/utils.d.ts +93 -0
  205. package/build/types/integrations/express/utils.d.ts.map +1 -0
  206. package/build/types/integrations/mcp-server/correlation.d.ts +2 -1
  207. package/build/types/integrations/mcp-server/correlation.d.ts.map +1 -1
  208. package/build/types/integrations/mcp-server/handlers.d.ts +9 -4
  209. package/build/types/integrations/mcp-server/handlers.d.ts.map +1 -1
  210. package/build/types/integrations/mcp-server/index.d.ts +2 -1
  211. package/build/types/integrations/mcp-server/index.d.ts.map +1 -1
  212. package/build/types/integrations/mcp-server/types.d.ts +40 -7
  213. package/build/types/integrations/mcp-server/types.d.ts.map +1 -1
  214. package/build/types/integrations/mcp-server/validation.d.ts +4 -1
  215. package/build/types/integrations/mcp-server/validation.d.ts.map +1 -1
  216. package/build/types/integrations/spanStreaming.d.ts +2 -0
  217. package/build/types/integrations/spanStreaming.d.ts.map +1 -0
  218. package/build/types/semanticAttributes.d.ts +23 -3
  219. package/build/types/semanticAttributes.d.ts.map +1 -1
  220. package/build/types/tracing/ai/gen-ai-attributes.d.ts +6 -38
  221. package/build/types/tracing/ai/gen-ai-attributes.d.ts.map +1 -1
  222. package/build/types/tracing/ai/utils.d.ts +21 -2
  223. package/build/types/tracing/ai/utils.d.ts.map +1 -1
  224. package/build/types/tracing/anthropic-ai/index.d.ts.map +1 -1
  225. package/build/types/tracing/anthropic-ai/streaming.d.ts.map +1 -1
  226. package/build/types/tracing/dynamicSamplingContext.d.ts.map +1 -1
  227. package/build/types/tracing/google-genai/constants.d.ts +1 -3
  228. package/build/types/tracing/google-genai/constants.d.ts.map +1 -1
  229. package/build/types/tracing/google-genai/index.d.ts.map +1 -1
  230. package/build/types/tracing/google-genai/streaming.d.ts.map +1 -1
  231. package/build/types/tracing/index.d.ts +1 -0
  232. package/build/types/tracing/index.d.ts.map +1 -1
  233. package/build/types/tracing/langchain/embeddings.d.ts +27 -0
  234. package/build/types/tracing/langchain/embeddings.d.ts.map +1 -0
  235. package/build/types/tracing/langchain/index.d.ts +1 -0
  236. package/build/types/tracing/langchain/index.d.ts.map +1 -1
  237. package/build/types/tracing/openai/index.d.ts.map +1 -1
  238. package/build/types/tracing/openai/streaming.d.ts.map +1 -1
  239. package/build/types/tracing/openai/utils.d.ts +4 -49
  240. package/build/types/tracing/openai/utils.d.ts.map +1 -1
  241. package/build/types/tracing/sentryNonRecordingSpan.d.ts +12 -1
  242. package/build/types/tracing/sentryNonRecordingSpan.d.ts.map +1 -1
  243. package/build/types/tracing/sentrySpan.d.ts +10 -1
  244. package/build/types/tracing/sentrySpan.d.ts.map +1 -1
  245. package/build/types/tracing/spans/beforeSendSpan.d.ts +35 -0
  246. package/build/types/tracing/spans/beforeSendSpan.d.ts.map +1 -0
  247. package/build/types/tracing/spans/captureSpan.d.ts +26 -0
  248. package/build/types/tracing/spans/captureSpan.d.ts.map +1 -0
  249. package/build/types/tracing/spans/envelope.d.ts +8 -0
  250. package/build/types/tracing/spans/envelope.d.ts.map +1 -0
  251. package/build/types/tracing/spans/estimateSize.d.ts +12 -0
  252. package/build/types/tracing/spans/estimateSize.d.ts.map +1 -0
  253. package/build/types/tracing/spans/hasSpanStreamingEnabled.d.ts +6 -0
  254. package/build/types/tracing/spans/hasSpanStreamingEnabled.d.ts.map +1 -0
  255. package/build/types/tracing/spans/spanBuffer.d.ts +60 -0
  256. package/build/types/tracing/spans/spanBuffer.d.ts.map +1 -0
  257. package/build/types/tracing/trace.d.ts.map +1 -1
  258. package/build/types/tracing/vercel-ai/utils.d.ts.map +1 -1
  259. package/build/types/types-hoist/envelope.d.ts +22 -2
  260. package/build/types/types-hoist/envelope.d.ts.map +1 -1
  261. package/build/types/types-hoist/integration.d.ts +8 -0
  262. package/build/types/types-hoist/integration.d.ts.map +1 -1
  263. package/build/types/types-hoist/link.d.ts +2 -2
  264. package/build/types/types-hoist/link.d.ts.map +1 -1
  265. package/build/types/types-hoist/options.d.ts +26 -2
  266. package/build/types/types-hoist/options.d.ts.map +1 -1
  267. package/build/types/types-hoist/span.d.ts +35 -0
  268. package/build/types/types-hoist/span.d.ts.map +1 -1
  269. package/build/types/utils/featureFlags.d.ts.map +1 -1
  270. package/build/types/utils/object.d.ts +10 -0
  271. package/build/types/utils/object.d.ts.map +1 -1
  272. package/build/types/utils/spanUtils.d.ts +27 -2
  273. package/build/types/utils/spanUtils.d.ts.map +1 -1
  274. package/build/types/utils/stacktrace.d.ts.map +1 -1
  275. package/build/types/utils/string.d.ts +2 -2
  276. package/build/types/utils/string.d.ts.map +1 -1
  277. package/build/types-ts3.8/attributes.d.ts +5 -0
  278. package/build/types-ts3.8/client.d.ts +35 -1
  279. package/build/types-ts3.8/index.d.ts +12 -4
  280. package/build/types-ts3.8/integrations/express/index.d.ts +75 -0
  281. package/build/types-ts3.8/integrations/express/patch-layer.d.ts +32 -0
  282. package/build/types-ts3.8/integrations/express/request-layer-store.d.ts +32 -0
  283. package/build/types-ts3.8/integrations/express/set-sdk-processing-metadata.d.ts +35 -0
  284. package/build/types-ts3.8/integrations/express/types.d.ts +154 -0
  285. package/build/types-ts3.8/integrations/express/utils.d.ts +96 -0
  286. package/build/types-ts3.8/integrations/mcp-server/correlation.d.ts +2 -1
  287. package/build/types-ts3.8/integrations/mcp-server/handlers.d.ts +9 -4
  288. package/build/types-ts3.8/integrations/mcp-server/index.d.ts +2 -1
  289. package/build/types-ts3.8/integrations/mcp-server/types.d.ts +40 -7
  290. package/build/types-ts3.8/integrations/mcp-server/validation.d.ts +4 -1
  291. package/build/types-ts3.8/integrations/spanStreaming.d.ts +2 -0
  292. package/build/types-ts3.8/semanticAttributes.d.ts +23 -3
  293. package/build/types-ts3.8/tracing/ai/gen-ai-attributes.d.ts +6 -38
  294. package/build/types-ts3.8/tracing/ai/utils.d.ts +21 -2
  295. package/build/types-ts3.8/tracing/google-genai/constants.d.ts +1 -3
  296. package/build/types-ts3.8/tracing/index.d.ts +1 -0
  297. package/build/types-ts3.8/tracing/langchain/embeddings.d.ts +27 -0
  298. package/build/types-ts3.8/tracing/langchain/index.d.ts +1 -0
  299. package/build/types-ts3.8/tracing/openai/utils.d.ts +4 -49
  300. package/build/types-ts3.8/tracing/sentryNonRecordingSpan.d.ts +12 -1
  301. package/build/types-ts3.8/tracing/sentrySpan.d.ts +10 -1
  302. package/build/types-ts3.8/tracing/spans/beforeSendSpan.d.ts +35 -0
  303. package/build/types-ts3.8/tracing/spans/captureSpan.d.ts +26 -0
  304. package/build/types-ts3.8/tracing/spans/envelope.d.ts +8 -0
  305. package/build/types-ts3.8/tracing/spans/estimateSize.d.ts +12 -0
  306. package/build/types-ts3.8/tracing/spans/hasSpanStreamingEnabled.d.ts +6 -0
  307. package/build/types-ts3.8/tracing/spans/spanBuffer.d.ts +60 -0
  308. package/build/types-ts3.8/types-hoist/envelope.d.ts +22 -2
  309. package/build/types-ts3.8/types-hoist/integration.d.ts +8 -0
  310. package/build/types-ts3.8/types-hoist/link.d.ts +2 -2
  311. package/build/types-ts3.8/types-hoist/options.d.ts +26 -2
  312. package/build/types-ts3.8/types-hoist/span.d.ts +35 -0
  313. package/build/types-ts3.8/utils/object.d.ts +10 -0
  314. package/build/types-ts3.8/utils/spanUtils.d.ts +27 -2
  315. package/build/types-ts3.8/utils/string.d.ts +2 -2
  316. package/package.json +1 -1
@@ -0,0 +1,251 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const debugBuild = require('../../debug-build.js');
4
+ const semanticAttributes = require('../../semanticAttributes.js');
5
+ const debugLogger = require('../../utils/debug-logger.js');
6
+ const spanUtils = require('../../utils/spanUtils.js');
7
+ const spanstatus = require('../../tracing/spanstatus.js');
8
+ const object = require('../../utils/object.js');
9
+ const currentScopes = require('../../currentScopes.js');
10
+ const trace = require('../../tracing/trace.js');
11
+ const requestLayerStore = require('./request-layer-store.js');
12
+ const types = require('./types.js');
13
+ const utils = require('./utils.js');
14
+ const defaultScopes = require('../../defaultScopes.js');
15
+ const setSdkProcessingMetadata = require('./set-sdk-processing-metadata.js');
16
+
17
+ /**
18
+ * Platform-portable Express tracing integration.
19
+ *
20
+ * @module
21
+ *
22
+ * This Sentry integration is a derivative work based on the OpenTelemetry
23
+ * Express instrumentation.
24
+ *
25
+ * <https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-express>
26
+ *
27
+ * Extended under the terms of the Apache 2.0 license linked below:
28
+ *
29
+ * ----
30
+ *
31
+ * Copyright The OpenTelemetry Authors
32
+ *
33
+ * Licensed under the Apache License, Version 2.0 (the "License");
34
+ * you may not use this file except in compliance with the License.
35
+ * You may obtain a copy of the License at
36
+ *
37
+ * https://www.apache.org/licenses/LICENSE-2.0
38
+ *
39
+ * Unless required by applicable law or agreed to in writing, software
40
+ * distributed under the License is distributed on an "AS IS" BASIS,
41
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
42
+ * See the License for the specific language governing permissions and
43
+ * limitations under the License.
44
+ */
45
+
46
+
47
+ function patchLayer(options, maybeLayer, layerPath) {
48
+ if (!maybeLayer?.handle) {
49
+ return;
50
+ }
51
+ const layer = maybeLayer;
52
+
53
+ const layerHandleOriginal = layer.handle;
54
+
55
+ // avoid patching multiple times the same layer
56
+ if (object.getOriginalFunction(layerHandleOriginal)) {
57
+ return;
58
+ }
59
+
60
+ if (layerHandleOriginal.length === 4) {
61
+ // todo: instrument error handlers
62
+ return;
63
+ }
64
+
65
+ function layerHandlePatched(
66
+
67
+ req,
68
+ res,
69
+ //oxlint-disable-next-line no-explicit-any
70
+ ...otherArgs
71
+ ) {
72
+ // Set normalizedRequest here because expressRequestHandler middleware
73
+ // (registered via setupExpressErrorHandler) is added after routes and
74
+ // therefore never runs for successful requests — route handlers typically
75
+ // send a response without calling next(). It would be safe to set this
76
+ // multiple times, since the data is identical, but more performant not to.
77
+ setSdkProcessingMetadata.setSDKProcessingMetadata(req);
78
+
79
+ // Only create spans when there's an active parent span
80
+ // Without a parent span, this request is being ignored, so skip it
81
+ const parentSpan = spanUtils.getActiveSpan();
82
+ if (!parentSpan) {
83
+ return layerHandleOriginal.apply(this, [req, res, ...otherArgs]);
84
+ }
85
+
86
+ if (layerPath) {
87
+ requestLayerStore.storeLayer(req, layerPath);
88
+ }
89
+ const storedLayers = requestLayerStore.getStoredLayers(req);
90
+ const isLayerPathStored = !!layerPath;
91
+
92
+ const constructedRoute = utils.getConstructedRoute(req);
93
+ const actualMatchedRoute = utils.getActualMatchedRoute(req, constructedRoute);
94
+
95
+ options.onRouteResolved?.(actualMatchedRoute);
96
+
97
+ const metadata = utils.getLayerMetadata(constructedRoute, layer, layerPath);
98
+ const name = metadata.attributes[types.ATTR_EXPRESS_NAME];
99
+ const type = metadata.attributes[types.ATTR_EXPRESS_TYPE];
100
+ const attributes = Object.assign(metadata.attributes, {
101
+ [semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.express',
102
+ [semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_OP]: `${type}.express`,
103
+ });
104
+ if (actualMatchedRoute) {
105
+ attributes[types.ATTR_HTTP_ROUTE] = actualMatchedRoute;
106
+ }
107
+
108
+ // verify against the config if the layer should be ignored
109
+ if (utils.isLayerIgnored(metadata.attributes[types.ATTR_EXPRESS_NAME], type, options)) {
110
+ // XXX: the isLayerPathStored guard here is *not* present in the
111
+ // original @opentelemetry/instrumentation-express impl, but was
112
+ // suggested by the Sentry code review bot. It appears to correctly
113
+ // prevent improper layer calculation in the case where there's a
114
+ // middleware without a layerPath argument. It's unclear whether
115
+ // that's possible, or if any existing code depends on that "bug".
116
+ if (isLayerPathStored) {
117
+ storedLayers.pop();
118
+ }
119
+ return layerHandleOriginal.apply(this, [req, res, ...otherArgs]);
120
+ }
121
+
122
+ const currentScope = currentScopes.getIsolationScope();
123
+ if (currentScope !== defaultScopes.getDefaultIsolationScope()) {
124
+ if (type === 'request_handler') {
125
+ // type cast b/c Otel unfortunately types info.request as any :(
126
+ const method = req.method ? req.method.toUpperCase() : 'GET';
127
+ currentScope.setTransactionName(`${method} ${constructedRoute}`);
128
+ }
129
+ } else {
130
+ debugBuild.DEBUG_BUILD && debugLogger.debug.warn('Isolation scope is still default isolation scope - skipping setting transactionName');
131
+ }
132
+
133
+ return trace.startSpanManual({ name, attributes }, span => {
134
+ let spanHasEnded = false;
135
+ // TODO: Fix router spans (getRouterPath does not work properly) to
136
+ // have useful names before removing this branch
137
+ if (metadata.attributes[types.ATTR_EXPRESS_TYPE] === types.ExpressLayerType_ROUTER) {
138
+ span.end();
139
+ spanHasEnded = true;
140
+ }
141
+ // listener for response.on('finish')
142
+ const onResponseFinish = () => {
143
+ if (!spanHasEnded) {
144
+ spanHasEnded = true;
145
+ span.end();
146
+ }
147
+ };
148
+
149
+ // verify we have a callback
150
+ for (let i = 0; i < otherArgs.length; i++) {
151
+ const callback = otherArgs[i] ;
152
+ if (typeof callback !== 'function') {
153
+ continue;
154
+ }
155
+
156
+ //oxlint-disable-next-line no-explicit-any
157
+ otherArgs[i] = function (...args) {
158
+ // express considers anything but an empty value, "route" or "router"
159
+ // passed to its callback to be an error
160
+ const maybeError = args[0];
161
+ const isError = !!maybeError && maybeError !== 'route' && maybeError !== 'router';
162
+ if (!spanHasEnded && isError) {
163
+ const [_, message] = utils.asErrorAndMessage(maybeError);
164
+ // intentionally do not record the exception here, because
165
+ // the error handler we assign does that, provided the user
166
+ // correctly calls setupExpressErrorHandler.
167
+ // TODO: A future enhancement can automatically attach
168
+ // the error handler if we detect that it has not been added.
169
+ span.setStatus({
170
+ code: spanstatus.SPAN_STATUS_ERROR,
171
+ message,
172
+ });
173
+ }
174
+
175
+ if (!spanHasEnded) {
176
+ spanHasEnded = true;
177
+ res.removeListener('finish', onResponseFinish);
178
+ span.end();
179
+ }
180
+ if (!(req.route && isError) && isLayerPathStored) {
181
+ storedLayers.pop();
182
+ }
183
+ // execute the callback back in the parent's scope, so that
184
+ // we bubble up each level as next() is called.
185
+ return trace.withActiveSpan(parentSpan, () => callback.apply(this, args));
186
+ };
187
+ break;
188
+ }
189
+
190
+ try {
191
+ return layerHandleOriginal.apply(this, [req, res, ...otherArgs]);
192
+ } catch (anyError) {
193
+ const [_, message] = utils.asErrorAndMessage(anyError);
194
+ // intentionally do not record the exception here, because
195
+ // the error handler we assign does that, provided the user
196
+ // correctly calls setupExpressErrorHandler.
197
+ // TODO: A future enhancement can automatically attach
198
+ // the error handler if we detect that it has not been added.
199
+ span.setStatus({
200
+ code: spanstatus.SPAN_STATUS_ERROR,
201
+ message,
202
+ });
203
+ throw anyError;
204
+ /* v8 ignore next - it sees the block end at the throw */
205
+ } finally {
206
+ // At this point if the callback wasn't called, that means
207
+ // either the layer is asynchronous (so it will call the
208
+ // callback later on) or that the layer directly ends the
209
+ // http response, so we'll hook into the "finish" event to
210
+ // handle the later case.
211
+ if (!spanHasEnded) {
212
+ res.once('finish', onResponseFinish);
213
+ }
214
+ }
215
+ });
216
+ }
217
+
218
+ // `handle` isn't just a regular function in some cases. It also contains
219
+ // some properties holding metadata and state so we need to proxy them
220
+ // through through patched function. Use a for-in to also pick up properties
221
+ // that other libraries might add to the prototype before we instrument.
222
+ // ref: https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1950
223
+ // ref: https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2271
224
+ // oxlint-disable-next-line guard-for-in
225
+ for (const key in layerHandleOriginal ) {
226
+ // skip standard function prototype fields that both have
227
+ if (key in layerHandlePatched) {
228
+ continue;
229
+ }
230
+ Object.defineProperty(layerHandlePatched, key, {
231
+ get() {
232
+ return layerHandleOriginal[key];
233
+ },
234
+ set(value) {
235
+ layerHandleOriginal[key] = value;
236
+ },
237
+ });
238
+ }
239
+
240
+ object.markFunctionWrapped(layerHandlePatched, layerHandleOriginal);
241
+
242
+ Object.defineProperty(layer, 'handle', {
243
+ enumerable: true,
244
+ configurable: true,
245
+ writable: true,
246
+ value: layerHandlePatched,
247
+ });
248
+ }
249
+
250
+ exports.patchLayer = patchLayer;
251
+ //# sourceMappingURL=patch-layer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patch-layer.js","sources":["../../../../src/integrations/express/patch-layer.ts"],"sourcesContent":["/**\n * Platform-portable Express tracing integration.\n *\n * @module\n *\n * This Sentry integration is a derivative work based on the OpenTelemetry\n * Express instrumentation.\n *\n * <https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-express>\n *\n * Extended under the terms of the Apache 2.0 license linked below:\n *\n * ----\n *\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';\nimport { SPAN_STATUS_ERROR, startSpanManual, withActiveSpan } from '../../tracing';\nimport { debug } from '../../utils/debug-logger';\nimport type { SpanAttributes } from '../../types-hoist/span';\nimport { getActiveSpan } from '../../utils/spanUtils';\nimport { getStoredLayers, storeLayer } from './request-layer-store';\nimport {\n type ExpressRequest,\n type ExpressResponse,\n type ExpressIntegrationOptions,\n type ExpressLayer,\n ATTR_HTTP_ROUTE,\n ATTR_EXPRESS_TYPE,\n ATTR_EXPRESS_NAME,\n ExpressLayerType_ROUTER,\n} from './types';\nimport {\n asErrorAndMessage,\n getActualMatchedRoute,\n getConstructedRoute,\n getLayerMetadata,\n isLayerIgnored,\n} from './utils';\nimport { getIsolationScope } from '../../currentScopes';\nimport { getDefaultIsolationScope } from '../../defaultScopes';\nimport { getOriginalFunction, markFunctionWrapped } from '../../utils/object';\nimport { setSDKProcessingMetadata } from './set-sdk-processing-metadata';\n\nexport type ExpressPatchLayerOptions = Pick<\n ExpressIntegrationOptions,\n 'onRouteResolved' | 'ignoreLayers' | 'ignoreLayersType'\n>;\n\nexport function patchLayer(options: ExpressPatchLayerOptions, maybeLayer?: ExpressLayer, layerPath?: string): void {\n if (!maybeLayer?.handle) {\n return;\n }\n const layer = maybeLayer;\n\n const layerHandleOriginal = layer.handle;\n\n // avoid patching multiple times the same layer\n if (getOriginalFunction(layerHandleOriginal)) {\n return;\n }\n\n if (layerHandleOriginal.length === 4) {\n // todo: instrument error handlers\n return;\n }\n\n function layerHandlePatched(\n this: ExpressLayer,\n req: ExpressRequest,\n res: ExpressResponse,\n //oxlint-disable-next-line no-explicit-any\n ...otherArgs: any[]\n ) {\n // Set normalizedRequest here because expressRequestHandler middleware\n // (registered via setupExpressErrorHandler) is added after routes and\n // therefore never runs for successful requests — route handlers typically\n // send a response without calling next(). It would be safe to set this\n // multiple times, since the data is identical, but more performant not to.\n setSDKProcessingMetadata(req);\n\n // Only create spans when there's an active parent span\n // Without a parent span, this request is being ignored, so skip it\n const parentSpan = getActiveSpan();\n if (!parentSpan) {\n return layerHandleOriginal.apply(this, [req, res, ...otherArgs]);\n }\n\n if (layerPath) {\n storeLayer(req, layerPath);\n }\n const storedLayers = getStoredLayers(req);\n const isLayerPathStored = !!layerPath;\n\n const constructedRoute = getConstructedRoute(req);\n const actualMatchedRoute = getActualMatchedRoute(req, constructedRoute);\n\n options.onRouteResolved?.(actualMatchedRoute);\n\n const metadata = getLayerMetadata(constructedRoute, layer, layerPath);\n const name = metadata.attributes[ATTR_EXPRESS_NAME];\n const type = metadata.attributes[ATTR_EXPRESS_TYPE];\n const attributes: SpanAttributes = Object.assign(metadata.attributes, {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.express',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: `${type}.express`,\n });\n if (actualMatchedRoute) {\n attributes[ATTR_HTTP_ROUTE] = actualMatchedRoute;\n }\n\n // verify against the config if the layer should be ignored\n if (isLayerIgnored(metadata.attributes[ATTR_EXPRESS_NAME], type, options)) {\n // XXX: the isLayerPathStored guard here is *not* present in the\n // original @opentelemetry/instrumentation-express impl, but was\n // suggested by the Sentry code review bot. It appears to correctly\n // prevent improper layer calculation in the case where there's a\n // middleware without a layerPath argument. It's unclear whether\n // that's possible, or if any existing code depends on that \"bug\".\n if (isLayerPathStored) {\n storedLayers.pop();\n }\n return layerHandleOriginal.apply(this, [req, res, ...otherArgs]);\n }\n\n const currentScope = getIsolationScope();\n if (currentScope !== getDefaultIsolationScope()) {\n if (type === 'request_handler') {\n // type cast b/c Otel unfortunately types info.request as any :(\n const method = req.method ? req.method.toUpperCase() : 'GET';\n currentScope.setTransactionName(`${method} ${constructedRoute}`);\n }\n } else {\n DEBUG_BUILD && debug.warn('Isolation scope is still default isolation scope - skipping setting transactionName');\n }\n\n return startSpanManual({ name, attributes }, span => {\n let spanHasEnded = false;\n // TODO: Fix router spans (getRouterPath does not work properly) to\n // have useful names before removing this branch\n if (metadata.attributes[ATTR_EXPRESS_TYPE] === ExpressLayerType_ROUTER) {\n span.end();\n spanHasEnded = true;\n }\n // listener for response.on('finish')\n const onResponseFinish = () => {\n if (!spanHasEnded) {\n spanHasEnded = true;\n span.end();\n }\n };\n\n // verify we have a callback\n for (let i = 0; i < otherArgs.length; i++) {\n const callback = otherArgs[i] as Function;\n if (typeof callback !== 'function') {\n continue;\n }\n\n //oxlint-disable-next-line no-explicit-any\n otherArgs[i] = function (...args: any[]) {\n // express considers anything but an empty value, \"route\" or \"router\"\n // passed to its callback to be an error\n const maybeError = args[0];\n const isError = !!maybeError && maybeError !== 'route' && maybeError !== 'router';\n if (!spanHasEnded && isError) {\n const [_, message] = asErrorAndMessage(maybeError);\n // intentionally do not record the exception here, because\n // the error handler we assign does that, provided the user\n // correctly calls setupExpressErrorHandler.\n // TODO: A future enhancement can automatically attach\n // the error handler if we detect that it has not been added.\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n message,\n });\n }\n\n if (!spanHasEnded) {\n spanHasEnded = true;\n res.removeListener('finish', onResponseFinish);\n span.end();\n }\n if (!(req.route && isError) && isLayerPathStored) {\n storedLayers.pop();\n }\n // execute the callback back in the parent's scope, so that\n // we bubble up each level as next() is called.\n return withActiveSpan(parentSpan, () => callback.apply(this, args));\n };\n break;\n }\n\n try {\n return layerHandleOriginal.apply(this, [req, res, ...otherArgs]);\n } catch (anyError) {\n const [_, message] = asErrorAndMessage(anyError);\n // intentionally do not record the exception here, because\n // the error handler we assign does that, provided the user\n // correctly calls setupExpressErrorHandler.\n // TODO: A future enhancement can automatically attach\n // the error handler if we detect that it has not been added.\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n message,\n });\n throw anyError;\n /* v8 ignore next - it sees the block end at the throw */\n } finally {\n // At this point if the callback wasn't called, that means\n // either the layer is asynchronous (so it will call the\n // callback later on) or that the layer directly ends the\n // http response, so we'll hook into the \"finish\" event to\n // handle the later case.\n if (!spanHasEnded) {\n res.once('finish', onResponseFinish);\n }\n }\n });\n }\n\n // `handle` isn't just a regular function in some cases. It also contains\n // some properties holding metadata and state so we need to proxy them\n // through through patched function. Use a for-in to also pick up properties\n // that other libraries might add to the prototype before we instrument.\n // ref: https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1950\n // ref: https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2271\n // oxlint-disable-next-line guard-for-in\n for (const key in layerHandleOriginal as Function & Record<string, unknown>) {\n // skip standard function prototype fields that both have\n if (key in layerHandlePatched) {\n continue;\n }\n Object.defineProperty(layerHandlePatched, key, {\n get() {\n return layerHandleOriginal[key];\n },\n set(value) {\n layerHandleOriginal[key] = value;\n },\n });\n }\n\n markFunctionWrapped(layerHandlePatched, layerHandleOriginal);\n\n Object.defineProperty(layer, 'handle', {\n enumerable: true,\n configurable: true,\n writable: true,\n value: layerHandlePatched,\n });\n}\n"],"names":["getOriginalFunction","setSDKProcessingMetadata","getActiveSpan","storeLayer","getStoredLayers","getConstructedRoute","getActualMatchedRoute","getLayerMetadata","ATTR_EXPRESS_NAME","ATTR_EXPRESS_TYPE","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_OP","ATTR_HTTP_ROUTE","isLayerIgnored","getIsolationScope","getDefaultIsolationScope","DEBUG_BUILD","debug","startSpanManual","ExpressLayerType_ROUTER","asErrorAndMessage","SPAN_STATUS_ERROR","withActiveSpan","markFunctionWrapped"],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ // map of patched request objects to stored layers
4
+ const requestLayerStore = new WeakMap();
5
+ const storeLayer = (req, layer) => {
6
+ const store = requestLayerStore.get(req);
7
+ if (!store) {
8
+ requestLayerStore.set(req, [layer]);
9
+ } else {
10
+ store.push(layer);
11
+ }
12
+ };
13
+
14
+ const getStoredLayers = (req) => {
15
+ let store = requestLayerStore.get(req);
16
+ if (!store) {
17
+ store = [];
18
+ requestLayerStore.set(req, store);
19
+ }
20
+ return store;
21
+ };
22
+
23
+ exports.getStoredLayers = getStoredLayers;
24
+ exports.storeLayer = storeLayer;
25
+ //# sourceMappingURL=request-layer-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-layer-store.js","sources":["../../../../src/integrations/express/request-layer-store.ts"],"sourcesContent":["/**\n * Platform-portable Express tracing integration.\n *\n * @module\n *\n * This Sentry integration is a derivative work based on the OpenTelemetry\n * Express instrumentation.\n *\n * <https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-express>\n *\n * Extended under the terms of the Apache 2.0 license linked below:\n *\n * ----\n *\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ExpressRequest } from './types';\n\n// map of patched request objects to stored layers\nconst requestLayerStore = new WeakMap<ExpressRequest, string[]>();\nexport const storeLayer = (req: ExpressRequest, layer: string) => {\n const store = requestLayerStore.get(req);\n if (!store) {\n requestLayerStore.set(req, [layer]);\n } else {\n store.push(layer);\n }\n};\n\nexport const getStoredLayers = (req: ExpressRequest) => {\n let store = requestLayerStore.get(req);\n if (!store) {\n store = [];\n requestLayerStore.set(req, store);\n }\n return store;\n};\n"],"names":[],"mappings":";;AA+BA;AACA,MAAM,iBAAA,GAAoB,IAAI,OAAO,EAA4B;AAC1D,MAAM,aAAa,CAAC,GAAG,EAAkB,KAAK,KAAa;AAClE,EAAE,MAAM,QAAQ,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC;AAC1C,EAAE,IAAI,CAAC,KAAK,EAAE;AACd,IAAI,iBAAiB,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;AACvC,EAAE,OAAO;AACT,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;AACrB,EAAE;AACF;;MAEa,eAAA,GAAkB,CAAC,GAAG,KAAqB;AACxD,EAAE,IAAI,QAAQ,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC;AACxC,EAAE,IAAI,CAAC,KAAK,EAAE;AACd,IAAI,KAAA,GAAQ,EAAE;AACd,IAAI,iBAAiB,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC;AACrC,EAAE;AACF,EAAE,OAAO,KAAK;AACd;;;;;"}
@@ -0,0 +1,17 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const currentScopes = require('../../currentScopes.js');
4
+ const request = require('../../utils/request.js');
5
+
6
+ // TODO: consider moving this into a core util, eg
7
+ // setSDKProcessingMetadataFromRequest(..), if other integrations need it.
8
+ function setSDKProcessingMetadata(request$1) {
9
+ const sdkProcMeta = currentScopes.getIsolationScope()?.getScopeData()?.sdkProcessingMetadata;
10
+ if (!sdkProcMeta?.normalizedRequest) {
11
+ const normalizedRequest = request.httpRequestToRequestData(request$1);
12
+ currentScopes.getIsolationScope().setSDKProcessingMetadata({ normalizedRequest });
13
+ }
14
+ }
15
+
16
+ exports.setSDKProcessingMetadata = setSDKProcessingMetadata;
17
+ //# sourceMappingURL=set-sdk-processing-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set-sdk-processing-metadata.js","sources":["../../../../src/integrations/express/set-sdk-processing-metadata.ts"],"sourcesContent":["/**\n * Platform-portable Express tracing integration.\n *\n * @module\n *\n * This Sentry integration is a derivative work based on the OpenTelemetry\n * Express instrumentation.\n *\n * <https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-express>\n *\n * Extended under the terms of the Apache 2.0 license linked below:\n *\n * ----\n *\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Abstract this out because we call it in multiple places, and it's cheaper to\n * only do one time for any given request.\n */\n\nimport type { ExpressRequest } from './types';\nimport { getIsolationScope } from '../../currentScopes';\nimport { httpRequestToRequestData } from '../../utils/request';\n\n// TODO: consider moving this into a core util, eg\n// setSDKProcessingMetadataFromRequest(..), if other integrations need it.\nexport function setSDKProcessingMetadata(request: ExpressRequest) {\n const sdkProcMeta = getIsolationScope()?.getScopeData()?.sdkProcessingMetadata;\n if (!sdkProcMeta?.normalizedRequest) {\n const normalizedRequest = httpRequestToRequestData(request);\n getIsolationScope().setSDKProcessingMetadata({ normalizedRequest });\n }\n}\n"],"names":["request","getIsolationScope","httpRequestToRequestData"],"mappings":";;;;;AAsCA;AACA;AACO,SAAS,wBAAwB,CAACA,SAAO,EAAkB;AAClE,EAAE,MAAM,WAAA,GAAcC,+BAAiB,EAAE,EAAE,YAAY,EAAE,EAAE,qBAAqB;AAChF,EAAE,IAAI,CAAC,WAAW,EAAE,iBAAiB,EAAE;AACvC,IAAI,MAAM,iBAAA,GAAoBC,gCAAwB,CAACF,SAAO,CAAC;AAC/D,IAAIC,+BAAiB,EAAE,CAAC,wBAAwB,CAAC,EAAE,iBAAA,EAAmB,CAAC;AACvE,EAAE;AACF;;;;"}
@@ -0,0 +1,17 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const ATTR_EXPRESS_NAME = 'express.name';
4
+ const ATTR_HTTP_ROUTE = 'http.route';
5
+ const ATTR_EXPRESS_TYPE = 'express.type';
6
+
7
+ const ExpressLayerType_ROUTER = 'router';
8
+ const ExpressLayerType_MIDDLEWARE = 'middleware';
9
+ const ExpressLayerType_REQUEST_HANDLER = 'request_handler';
10
+
11
+ exports.ATTR_EXPRESS_NAME = ATTR_EXPRESS_NAME;
12
+ exports.ATTR_EXPRESS_TYPE = ATTR_EXPRESS_TYPE;
13
+ exports.ATTR_HTTP_ROUTE = ATTR_HTTP_ROUTE;
14
+ exports.ExpressLayerType_MIDDLEWARE = ExpressLayerType_MIDDLEWARE;
15
+ exports.ExpressLayerType_REQUEST_HANDLER = ExpressLayerType_REQUEST_HANDLER;
16
+ exports.ExpressLayerType_ROUTER = ExpressLayerType_ROUTER;
17
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sources":["../../../../src/integrations/express/types.ts"],"sourcesContent":["/**\n * Platform-portable Express tracing integration.\n *\n * @module\n *\n * This Sentry integration is a derivative work based on the OpenTelemetry\n * Express instrumentation.\n *\n * <https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-express>\n *\n * Extended under the terms of the Apache 2.0 license linked below:\n *\n * ----\n *\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { RequestEventData } from '../../types-hoist/request';\nimport type { SpanAttributes } from '../../types-hoist/span';\n\nexport const ATTR_EXPRESS_NAME = 'express.name';\nexport const ATTR_HTTP_ROUTE = 'http.route';\nexport const ATTR_EXPRESS_TYPE = 'express.type';\n\nexport type ExpressExport = {\n Router: ExpressRouterv5 | ExpressRouterv4;\n application: ExpressApplication;\n};\n\nexport type ExpressExportv5 = ExpressExport & {\n Router: ExpressRouterv5;\n};\n\nexport type ExpressExportv4 = ExpressExport & {\n Router: ExpressRouterv4;\n};\n\nexport type ExpressModuleExport = ExpressExport | { default: ExpressExport };\n\nexport interface ExpressRequest extends RequestEventData {\n originalUrl: string;\n route: unknown;\n // Note: req.res is typed as optional (only present after middleware init).\n // mark optional to preserve compat with express v4 types.\n res?: ExpressResponse;\n}\n\n// just a minimum type def for what we need, since this also needs to\n// work in environments lacking node:http\nexport interface ExpressResponse {\n once(ev: string, listener: Function): this;\n removeListener(ev: string, listener?: Function): this;\n emit(ev: string, ...data: unknown[]): this;\n}\n\nexport interface NextFunction {\n (err?: unknown): void;\n /**\n * \"Break-out\" of a router by calling {next('router')};\n * @see {https://expressjs.com/en/guide/using-middleware.html#middleware.router}\n */\n (deferToNext: 'router'): void;\n /**\n * \"Break-out\" of a route by calling {next('route')};\n * @see {https://expressjs.com/en/guide/using-middleware.html#middleware.application}\n */\n (deferToNext: 'route'): void;\n}\n\n// Need to mark this as `any` so they don't conflict with the actual express\n//oxlint-disable-next-line no-explicit-any\nexport type ExpressApplicationRequestHandler = (...handlers: any[]) => any;\n\nexport type ExpressRequestInfo<T = unknown> = {\n /** An express request object */\n request: T;\n route: string;\n layerType: ExpressLayerType;\n};\n\nexport type ExpressLayerType = 'router' | 'middleware' | 'request_handler';\nexport const ExpressLayerType_ROUTER = 'router';\nexport const ExpressLayerType_MIDDLEWARE = 'middleware';\nexport const ExpressLayerType_REQUEST_HANDLER = 'request_handler';\n\nexport type PathParams = string | RegExp | Array<string | RegExp>;\nexport type LayerPathSegment = string | RegExp | number;\n\nexport interface ExpressRoute {\n path: string;\n stack: ExpressLayer[];\n}\n\nexport type ExpressRouterv4 = ExpressRouter;\n\nexport interface ExpressRouterv5 {\n prototype: ExpressRouter;\n}\n\n// https://github.com/expressjs/express/blob/main/lib/router/layer.js#L33\nexport type ExpressLayer = {\n handle: Function &\n Record<string, unknown> & {\n stack?: ExpressLayer[];\n };\n name: string;\n params: { [key: string]: string };\n path?: string;\n regexp: RegExp;\n route?: ExpressLayer;\n};\n\nexport type ExpressRouter = {\n params: { [key: string]: string };\n _params: string[];\n caseSensitive: boolean;\n mergeParams: boolean;\n strict: boolean;\n stack: ExpressLayer[];\n route(prefix: PathParams): ExpressRoute;\n use(...handlers: unknown[]): unknown;\n};\n\nexport type IgnoreMatcher = string | RegExp | ((name: string) => boolean);\n\nexport type ExpressIntegrationOptions = {\n express: ExpressModuleExport; //Express\n /** Ignore specific based on their name */\n ignoreLayers?: IgnoreMatcher[];\n /** Ignore specific layers based on their type */\n ignoreLayersType?: ExpressLayerType[];\n /**\n * Optional callback invoked each time a layer resolves the matched HTTP route.\n * Platform-specific integrations (e.g. Node.js) use this to propagate the\n * resolved route to the underlying transport layer (e.g. OTel RPCMetadata).\n */\n onRouteResolved?: (route: string | undefined) => void;\n};\n\nexport type LayerMetadata = {\n attributes: SpanAttributes;\n name: string;\n};\n\nexport interface ExpressApplication {\n stack: ExpressLayer[];\n use: ExpressApplicationRequestHandler;\n}\n\nexport interface MiddlewareError extends Error {\n status?: number | string;\n statusCode?: number | string;\n status_code?: number | string;\n output?: {\n statusCode?: number | string;\n };\n}\n\nexport type ExpressMiddleware = (req: ExpressRequest, res: ExpressResponse, next: () => void) => void;\n\nexport type ExpressErrorMiddleware = (\n error: MiddlewareError,\n req: ExpressRequest,\n res: ExpressResponse,\n next: (error: MiddlewareError) => void,\n) => void;\n\nexport interface ExpressHandlerOptions {\n /**\n * Callback method deciding whether error should be captured and sent to Sentry\n * @param error Captured middleware error\n */\n shouldHandleError?(this: void, error: MiddlewareError): boolean;\n}\n"],"names":[],"mappings":";;AAgCO,MAAM,iBAAA,GAAoB;AAC1B,MAAM,eAAA,GAAkB;AACxB,MAAM,iBAAA,GAAoB;;AA2D1B,MAAM,uBAAA,GAA0B;AAChC,MAAM,2BAAA,GAA8B;AACpC,MAAM,gCAAA,GAAmC;;;;;;;;;"}
@@ -0,0 +1,238 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const requestLayerStore = require('./request-layer-store.js');
4
+ const types = require('./types.js');
5
+ const string = require('../../utils/string.js');
6
+
7
+ /**
8
+ * Converts a user-provided error value into an error and error message pair
9
+ *
10
+ * @param error - User-provided error value
11
+ * @returns Both an Error or string representation of the value and an error message
12
+ */
13
+ const asErrorAndMessage = (error) =>
14
+ error instanceof Error ? [error, error.message] : [String(error), String(error)];
15
+
16
+ /**
17
+ * Checks if a route contains parameter patterns (e.g., :id, :userId)
18
+ * which are valid even if they don't exactly match the original URL
19
+ */
20
+ function isRoutePattern(route) {
21
+ return route.includes(':') || route.includes('*');
22
+ }
23
+
24
+ /**
25
+ * Parse express layer context to retrieve a name and attributes.
26
+ * @param route The route of the layer
27
+ * @param layer Express layer
28
+ * @param [layerPath] if present, the path on which the layer has been mounted
29
+ */
30
+ const getLayerMetadata = (
31
+ route,
32
+ layer,
33
+ layerPath,
34
+
35
+ ) => {
36
+ if (layer.name === 'router') {
37
+ const maybeRouterPath = getRouterPath('', layer);
38
+ const extractedRouterPath = maybeRouterPath ? maybeRouterPath : layerPath || route || '/';
39
+
40
+ return {
41
+ attributes: {
42
+ [types.ATTR_EXPRESS_NAME]: extractedRouterPath,
43
+ [types.ATTR_EXPRESS_TYPE]: types.ExpressLayerType_ROUTER,
44
+ },
45
+ name: `router - ${extractedRouterPath}`,
46
+ };
47
+ } else if (layer.name === 'bound dispatch' || layer.name === 'handle') {
48
+ return {
49
+ attributes: {
50
+ [types.ATTR_EXPRESS_NAME]: (route || layerPath) ?? 'request handler',
51
+ [types.ATTR_EXPRESS_TYPE]: types.ExpressLayerType_REQUEST_HANDLER,
52
+ },
53
+ name: `request handler${layer.path ? ` - ${route || layerPath}` : ''}`,
54
+ };
55
+ } else {
56
+ return {
57
+ attributes: {
58
+ [types.ATTR_EXPRESS_NAME]: layer.name,
59
+ [types.ATTR_EXPRESS_TYPE]: types.ExpressLayerType_MIDDLEWARE,
60
+ },
61
+ name: `middleware - ${layer.name}`,
62
+ };
63
+ }
64
+ };
65
+
66
+ /**
67
+ * Recursively search the router path from layer stack
68
+ * @param path The path to reconstruct
69
+ * @param layer The layer to reconstruct from
70
+ * @returns The reconstructed path
71
+ */
72
+ const getRouterPath = (path, layer) => {
73
+ const stackLayer = Array.isArray(layer.handle?.stack) ? layer.handle?.stack?.[0] : undefined;
74
+
75
+ if (stackLayer?.route?.path) {
76
+ return `${path}${stackLayer.route.path}`;
77
+ }
78
+
79
+ if (stackLayer && Array.isArray(stackLayer?.handle?.stack)) {
80
+ return getRouterPath(path, stackLayer);
81
+ }
82
+
83
+ return path;
84
+ };
85
+
86
+ /**
87
+ * Check whether the given request is ignored by configuration
88
+ * It will not re-throw exceptions from `list` provided by the client
89
+ * @param constant e.g URL of request
90
+ * @param [list] List of ignore patterns
91
+ * @param [onException] callback for doing something when an exception has
92
+ * occurred
93
+ */
94
+
95
+ const isLayerIgnored = (
96
+ name,
97
+ type,
98
+ config,
99
+ ) => {
100
+ if (Array.isArray(config?.ignoreLayersType) && config?.ignoreLayersType?.includes(type)) {
101
+ return true;
102
+ }
103
+ if (!Array.isArray(config?.ignoreLayers)) {
104
+ return false;
105
+ }
106
+ try {
107
+ return string.stringMatchesSomePattern(name, config.ignoreLayers, true);
108
+ } catch {}
109
+
110
+ return false;
111
+ };
112
+
113
+ /**
114
+ * Extracts the actual matched route from Express request for OpenTelemetry instrumentation.
115
+ * Returns the route that should be used as the http.route attribute.
116
+ *
117
+ * @param req - The Express request object with layers store
118
+ * @param constructedRoute - The constructed route from `getConstructedRoute`
119
+ * @returns The matched route string or undefined if no valid route is found
120
+ */
121
+ function getActualMatchedRoute(req, constructedRoute) {
122
+ const layersStore = requestLayerStore.getStoredLayers(req);
123
+
124
+ // If no layers are stored, no route can be determined
125
+ if (layersStore.length === 0) {
126
+ return undefined;
127
+ }
128
+
129
+ // Handle root path case - if all paths are root, only return root if originalUrl is also root
130
+ // The layer store also includes root paths in case a non-existing url was requested
131
+ if (layersStore.every(path => path === '/')) {
132
+ return req.originalUrl === '/' ? '/' : undefined;
133
+ }
134
+
135
+ if (constructedRoute === '*') {
136
+ return constructedRoute;
137
+ }
138
+
139
+ // For RegExp routes or route arrays, return the constructed route
140
+ // This handles the case where the route is defined using RegExp or an array
141
+ if (
142
+ constructedRoute.includes('/') &&
143
+ (constructedRoute.includes(',') ||
144
+ constructedRoute.includes('\\') ||
145
+ constructedRoute.includes('*') ||
146
+ constructedRoute.includes('['))
147
+ ) {
148
+ return constructedRoute;
149
+ }
150
+
151
+ // Ensure route starts with '/' if it doesn't already
152
+ const normalizedRoute = constructedRoute.startsWith('/') ? constructedRoute : `/${constructedRoute}`;
153
+
154
+ // Validate that this appears to be a matched route
155
+ // A route is considered matched if:
156
+ // 1. We have a constructed route
157
+ // 2. The original URL matches or starts with our route pattern
158
+ const isValidRoute =
159
+ normalizedRoute.length > 0 &&
160
+ (req.originalUrl === normalizedRoute ||
161
+ req.originalUrl.startsWith(normalizedRoute) ||
162
+ isRoutePattern(normalizedRoute));
163
+
164
+ return isValidRoute ? normalizedRoute : undefined;
165
+ }
166
+
167
+ function getConstructedRoute(req) {
168
+ const layersStore = requestLayerStore.getStoredLayers(req);
169
+
170
+ let constructedRoute = '';
171
+ for (const path of layersStore) {
172
+ if (path === '/' || path === '/*') {
173
+ continue;
174
+ }
175
+ constructedRoute += !constructedRoute || constructedRoute.endsWith('/') ? path : `/${path}`;
176
+ }
177
+
178
+ return constructedRoute.replace(/\/{2,}/g, '/');
179
+ }
180
+
181
+ const getLayerPath = (args) => {
182
+ const firstArg = args[0];
183
+
184
+ if (Array.isArray(firstArg)) {
185
+ return firstArg.map(arg => extractLayerPathSegment(arg) || '').join(',');
186
+ }
187
+
188
+ return extractLayerPathSegment(firstArg );
189
+ };
190
+
191
+ const extractLayerPathSegment = (arg) =>
192
+ typeof arg === 'string' ? arg : arg instanceof RegExp || typeof arg === 'number' ? String(arg) : undefined;
193
+
194
+ // v5 we instrument Router.prototype
195
+ // v4 we instrument Router itself
196
+ const isExpressWithRouterPrototype = (express) =>
197
+ isExpressRouterPrototype((express )?.Router?.prototype);
198
+
199
+ // In Express v4, Router is a function (not a plain object), so we need to accept both
200
+ const isExpressRouterPrototype = (routerProto) =>
201
+ (typeof routerProto === 'object' || typeof routerProto === 'function') &&
202
+ !!routerProto &&
203
+ 'route' in routerProto &&
204
+ typeof (routerProto ).route === 'function';
205
+
206
+ const isExpressWithoutRouterPrototype = (express) =>
207
+ isExpressRouterPrototype((express ).Router) && !isExpressWithRouterPrototype(express);
208
+
209
+ // dynamic puts the default on .default, require or normal import are fine
210
+ const hasDefaultProp = (
211
+ express,
212
+
213
+ ) => !!express && typeof express === 'object' && 'default' in express && typeof express.default === 'function';
214
+
215
+ function getStatusCodeFromResponse(error) {
216
+ const statusCode = error.status || error.statusCode || error.status_code || error.output?.statusCode;
217
+ return statusCode ? parseInt(statusCode , 10) : 500;
218
+ }
219
+
220
+ /** Returns true if response code is internal server error */
221
+ function defaultShouldHandleError(error) {
222
+ const status = getStatusCodeFromResponse(error);
223
+ return status >= 500;
224
+ }
225
+
226
+ exports.asErrorAndMessage = asErrorAndMessage;
227
+ exports.defaultShouldHandleError = defaultShouldHandleError;
228
+ exports.getActualMatchedRoute = getActualMatchedRoute;
229
+ exports.getConstructedRoute = getConstructedRoute;
230
+ exports.getLayerMetadata = getLayerMetadata;
231
+ exports.getLayerPath = getLayerPath;
232
+ exports.getRouterPath = getRouterPath;
233
+ exports.hasDefaultProp = hasDefaultProp;
234
+ exports.isExpressWithRouterPrototype = isExpressWithRouterPrototype;
235
+ exports.isExpressWithoutRouterPrototype = isExpressWithoutRouterPrototype;
236
+ exports.isLayerIgnored = isLayerIgnored;
237
+ exports.isRoutePattern = isRoutePattern;
238
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sources":["../../../../src/integrations/express/utils.ts"],"sourcesContent":["/**\n * Platform-portable Express tracing integration.\n *\n * @module\n *\n * This Sentry integration is a derivative work based on the OpenTelemetry\n * Express instrumentation.\n *\n * <https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-express>\n *\n * Extended under the terms of the Apache 2.0 license linked below:\n *\n * ----\n *\n * Copyright The OpenTelemetry Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { SpanAttributes } from '../../types-hoist/span';\nimport { getStoredLayers } from './request-layer-store';\nimport type {\n ExpressExport,\n ExpressIntegrationOptions,\n ExpressLayer,\n ExpressLayerType,\n ExpressRequest,\n LayerPathSegment,\n MiddlewareError,\n ExpressRouterv4,\n ExpressExportv5,\n ExpressExportv4,\n} from './types';\nimport {\n ATTR_EXPRESS_NAME,\n ATTR_EXPRESS_TYPE,\n ExpressLayerType_MIDDLEWARE,\n ExpressLayerType_REQUEST_HANDLER,\n ExpressLayerType_ROUTER,\n} from './types';\nimport { stringMatchesSomePattern } from '../../utils/string';\n\n/**\n * Converts a user-provided error value into an error and error message pair\n *\n * @param error - User-provided error value\n * @returns Both an Error or string representation of the value and an error message\n */\nexport const asErrorAndMessage = (error: unknown): [string | Error, string] =>\n error instanceof Error ? [error, error.message] : [String(error), String(error)];\n\n/**\n * Checks if a route contains parameter patterns (e.g., :id, :userId)\n * which are valid even if they don't exactly match the original URL\n */\nexport function isRoutePattern(route: string): boolean {\n return route.includes(':') || route.includes('*');\n}\n\n/**\n * Parse express layer context to retrieve a name and attributes.\n * @param route The route of the layer\n * @param layer Express layer\n * @param [layerPath] if present, the path on which the layer has been mounted\n */\nexport const getLayerMetadata = (\n route: string,\n layer: ExpressLayer,\n layerPath?: string,\n): {\n attributes: SpanAttributes & { [ATTR_EXPRESS_NAME]: string; [ATTR_EXPRESS_TYPE]: ExpressLayerType };\n name: string;\n} => {\n if (layer.name === 'router') {\n const maybeRouterPath = getRouterPath('', layer);\n const extractedRouterPath = maybeRouterPath ? maybeRouterPath : layerPath || route || '/';\n\n return {\n attributes: {\n [ATTR_EXPRESS_NAME]: extractedRouterPath,\n [ATTR_EXPRESS_TYPE]: ExpressLayerType_ROUTER,\n },\n name: `router - ${extractedRouterPath}`,\n };\n } else if (layer.name === 'bound dispatch' || layer.name === 'handle') {\n return {\n attributes: {\n [ATTR_EXPRESS_NAME]: (route || layerPath) ?? 'request handler',\n [ATTR_EXPRESS_TYPE]: ExpressLayerType_REQUEST_HANDLER,\n },\n name: `request handler${layer.path ? ` - ${route || layerPath}` : ''}`,\n };\n } else {\n return {\n attributes: {\n [ATTR_EXPRESS_NAME]: layer.name,\n [ATTR_EXPRESS_TYPE]: ExpressLayerType_MIDDLEWARE,\n },\n name: `middleware - ${layer.name}`,\n };\n }\n};\n\n/**\n * Recursively search the router path from layer stack\n * @param path The path to reconstruct\n * @param layer The layer to reconstruct from\n * @returns The reconstructed path\n */\nexport const getRouterPath = (path: string, layer: ExpressLayer): string => {\n const stackLayer = Array.isArray(layer.handle?.stack) ? layer.handle?.stack?.[0] : undefined;\n\n if (stackLayer?.route?.path) {\n return `${path}${stackLayer.route.path}`;\n }\n\n if (stackLayer && Array.isArray(stackLayer?.handle?.stack)) {\n return getRouterPath(path, stackLayer);\n }\n\n return path;\n};\n\n/**\n * Check whether the given request is ignored by configuration\n * It will not re-throw exceptions from `list` provided by the client\n * @param constant e.g URL of request\n * @param [list] List of ignore patterns\n * @param [onException] callback for doing something when an exception has\n * occurred\n */\nexport type ExpressIsLayerIgnoredOptions = Pick<ExpressIntegrationOptions, 'ignoreLayersType' | 'ignoreLayers'>;\nexport const isLayerIgnored = (\n name: string,\n type: ExpressLayerType,\n config?: ExpressIsLayerIgnoredOptions,\n): boolean => {\n if (Array.isArray(config?.ignoreLayersType) && config?.ignoreLayersType?.includes(type)) {\n return true;\n }\n if (!Array.isArray(config?.ignoreLayers)) {\n return false;\n }\n try {\n return stringMatchesSomePattern(name, config.ignoreLayers, true);\n } catch {}\n\n return false;\n};\n\n/**\n * Extracts the actual matched route from Express request for OpenTelemetry instrumentation.\n * Returns the route that should be used as the http.route attribute.\n *\n * @param req - The Express request object with layers store\n * @param constructedRoute - The constructed route from `getConstructedRoute`\n * @returns The matched route string or undefined if no valid route is found\n */\nexport function getActualMatchedRoute(req: ExpressRequest, constructedRoute: string): string | undefined {\n const layersStore = getStoredLayers(req);\n\n // If no layers are stored, no route can be determined\n if (layersStore.length === 0) {\n return undefined;\n }\n\n // Handle root path case - if all paths are root, only return root if originalUrl is also root\n // The layer store also includes root paths in case a non-existing url was requested\n if (layersStore.every(path => path === '/')) {\n return req.originalUrl === '/' ? '/' : undefined;\n }\n\n if (constructedRoute === '*') {\n return constructedRoute;\n }\n\n // For RegExp routes or route arrays, return the constructed route\n // This handles the case where the route is defined using RegExp or an array\n if (\n constructedRoute.includes('/') &&\n (constructedRoute.includes(',') ||\n constructedRoute.includes('\\\\') ||\n constructedRoute.includes('*') ||\n constructedRoute.includes('['))\n ) {\n return constructedRoute;\n }\n\n // Ensure route starts with '/' if it doesn't already\n const normalizedRoute = constructedRoute.startsWith('/') ? constructedRoute : `/${constructedRoute}`;\n\n // Validate that this appears to be a matched route\n // A route is considered matched if:\n // 1. We have a constructed route\n // 2. The original URL matches or starts with our route pattern\n const isValidRoute =\n normalizedRoute.length > 0 &&\n (req.originalUrl === normalizedRoute ||\n req.originalUrl.startsWith(normalizedRoute) ||\n isRoutePattern(normalizedRoute));\n\n return isValidRoute ? normalizedRoute : undefined;\n}\n\nexport function getConstructedRoute(req: ExpressRequest) {\n const layersStore: string[] = getStoredLayers(req);\n\n let constructedRoute: string = '';\n for (const path of layersStore) {\n if (path === '/' || path === '/*') {\n continue;\n }\n constructedRoute += !constructedRoute || constructedRoute.endsWith('/') ? path : `/${path}`;\n }\n\n return constructedRoute.replace(/\\/{2,}/g, '/');\n}\n\nexport const getLayerPath = (args: unknown[]): string | undefined => {\n const firstArg = args[0];\n\n if (Array.isArray(firstArg)) {\n return firstArg.map(arg => extractLayerPathSegment(arg) || '').join(',');\n }\n\n return extractLayerPathSegment(firstArg as LayerPathSegment);\n};\n\nconst extractLayerPathSegment = (arg: LayerPathSegment): string | undefined =>\n typeof arg === 'string' ? arg : arg instanceof RegExp || typeof arg === 'number' ? String(arg) : undefined;\n\n// v5 we instrument Router.prototype\n// v4 we instrument Router itself\nexport const isExpressWithRouterPrototype = (express: unknown): express is ExpressExportv5 =>\n isExpressRouterPrototype((express as ExpressExportv5)?.Router?.prototype);\n\n// In Express v4, Router is a function (not a plain object), so we need to accept both\nconst isExpressRouterPrototype = (routerProto?: unknown): routerProto is ExpressRouterv4 =>\n (typeof routerProto === 'object' || typeof routerProto === 'function') &&\n !!routerProto &&\n 'route' in routerProto &&\n typeof (routerProto as ExpressRouterv4).route === 'function';\n\nexport const isExpressWithoutRouterPrototype = (express: unknown): express is ExpressExportv4 =>\n isExpressRouterPrototype((express as ExpressExportv4).Router) && !isExpressWithRouterPrototype(express);\n\n// dynamic puts the default on .default, require or normal import are fine\nexport const hasDefaultProp = (\n express: unknown,\n): express is {\n [k: string]: unknown;\n default: ExpressExport;\n} => !!express && typeof express === 'object' && 'default' in express && typeof express.default === 'function';\n\nfunction getStatusCodeFromResponse(error: MiddlewareError): number {\n const statusCode = error.status || error.statusCode || error.status_code || error.output?.statusCode;\n return statusCode ? parseInt(statusCode as string, 10) : 500;\n}\n\n/** Returns true if response code is internal server error */\nexport function defaultShouldHandleError(error: MiddlewareError): boolean {\n const status = getStatusCodeFromResponse(error);\n return status >= 500;\n}\n"],"names":["ATTR_EXPRESS_NAME","ATTR_EXPRESS_TYPE","ExpressLayerType_ROUTER","ExpressLayerType_REQUEST_HANDLER","ExpressLayerType_MIDDLEWARE","stringMatchesSomePattern","getStoredLayers"],"mappings":"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"}