@sentry/node 9.14.0 → 9.16.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 (167) hide show
  1. package/build/cjs/index.js +3 -2
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/cjs/integrations/anr/index.js +1 -1
  4. package/build/cjs/integrations/anr/index.js.map +1 -1
  5. package/build/cjs/integrations/context.js +1 -0
  6. package/build/cjs/integrations/context.js.map +1 -1
  7. package/build/cjs/integrations/contextlines.js.map +1 -1
  8. package/build/cjs/integrations/fs.js.map +1 -1
  9. package/build/cjs/integrations/http/SentryHttpInstrumentation.js +130 -128
  10. package/build/cjs/integrations/http/SentryHttpInstrumentation.js.map +1 -1
  11. package/build/cjs/integrations/http/SentryHttpInstrumentationBeforeOtel.js +50 -44
  12. package/build/cjs/integrations/http/SentryHttpInstrumentationBeforeOtel.js.map +1 -1
  13. package/build/cjs/integrations/http/index.js +31 -7
  14. package/build/cjs/integrations/http/index.js.map +1 -1
  15. package/build/cjs/integrations/local-variables/local-variables-async.js +1 -1
  16. package/build/cjs/integrations/local-variables/local-variables-async.js.map +1 -1
  17. package/build/cjs/integrations/local-variables/local-variables-sync.js.map +1 -1
  18. package/build/cjs/integrations/node-fetch/SentryNodeFetchInstrumentation.js.map +1 -1
  19. package/build/cjs/integrations/node-fetch/index.js.map +1 -1
  20. package/build/cjs/integrations/tracing/amqplib.js.map +1 -1
  21. package/build/cjs/integrations/tracing/connect.js.map +1 -1
  22. package/build/cjs/integrations/tracing/dataloader.js.map +1 -1
  23. package/build/cjs/integrations/tracing/express-v5/instrumentation.js +4 -2
  24. package/build/cjs/integrations/tracing/express-v5/instrumentation.js.map +1 -1
  25. package/build/cjs/integrations/tracing/express.js.map +1 -1
  26. package/build/cjs/integrations/tracing/fastify.js.map +1 -1
  27. package/build/cjs/integrations/tracing/genericPool.js.map +1 -1
  28. package/build/cjs/integrations/tracing/graphql.js.map +1 -1
  29. package/build/cjs/integrations/tracing/hapi/index.js.map +1 -1
  30. package/build/cjs/integrations/tracing/index.js +2 -4
  31. package/build/cjs/integrations/tracing/index.js.map +1 -1
  32. package/build/cjs/integrations/tracing/knex.js.map +1 -1
  33. package/build/cjs/integrations/tracing/koa.js.map +1 -1
  34. package/build/cjs/integrations/tracing/lrumemoizer.js.map +1 -1
  35. package/build/cjs/integrations/tracing/mongo.js.map +1 -1
  36. package/build/cjs/integrations/tracing/mongoose.js.map +1 -1
  37. package/build/cjs/integrations/tracing/mysql.js.map +1 -1
  38. package/build/cjs/integrations/tracing/mysql2.js.map +1 -1
  39. package/build/cjs/integrations/tracing/postgres.js.map +1 -1
  40. package/build/cjs/integrations/tracing/prisma.js +2 -7
  41. package/build/cjs/integrations/tracing/prisma.js.map +1 -1
  42. package/build/cjs/integrations/tracing/redis.js.map +1 -1
  43. package/build/cjs/integrations/tracing/tedious.js.map +1 -1
  44. package/build/cjs/integrations/tracing/vercelai/index.js +0 -2
  45. package/build/cjs/integrations/tracing/vercelai/index.js.map +1 -1
  46. package/build/cjs/integrations/tracing/vercelai/instrumentation.js +20 -7
  47. package/build/cjs/integrations/tracing/vercelai/instrumentation.js.map +1 -1
  48. package/build/cjs/integrations/winston.js +2 -2
  49. package/build/cjs/integrations/winston.js.map +1 -1
  50. package/build/cjs/logs/capture.js.map +1 -1
  51. package/build/cjs/logs/exports.js.map +1 -1
  52. package/build/cjs/proxy/index.js.map +1 -1
  53. package/build/cjs/sdk/api.js.map +1 -1
  54. package/build/cjs/sdk/client.js.map +1 -1
  55. package/build/cjs/sdk/index.js.map +1 -1
  56. package/build/cjs/sdk/initOtel.js +2 -2
  57. package/build/cjs/sdk/initOtel.js.map +1 -1
  58. package/build/cjs/utils/addOriginToSpan.js.map +1 -1
  59. package/build/esm/index.js +3 -3
  60. package/build/esm/integrations/anr/index.js +1 -1
  61. package/build/esm/integrations/anr/index.js.map +1 -1
  62. package/build/esm/integrations/anr/worker-script.js +2 -2
  63. package/build/esm/integrations/context.js +1 -0
  64. package/build/esm/integrations/context.js.map +1 -1
  65. package/build/esm/integrations/contextlines.js.map +1 -1
  66. package/build/esm/integrations/fs.js.map +1 -1
  67. package/build/esm/integrations/http/SentryHttpInstrumentation.js +131 -129
  68. package/build/esm/integrations/http/SentryHttpInstrumentation.js.map +1 -1
  69. package/build/esm/integrations/http/SentryHttpInstrumentationBeforeOtel.js +51 -45
  70. package/build/esm/integrations/http/SentryHttpInstrumentationBeforeOtel.js.map +1 -1
  71. package/build/esm/integrations/http/index.js +31 -7
  72. package/build/esm/integrations/http/index.js.map +1 -1
  73. package/build/esm/integrations/local-variables/local-variables-async.js +1 -1
  74. package/build/esm/integrations/local-variables/local-variables-async.js.map +1 -1
  75. package/build/esm/integrations/local-variables/local-variables-sync.js.map +1 -1
  76. package/build/esm/integrations/local-variables/worker-script.js +2 -2
  77. package/build/esm/integrations/node-fetch/SentryNodeFetchInstrumentation.js.map +1 -1
  78. package/build/esm/integrations/node-fetch/index.js.map +1 -1
  79. package/build/esm/integrations/tracing/amqplib.js.map +1 -1
  80. package/build/esm/integrations/tracing/connect.js.map +1 -1
  81. package/build/esm/integrations/tracing/dataloader.js.map +1 -1
  82. package/build/esm/integrations/tracing/express-v5/instrumentation.js +4 -2
  83. package/build/esm/integrations/tracing/express-v5/instrumentation.js.map +1 -1
  84. package/build/esm/integrations/tracing/express.js.map +1 -1
  85. package/build/esm/integrations/tracing/fastify.js.map +1 -1
  86. package/build/esm/integrations/tracing/genericPool.js.map +1 -1
  87. package/build/esm/integrations/tracing/graphql.js.map +1 -1
  88. package/build/esm/integrations/tracing/hapi/index.js.map +1 -1
  89. package/build/esm/integrations/tracing/index.js +2 -4
  90. package/build/esm/integrations/tracing/index.js.map +1 -1
  91. package/build/esm/integrations/tracing/knex.js.map +1 -1
  92. package/build/esm/integrations/tracing/koa.js.map +1 -1
  93. package/build/esm/integrations/tracing/lrumemoizer.js.map +1 -1
  94. package/build/esm/integrations/tracing/mongo.js.map +1 -1
  95. package/build/esm/integrations/tracing/mongoose.js.map +1 -1
  96. package/build/esm/integrations/tracing/mysql.js.map +1 -1
  97. package/build/esm/integrations/tracing/mysql2.js.map +1 -1
  98. package/build/esm/integrations/tracing/postgres.js.map +1 -1
  99. package/build/esm/integrations/tracing/prisma.js +2 -7
  100. package/build/esm/integrations/tracing/prisma.js.map +1 -1
  101. package/build/esm/integrations/tracing/redis.js.map +1 -1
  102. package/build/esm/integrations/tracing/tedious.js.map +1 -1
  103. package/build/esm/integrations/tracing/vercelai/index.js +0 -2
  104. package/build/esm/integrations/tracing/vercelai/index.js.map +1 -1
  105. package/build/esm/integrations/tracing/vercelai/instrumentation.js +20 -7
  106. package/build/esm/integrations/tracing/vercelai/instrumentation.js.map +1 -1
  107. package/build/esm/integrations/winston.js +2 -2
  108. package/build/esm/integrations/winston.js.map +1 -1
  109. package/build/esm/logs/capture.js.map +1 -1
  110. package/build/esm/logs/exports.js.map +1 -1
  111. package/build/esm/package.json +1 -1
  112. package/build/esm/proxy/index.js.map +1 -1
  113. package/build/esm/sdk/api.js.map +1 -1
  114. package/build/esm/sdk/client.js.map +1 -1
  115. package/build/esm/sdk/index.js.map +1 -1
  116. package/build/esm/sdk/initOtel.js +2 -2
  117. package/build/esm/sdk/initOtel.js.map +1 -1
  118. package/build/esm/utils/addOriginToSpan.js.map +1 -1
  119. package/build/types/index.d.ts +2 -2
  120. package/build/types/index.d.ts.map +1 -1
  121. package/build/types/integrations/context.d.ts +1 -1
  122. package/build/types/integrations/context.d.ts.map +1 -1
  123. package/build/types/integrations/http/SentryHttpInstrumentation.d.ts +10 -14
  124. package/build/types/integrations/http/SentryHttpInstrumentation.d.ts.map +1 -1
  125. package/build/types/integrations/http/SentryHttpInstrumentationBeforeOtel.d.ts.map +1 -1
  126. package/build/types/integrations/http/index.d.ts +8 -0
  127. package/build/types/integrations/http/index.d.ts.map +1 -1
  128. package/build/types/integrations/node-fetch/SentryNodeFetchInstrumentation.d.ts.map +1 -1
  129. package/build/types/integrations/tracing/amqplib.d.ts.map +1 -1
  130. package/build/types/integrations/tracing/express-v5/instrumentation.d.ts.map +1 -1
  131. package/build/types/integrations/tracing/graphql.d.ts.map +1 -1
  132. package/build/types/integrations/tracing/index.d.ts.map +1 -1
  133. package/build/types/integrations/tracing/lrumemoizer.d.ts.map +1 -1
  134. package/build/types/integrations/tracing/mongo.d.ts.map +1 -1
  135. package/build/types/integrations/tracing/mongoose.d.ts.map +1 -1
  136. package/build/types/integrations/tracing/mysql2.d.ts.map +1 -1
  137. package/build/types/integrations/tracing/postgres.d.ts.map +1 -1
  138. package/build/types/integrations/tracing/prisma.d.ts.map +1 -1
  139. package/build/types/integrations/tracing/vercelai/instrumentation.d.ts +1 -1
  140. package/build/types/integrations/tracing/vercelai/instrumentation.d.ts.map +1 -1
  141. package/build/types/integrations/winston.d.ts +3 -3
  142. package/build/types/logs/capture.d.ts +1 -1
  143. package/build/types/logs/capture.d.ts.map +1 -1
  144. package/build/types/logs/exports.d.ts.map +1 -1
  145. package/build/types/proxy/index.d.ts +1 -1
  146. package/build/types/proxy/index.d.ts.map +1 -1
  147. package/build/types/sdk/client.d.ts.map +1 -1
  148. package/build/types/sdk/initOtel.d.ts.map +1 -1
  149. package/build/types/types.d.ts.map +1 -1
  150. package/build/types/utils/addOriginToSpan.d.ts.map +1 -1
  151. package/build/types/utils/prepareEvent.d.ts.map +1 -1
  152. package/build/types-ts3.8/index.d.ts +2 -2
  153. package/build/types-ts3.8/integrations/context.d.ts +1 -1
  154. package/build/types-ts3.8/integrations/http/SentryHttpInstrumentation.d.ts +10 -14
  155. package/build/types-ts3.8/integrations/http/index.d.ts +11 -0
  156. package/build/types-ts3.8/integrations/tracing/vercelai/instrumentation.d.ts +1 -1
  157. package/build/types-ts3.8/integrations/winston.d.ts +3 -3
  158. package/build/types-ts3.8/logs/capture.d.ts +1 -1
  159. package/build/types-ts3.8/proxy/index.d.ts +1 -1
  160. package/package.json +4 -4
  161. package/build/cjs/integrations/http/vendor/getRequestInfo.js +0 -130
  162. package/build/cjs/integrations/http/vendor/getRequestInfo.js.map +0 -1
  163. package/build/esm/integrations/http/vendor/getRequestInfo.js +0 -128
  164. package/build/esm/integrations/http/vendor/getRequestInfo.js.map +0 -1
  165. package/build/types/integrations/http/vendor/getRequestInfo.d.ts +0 -21
  166. package/build/types/integrations/http/vendor/getRequestInfo.d.ts.map +0 -1
  167. package/build/types-ts3.8/integrations/http/vendor/getRequestInfo.d.ts +0 -21
@@ -1 +1 @@
1
- {"version":3,"file":"fs.js","sources":["../../../src/integrations/fs.ts"],"sourcesContent":["import { FsInstrumentation } from '@opentelemetry/instrumentation-fs';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, defineIntegration } from '@sentry/core';\nimport { generateInstrumentOnce } from '../otel/instrument';\n\nconst INTEGRATION_NAME = 'FileSystem';\n\n/**\n * This integration will create spans for `fs` API operations, like reading and writing files.\n *\n * **WARNING:** This integration may add significant overhead to your application. Especially in scenarios with a lot of\n * file I/O, like for example when running a framework dev server, including this integration can massively slow down\n * your application.\n *\n * @param options Configuration for this integration.\n */\nexport const fsIntegration = defineIntegration(\n (\n options: {\n /**\n * Setting this option to `true` will include any filepath arguments from your `fs` API calls as span attributes.\n *\n * Defaults to `false`.\n */\n recordFilePaths?: boolean;\n\n /**\n * Setting this option to `true` will include the error messages of failed `fs` API calls as a span attribute.\n *\n * Defaults to `false`.\n */\n recordErrorMessagesAsSpanAttributes?: boolean;\n } = {},\n ) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n generateInstrumentOnce(\n INTEGRATION_NAME,\n () =>\n new FsInstrumentation({\n requireParentSpan: true,\n endHook(functionName, { args, span, error }) {\n span.updateName(`fs.${functionName}`);\n\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'file',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.file.fs',\n });\n\n if (options.recordErrorMessagesAsSpanAttributes) {\n if (typeof args[0] === 'string' && FS_OPERATIONS_WITH_PATH_ARG.includes(functionName)) {\n span.setAttribute('path_argument', args[0]);\n } else if (\n typeof args[0] === 'string' &&\n typeof args[1] === 'string' &&\n FS_OPERATIONS_WITH_TARGET_PATH.includes(functionName)\n ) {\n span.setAttribute('target_argument', args[0]);\n span.setAttribute('path_argument', args[1]);\n } else if (typeof args[0] === 'string' && FS_OPERATIONS_WITH_PREFIX.includes(functionName)) {\n span.setAttribute('prefix_argument', args[0]);\n } else if (\n typeof args[0] === 'string' &&\n typeof args[1] === 'string' &&\n FS_OPERATIONS_WITH_EXISTING_PATH_NEW_PATH.includes(functionName)\n ) {\n span.setAttribute('existing_path_argument', args[0]);\n span.setAttribute('new_path_argument', args[1]);\n } else if (\n typeof args[0] === 'string' &&\n typeof args[1] === 'string' &&\n FS_OPERATIONS_WITH_SRC_DEST.includes(functionName)\n ) {\n span.setAttribute('src_argument', args[0]);\n span.setAttribute('dest_argument', args[1]);\n } else if (\n typeof args[0] === 'string' &&\n typeof args[1] === 'string' &&\n FS_OPERATIONS_WITH_OLD_PATH_NEW_PATH.includes(functionName)\n ) {\n span.setAttribute('old_path_argument', args[0]);\n span.setAttribute('new_path_argument', args[1]);\n }\n }\n\n if (error && options.recordErrorMessagesAsSpanAttributes) {\n span.setAttribute('fs_error', error.message);\n }\n },\n }),\n )();\n },\n };\n },\n);\n\nconst FS_OPERATIONS_WITH_OLD_PATH_NEW_PATH = ['rename', 'renameSync'];\nconst FS_OPERATIONS_WITH_SRC_DEST = ['copyFile', 'cp', 'copyFileSync', 'cpSync'];\nconst FS_OPERATIONS_WITH_EXISTING_PATH_NEW_PATH = ['link', 'linkSync'];\nconst FS_OPERATIONS_WITH_PREFIX = ['mkdtemp', 'mkdtempSync'];\nconst FS_OPERATIONS_WITH_TARGET_PATH = ['symlink', 'symlinkSync'];\nconst FS_OPERATIONS_WITH_PATH_ARG = [\n 'access',\n 'appendFile',\n 'chmod',\n 'chown',\n 'exists',\n 'mkdir',\n 'lchown',\n 'lstat',\n 'lutimes',\n 'open',\n 'opendir',\n 'readdir',\n 'readFile',\n 'readlink',\n 'realpath',\n 'realpath.native',\n 'rm',\n 'rmdir',\n 'stat',\n 'truncate',\n 'unlink',\n 'utimes',\n 'writeFile',\n 'accessSync',\n 'appendFileSync',\n 'chmodSync',\n 'chownSync',\n 'existsSync',\n 'lchownSync',\n 'lstatSync',\n 'lutimesSync',\n 'opendirSync',\n 'mkdirSync',\n 'openSync',\n 'readdirSync',\n 'readFileSync',\n 'readlinkSync',\n 'realpathSync',\n 'realpathSync.native',\n 'rmdirSync',\n 'rmSync',\n 'statSync',\n 'truncateSync',\n 'unlinkSync',\n 'utimesSync',\n 'writeFileSync',\n];\n"],"names":["defineIntegration","generateInstrumentOnce","FsInstrumentation","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN"],"mappings":";;;;;;AAIA,MAAM,gBAAA,GAAmB,YAAY;;AAErC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,aAAc,GAAEA,sBAAiB;AAC9C,EAAE;AACF,IAAI;;AAcA,GAAI,EAAE;AACV,OAAO;AACP,IAAI,OAAO;AACX,MAAM,IAAI,EAAE,gBAAgB;AAC5B,MAAM,SAAS,GAAG;AAClB,QAAQC,iCAAsB;AAC9B,UAAU,gBAAgB;AAC1B,UAAU;AACV,YAAY,IAAIC,mCAAiB,CAAC;AAClC,cAAc,iBAAiB,EAAE,IAAI;AACrC,cAAc,OAAO,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAM,EAAC,EAAE;AAC3D,gBAAgB,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,CAAA,CAAA;;AAEA,gBAAA,IAAA,CAAA,aAAA,CAAA;AACA,kBAAA,CAAAC,iCAAA,GAAA,MAAA;AACA,kBAAA,CAAAC,qCAAA,GAAA,cAAA;AACA,iBAAA,CAAA;;AAEA,gBAAA,IAAA,OAAA,CAAA,mCAAA,EAAA;AACA,kBAAA,IAAA,OAAA,IAAA,CAAA,CAAA,CAAA,KAAA,QAAA,IAAA,2BAAA,CAAA,QAAA,CAAA,YAAA,CAAA,EAAA;AACA,oBAAA,IAAA,CAAA,YAAA,CAAA,eAAA,EAAA,IAAA,CAAA,CAAA,CAAA,CAAA;AACA,mBAAA,MAAA;AACA,oBAAA,OAAA,IAAA,CAAA,CAAA,CAAA,KAAA,QAAA;AACA,oBAAA,OAAA,IAAA,CAAA,CAAA,CAAA,KAAA,QAAA;AACA,oBAAA,8BAAA,CAAA,QAAA,CAAA,YAAA;AACA,oBAAA;AACA,oBAAA,IAAA,CAAA,YAAA,CAAA,iBAAA,EAAA,IAAA,CAAA,CAAA,CAAA,CAAA;AACA,oBAAA,IAAA,CAAA,YAAA,CAAA,eAAA,EAAA,IAAA,CAAA,CAAA,CAAA,CAAA;AACA,mBAAA,MAAA,IAAA,OAAA,IAAA,CAAA,CAAA,CAAA,KAAA,QAAA,IAAA,yBAAA,CAAA,QAAA,CAAA,YAAA,CAAA,EAAA;AACA,oBAAA,IAAA,CAAA,YAAA,CAAA,iBAAA,EAAA,IAAA,CAAA,CAAA,CAAA,CAAA;AACA,mBAAA,MAAA;AACA,oBAAA,OAAA,IAAA,CAAA,CAAA,CAAA,KAAA,QAAA;AACA,oBAAA,OAAA,IAAA,CAAA,CAAA,CAAA,KAAA,QAAA;AACA,oBAAA,yCAAA,CAAA,QAAA,CAAA,YAAA;AACA,oBAAA;AACA,oBAAA,IAAA,CAAA,YAAA,CAAA,wBAAA,EAAA,IAAA,CAAA,CAAA,CAAA,CAAA;AACA,oBAAA,IAAA,CAAA,YAAA,CAAA,mBAAA,EAAA,IAAA,CAAA,CAAA,CAAA,CAAA;AACA,mBAAA,MAAA;AACA,oBAAA,OAAA,IAAA,CAAA,CAAA,CAAA,KAAA,QAAA;AACA,oBAAA,OAAA,IAAA,CAAA,CAAA,CAAA,KAAA,QAAA;AACA,oBAAA,2BAAA,CAAA,QAAA,CAAA,YAAA;AACA,oBAAA;AACA,oBAAA,IAAA,CAAA,YAAA,CAAA,cAAA,EAAA,IAAA,CAAA,CAAA,CAAA,CAAA;AACA,oBAAA,IAAA,CAAA,YAAA,CAAA,eAAA,EAAA,IAAA,CAAA,CAAA,CAAA,CAAA;AACA,mBAAA,MAAA;AACA,oBAAA,OAAA,IAAA,CAAA,CAAA,CAAA,KAAA,QAAA;AACA,oBAAA,OAAA,IAAA,CAAA,CAAA,CAAA,KAAA,QAAA;AACA,oBAAA,oCAAA,CAAA,QAAA,CAAA,YAAA;AACA,oBAAA;AACA,oBAAA,IAAA,CAAA,YAAA,CAAA,mBAAA,EAAA,IAAA,CAAA,CAAA,CAAA,CAAA;AACA,oBAAA,IAAA,CAAA,YAAA,CAAA,mBAAA,EAAA,IAAA,CAAA,CAAA,CAAA,CAAA;AACA;AACA;;AAEA,gBAAA,IAAA,KAAA,IAAA,OAAA,CAAA,mCAAA,EAAA;AACA,kBAAA,IAAA,CAAA,YAAA,CAAA,UAAA,EAAA,KAAA,CAAA,OAAA,CAAA;AACA;AACA,eAAA;AACA,aAAA,CAAA;AACA,SAAA,EAAA;AACA,OAAA;AACA,KAAA;AACA,GAAA;AACA;;AAEA,MAAA,oCAAA,GAAA,CAAA,QAAA,EAAA,YAAA,CAAA;AACA,MAAA,2BAAA,GAAA,CAAA,UAAA,EAAA,IAAA,EAAA,cAAA,EAAA,QAAA,CAAA;AACA,MAAA,yCAAA,GAAA,CAAA,MAAA,EAAA,UAAA,CAAA;AACA,MAAA,yBAAA,GAAA,CAAA,SAAA,EAAA,aAAA,CAAA;AACA,MAAA,8BAAA,GAAA,CAAA,SAAA,EAAA,aAAA,CAAA;AACA,MAAA,2BAAA,GAAA;AACA,EAAA,QAAA;AACA,EAAA,YAAA;AACA,EAAA,OAAA;AACA,EAAA,OAAA;AACA,EAAA,QAAA;AACA,EAAA,OAAA;AACA,EAAA,QAAA;AACA,EAAA,OAAA;AACA,EAAA,SAAA;AACA,EAAA,MAAA;AACA,EAAA,SAAA;AACA,EAAA,SAAA;AACA,EAAA,UAAA;AACA,EAAA,UAAA;AACA,EAAA,UAAA;AACA,EAAA,iBAAA;AACA,EAAA,IAAA;AACA,EAAA,OAAA;AACA,EAAA,MAAA;AACA,EAAA,UAAA;AACA,EAAA,QAAA;AACA,EAAA,QAAA;AACA,EAAA,WAAA;AACA,EAAA,YAAA;AACA,EAAA,gBAAA;AACA,EAAA,WAAA;AACA,EAAA,WAAA;AACA,EAAA,YAAA;AACA,EAAA,YAAA;AACA,EAAA,WAAA;AACA,EAAA,aAAA;AACA,EAAA,aAAA;AACA,EAAA,WAAA;AACA,EAAA,UAAA;AACA,EAAA,aAAA;AACA,EAAA,cAAA;AACA,EAAA,cAAA;AACA,EAAA,cAAA;AACA,EAAA,qBAAA;AACA,EAAA,WAAA;AACA,EAAA,QAAA;AACA,EAAA,UAAA;AACA,EAAA,cAAA;AACA,EAAA,YAAA;AACA,EAAA,YAAA;AACA,EAAA,eAAA;AACA,CAAA;;;;"}
1
+ {"version":3,"file":"fs.js","sources":["../../../src/integrations/fs.ts"],"sourcesContent":["import { FsInstrumentation } from '@opentelemetry/instrumentation-fs';\nimport { defineIntegration, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';\nimport { generateInstrumentOnce } from '../otel/instrument';\n\nconst INTEGRATION_NAME = 'FileSystem';\n\n/**\n * This integration will create spans for `fs` API operations, like reading and writing files.\n *\n * **WARNING:** This integration may add significant overhead to your application. Especially in scenarios with a lot of\n * file I/O, like for example when running a framework dev server, including this integration can massively slow down\n * your application.\n *\n * @param options Configuration for this integration.\n */\nexport const fsIntegration = defineIntegration(\n (\n options: {\n /**\n * Setting this option to `true` will include any filepath arguments from your `fs` API calls as span attributes.\n *\n * Defaults to `false`.\n */\n recordFilePaths?: boolean;\n\n /**\n * Setting this option to `true` will include the error messages of failed `fs` API calls as a span attribute.\n *\n * Defaults to `false`.\n */\n recordErrorMessagesAsSpanAttributes?: boolean;\n } = {},\n ) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n generateInstrumentOnce(\n INTEGRATION_NAME,\n () =>\n new FsInstrumentation({\n requireParentSpan: true,\n endHook(functionName, { args, span, error }) {\n span.updateName(`fs.${functionName}`);\n\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'file',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.file.fs',\n });\n\n if (options.recordErrorMessagesAsSpanAttributes) {\n if (typeof args[0] === 'string' && FS_OPERATIONS_WITH_PATH_ARG.includes(functionName)) {\n span.setAttribute('path_argument', args[0]);\n } else if (\n typeof args[0] === 'string' &&\n typeof args[1] === 'string' &&\n FS_OPERATIONS_WITH_TARGET_PATH.includes(functionName)\n ) {\n span.setAttribute('target_argument', args[0]);\n span.setAttribute('path_argument', args[1]);\n } else if (typeof args[0] === 'string' && FS_OPERATIONS_WITH_PREFIX.includes(functionName)) {\n span.setAttribute('prefix_argument', args[0]);\n } else if (\n typeof args[0] === 'string' &&\n typeof args[1] === 'string' &&\n FS_OPERATIONS_WITH_EXISTING_PATH_NEW_PATH.includes(functionName)\n ) {\n span.setAttribute('existing_path_argument', args[0]);\n span.setAttribute('new_path_argument', args[1]);\n } else if (\n typeof args[0] === 'string' &&\n typeof args[1] === 'string' &&\n FS_OPERATIONS_WITH_SRC_DEST.includes(functionName)\n ) {\n span.setAttribute('src_argument', args[0]);\n span.setAttribute('dest_argument', args[1]);\n } else if (\n typeof args[0] === 'string' &&\n typeof args[1] === 'string' &&\n FS_OPERATIONS_WITH_OLD_PATH_NEW_PATH.includes(functionName)\n ) {\n span.setAttribute('old_path_argument', args[0]);\n span.setAttribute('new_path_argument', args[1]);\n }\n }\n\n if (error && options.recordErrorMessagesAsSpanAttributes) {\n span.setAttribute('fs_error', error.message);\n }\n },\n }),\n )();\n },\n };\n },\n);\n\nconst FS_OPERATIONS_WITH_OLD_PATH_NEW_PATH = ['rename', 'renameSync'];\nconst FS_OPERATIONS_WITH_SRC_DEST = ['copyFile', 'cp', 'copyFileSync', 'cpSync'];\nconst FS_OPERATIONS_WITH_EXISTING_PATH_NEW_PATH = ['link', 'linkSync'];\nconst FS_OPERATIONS_WITH_PREFIX = ['mkdtemp', 'mkdtempSync'];\nconst FS_OPERATIONS_WITH_TARGET_PATH = ['symlink', 'symlinkSync'];\nconst FS_OPERATIONS_WITH_PATH_ARG = [\n 'access',\n 'appendFile',\n 'chmod',\n 'chown',\n 'exists',\n 'mkdir',\n 'lchown',\n 'lstat',\n 'lutimes',\n 'open',\n 'opendir',\n 'readdir',\n 'readFile',\n 'readlink',\n 'realpath',\n 'realpath.native',\n 'rm',\n 'rmdir',\n 'stat',\n 'truncate',\n 'unlink',\n 'utimes',\n 'writeFile',\n 'accessSync',\n 'appendFileSync',\n 'chmodSync',\n 'chownSync',\n 'existsSync',\n 'lchownSync',\n 'lstatSync',\n 'lutimesSync',\n 'opendirSync',\n 'mkdirSync',\n 'openSync',\n 'readdirSync',\n 'readFileSync',\n 'readlinkSync',\n 'realpathSync',\n 'realpathSync.native',\n 'rmdirSync',\n 'rmSync',\n 'statSync',\n 'truncateSync',\n 'unlinkSync',\n 'utimesSync',\n 'writeFileSync',\n];\n"],"names":["defineIntegration","generateInstrumentOnce","FsInstrumentation","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN"],"mappings":"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"}
@@ -1,15 +1,12 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
+ const diagnosticsChannel = require('node:diagnostics_channel');
3
4
  const api = require('@opentelemetry/api');
4
5
  const core = require('@opentelemetry/core');
5
6
  const instrumentation = require('@opentelemetry/instrumentation');
6
7
  const core$1 = require('@sentry/core');
7
8
  const debugBuild = require('../../debug-build.js');
8
9
  const getRequestUrl = require('../../utils/getRequestUrl.js');
9
- const utils = require('./utils.js');
10
- const getRequestInfo = require('./vendor/getRequestInfo.js');
11
-
12
- /* eslint-disable max-lines */
13
10
 
14
11
  const INSTRUMENTATION_NAME = '@sentry/instrumentation-http';
15
12
 
@@ -36,71 +33,134 @@ class SentryHttpInstrumentation extends instrumentation.InstrumentationBase {
36
33
 
37
34
  /** @inheritdoc */
38
35
  init() {
39
- return [this._getHttpsInstrumentation(), this._getHttpInstrumentation()];
40
- }
36
+ // We register handlers when either http or https is instrumented
37
+ // but we only want to register them once, whichever is loaded first
38
+ let hasRegisteredHandlers = false;
39
+
40
+ const onHttpServerRequestStart = ((_data) => {
41
+ const data = _data ;
42
+ this._patchServerEmitOnce(data.server);
43
+ }) ;
44
+
45
+ const onHttpClientResponseFinish = ((_data) => {
46
+ const data = _data ;
47
+ this._onOutgoingRequestFinish(data.request, data.response);
48
+ }) ;
49
+
50
+ const onHttpClientRequestError = ((_data) => {
51
+ const data = _data ;
52
+ this._onOutgoingRequestFinish(data.request, undefined);
53
+ }) ;
54
+
55
+ /**
56
+ * You may be wondering why we register these diagnostics-channel listeners
57
+ * in such a convoluted way (as InstrumentationNodeModuleDefinition...)˝,
58
+ * instead of simply subscribing to the events once in here.
59
+ * The reason for this is timing semantics: These functions are called once the http or https module is loaded.
60
+ * If we'd subscribe before that, there seem to be conflicts with the OTEL native instrumentation in some scenarios,
61
+ * especially the "import-on-top" pattern of setting up ESM applications.
62
+ */
63
+ return [
64
+ new instrumentation.InstrumentationNodeModuleDefinition(
65
+ 'http',
66
+ ['*'],
67
+ (moduleExports) => {
68
+ if (hasRegisteredHandlers) {
69
+ return moduleExports;
70
+ }
41
71
 
42
- /** Get the instrumentation for the http module. */
43
- _getHttpInstrumentation() {
44
- return new instrumentation.InstrumentationNodeModuleDefinition(
45
- 'http',
46
- ['*'],
47
- (moduleExports) => {
48
- // Patch incoming requests for request isolation
49
- utils.stealthWrap(moduleExports.Server.prototype, 'emit', this._getPatchIncomingRequestFunction());
72
+ hasRegisteredHandlers = true;
73
+
74
+ diagnosticsChannel.subscribe('http.server.request.start', onHttpServerRequestStart);
75
+ diagnosticsChannel.subscribe('http.client.response.finish', onHttpClientResponseFinish);
76
+
77
+ // When an error happens, we still want to have a breadcrumb
78
+ // In this case, `http.client.response.finish` is not triggered
79
+ diagnosticsChannel.subscribe('http.client.request.error', onHttpClientRequestError);
80
+
81
+ return moduleExports;
82
+ },
83
+ () => {
84
+ diagnosticsChannel.unsubscribe('http.server.request.start', onHttpServerRequestStart);
85
+ diagnosticsChannel.unsubscribe('http.client.response.finish', onHttpClientResponseFinish);
86
+ diagnosticsChannel.unsubscribe('http.client.request.error', onHttpClientRequestError);
87
+ },
88
+ ),
89
+ new instrumentation.InstrumentationNodeModuleDefinition(
90
+ 'https',
91
+ ['*'],
92
+ (moduleExports) => {
93
+ if (hasRegisteredHandlers) {
94
+ return moduleExports;
95
+ }
50
96
 
51
- // Patch outgoing requests for breadcrumbs
52
- const patchedRequest = utils.stealthWrap(moduleExports, 'request', this._getPatchOutgoingRequestFunction());
53
- utils.stealthWrap(moduleExports, 'get', this._getPatchOutgoingGetFunction(patchedRequest));
97
+ hasRegisteredHandlers = true;
54
98
 
55
- return moduleExports;
56
- },
57
- () => {
58
- // no unwrap here
59
- },
60
- );
99
+ diagnosticsChannel.subscribe('http.server.request.start', onHttpServerRequestStart);
100
+ diagnosticsChannel.subscribe('http.client.response.finish', onHttpClientResponseFinish);
101
+
102
+ // When an error happens, we still want to have a breadcrumb
103
+ // In this case, `http.client.response.finish` is not triggered
104
+ diagnosticsChannel.subscribe('http.client.request.error', onHttpClientRequestError);
105
+
106
+ return moduleExports;
107
+ },
108
+ () => {
109
+ diagnosticsChannel.unsubscribe('http.server.request.start', onHttpServerRequestStart);
110
+ diagnosticsChannel.unsubscribe('http.client.response.finish', onHttpClientResponseFinish);
111
+ diagnosticsChannel.unsubscribe('http.client.request.error', onHttpClientRequestError);
112
+ },
113
+ ),
114
+ ];
61
115
  }
62
116
 
63
- /** Get the instrumentation for the https module. */
64
- _getHttpsInstrumentation() {
65
- return new instrumentation.InstrumentationNodeModuleDefinition(
66
- 'https',
67
- ['*'],
68
- (moduleExports) => {
69
- // Patch incoming requests for request isolation
70
- utils.stealthWrap(moduleExports.Server.prototype, 'emit', this._getPatchIncomingRequestFunction());
117
+ /**
118
+ * This is triggered when an outgoing request finishes.
119
+ * It has access to the final request and response objects.
120
+ */
121
+ _onOutgoingRequestFinish(request, response) {
122
+ debugBuild.DEBUG_BUILD && core$1.logger.log(INSTRUMENTATION_NAME, 'Handling finished outgoing request');
71
123
 
72
- // Patch outgoing requests for breadcrumbs
73
- const patchedRequest = utils.stealthWrap(moduleExports, 'request', this._getPatchOutgoingRequestFunction());
74
- utils.stealthWrap(moduleExports, 'get', this._getPatchOutgoingGetFunction(patchedRequest));
124
+ const _breadcrumbs = this.getConfig().breadcrumbs;
125
+ const breadCrumbsEnabled = typeof _breadcrumbs === 'undefined' ? true : _breadcrumbs;
126
+ const options = getRequestOptions(request);
75
127
 
76
- return moduleExports;
77
- },
78
- () => {
79
- // no unwrap here
80
- },
81
- );
128
+ const _ignoreOutgoingRequests = this.getConfig().ignoreOutgoingRequests;
129
+ const shouldCreateBreadcrumb =
130
+ typeof _ignoreOutgoingRequests === 'function' ? !_ignoreOutgoingRequests(getRequestUrl.getRequestUrl(request), options) : true;
131
+
132
+ if (breadCrumbsEnabled && shouldCreateBreadcrumb) {
133
+ addRequestBreadcrumb(request, response);
134
+ }
82
135
  }
83
136
 
84
137
  /**
85
- * Patch the incoming request function for request isolation.
138
+ * Patch a server.emit function to handle process isolation for incoming requests.
139
+ * This will only patch the emit function if it was not already patched.
86
140
  */
87
- _getPatchIncomingRequestFunction()
141
+ _patchServerEmitOnce(server) {
142
+ // eslint-disable-next-line @typescript-eslint/unbound-method
143
+ const originalEmit = server.emit;
144
+
145
+ // This means it was already patched, do nothing
146
+ if ((originalEmit ).__sentry_patched__) {
147
+ return;
148
+ }
149
+
150
+ debugBuild.DEBUG_BUILD && core$1.logger.log(INSTRUMENTATION_NAME, 'Patching server.emit');
88
151
 
89
- {
90
152
  // eslint-disable-next-line @typescript-eslint/no-this-alias
91
153
  const instrumentation = this;
92
154
  const { ignoreIncomingRequestBody } = instrumentation.getConfig();
93
155
 
94
- return (
95
- original,
96
- ) => {
97
- return function incomingRequest( ...args) {
156
+ const newEmit = new Proxy(originalEmit, {
157
+ apply(target, thisArg, args) {
98
158
  // Only traces request events
99
159
  if (args[0] !== 'request') {
100
- return original.apply(this, args);
160
+ return target.apply(thisArg, args);
101
161
  }
102
162
 
103
- instrumentation._diag.debug('http instrumentation for incoming request');
163
+ debugBuild.DEBUG_BUILD && core$1.logger.log(INSTRUMENTATION_NAME, 'Handling incoming request');
104
164
 
105
165
  const isolationScope = core$1.getIsolationScope().clone();
106
166
  const request = args[1] ;
@@ -145,88 +205,20 @@ class SentryHttpInstrumentation extends instrumentation.InstrumentationBase {
145
205
 
146
206
  // If we don't want to extract the trace from the header, we can skip this
147
207
  if (!instrumentation.getConfig().extractIncomingTraceFromHeader) {
148
- return original.apply(this, args);
208
+ return target.apply(thisArg, args);
149
209
  }
150
210
 
151
211
  const ctx = api.propagation.extract(api.context.active(), normalizedRequest.headers);
152
212
  return api.context.with(ctx, () => {
153
- return original.apply(this, args);
213
+ return target.apply(thisArg, args);
154
214
  });
155
215
  });
156
- };
157
- };
158
- }
159
-
160
- /**
161
- * Patch the outgoing request function for breadcrumbs.
162
- */
163
- _getPatchOutgoingRequestFunction()
164
-
165
- {
166
- // eslint-disable-next-line @typescript-eslint/no-this-alias
167
- const instrumentation = this;
168
-
169
- return (original) => {
170
- return function outgoingRequest( ...args) {
171
- instrumentation._diag.debug('http instrumentation for outgoing requests');
172
-
173
- // Making a copy to avoid mutating the original args array
174
- // We need to access and reconstruct the request options object passed to `ignoreOutgoingRequests`
175
- // so that it matches what Otel instrumentation passes to `ignoreOutgoingRequestHook`.
176
- // @see https://github.com/open-telemetry/opentelemetry-js/blob/7293e69c1e55ca62e15d0724d22605e61bd58952/experimental/packages/opentelemetry-instrumentation-http/src/http.ts#L756-L789
177
- const argsCopy = [...args];
178
-
179
- const options = argsCopy.shift() ;
180
-
181
- const extraOptions =
182
- typeof argsCopy[0] === 'object' && (typeof options === 'string' || options instanceof URL)
183
- ? (argsCopy.shift() )
184
- : undefined;
185
-
186
- const { optionsParsed } = getRequestInfo.getRequestInfo(instrumentation._diag, options, extraOptions);
187
-
188
- const request = original.apply(this, args) ;
189
-
190
- request.prependListener('response', (response) => {
191
- const _breadcrumbs = instrumentation.getConfig().breadcrumbs;
192
- const breadCrumbsEnabled = typeof _breadcrumbs === 'undefined' ? true : _breadcrumbs;
193
-
194
- const _ignoreOutgoingRequests = instrumentation.getConfig().ignoreOutgoingRequests;
195
- const shouldCreateBreadcrumb =
196
- typeof _ignoreOutgoingRequests === 'function'
197
- ? !_ignoreOutgoingRequests(getRequestUrl.getRequestUrl(request), optionsParsed)
198
- : true;
199
-
200
- if (breadCrumbsEnabled && shouldCreateBreadcrumb) {
201
- addRequestBreadcrumb(request, response);
202
- }
203
- });
216
+ },
217
+ });
204
218
 
205
- return request;
206
- };
207
- };
208
- }
219
+ core$1.addNonEnumerableProperty(newEmit, '__sentry_patched__', true);
209
220
 
210
- /** Path the outgoing get function for breadcrumbs. */
211
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
212
- _getPatchOutgoingGetFunction(clientRequest) {
213
- return (_original) => {
214
- // Re-implement http.get. This needs to be done (instead of using
215
- // getPatchOutgoingRequestFunction to patch it) because we need to
216
- // set the trace context header before the returned http.ClientRequest is
217
- // ended. The Node.js docs state that the only differences between
218
- // request and get are that (1) get defaults to the HTTP GET method and
219
- // (2) the returned request object is ended immediately. The former is
220
- // already true (at least in supported Node versions up to v10), so we
221
- // simply follow the latter. Ref:
222
- // https://nodejs.org/dist/latest/docs/api/http.html#http_http_get_options_callback
223
- // https://github.com/googleapis/cloud-trace-nodejs/blob/master/src/instrumentations/instrumentation-http.ts#L198
224
- return function outgoingGetRequest(...args) {
225
- const req = clientRequest(...args);
226
- req.end();
227
- return req;
228
- };
229
- };
221
+ server.emit = newEmit;
230
222
  }
231
223
  }
232
224
 
@@ -234,7 +226,7 @@ class SentryHttpInstrumentation extends instrumentation.InstrumentationBase {
234
226
  function addRequestBreadcrumb(request, response) {
235
227
  const data = getBreadcrumbData(request);
236
228
 
237
- const statusCode = response.statusCode;
229
+ const statusCode = response?.statusCode;
238
230
  const level = core$1.getBreadcrumbLogLevelFromHttpStatusCode(statusCode);
239
231
 
240
232
  core$1.addBreadcrumb(
@@ -290,6 +282,8 @@ function patchRequestToCaptureBody(req, isolationScope) {
290
282
  let bodyByteLength = 0;
291
283
  const chunks = [];
292
284
 
285
+ debugBuild.DEBUG_BUILD && core$1.logger.log(INSTRUMENTATION_NAME, 'Patching request.on');
286
+
293
287
  /**
294
288
  * We need to keep track of the original callbacks, in order to be able to remove listeners again.
295
289
  * Since `off` depends on having the exact same function reference passed in, we need to be able to map
@@ -303,11 +297,8 @@ function patchRequestToCaptureBody(req, isolationScope) {
303
297
  apply: (target, thisArg, args) => {
304
298
  const [event, listener, ...restArgs] = args;
305
299
 
306
- if (debugBuild.DEBUG_BUILD) {
307
- core$1.logger.log(INSTRUMENTATION_NAME, 'Patching request.on', event);
308
- }
309
-
310
300
  if (event === 'data') {
301
+ debugBuild.DEBUG_BUILD && core$1.logger.log(INSTRUMENTATION_NAME, 'Handling request.on("data")');
311
302
  const callback = new Proxy(listener, {
312
303
  apply: (target, thisArg, args) => {
313
304
  try {
@@ -378,6 +369,17 @@ function patchRequestToCaptureBody(req, isolationScope) {
378
369
  }
379
370
  }
380
371
 
372
+ function getRequestOptions(request) {
373
+ return {
374
+ method: request.method,
375
+ protocol: request.protocol,
376
+ host: request.host,
377
+ hostname: request.host,
378
+ path: request.path,
379
+ headers: request.getHeaders(),
380
+ };
381
+ }
382
+
381
383
  /**
382
384
  * Starts a session and tracks it in the context of a given isolation scope.
383
385
  * When the passed response is finished, the session is put into a task and is
@@ -1 +1 @@
1
- {"version":3,"file":"SentryHttpInstrumentation.js","sources":["../../../../src/integrations/http/SentryHttpInstrumentation.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport { context, propagation } from '@opentelemetry/api';\nimport { VERSION } from '@opentelemetry/core';\nimport type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';\nimport type { AggregationCounts, Client, SanitizedRequestData, Scope } from '@sentry/core';\nimport {\n addBreadcrumb,\n generateSpanId,\n getBreadcrumbLogLevelFromHttpStatusCode,\n getClient,\n getCurrentScope,\n getIsolationScope,\n getSanitizedUrlString,\n httpRequestToRequestData,\n logger,\n parseUrl,\n stripUrlQueryAndFragment,\n withIsolationScope,\n} from '@sentry/core';\nimport type * as http from 'node:http';\nimport type { IncomingMessage, RequestOptions } from 'node:http';\nimport type * as https from 'node:https';\nimport type { EventEmitter } from 'node:stream';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { getRequestUrl } from '../../utils/getRequestUrl';\nimport { stealthWrap } from './utils';\nimport { getRequestInfo } from './vendor/getRequestInfo';\n\ntype Http = typeof http;\ntype Https = typeof https;\n\nconst INSTRUMENTATION_NAME = '@sentry/instrumentation-http';\n\nexport type SentryHttpInstrumentationOptions = InstrumentationConfig & {\n /**\n * Whether breadcrumbs should be recorded for requests.\n *\n * @default `true`\n */\n breadcrumbs?: boolean;\n\n /**\n * Whether to extract the trace ID from the `sentry-trace` header for incoming requests.\n * By default this is done by the HttpInstrumentation, but if that is not added (e.g. because tracing is disabled, ...)\n * then this instrumentation can take over.\n *\n * @default `false`\n */\n extractIncomingTraceFromHeader?: boolean;\n\n /**\n * Do not capture breadcrumbs for outgoing HTTP requests to URLs where the given callback returns `true`.\n * For the scope of this instrumentation, this callback only controls breadcrumb creation.\n * The same option can be passed to the top-level httpIntegration where it controls both, breadcrumb and\n * span creation.\n *\n * @param url Contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n * @param request Contains the {@type RequestOptions} object used to make the outgoing request.\n */\n ignoreOutgoingRequests?: (url: string, request: RequestOptions) => boolean;\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 outgoing request.\n * @param request Contains the {@type RequestOptions} object used to make the outgoing request.\n */\n ignoreIncomingRequestBody?: (url: string, request: RequestOptions) => 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// We only want to capture request bodies up to 1mb.\nconst MAX_BODY_BYTE_LENGTH = 1024 * 1024;\n\n/**\n * This custom HTTP instrumentation is used to isolate incoming requests and annotate them with additional information.\n * It does not emit any spans.\n *\n * The reason this is isolated from the OpenTelemetry instrumentation is that users may overwrite this,\n * which would lead to Sentry not working as expected.\n *\n * Important note: Contrary to other OTEL instrumentation, this one cannot be unwrapped.\n * It only does minimal things though and does not emit any spans.\n *\n * This is heavily inspired & adapted from:\n * https://github.com/open-telemetry/opentelemetry-js/blob/f8ab5592ddea5cba0a3b33bf8d74f27872c0367f/experimental/packages/opentelemetry-instrumentation-http/src/http.ts\n */\nexport class SentryHttpInstrumentation extends InstrumentationBase<SentryHttpInstrumentationOptions> {\n public constructor(config: SentryHttpInstrumentationOptions = {}) {\n super(INSTRUMENTATION_NAME, VERSION, config);\n }\n\n /** @inheritdoc */\n public init(): [InstrumentationNodeModuleDefinition, InstrumentationNodeModuleDefinition] {\n return [this._getHttpsInstrumentation(), this._getHttpInstrumentation()];\n }\n\n /** Get the instrumentation for the http module. */\n private _getHttpInstrumentation(): InstrumentationNodeModuleDefinition {\n return new InstrumentationNodeModuleDefinition(\n 'http',\n ['*'],\n (moduleExports: Http): Http => {\n // Patch incoming requests for request isolation\n stealthWrap(moduleExports.Server.prototype, 'emit', this._getPatchIncomingRequestFunction());\n\n // Patch outgoing requests for breadcrumbs\n const patchedRequest = stealthWrap(moduleExports, 'request', this._getPatchOutgoingRequestFunction());\n stealthWrap(moduleExports, 'get', this._getPatchOutgoingGetFunction(patchedRequest));\n\n return moduleExports;\n },\n () => {\n // no unwrap here\n },\n );\n }\n\n /** Get the instrumentation for the https module. */\n private _getHttpsInstrumentation(): InstrumentationNodeModuleDefinition {\n return new InstrumentationNodeModuleDefinition(\n 'https',\n ['*'],\n (moduleExports: Https): Https => {\n // Patch incoming requests for request isolation\n stealthWrap(moduleExports.Server.prototype, 'emit', this._getPatchIncomingRequestFunction());\n\n // Patch outgoing requests for breadcrumbs\n const patchedRequest = stealthWrap(moduleExports, 'request', this._getPatchOutgoingRequestFunction());\n stealthWrap(moduleExports, 'get', this._getPatchOutgoingGetFunction(patchedRequest));\n\n return moduleExports;\n },\n () => {\n // no unwrap here\n },\n );\n }\n\n /**\n * Patch the incoming request function for request isolation.\n */\n private _getPatchIncomingRequestFunction(): (\n original: (event: string, ...args: unknown[]) => boolean,\n ) => (this: unknown, event: string, ...args: unknown[]) => boolean {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const instrumentation = this;\n const { ignoreIncomingRequestBody } = instrumentation.getConfig();\n\n return (\n original: (event: string, ...args: unknown[]) => boolean,\n ): ((this: unknown, event: string, ...args: unknown[]) => boolean) => {\n return function incomingRequest(this: unknown, ...args: [event: string, ...args: unknown[]]): boolean {\n // Only traces request events\n if (args[0] !== 'request') {\n return original.apply(this, args);\n }\n\n instrumentation._diag.debug('http instrumentation for incoming request');\n\n const isolationScope = getIsolationScope().clone();\n const request = args[1] as http.IncomingMessage;\n const response = args[2] as http.OutgoingMessage;\n\n const normalizedRequest = httpRequestToRequestData(request);\n\n // request.ip is non-standard but some frameworks set this\n const ipAddress = (request as { ip?: string }).ip || request.socket?.remoteAddress;\n\n const url = request.url || '/';\n if (!ignoreIncomingRequestBody?.(url, request)) {\n patchRequestToCaptureBody(request, isolationScope);\n }\n\n // Update the isolation scope, isolate this request\n isolationScope.setSDKProcessingMetadata({ normalizedRequest, ipAddress });\n\n // attempt to update the scope's `transactionName` based on the request URL\n // Ideally, framework instrumentations coming after the HttpInstrumentation\n // update the transactionName once we get a parameterized route.\n const httpMethod = (request.method || 'GET').toUpperCase();\n const httpTarget = stripUrlQueryAndFragment(url);\n\n const bestEffortTransactionName = `${httpMethod} ${httpTarget}`;\n\n isolationScope.setTransactionName(bestEffortTransactionName);\n\n if (instrumentation.getConfig().trackIncomingRequestsAsSessions !== false) {\n recordRequestSession({\n requestIsolationScope: isolationScope,\n response,\n sessionFlushingDelayMS: instrumentation.getConfig().sessionFlushingDelayMS ?? 60_000,\n });\n }\n\n return withIsolationScope(isolationScope, () => {\n // Set a new propagationSpanId for this request\n // We rely on the fact that `withIsolationScope()` will implicitly also fork the current scope\n // This way we can save an \"unnecessary\" `withScope()` invocation\n getCurrentScope().getPropagationContext().propagationSpanId = generateSpanId();\n\n // If we don't want to extract the trace from the header, we can skip this\n if (!instrumentation.getConfig().extractIncomingTraceFromHeader) {\n return original.apply(this, args);\n }\n\n const ctx = propagation.extract(context.active(), normalizedRequest.headers);\n return context.with(ctx, () => {\n return original.apply(this, args);\n });\n });\n };\n };\n }\n\n /**\n * Patch the outgoing request function for breadcrumbs.\n */\n private _getPatchOutgoingRequestFunction(): (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n original: (...args: any[]) => http.ClientRequest,\n ) => (options: URL | http.RequestOptions | string, ...args: unknown[]) => http.ClientRequest {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const instrumentation = this;\n\n return (original: (...args: unknown[]) => http.ClientRequest): ((...args: unknown[]) => http.ClientRequest) => {\n return function outgoingRequest(this: unknown, ...args: unknown[]): http.ClientRequest {\n instrumentation._diag.debug('http instrumentation for outgoing requests');\n\n // Making a copy to avoid mutating the original args array\n // We need to access and reconstruct the request options object passed to `ignoreOutgoingRequests`\n // so that it matches what Otel instrumentation passes to `ignoreOutgoingRequestHook`.\n // @see https://github.com/open-telemetry/opentelemetry-js/blob/7293e69c1e55ca62e15d0724d22605e61bd58952/experimental/packages/opentelemetry-instrumentation-http/src/http.ts#L756-L789\n const argsCopy = [...args];\n\n const options = argsCopy.shift() as URL | http.RequestOptions | string;\n\n const extraOptions =\n typeof argsCopy[0] === 'object' && (typeof options === 'string' || options instanceof URL)\n ? (argsCopy.shift() as http.RequestOptions)\n : undefined;\n\n const { optionsParsed } = getRequestInfo(instrumentation._diag, options, extraOptions);\n\n const request = original.apply(this, args) as ReturnType<typeof http.request>;\n\n request.prependListener('response', (response: http.IncomingMessage) => {\n const _breadcrumbs = instrumentation.getConfig().breadcrumbs;\n const breadCrumbsEnabled = typeof _breadcrumbs === 'undefined' ? true : _breadcrumbs;\n\n const _ignoreOutgoingRequests = instrumentation.getConfig().ignoreOutgoingRequests;\n const shouldCreateBreadcrumb =\n typeof _ignoreOutgoingRequests === 'function'\n ? !_ignoreOutgoingRequests(getRequestUrl(request), optionsParsed)\n : true;\n\n if (breadCrumbsEnabled && shouldCreateBreadcrumb) {\n addRequestBreadcrumb(request, response);\n }\n });\n\n return request;\n };\n };\n }\n\n /** Path the outgoing get function for breadcrumbs. */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private _getPatchOutgoingGetFunction(clientRequest: (...args: any[]) => http.ClientRequest) {\n return (_original: unknown): ((...args: unknown[]) => http.ClientRequest) => {\n // Re-implement http.get. This needs to be done (instead of using\n // getPatchOutgoingRequestFunction to patch it) because we need to\n // set the trace context header before the returned http.ClientRequest is\n // ended. The Node.js docs state that the only differences between\n // request and get are that (1) get defaults to the HTTP GET method and\n // (2) the returned request object is ended immediately. The former is\n // already true (at least in supported Node versions up to v10), so we\n // simply follow the latter. Ref:\n // https://nodejs.org/dist/latest/docs/api/http.html#http_http_get_options_callback\n // https://github.com/googleapis/cloud-trace-nodejs/blob/master/src/instrumentations/instrumentation-http.ts#L198\n return function outgoingGetRequest(...args: unknown[]): http.ClientRequest {\n const req = clientRequest(...args);\n req.end();\n return req;\n };\n };\n }\n}\n\n/** Add a breadcrumb for outgoing requests. */\nfunction addRequestBreadcrumb(request: http.ClientRequest, response: http.IncomingMessage): void {\n const data = getBreadcrumbData(request);\n\n const statusCode = response.statusCode;\n const level = getBreadcrumbLogLevelFromHttpStatusCode(statusCode);\n\n addBreadcrumb(\n {\n category: 'http',\n data: {\n status_code: statusCode,\n ...data,\n },\n type: 'http',\n level,\n },\n {\n event: 'response',\n request,\n response,\n },\n );\n}\n\nfunction getBreadcrumbData(request: http.ClientRequest): Partial<SanitizedRequestData> {\n try {\n // `request.host` does not contain the port, but the host header does\n const host = request.getHeader('host') || request.host;\n const url = new URL(request.path, `${request.protocol}//${host}`);\n const parsedUrl = parseUrl(url.toString());\n\n const data: Partial<SanitizedRequestData> = {\n url: getSanitizedUrlString(parsedUrl),\n 'http.method': request.method || 'GET',\n };\n\n if (parsedUrl.search) {\n data['http.query'] = parsedUrl.search;\n }\n if (parsedUrl.hash) {\n data['http.fragment'] = parsedUrl.hash;\n }\n\n return data;\n } catch {\n return {};\n }\n}\n\n/**\n * This method patches the request object to capture the body.\n * Instead of actually consuming the streamed body ourselves, which has potential side effects,\n * we monkey patch `req.on('data')` to intercept the body chunks.\n * This way, we only read the body if the user also consumes the body, ensuring we do not change any behavior in unexpected ways.\n */\nfunction patchRequestToCaptureBody(req: IncomingMessage, isolationScope: Scope): void {\n let bodyByteLength = 0;\n const chunks: Buffer[] = [];\n\n /**\n * We need to keep track of the original callbacks, in order to be able to remove listeners again.\n * Since `off` depends on having the exact same function reference passed in, we need to be able to map\n * original listeners to our wrapped ones.\n */\n const callbackMap = new WeakMap();\n\n try {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n req.on = new Proxy(req.on, {\n apply: (target, thisArg, args: Parameters<typeof req.on>) => {\n const [event, listener, ...restArgs] = args;\n\n if (DEBUG_BUILD) {\n logger.log(INSTRUMENTATION_NAME, 'Patching request.on', event);\n }\n\n if (event === 'data') {\n const callback = new Proxy(listener, {\n apply: (target, thisArg, args: Parameters<typeof listener>) => {\n try {\n const chunk = args[0] as Buffer | string;\n const bufferifiedChunk = Buffer.from(chunk);\n\n if (bodyByteLength < MAX_BODY_BYTE_LENGTH) {\n chunks.push(bufferifiedChunk);\n bodyByteLength += bufferifiedChunk.byteLength;\n } else if (DEBUG_BUILD) {\n logger.log(\n INSTRUMENTATION_NAME,\n `Dropping request body chunk because maximum body length of ${MAX_BODY_BYTE_LENGTH}b is exceeded.`,\n );\n }\n } catch (err) {\n DEBUG_BUILD && logger.error(INSTRUMENTATION_NAME, 'Encountered error while storing body chunk.');\n }\n\n return Reflect.apply(target, thisArg, args);\n },\n });\n\n callbackMap.set(listener, callback);\n\n return Reflect.apply(target, thisArg, [event, callback, ...restArgs]);\n }\n\n return Reflect.apply(target, thisArg, args);\n },\n });\n\n // Ensure we also remove callbacks correctly\n // eslint-disable-next-line @typescript-eslint/unbound-method\n req.off = new Proxy(req.off, {\n apply: (target, thisArg, args: Parameters<typeof req.off>) => {\n const [, listener] = args;\n\n const callback = callbackMap.get(listener);\n if (callback) {\n callbackMap.delete(listener);\n\n const modifiedArgs = args.slice();\n modifiedArgs[1] = callback;\n return Reflect.apply(target, thisArg, modifiedArgs);\n }\n\n return Reflect.apply(target, thisArg, args);\n },\n });\n\n req.on('end', () => {\n try {\n const body = Buffer.concat(chunks).toString('utf-8');\n if (body) {\n isolationScope.setSDKProcessingMetadata({ normalizedRequest: { data: body } });\n }\n } catch (error) {\n if (DEBUG_BUILD) {\n logger.error(INSTRUMENTATION_NAME, 'Error building captured request body', error);\n }\n }\n });\n } catch (error) {\n if (DEBUG_BUILD) {\n logger.error(INSTRUMENTATION_NAME, 'Error patching request to capture body', error);\n }\n }\n}\n\n/**\n * Starts a session and tracks it in the context of a given isolation scope.\n * When the passed response is finished, the session is put into a task and is\n * aggregated with other sessions that may happen in a certain time window\n * (sessionFlushingDelayMs).\n *\n * The sessions are always aggregated by the client that is on the current scope\n * at the time of ending the response (if there is one).\n */\n// Exported for unit tests\nexport function recordRequestSession({\n requestIsolationScope,\n response,\n sessionFlushingDelayMS,\n}: {\n requestIsolationScope: Scope;\n response: EventEmitter;\n sessionFlushingDelayMS?: number;\n}): void {\n requestIsolationScope.setSDKProcessingMetadata({\n requestSession: { status: 'ok' },\n });\n response.once('close', () => {\n // We need to grab the client off the current scope instead of the isolation scope because the isolation scope doesn't hold any client out of the box.\n const client = getClient();\n const requestSession = requestIsolationScope.getScopeData().sdkProcessingMetadata.requestSession;\n\n if (client && requestSession) {\n DEBUG_BUILD && logger.debug(`Recorded request session with status: ${requestSession.status}`);\n\n const roundedDate = new Date();\n roundedDate.setSeconds(0, 0);\n const dateBucketKey = roundedDate.toISOString();\n\n const existingClientAggregate = clientToRequestSessionAggregatesMap.get(client);\n const bucket = existingClientAggregate?.[dateBucketKey] || { exited: 0, crashed: 0, errored: 0 };\n bucket[({ ok: 'exited', crashed: 'crashed', errored: 'errored' } as const)[requestSession.status]]++;\n\n if (existingClientAggregate) {\n existingClientAggregate[dateBucketKey] = bucket;\n } else {\n DEBUG_BUILD && logger.debug('Opened new request session aggregate.');\n const newClientAggregate = { [dateBucketKey]: bucket };\n clientToRequestSessionAggregatesMap.set(client, newClientAggregate);\n\n const flushPendingClientAggregates = (): void => {\n clearTimeout(timeout);\n unregisterClientFlushHook();\n clientToRequestSessionAggregatesMap.delete(client);\n\n const aggregatePayload: AggregationCounts[] = Object.entries(newClientAggregate).map(\n ([timestamp, value]) => ({\n started: timestamp,\n exited: value.exited,\n errored: value.errored,\n crashed: value.crashed,\n }),\n );\n client.sendSession({ aggregates: aggregatePayload });\n };\n\n const unregisterClientFlushHook = client.on('flush', () => {\n DEBUG_BUILD && logger.debug('Sending request session aggregate due to client flush');\n flushPendingClientAggregates();\n });\n const timeout = setTimeout(() => {\n DEBUG_BUILD && logger.debug('Sending request session aggregate due to flushing schedule');\n flushPendingClientAggregates();\n }, sessionFlushingDelayMS).unref();\n }\n }\n });\n}\n\nconst clientToRequestSessionAggregatesMap = new Map<\n Client,\n { [timestampRoundedToSeconds: string]: { exited: number; crashed: number; errored: number } }\n>();\n"],"names":["InstrumentationBase","VERSION","InstrumentationNodeModuleDefinition","stealthWrap","getIsolationScope","httpRequestToRequestData","stripUrlQueryAndFragment","withIsolationScope","getCurrentScope","generateSpanId","propagation","context","getRequestInfo","getRequestUrl","getBreadcrumbLogLevelFromHttpStatusCode","addBreadcrumb","parseUrl","getSanitizedUrlString","DEBUG_BUILD","logger","getClient"],"mappings":"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"}
1
+ {"version":3,"file":"SentryHttpInstrumentation.js","sources":["../../../../src/integrations/http/SentryHttpInstrumentation.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { ChannelListener } from 'node:diagnostics_channel';\nimport { subscribe, unsubscribe } from 'node:diagnostics_channel';\nimport type * as http from 'node:http';\nimport type * as https from 'node:https';\nimport type { EventEmitter } from 'node:stream';\nimport { context, propagation } from '@opentelemetry/api';\nimport { VERSION } from '@opentelemetry/core';\nimport type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';\nimport type { AggregationCounts, Client, SanitizedRequestData, Scope } from '@sentry/core';\nimport {\n addBreadcrumb,\n addNonEnumerableProperty,\n generateSpanId,\n getBreadcrumbLogLevelFromHttpStatusCode,\n getClient,\n getCurrentScope,\n getIsolationScope,\n getSanitizedUrlString,\n httpRequestToRequestData,\n logger,\n parseUrl,\n stripUrlQueryAndFragment,\n withIsolationScope,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { getRequestUrl } from '../../utils/getRequestUrl';\n\nconst INSTRUMENTATION_NAME = '@sentry/instrumentation-http';\n\ntype Http = typeof http;\ntype Https = typeof https;\n\nexport type SentryHttpInstrumentationOptions = InstrumentationConfig & {\n /**\n * Whether breadcrumbs should be recorded for requests.\n *\n * @default `true`\n */\n breadcrumbs?: boolean;\n\n /**\n * Whether to extract the trace ID from the `sentry-trace` header for incoming requests.\n * By default this is done by the HttpInstrumentation, but if that is not added (e.g. because tracing is disabled, ...)\n * then this instrumentation can take over.\n *\n * @default `false`\n */\n extractIncomingTraceFromHeader?: boolean;\n\n /**\n * Do not capture breadcrumbs for outgoing HTTP requests to URLs where the given callback returns `true`.\n * For the scope of this instrumentation, this callback only controls breadcrumb creation.\n * The same option can be passed to the top-level httpIntegration where it controls both, breadcrumb and\n * span creation.\n *\n * @param url Contains the entire URL, including query string (if any), protocol, host, etc. of the outgoing request.\n * @param request Contains the {@type RequestOptions} object used to make the outgoing request.\n */\n ignoreOutgoingRequests?: (url: string, request: http.RequestOptions) => boolean;\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 outgoing request.\n * @param request Contains the {@type RequestOptions} object used to make the outgoing request.\n */\n ignoreIncomingRequestBody?: (url: string, request: http.RequestOptions) => 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// We only want to capture request bodies up to 1mb.\nconst MAX_BODY_BYTE_LENGTH = 1024 * 1024;\n\n/**\n * This custom HTTP instrumentation is used to isolate incoming requests and annotate them with additional information.\n * It does not emit any spans.\n *\n * The reason this is isolated from the OpenTelemetry instrumentation is that users may overwrite this,\n * which would lead to Sentry not working as expected.\n *\n * Important note: Contrary to other OTEL instrumentation, this one cannot be unwrapped.\n * It only does minimal things though and does not emit any spans.\n *\n * This is heavily inspired & adapted from:\n * https://github.com/open-telemetry/opentelemetry-js/blob/f8ab5592ddea5cba0a3b33bf8d74f27872c0367f/experimental/packages/opentelemetry-instrumentation-http/src/http.ts\n */\nexport class SentryHttpInstrumentation extends InstrumentationBase<SentryHttpInstrumentationOptions> {\n public constructor(config: SentryHttpInstrumentationOptions = {}) {\n super(INSTRUMENTATION_NAME, VERSION, config);\n }\n\n /** @inheritdoc */\n public init(): [InstrumentationNodeModuleDefinition, InstrumentationNodeModuleDefinition] {\n // We register handlers when either http or https is instrumented\n // but we only want to register them once, whichever is loaded first\n let hasRegisteredHandlers = false;\n\n const onHttpServerRequestStart = ((_data: unknown) => {\n const data = _data as { server: http.Server };\n this._patchServerEmitOnce(data.server);\n }) satisfies ChannelListener;\n\n const onHttpClientResponseFinish = ((_data: unknown) => {\n const data = _data as { request: http.ClientRequest; response: http.IncomingMessage };\n this._onOutgoingRequestFinish(data.request, data.response);\n }) satisfies ChannelListener;\n\n const onHttpClientRequestError = ((_data: unknown) => {\n const data = _data as { request: http.ClientRequest };\n this._onOutgoingRequestFinish(data.request, undefined);\n }) satisfies ChannelListener;\n\n /**\n * You may be wondering why we register these diagnostics-channel listeners\n * in such a convoluted way (as InstrumentationNodeModuleDefinition...)˝,\n * instead of simply subscribing to the events once in here.\n * The reason for this is timing semantics: These functions are called once the http or https module is loaded.\n * If we'd subscribe before that, there seem to be conflicts with the OTEL native instrumentation in some scenarios,\n * especially the \"import-on-top\" pattern of setting up ESM applications.\n */\n return [\n new InstrumentationNodeModuleDefinition(\n 'http',\n ['*'],\n (moduleExports: Http): Http => {\n if (hasRegisteredHandlers) {\n return moduleExports;\n }\n\n hasRegisteredHandlers = true;\n\n subscribe('http.server.request.start', onHttpServerRequestStart);\n subscribe('http.client.response.finish', onHttpClientResponseFinish);\n\n // When an error happens, we still want to have a breadcrumb\n // In this case, `http.client.response.finish` is not triggered\n subscribe('http.client.request.error', onHttpClientRequestError);\n\n return moduleExports;\n },\n () => {\n unsubscribe('http.server.request.start', onHttpServerRequestStart);\n unsubscribe('http.client.response.finish', onHttpClientResponseFinish);\n unsubscribe('http.client.request.error', onHttpClientRequestError);\n },\n ),\n new InstrumentationNodeModuleDefinition(\n 'https',\n ['*'],\n (moduleExports: Https): Https => {\n if (hasRegisteredHandlers) {\n return moduleExports;\n }\n\n hasRegisteredHandlers = true;\n\n subscribe('http.server.request.start', onHttpServerRequestStart);\n subscribe('http.client.response.finish', onHttpClientResponseFinish);\n\n // When an error happens, we still want to have a breadcrumb\n // In this case, `http.client.response.finish` is not triggered\n subscribe('http.client.request.error', onHttpClientRequestError);\n\n return moduleExports;\n },\n () => {\n unsubscribe('http.server.request.start', onHttpServerRequestStart);\n unsubscribe('http.client.response.finish', onHttpClientResponseFinish);\n unsubscribe('http.client.request.error', onHttpClientRequestError);\n },\n ),\n ];\n }\n\n /**\n * This is triggered when an outgoing request finishes.\n * It has access to the final request and response objects.\n */\n private _onOutgoingRequestFinish(request: http.ClientRequest, response?: http.IncomingMessage): void {\n DEBUG_BUILD && logger.log(INSTRUMENTATION_NAME, 'Handling finished outgoing request');\n\n const _breadcrumbs = this.getConfig().breadcrumbs;\n const breadCrumbsEnabled = typeof _breadcrumbs === 'undefined' ? true : _breadcrumbs;\n const options = getRequestOptions(request);\n\n const _ignoreOutgoingRequests = this.getConfig().ignoreOutgoingRequests;\n const shouldCreateBreadcrumb =\n typeof _ignoreOutgoingRequests === 'function' ? !_ignoreOutgoingRequests(getRequestUrl(request), options) : true;\n\n if (breadCrumbsEnabled && shouldCreateBreadcrumb) {\n addRequestBreadcrumb(request, response);\n }\n }\n\n /**\n * Patch a server.emit function to handle process isolation for incoming requests.\n * This will only patch the emit function if it was not already patched.\n */\n private _patchServerEmitOnce(server: http.Server): void {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const originalEmit = server.emit;\n\n // This means it was already patched, do nothing\n if ((originalEmit as { __sentry_patched__?: boolean }).__sentry_patched__) {\n return;\n }\n\n DEBUG_BUILD && logger.log(INSTRUMENTATION_NAME, 'Patching server.emit');\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const instrumentation = this;\n const { ignoreIncomingRequestBody } = instrumentation.getConfig();\n\n const newEmit = new Proxy(originalEmit, {\n apply(target, thisArg, args: [event: string, ...args: unknown[]]) {\n // Only traces request events\n if (args[0] !== 'request') {\n return target.apply(thisArg, args);\n }\n\n DEBUG_BUILD && logger.log(INSTRUMENTATION_NAME, 'Handling incoming request');\n\n const isolationScope = getIsolationScope().clone();\n const request = args[1] as http.IncomingMessage;\n const response = args[2] as http.OutgoingMessage;\n\n const normalizedRequest = httpRequestToRequestData(request);\n\n // request.ip is non-standard but some frameworks set this\n const ipAddress = (request as { ip?: string }).ip || request.socket?.remoteAddress;\n\n const url = request.url || '/';\n if (!ignoreIncomingRequestBody?.(url, request)) {\n patchRequestToCaptureBody(request, isolationScope);\n }\n\n // Update the isolation scope, isolate this request\n isolationScope.setSDKProcessingMetadata({ normalizedRequest, ipAddress });\n\n // attempt to update the scope's `transactionName` based on the request URL\n // Ideally, framework instrumentations coming after the HttpInstrumentation\n // update the transactionName once we get a parameterized route.\n const httpMethod = (request.method || 'GET').toUpperCase();\n const httpTarget = stripUrlQueryAndFragment(url);\n\n const bestEffortTransactionName = `${httpMethod} ${httpTarget}`;\n\n isolationScope.setTransactionName(bestEffortTransactionName);\n\n if (instrumentation.getConfig().trackIncomingRequestsAsSessions !== false) {\n recordRequestSession({\n requestIsolationScope: isolationScope,\n response,\n sessionFlushingDelayMS: instrumentation.getConfig().sessionFlushingDelayMS ?? 60_000,\n });\n }\n\n return withIsolationScope(isolationScope, () => {\n // Set a new propagationSpanId for this request\n // We rely on the fact that `withIsolationScope()` will implicitly also fork the current scope\n // This way we can save an \"unnecessary\" `withScope()` invocation\n getCurrentScope().getPropagationContext().propagationSpanId = generateSpanId();\n\n // If we don't want to extract the trace from the header, we can skip this\n if (!instrumentation.getConfig().extractIncomingTraceFromHeader) {\n return target.apply(thisArg, args);\n }\n\n const ctx = propagation.extract(context.active(), normalizedRequest.headers);\n return context.with(ctx, () => {\n return target.apply(thisArg, args);\n });\n });\n },\n });\n\n addNonEnumerableProperty(newEmit, '__sentry_patched__', true);\n\n server.emit = newEmit;\n }\n}\n\n/** Add a breadcrumb for outgoing requests. */\nfunction addRequestBreadcrumb(request: http.ClientRequest, response: http.IncomingMessage | undefined): void {\n const data = getBreadcrumbData(request);\n\n const statusCode = response?.statusCode;\n const level = getBreadcrumbLogLevelFromHttpStatusCode(statusCode);\n\n addBreadcrumb(\n {\n category: 'http',\n data: {\n status_code: statusCode,\n ...data,\n },\n type: 'http',\n level,\n },\n {\n event: 'response',\n request,\n response,\n },\n );\n}\n\nfunction getBreadcrumbData(request: http.ClientRequest): Partial<SanitizedRequestData> {\n try {\n // `request.host` does not contain the port, but the host header does\n const host = request.getHeader('host') || request.host;\n const url = new URL(request.path, `${request.protocol}//${host}`);\n const parsedUrl = parseUrl(url.toString());\n\n const data: Partial<SanitizedRequestData> = {\n url: getSanitizedUrlString(parsedUrl),\n 'http.method': request.method || 'GET',\n };\n\n if (parsedUrl.search) {\n data['http.query'] = parsedUrl.search;\n }\n if (parsedUrl.hash) {\n data['http.fragment'] = parsedUrl.hash;\n }\n\n return data;\n } catch {\n return {};\n }\n}\n\n/**\n * This method patches the request object to capture the body.\n * Instead of actually consuming the streamed body ourselves, which has potential side effects,\n * we monkey patch `req.on('data')` to intercept the body chunks.\n * This way, we only read the body if the user also consumes the body, ensuring we do not change any behavior in unexpected ways.\n */\nfunction patchRequestToCaptureBody(req: http.IncomingMessage, isolationScope: Scope): void {\n let bodyByteLength = 0;\n const chunks: Buffer[] = [];\n\n DEBUG_BUILD && logger.log(INSTRUMENTATION_NAME, 'Patching request.on');\n\n /**\n * We need to keep track of the original callbacks, in order to be able to remove listeners again.\n * Since `off` depends on having the exact same function reference passed in, we need to be able to map\n * original listeners to our wrapped ones.\n */\n const callbackMap = new WeakMap();\n\n try {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n req.on = new Proxy(req.on, {\n apply: (target, thisArg, args: Parameters<typeof req.on>) => {\n const [event, listener, ...restArgs] = args;\n\n if (event === 'data') {\n DEBUG_BUILD && logger.log(INSTRUMENTATION_NAME, 'Handling request.on(\"data\")');\n const callback = new Proxy(listener, {\n apply: (target, thisArg, args: Parameters<typeof listener>) => {\n try {\n const chunk = args[0] as Buffer | string;\n const bufferifiedChunk = Buffer.from(chunk);\n\n if (bodyByteLength < MAX_BODY_BYTE_LENGTH) {\n chunks.push(bufferifiedChunk);\n bodyByteLength += bufferifiedChunk.byteLength;\n } else if (DEBUG_BUILD) {\n logger.log(\n INSTRUMENTATION_NAME,\n `Dropping request body chunk because maximum body length of ${MAX_BODY_BYTE_LENGTH}b is exceeded.`,\n );\n }\n } catch (err) {\n DEBUG_BUILD && logger.error(INSTRUMENTATION_NAME, 'Encountered error while storing body chunk.');\n }\n\n return Reflect.apply(target, thisArg, args);\n },\n });\n\n callbackMap.set(listener, callback);\n\n return Reflect.apply(target, thisArg, [event, callback, ...restArgs]);\n }\n\n return Reflect.apply(target, thisArg, args);\n },\n });\n\n // Ensure we also remove callbacks correctly\n // eslint-disable-next-line @typescript-eslint/unbound-method\n req.off = new Proxy(req.off, {\n apply: (target, thisArg, args: Parameters<typeof req.off>) => {\n const [, listener] = args;\n\n const callback = callbackMap.get(listener);\n if (callback) {\n callbackMap.delete(listener);\n\n const modifiedArgs = args.slice();\n modifiedArgs[1] = callback;\n return Reflect.apply(target, thisArg, modifiedArgs);\n }\n\n return Reflect.apply(target, thisArg, args);\n },\n });\n\n req.on('end', () => {\n try {\n const body = Buffer.concat(chunks).toString('utf-8');\n if (body) {\n isolationScope.setSDKProcessingMetadata({ normalizedRequest: { data: body } });\n }\n } catch (error) {\n if (DEBUG_BUILD) {\n logger.error(INSTRUMENTATION_NAME, 'Error building captured request body', error);\n }\n }\n });\n } catch (error) {\n if (DEBUG_BUILD) {\n logger.error(INSTRUMENTATION_NAME, 'Error patching request to capture body', error);\n }\n }\n}\n\nfunction getRequestOptions(request: http.ClientRequest): http.RequestOptions {\n return {\n method: request.method,\n protocol: request.protocol,\n host: request.host,\n hostname: request.host,\n path: request.path,\n headers: request.getHeaders(),\n };\n}\n\n/**\n * Starts a session and tracks it in the context of a given isolation scope.\n * When the passed response is finished, the session is put into a task and is\n * aggregated with other sessions that may happen in a certain time window\n * (sessionFlushingDelayMs).\n *\n * The sessions are always aggregated by the client that is on the current scope\n * at the time of ending the response (if there is one).\n */\n// Exported for unit tests\nexport function recordRequestSession({\n requestIsolationScope,\n response,\n sessionFlushingDelayMS,\n}: {\n requestIsolationScope: Scope;\n response: EventEmitter;\n sessionFlushingDelayMS?: number;\n}): void {\n requestIsolationScope.setSDKProcessingMetadata({\n requestSession: { status: 'ok' },\n });\n response.once('close', () => {\n // We need to grab the client off the current scope instead of the isolation scope because the isolation scope doesn't hold any client out of the box.\n const client = getClient();\n const requestSession = requestIsolationScope.getScopeData().sdkProcessingMetadata.requestSession;\n\n if (client && requestSession) {\n DEBUG_BUILD && logger.debug(`Recorded request session with status: ${requestSession.status}`);\n\n const roundedDate = new Date();\n roundedDate.setSeconds(0, 0);\n const dateBucketKey = roundedDate.toISOString();\n\n const existingClientAggregate = clientToRequestSessionAggregatesMap.get(client);\n const bucket = existingClientAggregate?.[dateBucketKey] || { exited: 0, crashed: 0, errored: 0 };\n bucket[({ ok: 'exited', crashed: 'crashed', errored: 'errored' } as const)[requestSession.status]]++;\n\n if (existingClientAggregate) {\n existingClientAggregate[dateBucketKey] = bucket;\n } else {\n DEBUG_BUILD && logger.debug('Opened new request session aggregate.');\n const newClientAggregate = { [dateBucketKey]: bucket };\n clientToRequestSessionAggregatesMap.set(client, newClientAggregate);\n\n const flushPendingClientAggregates = (): void => {\n clearTimeout(timeout);\n unregisterClientFlushHook();\n clientToRequestSessionAggregatesMap.delete(client);\n\n const aggregatePayload: AggregationCounts[] = Object.entries(newClientAggregate).map(\n ([timestamp, value]) => ({\n started: timestamp,\n exited: value.exited,\n errored: value.errored,\n crashed: value.crashed,\n }),\n );\n client.sendSession({ aggregates: aggregatePayload });\n };\n\n const unregisterClientFlushHook = client.on('flush', () => {\n DEBUG_BUILD && logger.debug('Sending request session aggregate due to client flush');\n flushPendingClientAggregates();\n });\n const timeout = setTimeout(() => {\n DEBUG_BUILD && logger.debug('Sending request session aggregate due to flushing schedule');\n flushPendingClientAggregates();\n }, sessionFlushingDelayMS).unref();\n }\n }\n });\n}\n\nconst clientToRequestSessionAggregatesMap = new Map<\n Client,\n { [timestampRoundedToSeconds: string]: { exited: number; crashed: number; errored: number } }\n>();\n"],"names":["InstrumentationBase","VERSION","InstrumentationNodeModuleDefinition","subscribe","unsubscribe","DEBUG_BUILD","logger","getRequestUrl","getIsolationScope","httpRequestToRequestData","stripUrlQueryAndFragment","withIsolationScope","getCurrentScope","generateSpanId","propagation","context","addNonEnumerableProperty","getBreadcrumbLogLevelFromHttpStatusCode","addBreadcrumb","parseUrl","getSanitizedUrlString","getClient"],"mappings":"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"}