@sentry/node 10.63.0 → 10.65.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 (286) hide show
  1. package/build/cjs/index.js +15 -14
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/cjs/integrations/http.js +4 -7
  4. package/build/cjs/integrations/http.js.map +1 -1
  5. package/build/cjs/integrations/node-fetch.js +24 -0
  6. package/build/cjs/integrations/node-fetch.js.map +1 -0
  7. package/build/cjs/integrations/tracing/amqplib/vendored/semconv.js +0 -6
  8. package/build/cjs/integrations/tracing/amqplib/vendored/semconv.js.map +1 -1
  9. package/build/cjs/integrations/tracing/amqplib/vendored/utils.js +11 -10
  10. package/build/cjs/integrations/tracing/amqplib/vendored/utils.js.map +1 -1
  11. package/build/cjs/integrations/tracing/connect/vendored/instrumentation.js +2 -2
  12. package/build/cjs/integrations/tracing/connect/vendored/instrumentation.js.map +1 -1
  13. package/build/cjs/integrations/tracing/fastify/v3/instrumentation.js +2 -2
  14. package/build/cjs/integrations/tracing/fastify/v3/instrumentation.js.map +1 -1
  15. package/build/cjs/integrations/tracing/firebase/otel/patches/firestore.js +9 -9
  16. package/build/cjs/integrations/tracing/firebase/otel/patches/firestore.js.map +1 -1
  17. package/build/cjs/integrations/tracing/graphql/index.js +3 -2
  18. package/build/cjs/integrations/tracing/graphql/index.js.map +1 -1
  19. package/build/cjs/integrations/tracing/graphql/vendored/instrumentation.js.map +1 -1
  20. package/build/cjs/integrations/tracing/graphql/vendored/utils.js +1 -4
  21. package/build/cjs/integrations/tracing/graphql/vendored/utils.js.map +1 -1
  22. package/build/cjs/integrations/tracing/hapi/vendored/utils.js +8 -9
  23. package/build/cjs/integrations/tracing/hapi/vendored/utils.js.map +1 -1
  24. package/build/cjs/integrations/tracing/hono/index.js +7 -7
  25. package/build/cjs/integrations/tracing/hono/index.js.map +1 -1
  26. package/build/cjs/integrations/tracing/kafka/vendored/instrumentation.js +2 -1
  27. package/build/cjs/integrations/tracing/kafka/vendored/instrumentation.js.map +1 -1
  28. package/build/cjs/integrations/tracing/kafka/vendored/semconv.js +0 -12
  29. package/build/cjs/integrations/tracing/kafka/vendored/semconv.js.map +1 -1
  30. package/build/cjs/integrations/tracing/kafka/vendored/utils.js +12 -11
  31. package/build/cjs/integrations/tracing/kafka/vendored/utils.js.map +1 -1
  32. package/build/cjs/integrations/tracing/knex/vendored/instrumentation.js +11 -10
  33. package/build/cjs/integrations/tracing/knex/vendored/instrumentation.js.map +1 -1
  34. package/build/cjs/integrations/tracing/knex/vendored/semconv.js +0 -16
  35. package/build/cjs/integrations/tracing/knex/vendored/semconv.js.map +1 -1
  36. package/build/cjs/integrations/tracing/koa/vendored/instrumentation.js +2 -2
  37. package/build/cjs/integrations/tracing/koa/vendored/instrumentation.js.map +1 -1
  38. package/build/cjs/integrations/tracing/koa/vendored/utils.js +2 -2
  39. package/build/cjs/integrations/tracing/koa/vendored/utils.js.map +1 -1
  40. package/build/cjs/integrations/tracing/mongo/vendored/semconv.js +0 -12
  41. package/build/cjs/integrations/tracing/mongo/vendored/semconv.js.map +1 -1
  42. package/build/cjs/integrations/tracing/mongo/vendored/utils.js +13 -12
  43. package/build/cjs/integrations/tracing/mongo/vendored/utils.js.map +1 -1
  44. package/build/cjs/integrations/tracing/mongoose/index.js +3 -2
  45. package/build/cjs/integrations/tracing/mongoose/index.js.map +1 -1
  46. package/build/cjs/integrations/tracing/mongoose/vendored/mongoose.js +11 -8
  47. package/build/cjs/integrations/tracing/mongoose/vendored/mongoose.js.map +1 -1
  48. package/build/cjs/integrations/tracing/mongoose/vendored/semconv.js +0 -12
  49. package/build/cjs/integrations/tracing/mongoose/vendored/semconv.js.map +1 -1
  50. package/build/cjs/integrations/tracing/mongoose/vendored/utils.js +9 -9
  51. package/build/cjs/integrations/tracing/mongoose/vendored/utils.js.map +1 -1
  52. package/build/cjs/integrations/tracing/mysql/vendored/instrumentation.js +9 -8
  53. package/build/cjs/integrations/tracing/mysql/vendored/instrumentation.js.map +1 -1
  54. package/build/cjs/integrations/tracing/mysql/vendored/semconv.js +0 -12
  55. package/build/cjs/integrations/tracing/mysql/vendored/semconv.js.map +1 -1
  56. package/build/cjs/integrations/tracing/mysql2/index.js +3 -2
  57. package/build/cjs/integrations/tracing/mysql2/index.js.map +1 -1
  58. package/build/cjs/integrations/tracing/mysql2/vendored/instrumentation.js +8 -5
  59. package/build/cjs/integrations/tracing/mysql2/vendored/instrumentation.js.map +1 -1
  60. package/build/cjs/integrations/tracing/mysql2/vendored/semconv.js +0 -12
  61. package/build/cjs/integrations/tracing/mysql2/vendored/semconv.js.map +1 -1
  62. package/build/cjs/integrations/tracing/mysql2/vendored/utils.js +7 -4
  63. package/build/cjs/integrations/tracing/mysql2/vendored/utils.js.map +1 -1
  64. package/build/cjs/integrations/tracing/postgres/vendored/semconv.js +0 -12
  65. package/build/cjs/integrations/tracing/postgres/vendored/semconv.js.map +1 -1
  66. package/build/cjs/integrations/tracing/postgres/vendored/utils.js +12 -11
  67. package/build/cjs/integrations/tracing/postgres/vendored/utils.js.map +1 -1
  68. package/build/cjs/integrations/tracing/postgresjs.js +8 -7
  69. package/build/cjs/integrations/tracing/postgresjs.js.map +1 -1
  70. package/build/cjs/integrations/tracing/prisma/index.js +48 -53
  71. package/build/cjs/integrations/tracing/prisma/index.js.map +1 -1
  72. package/build/cjs/integrations/tracing/redis/cache.js +41 -0
  73. package/build/cjs/integrations/tracing/redis/cache.js.map +1 -0
  74. package/build/cjs/integrations/tracing/redis/index.js +15 -42
  75. package/build/cjs/integrations/tracing/redis/index.js.map +1 -1
  76. package/build/cjs/integrations/tracing/redis/vendored/ioredis-instrumentation.js +22 -13
  77. package/build/cjs/integrations/tracing/redis/vendored/ioredis-instrumentation.js.map +1 -1
  78. package/build/cjs/integrations/tracing/redis/vendored/redis-instrumentation.js +21 -15
  79. package/build/cjs/integrations/tracing/redis/vendored/redis-instrumentation.js.map +1 -1
  80. package/build/cjs/integrations/tracing/redis/vendored/semconv.js +0 -8
  81. package/build/cjs/integrations/tracing/redis/vendored/semconv.js.map +1 -1
  82. package/build/cjs/integrations/tracing/tedious/vendored/instrumentation.js +9 -8
  83. package/build/cjs/integrations/tracing/tedious/vendored/instrumentation.js.map +1 -1
  84. package/build/cjs/integrations/tracing/tedious/vendored/semconv.js +0 -12
  85. package/build/cjs/integrations/tracing/tedious/vendored/semconv.js.map +1 -1
  86. package/build/cjs/sdk/experimentalUseDiagnosticsChannelInjection.js +14 -2
  87. package/build/cjs/sdk/experimentalUseDiagnosticsChannelInjection.js.map +1 -1
  88. package/build/cjs/sdk/index.js +2 -2
  89. package/build/cjs/sdk/index.js.map +1 -1
  90. package/build/cjs/sdk/initOtel.js +36 -0
  91. package/build/cjs/sdk/initOtel.js.map +1 -1
  92. package/build/esm/index.js +2 -2
  93. package/build/esm/integrations/http.js +5 -8
  94. package/build/esm/integrations/http.js.map +1 -1
  95. package/build/esm/integrations/node-fetch.js +22 -0
  96. package/build/esm/integrations/node-fetch.js.map +1 -0
  97. package/build/esm/integrations/tracing/amqplib/vendored/semconv.js +1 -4
  98. package/build/esm/integrations/tracing/amqplib/vendored/semconv.js.map +1 -1
  99. package/build/esm/integrations/tracing/amqplib/vendored/utils.js +7 -6
  100. package/build/esm/integrations/tracing/amqplib/vendored/utils.js.map +1 -1
  101. package/build/esm/integrations/tracing/connect/vendored/instrumentation.js +2 -2
  102. package/build/esm/integrations/tracing/connect/vendored/instrumentation.js.map +1 -1
  103. package/build/esm/integrations/tracing/fastify/v3/instrumentation.js +2 -2
  104. package/build/esm/integrations/tracing/fastify/v3/instrumentation.js.map +1 -1
  105. package/build/esm/integrations/tracing/firebase/otel/patches/firestore.js +7 -7
  106. package/build/esm/integrations/tracing/firebase/otel/patches/firestore.js.map +1 -1
  107. package/build/esm/integrations/tracing/graphql/index.js +4 -3
  108. package/build/esm/integrations/tracing/graphql/index.js.map +1 -1
  109. package/build/esm/integrations/tracing/graphql/vendored/instrumentation.js.map +1 -1
  110. package/build/esm/integrations/tracing/graphql/vendored/utils.js +1 -4
  111. package/build/esm/integrations/tracing/graphql/vendored/utils.js.map +1 -1
  112. package/build/esm/integrations/tracing/hapi/vendored/utils.js +3 -4
  113. package/build/esm/integrations/tracing/hapi/vendored/utils.js.map +1 -1
  114. package/build/esm/integrations/tracing/hono/index.js +3 -3
  115. package/build/esm/integrations/tracing/hono/index.js.map +1 -1
  116. package/build/esm/integrations/tracing/kafka/vendored/instrumentation.js +3 -2
  117. package/build/esm/integrations/tracing/kafka/vendored/instrumentation.js.map +1 -1
  118. package/build/esm/integrations/tracing/kafka/vendored/semconv.js +1 -7
  119. package/build/esm/integrations/tracing/kafka/vendored/semconv.js.map +1 -1
  120. package/build/esm/integrations/tracing/kafka/vendored/utils.js +11 -10
  121. package/build/esm/integrations/tracing/kafka/vendored/utils.js.map +1 -1
  122. package/build/esm/integrations/tracing/knex/vendored/instrumentation.js +10 -9
  123. package/build/esm/integrations/tracing/knex/vendored/instrumentation.js.map +1 -1
  124. package/build/esm/integrations/tracing/knex/vendored/semconv.js +1 -9
  125. package/build/esm/integrations/tracing/knex/vendored/semconv.js.map +1 -1
  126. package/build/esm/integrations/tracing/koa/vendored/instrumentation.js +2 -2
  127. package/build/esm/integrations/tracing/koa/vendored/instrumentation.js.map +1 -1
  128. package/build/esm/integrations/tracing/koa/vendored/utils.js +2 -2
  129. package/build/esm/integrations/tracing/koa/vendored/utils.js.map +1 -1
  130. package/build/esm/integrations/tracing/mongo/vendored/semconv.js +1 -7
  131. package/build/esm/integrations/tracing/mongo/vendored/semconv.js.map +1 -1
  132. package/build/esm/integrations/tracing/mongo/vendored/utils.js +11 -10
  133. package/build/esm/integrations/tracing/mongo/vendored/utils.js.map +1 -1
  134. package/build/esm/integrations/tracing/mongoose/index.js +4 -3
  135. package/build/esm/integrations/tracing/mongoose/index.js.map +1 -1
  136. package/build/esm/integrations/tracing/mongoose/vendored/mongoose.js +9 -6
  137. package/build/esm/integrations/tracing/mongoose/vendored/mongoose.js.map +1 -1
  138. package/build/esm/integrations/tracing/mongoose/vendored/semconv.js +1 -7
  139. package/build/esm/integrations/tracing/mongoose/vendored/semconv.js.map +1 -1
  140. package/build/esm/integrations/tracing/mongoose/vendored/utils.js +10 -10
  141. package/build/esm/integrations/tracing/mongoose/vendored/utils.js.map +1 -1
  142. package/build/esm/integrations/tracing/mysql/vendored/instrumentation.js +8 -7
  143. package/build/esm/integrations/tracing/mysql/vendored/instrumentation.js.map +1 -1
  144. package/build/esm/integrations/tracing/mysql/vendored/semconv.js +1 -7
  145. package/build/esm/integrations/tracing/mysql/vendored/semconv.js.map +1 -1
  146. package/build/esm/integrations/tracing/mysql2/index.js +4 -3
  147. package/build/esm/integrations/tracing/mysql2/index.js.map +1 -1
  148. package/build/esm/integrations/tracing/mysql2/vendored/instrumentation.js +7 -4
  149. package/build/esm/integrations/tracing/mysql2/vendored/instrumentation.js.map +1 -1
  150. package/build/esm/integrations/tracing/mysql2/vendored/semconv.js +1 -7
  151. package/build/esm/integrations/tracing/mysql2/vendored/semconv.js.map +1 -1
  152. package/build/esm/integrations/tracing/mysql2/vendored/utils.js +8 -5
  153. package/build/esm/integrations/tracing/mysql2/vendored/utils.js.map +1 -1
  154. package/build/esm/integrations/tracing/postgres/vendored/semconv.js +1 -7
  155. package/build/esm/integrations/tracing/postgres/vendored/semconv.js.map +1 -1
  156. package/build/esm/integrations/tracing/postgres/vendored/utils.js +13 -12
  157. package/build/esm/integrations/tracing/postgres/vendored/utils.js.map +1 -1
  158. package/build/esm/integrations/tracing/postgresjs.js +7 -6
  159. package/build/esm/integrations/tracing/postgresjs.js.map +1 -1
  160. package/build/esm/integrations/tracing/prisma/index.js +49 -54
  161. package/build/esm/integrations/tracing/prisma/index.js.map +1 -1
  162. package/build/esm/integrations/tracing/redis/cache.js +38 -0
  163. package/build/esm/integrations/tracing/redis/cache.js.map +1 -0
  164. package/build/esm/integrations/tracing/redis/index.js +12 -42
  165. package/build/esm/integrations/tracing/redis/index.js.map +1 -1
  166. package/build/esm/integrations/tracing/redis/vendored/ioredis-instrumentation.js +19 -10
  167. package/build/esm/integrations/tracing/redis/vendored/ioredis-instrumentation.js.map +1 -1
  168. package/build/esm/integrations/tracing/redis/vendored/redis-instrumentation.js +16 -10
  169. package/build/esm/integrations/tracing/redis/vendored/redis-instrumentation.js.map +1 -1
  170. package/build/esm/integrations/tracing/redis/vendored/semconv.js +1 -5
  171. package/build/esm/integrations/tracing/redis/vendored/semconv.js.map +1 -1
  172. package/build/esm/integrations/tracing/tedious/vendored/instrumentation.js +8 -7
  173. package/build/esm/integrations/tracing/tedious/vendored/instrumentation.js.map +1 -1
  174. package/build/esm/integrations/tracing/tedious/vendored/semconv.js +1 -7
  175. package/build/esm/integrations/tracing/tedious/vendored/semconv.js.map +1 -1
  176. package/build/esm/package.json +1 -1
  177. package/build/esm/sdk/experimentalUseDiagnosticsChannelInjection.js +15 -4
  178. package/build/esm/sdk/experimentalUseDiagnosticsChannelInjection.js.map +1 -1
  179. package/build/esm/sdk/index.js +1 -1
  180. package/build/esm/sdk/initOtel.js +38 -2
  181. package/build/esm/sdk/initOtel.js.map +1 -1
  182. package/build/types/index.d.ts +1 -1
  183. package/build/types/index.d.ts.map +1 -1
  184. package/build/types/integrations/http.d.ts +2 -2
  185. package/build/types/integrations/http.d.ts.map +1 -1
  186. package/build/types/integrations/node-fetch.d.ts +9 -0
  187. package/build/types/integrations/node-fetch.d.ts.map +1 -0
  188. package/build/types/integrations/tracing/amqplib/vendored/semconv.d.ts +0 -6
  189. package/build/types/integrations/tracing/amqplib/vendored/semconv.d.ts.map +1 -1
  190. package/build/types/integrations/tracing/amqplib/vendored/utils.d.ts.map +1 -1
  191. package/build/types/integrations/tracing/graphql/index.d.ts.map +1 -1
  192. package/build/types/integrations/tracing/graphql/vendored/graphql-types.d.ts +1 -135
  193. package/build/types/integrations/tracing/graphql/vendored/graphql-types.d.ts.map +1 -1
  194. package/build/types/integrations/tracing/graphql/vendored/utils.d.ts.map +1 -1
  195. package/build/types/integrations/tracing/hapi/vendored/utils.d.ts.map +1 -1
  196. package/build/types/integrations/tracing/kafka/vendored/semconv.d.ts +5 -63
  197. package/build/types/integrations/tracing/kafka/vendored/semconv.d.ts.map +1 -1
  198. package/build/types/integrations/tracing/kafka/vendored/utils.d.ts.map +1 -1
  199. package/build/types/integrations/tracing/knex/vendored/semconv.d.ts +0 -32
  200. package/build/types/integrations/tracing/knex/vendored/semconv.d.ts.map +1 -1
  201. package/build/types/integrations/tracing/mongo/vendored/semconv.d.ts +1 -37
  202. package/build/types/integrations/tracing/mongo/vendored/semconv.d.ts.map +1 -1
  203. package/build/types/integrations/tracing/mongo/vendored/utils.d.ts.map +1 -1
  204. package/build/types/integrations/tracing/mongoose/index.d.ts.map +1 -1
  205. package/build/types/integrations/tracing/mongoose/vendored/mongoose.d.ts.map +1 -1
  206. package/build/types/integrations/tracing/mongoose/vendored/semconv.d.ts +0 -48
  207. package/build/types/integrations/tracing/mongoose/vendored/semconv.d.ts.map +1 -1
  208. package/build/types/integrations/tracing/mongoose/vendored/utils.d.ts.map +1 -1
  209. package/build/types/integrations/tracing/mysql/vendored/instrumentation.d.ts.map +1 -1
  210. package/build/types/integrations/tracing/mysql/vendored/semconv.d.ts +1 -62
  211. package/build/types/integrations/tracing/mysql/vendored/semconv.d.ts.map +1 -1
  212. package/build/types/integrations/tracing/mysql2/index.d.ts.map +1 -1
  213. package/build/types/integrations/tracing/mysql2/vendored/instrumentation.d.ts.map +1 -1
  214. package/build/types/integrations/tracing/mysql2/vendored/semconv.d.ts +0 -6
  215. package/build/types/integrations/tracing/mysql2/vendored/semconv.d.ts.map +1 -1
  216. package/build/types/integrations/tracing/mysql2/vendored/utils.d.ts.map +1 -1
  217. package/build/types/integrations/tracing/postgres/vendored/semconv.d.ts +1 -50
  218. package/build/types/integrations/tracing/postgres/vendored/semconv.d.ts.map +1 -1
  219. package/build/types/integrations/tracing/postgres/vendored/utils.d.ts.map +1 -1
  220. package/build/types/integrations/tracing/postgresjs.d.ts.map +1 -1
  221. package/build/types/integrations/tracing/prisma/index.d.ts.map +1 -1
  222. package/build/types/integrations/tracing/redis/cache.d.ts +22 -0
  223. package/build/types/integrations/tracing/redis/cache.d.ts.map +1 -0
  224. package/build/types/integrations/tracing/redis/index.d.ts +2 -20
  225. package/build/types/integrations/tracing/redis/index.d.ts.map +1 -1
  226. package/build/types/integrations/tracing/redis/vendored/ioredis-instrumentation.d.ts.map +1 -1
  227. package/build/types/integrations/tracing/redis/vendored/redis-instrumentation.d.ts.map +1 -1
  228. package/build/types/integrations/tracing/redis/vendored/semconv.d.ts +0 -4
  229. package/build/types/integrations/tracing/redis/vendored/semconv.d.ts.map +1 -1
  230. package/build/types/integrations/tracing/tedious/vendored/instrumentation.d.ts.map +1 -1
  231. package/build/types/integrations/tracing/tedious/vendored/semconv.d.ts +1 -62
  232. package/build/types/integrations/tracing/tedious/vendored/semconv.d.ts.map +1 -1
  233. package/build/types/sdk/experimentalUseDiagnosticsChannelInjection.d.ts +2 -0
  234. package/build/types/sdk/experimentalUseDiagnosticsChannelInjection.d.ts.map +1 -1
  235. package/build/types/sdk/initOtel.d.ts +2 -3
  236. package/build/types/sdk/initOtel.d.ts.map +1 -1
  237. package/build/types-ts3.8/index.d.ts +1 -1
  238. package/build/types-ts3.8/integrations/http.d.ts +2 -2
  239. package/build/types-ts3.8/integrations/node-fetch.d.ts +9 -0
  240. package/build/types-ts3.8/integrations/tracing/amqplib/vendored/semconv.d.ts +0 -6
  241. package/build/types-ts3.8/integrations/tracing/graphql/vendored/graphql-types.d.ts +1 -135
  242. package/build/types-ts3.8/integrations/tracing/kafka/vendored/semconv.d.ts +5 -63
  243. package/build/types-ts3.8/integrations/tracing/knex/vendored/semconv.d.ts +0 -32
  244. package/build/types-ts3.8/integrations/tracing/mongo/vendored/semconv.d.ts +1 -37
  245. package/build/types-ts3.8/integrations/tracing/mongoose/vendored/semconv.d.ts +0 -48
  246. package/build/types-ts3.8/integrations/tracing/mysql/vendored/semconv.d.ts +1 -62
  247. package/build/types-ts3.8/integrations/tracing/mysql2/vendored/semconv.d.ts +0 -6
  248. package/build/types-ts3.8/integrations/tracing/postgres/vendored/semconv.d.ts +1 -50
  249. package/build/types-ts3.8/integrations/tracing/redis/cache.d.ts +22 -0
  250. package/build/types-ts3.8/integrations/tracing/redis/index.d.ts +2 -20
  251. package/build/types-ts3.8/integrations/tracing/redis/vendored/semconv.d.ts +0 -4
  252. package/build/types-ts3.8/integrations/tracing/tedious/vendored/semconv.d.ts +1 -62
  253. package/build/types-ts3.8/sdk/experimentalUseDiagnosticsChannelInjection.d.ts +2 -0
  254. package/build/types-ts3.8/sdk/initOtel.d.ts +3 -4
  255. package/package.json +8 -9
  256. package/build/cjs/integrations/node-fetch/index.js +0 -38
  257. package/build/cjs/integrations/node-fetch/index.js.map +0 -1
  258. package/build/cjs/integrations/node-fetch/undici-instrumentation.js +0 -266
  259. package/build/cjs/integrations/node-fetch/undici-instrumentation.js.map +0 -1
  260. package/build/cjs/integrations/tracing/hapi/vendored/semconv.js +0 -6
  261. package/build/cjs/integrations/tracing/hapi/vendored/semconv.js.map +0 -1
  262. package/build/cjs/integrations/tracing/redis/vendored/redis-common.js +0 -34
  263. package/build/cjs/integrations/tracing/redis/vendored/redis-common.js.map +0 -1
  264. package/build/esm/integrations/node-fetch/index.js +0 -36
  265. package/build/esm/integrations/node-fetch/index.js.map +0 -1
  266. package/build/esm/integrations/node-fetch/undici-instrumentation.js +0 -264
  267. package/build/esm/integrations/node-fetch/undici-instrumentation.js.map +0 -1
  268. package/build/esm/integrations/tracing/hapi/vendored/semconv.js +0 -4
  269. package/build/esm/integrations/tracing/hapi/vendored/semconv.js.map +0 -1
  270. package/build/esm/integrations/tracing/redis/vendored/redis-common.js +0 -32
  271. package/build/esm/integrations/tracing/redis/vendored/redis-common.js.map +0 -1
  272. package/build/types/integrations/node-fetch/index.d.ts +0 -5
  273. package/build/types/integrations/node-fetch/index.d.ts.map +0 -1
  274. package/build/types/integrations/node-fetch/types.d.ts +0 -96
  275. package/build/types/integrations/node-fetch/types.d.ts.map +0 -1
  276. package/build/types/integrations/node-fetch/undici-instrumentation.d.ts +0 -14
  277. package/build/types/integrations/node-fetch/undici-instrumentation.d.ts.map +0 -1
  278. package/build/types/integrations/tracing/hapi/vendored/semconv.d.ts +0 -13
  279. package/build/types/integrations/tracing/hapi/vendored/semconv.d.ts.map +0 -1
  280. package/build/types/integrations/tracing/redis/vendored/redis-common.d.ts +0 -6
  281. package/build/types/integrations/tracing/redis/vendored/redis-common.d.ts.map +0 -1
  282. package/build/types-ts3.8/integrations/node-fetch/index.d.ts +0 -5
  283. package/build/types-ts3.8/integrations/node-fetch/types.d.ts +0 -96
  284. package/build/types-ts3.8/integrations/node-fetch/undici-instrumentation.d.ts +0 -14
  285. package/build/types-ts3.8/integrations/tracing/hapi/vendored/semconv.d.ts +0 -13
  286. package/build/types-ts3.8/integrations/tracing/redis/vendored/redis-common.d.ts +0 -6
@@ -1,7 +1,8 @@
1
1
  import { getActiveSpan, SPAN_STATUS_ERROR, startInactiveSpan, SPAN_KIND, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
2
2
  import { AttributeNames } from './enums/AttributeNames.js';
3
3
  import { SpanNames } from './enums/SpanNames.js';
4
- import { DB_SYSTEM_VALUE_POSTGRESQL, ATTR_NET_PEER_PORT, ATTR_NET_PEER_NAME, ATTR_DB_USER, ATTR_DB_CONNECTION_STRING, ATTR_DB_NAME, ATTR_DB_SYSTEM, ATTR_DB_STATEMENT } from './semconv.js';
4
+ import { DB_SYSTEM_VALUE_POSTGRESQL, ATTR_DB_CONNECTION_STRING } from './semconv.js';
5
+ import { NET_PEER_PORT, NET_PEER_NAME, DB_USER, DB_NAME, DB_SYSTEM, DB_STATEMENT } from '@sentry/conventions/attributes';
5
6
 
6
7
  const ORIGIN = "auto.db.otel.postgres";
7
8
  function getQuerySpanName(dbName, queryConfig) {
@@ -43,13 +44,13 @@ function getPort(port) {
43
44
  }
44
45
  function getSemanticAttributesFromConnection(params) {
45
46
  return {
46
- [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_POSTGRESQL,
47
- [ATTR_DB_NAME]: params.database,
47
+ [DB_SYSTEM]: DB_SYSTEM_VALUE_POSTGRESQL,
48
+ [DB_NAME]: params.database,
48
49
  [ATTR_DB_CONNECTION_STRING]: getConnectionString(params),
49
- [ATTR_DB_USER]: params.user,
50
- [ATTR_NET_PEER_NAME]: params.host,
50
+ [DB_USER]: params.user,
51
+ [NET_PEER_NAME]: params.host,
51
52
  // required
52
- [ATTR_NET_PEER_PORT]: getPort(params.port)
53
+ [NET_PEER_PORT]: getPort(params.port)
53
54
  };
54
55
  }
55
56
  function getSemanticAttributesFromPoolConnection(params) {
@@ -62,12 +63,12 @@ function getSemanticAttributesFromPoolConnection(params) {
62
63
  return {
63
64
  [AttributeNames.IDLE_TIMEOUT_MILLIS]: params.idleTimeoutMillis,
64
65
  [AttributeNames.MAX_CLIENT]: params.maxClient,
65
- [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_POSTGRESQL,
66
- [ATTR_DB_NAME]: url?.pathname.slice(1) ?? params.database,
66
+ [DB_SYSTEM]: DB_SYSTEM_VALUE_POSTGRESQL,
67
+ [DB_NAME]: url?.pathname.slice(1) ?? params.database,
67
68
  [ATTR_DB_CONNECTION_STRING]: getConnectionString(params),
68
- [ATTR_NET_PEER_NAME]: url?.hostname ?? params.host,
69
- [ATTR_NET_PEER_PORT]: Number(url?.port) || getPort(params.port),
70
- [ATTR_DB_USER]: url?.username ?? params.user
69
+ [NET_PEER_NAME]: url?.hostname ?? params.host,
70
+ [NET_PEER_PORT]: Number(url?.port) || getPort(params.port),
71
+ [DB_USER]: url?.username ?? params.user
71
72
  };
72
73
  }
73
74
  function shouldSkipInstrumentation() {
@@ -89,7 +90,7 @@ function handleConfigQuery(queryConfig) {
89
90
  return span;
90
91
  }
91
92
  if (queryConfig.text) {
92
- span.setAttribute(ATTR_DB_STATEMENT, queryConfig.text);
93
+ span.setAttribute(DB_STATEMENT, queryConfig.text);
93
94
  }
94
95
  if (typeof queryConfig.name === "string") {
95
96
  span.setAttribute(AttributeNames.PG_PLAN, queryConfig.name);
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../../../../src/integrations/tracing/postgres/vendored/utils.ts"],"sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n *\n * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-pg\n * - Upstream version: @opentelemetry/instrumentation-pg@0.70.0\n * - Types from `pg` package inlined as simplified interfaces\n * - Refactored to use Sentry's span APIs instead of OpenTelemetry tracing APIs\n */\n\nimport type { Span, SpanAttributes } from '@sentry/core';\nimport {\n getActiveSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_KIND,\n SPAN_STATUS_ERROR,\n startInactiveSpan,\n} from '@sentry/core';\nimport { AttributeNames } from './enums/AttributeNames';\nimport { SpanNames } from './enums/SpanNames';\nimport type {\n PgClientExtended,\n PgParsedConnectionParams,\n PgPoolCallback,\n PgPoolExtended,\n PgPoolOptionsParams,\n PostgresCallback,\n} from './internal-types';\nimport type { PgClient } from './pg-types';\nimport {\n ATTR_DB_CONNECTION_STRING,\n ATTR_DB_NAME,\n ATTR_DB_STATEMENT,\n ATTR_DB_SYSTEM,\n ATTR_DB_USER,\n ATTR_NET_PEER_NAME,\n ATTR_NET_PEER_PORT,\n DB_SYSTEM_VALUE_POSTGRESQL,\n} from './semconv';\n\n/* oxlint-disable typescript/no-deprecated */\n\nexport const ORIGIN = 'auto.db.otel.postgres';\n\n/**\n * Helper function to get a low cardinality span name from whatever info we have\n * about the query.\n *\n * This is tricky, because we don't have most of the information (table name,\n * operation name, etc) the spec recommends using to build a low-cardinality\n * value w/o parsing. So, we use db.name and assume that, if the query's a named\n * prepared statement, those `name` values will be low cardinality. If we don't\n * have a named prepared statement, we try to parse an operation (despite the\n * spec's warnings).\n *\n * @params dbName The name of the db against which this query is being issued,\n * which could be missing if no db name was given at the time that the\n * connection was established.\n * @params queryConfig Information we have about the query being issued, typed\n * to reflect only the validation we've actually done on the args to\n * `client.query()`. This will be undefined if `client.query()` was called\n * with invalid arguments.\n */\nexport function getQuerySpanName(dbName: string | undefined, queryConfig?: { text: string; name?: unknown }): string {\n // NB: when the query config is invalid, we omit the dbName too, so that\n // someone (or some tool) reading the span name doesn't misinterpret the\n // dbName as being a prepared statement or sql commit name.\n if (!queryConfig) return SpanNames.QUERY_PREFIX;\n\n // Either the name of a prepared statement; or an attempted parse\n // of the SQL command, normalized to uppercase; or unknown.\n const command =\n typeof queryConfig.name === 'string' && queryConfig.name\n ? queryConfig.name\n : parseNormalizedOperationName(queryConfig.text);\n\n return `${SpanNames.QUERY_PREFIX}:${command}${dbName ? ` ${dbName}` : ''}`;\n}\n\nexport function parseNormalizedOperationName(queryText: string): string {\n // Trim the query text to handle leading/trailing whitespace\n const trimmedQuery = queryText.trim();\n const indexOfFirstSpace = trimmedQuery.indexOf(' ');\n let sqlCommand = indexOfFirstSpace === -1 ? trimmedQuery : trimmedQuery.slice(0, indexOfFirstSpace);\n sqlCommand = sqlCommand.toUpperCase();\n\n // Handle query text being \"COMMIT;\", which has an extra semicolon before the space.\n return sqlCommand.endsWith(';') ? sqlCommand.slice(0, -1) : sqlCommand;\n}\n\nexport function parseAndMaskConnectionString(connectionString: string): string {\n try {\n // Parse the connection string\n const url = new URL(connectionString);\n\n // Remove all auth information (username and password)\n url.username = '';\n url.password = '';\n\n return url.toString();\n } catch {\n // If parsing fails, return a generic connection string\n return 'postgresql://localhost:5432/';\n }\n}\n\nexport function getConnectionString(params: PgParsedConnectionParams | PgPoolOptionsParams): string {\n if ('connectionString' in params && params.connectionString) {\n return parseAndMaskConnectionString(params.connectionString);\n }\n const host = params.host || 'localhost';\n const port = params.port || 5432;\n const database = params.database || '';\n return `postgresql://${host}:${port}/${database}`;\n}\n\nfunction getPort(port: number | undefined): number | undefined {\n // Port may be NaN as parseInt() is used on the value, passing null will result in NaN being parsed.\n // https://github.com/brianc/node-postgres/blob/2a8efbee09a284be12748ed3962bc9b816965e36/packages/pg/lib/connection-parameters.js#L66\n if (Number.isInteger(port)) {\n return port;\n }\n\n // Unable to find the default used in pg code, so falling back to 'undefined'.\n return undefined;\n}\n\nexport function getSemanticAttributesFromConnection(params: PgParsedConnectionParams): SpanAttributes {\n return {\n [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_POSTGRESQL,\n [ATTR_DB_NAME]: params.database,\n [ATTR_DB_CONNECTION_STRING]: getConnectionString(params),\n [ATTR_DB_USER]: params.user,\n [ATTR_NET_PEER_NAME]: params.host, // required\n [ATTR_NET_PEER_PORT]: getPort(params.port),\n };\n}\n\nexport function getSemanticAttributesFromPoolConnection(params: PgPoolOptionsParams): SpanAttributes {\n let url: URL | undefined;\n try {\n url = params.connectionString ? new URL(params.connectionString) : undefined;\n } catch {\n url = undefined;\n }\n\n return {\n [AttributeNames.IDLE_TIMEOUT_MILLIS]: params.idleTimeoutMillis,\n [AttributeNames.MAX_CLIENT]: params.maxClient,\n [ATTR_DB_SYSTEM]: DB_SYSTEM_VALUE_POSTGRESQL,\n [ATTR_DB_NAME]: url?.pathname.slice(1) ?? params.database,\n [ATTR_DB_CONNECTION_STRING]: getConnectionString(params),\n [ATTR_NET_PEER_NAME]: url?.hostname ?? params.host,\n [ATTR_NET_PEER_PORT]: Number(url?.port) || getPort(params.port),\n [ATTR_DB_USER]: url?.username ?? params.user,\n };\n}\n\n/**\n * The SDK always requires a parent span (it sets `requireParentSpan: true`), so\n * we only instrument when there is an active span to parent the new span under.\n */\nexport function shouldSkipInstrumentation(): boolean {\n return getActiveSpan() === undefined;\n}\n\n// Create an (inactive) span from our normalized queryConfig object,\n// or return a basic span if no queryConfig was given/could be created.\nexport function handleConfigQuery(\n this: PgClientExtended,\n queryConfig?: { text: string; values?: unknown; name?: unknown },\n): Span {\n // Create child span.\n const { connectionParameters } = this;\n const dbName = connectionParameters.database;\n\n const spanName = getQuerySpanName(dbName, queryConfig);\n const span = startInactiveSpan({\n name: spanName,\n kind: SPAN_KIND.CLIENT,\n attributes: {\n ...getSemanticAttributesFromConnection(connectionParameters),\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n },\n });\n\n if (!queryConfig) {\n return span;\n }\n\n // Set attributes\n if (queryConfig.text) {\n span.setAttribute(ATTR_DB_STATEMENT, queryConfig.text);\n }\n\n // Set plan name attribute, if present\n if (typeof queryConfig.name === 'string') {\n span.setAttribute(AttributeNames.PG_PLAN, queryConfig.name);\n }\n\n return span;\n}\n\nexport function patchCallback(span: Span, cb: PostgresCallback): PostgresCallback {\n return function patchedCallback(this: PgClientExtended, err: Error, res: object) {\n if (err) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: err.message });\n }\n span.end();\n cb.call(this, err, res);\n };\n}\n\nexport function patchCallbackPGPool(span: Span, cb: PgPoolCallback): PgPoolCallback {\n return function patchedCallback(this: PgPoolExtended, err: Error, res: object, done: any) {\n if (err) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: err.message });\n }\n span.end();\n cb.call(this, err, res, done);\n };\n}\n\nexport function patchClientConnectCallback(span: Span, cb: (...args: unknown[]) => void): (...args: unknown[]) => void {\n return function patchedClientConnectCallback(this: PgClient, ...args: unknown[]) {\n const err = args[0];\n if (err instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: err.message });\n }\n span.end();\n cb.apply(this, args);\n };\n}\n\n/**\n * Attempt to get a message string from a thrown value, while being quite\n * defensive, to recognize the fact that, in JS, any kind of value (even\n * primitives) can be thrown.\n */\nexport function getErrorMessage(e: unknown): string | undefined {\n return typeof e === 'object' && e !== null && 'message' in e\n ? String((e as { message?: unknown }).message)\n : undefined;\n}\n\nexport function isObjectWithTextString(it: unknown): it is ObjectWithText {\n return typeof it === 'object' && typeof (it as null | { text?: unknown })?.text === 'string';\n}\n\nexport type ObjectWithText = {\n text: string;\n [k: string]: unknown;\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sources":["../../../../../../src/integrations/tracing/postgres/vendored/utils.ts"],"sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n *\n * NOTICE from the Sentry authors:\n * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-pg\n * - Upstream version: @opentelemetry/instrumentation-pg@0.70.0\n * - Types from `pg` package inlined as simplified interfaces\n * - Refactored to use Sentry's span APIs instead of OpenTelemetry tracing APIs\n */\n\nimport type { Span, SpanAttributes } from '@sentry/core';\nimport {\n getActiveSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_KIND,\n SPAN_STATUS_ERROR,\n startInactiveSpan,\n} from '@sentry/core';\nimport { AttributeNames } from './enums/AttributeNames';\nimport { SpanNames } from './enums/SpanNames';\nimport type {\n PgClientExtended,\n PgParsedConnectionParams,\n PgPoolCallback,\n PgPoolExtended,\n PgPoolOptionsParams,\n PostgresCallback,\n} from './internal-types';\nimport type { PgClient } from './pg-types';\nimport { ATTR_DB_CONNECTION_STRING, DB_SYSTEM_VALUE_POSTGRESQL } from './semconv';\nimport {\n DB_NAME,\n DB_STATEMENT,\n DB_SYSTEM,\n DB_USER,\n NET_PEER_NAME,\n NET_PEER_PORT,\n} from '@sentry/conventions/attributes';\n\n/* oxlint-disable typescript/no-deprecated */\n\nexport const ORIGIN = 'auto.db.otel.postgres';\n\n/**\n * Helper function to get a low cardinality span name from whatever info we have\n * about the query.\n *\n * This is tricky, because we don't have most of the information (table name,\n * operation name, etc) the spec recommends using to build a low-cardinality\n * value w/o parsing. So, we use db.name and assume that, if the query's a named\n * prepared statement, those `name` values will be low cardinality. If we don't\n * have a named prepared statement, we try to parse an operation (despite the\n * spec's warnings).\n *\n * @params dbName The name of the db against which this query is being issued,\n * which could be missing if no db name was given at the time that the\n * connection was established.\n * @params queryConfig Information we have about the query being issued, typed\n * to reflect only the validation we've actually done on the args to\n * `client.query()`. This will be undefined if `client.query()` was called\n * with invalid arguments.\n */\nexport function getQuerySpanName(dbName: string | undefined, queryConfig?: { text: string; name?: unknown }): string {\n // NB: when the query config is invalid, we omit the dbName too, so that\n // someone (or some tool) reading the span name doesn't misinterpret the\n // dbName as being a prepared statement or sql commit name.\n if (!queryConfig) return SpanNames.QUERY_PREFIX;\n\n // Either the name of a prepared statement; or an attempted parse\n // of the SQL command, normalized to uppercase; or unknown.\n const command =\n typeof queryConfig.name === 'string' && queryConfig.name\n ? queryConfig.name\n : parseNormalizedOperationName(queryConfig.text);\n\n return `${SpanNames.QUERY_PREFIX}:${command}${dbName ? ` ${dbName}` : ''}`;\n}\n\nexport function parseNormalizedOperationName(queryText: string): string {\n // Trim the query text to handle leading/trailing whitespace\n const trimmedQuery = queryText.trim();\n const indexOfFirstSpace = trimmedQuery.indexOf(' ');\n let sqlCommand = indexOfFirstSpace === -1 ? trimmedQuery : trimmedQuery.slice(0, indexOfFirstSpace);\n sqlCommand = sqlCommand.toUpperCase();\n\n // Handle query text being \"COMMIT;\", which has an extra semicolon before the space.\n return sqlCommand.endsWith(';') ? sqlCommand.slice(0, -1) : sqlCommand;\n}\n\nexport function parseAndMaskConnectionString(connectionString: string): string {\n try {\n // Parse the connection string\n const url = new URL(connectionString);\n\n // Remove all auth information (username and password)\n url.username = '';\n url.password = '';\n\n return url.toString();\n } catch {\n // If parsing fails, return a generic connection string\n return 'postgresql://localhost:5432/';\n }\n}\n\nexport function getConnectionString(params: PgParsedConnectionParams | PgPoolOptionsParams): string {\n if ('connectionString' in params && params.connectionString) {\n return parseAndMaskConnectionString(params.connectionString);\n }\n const host = params.host || 'localhost';\n const port = params.port || 5432;\n const database = params.database || '';\n return `postgresql://${host}:${port}/${database}`;\n}\n\nfunction getPort(port: number | undefined): number | undefined {\n // Port may be NaN as parseInt() is used on the value, passing null will result in NaN being parsed.\n // https://github.com/brianc/node-postgres/blob/2a8efbee09a284be12748ed3962bc9b816965e36/packages/pg/lib/connection-parameters.js#L66\n if (Number.isInteger(port)) {\n return port;\n }\n\n // Unable to find the default used in pg code, so falling back to 'undefined'.\n return undefined;\n}\n\nexport function getSemanticAttributesFromConnection(params: PgParsedConnectionParams): SpanAttributes {\n return {\n [DB_SYSTEM]: DB_SYSTEM_VALUE_POSTGRESQL,\n [DB_NAME]: params.database,\n [ATTR_DB_CONNECTION_STRING]: getConnectionString(params),\n [DB_USER]: params.user,\n [NET_PEER_NAME]: params.host, // required\n [NET_PEER_PORT]: getPort(params.port),\n };\n}\n\nexport function getSemanticAttributesFromPoolConnection(params: PgPoolOptionsParams): SpanAttributes {\n let url: URL | undefined;\n try {\n url = params.connectionString ? new URL(params.connectionString) : undefined;\n } catch {\n url = undefined;\n }\n\n return {\n [AttributeNames.IDLE_TIMEOUT_MILLIS]: params.idleTimeoutMillis,\n [AttributeNames.MAX_CLIENT]: params.maxClient,\n [DB_SYSTEM]: DB_SYSTEM_VALUE_POSTGRESQL,\n [DB_NAME]: url?.pathname.slice(1) ?? params.database,\n [ATTR_DB_CONNECTION_STRING]: getConnectionString(params),\n [NET_PEER_NAME]: url?.hostname ?? params.host,\n [NET_PEER_PORT]: Number(url?.port) || getPort(params.port),\n [DB_USER]: url?.username ?? params.user,\n };\n}\n\n/**\n * The SDK always requires a parent span (it sets `requireParentSpan: true`), so\n * we only instrument when there is an active span to parent the new span under.\n */\nexport function shouldSkipInstrumentation(): boolean {\n return getActiveSpan() === undefined;\n}\n\n// Create an (inactive) span from our normalized queryConfig object,\n// or return a basic span if no queryConfig was given/could be created.\nexport function handleConfigQuery(\n this: PgClientExtended,\n queryConfig?: { text: string; values?: unknown; name?: unknown },\n): Span {\n // Create child span.\n const { connectionParameters } = this;\n const dbName = connectionParameters.database;\n\n const spanName = getQuerySpanName(dbName, queryConfig);\n const span = startInactiveSpan({\n name: spanName,\n kind: SPAN_KIND.CLIENT,\n attributes: {\n ...getSemanticAttributesFromConnection(connectionParameters),\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n },\n });\n\n if (!queryConfig) {\n return span;\n }\n\n // Set attributes\n if (queryConfig.text) {\n span.setAttribute(DB_STATEMENT, queryConfig.text);\n }\n\n // Set plan name attribute, if present\n if (typeof queryConfig.name === 'string') {\n span.setAttribute(AttributeNames.PG_PLAN, queryConfig.name);\n }\n\n return span;\n}\n\nexport function patchCallback(span: Span, cb: PostgresCallback): PostgresCallback {\n return function patchedCallback(this: PgClientExtended, err: Error, res: object) {\n if (err) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: err.message });\n }\n span.end();\n cb.call(this, err, res);\n };\n}\n\nexport function patchCallbackPGPool(span: Span, cb: PgPoolCallback): PgPoolCallback {\n return function patchedCallback(this: PgPoolExtended, err: Error, res: object, done: any) {\n if (err) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: err.message });\n }\n span.end();\n cb.call(this, err, res, done);\n };\n}\n\nexport function patchClientConnectCallback(span: Span, cb: (...args: unknown[]) => void): (...args: unknown[]) => void {\n return function patchedClientConnectCallback(this: PgClient, ...args: unknown[]) {\n const err = args[0];\n if (err instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: err.message });\n }\n span.end();\n cb.apply(this, args);\n };\n}\n\n/**\n * Attempt to get a message string from a thrown value, while being quite\n * defensive, to recognize the fact that, in JS, any kind of value (even\n * primitives) can be thrown.\n */\nexport function getErrorMessage(e: unknown): string | undefined {\n return typeof e === 'object' && e !== null && 'message' in e\n ? String((e as { message?: unknown }).message)\n : undefined;\n}\n\nexport function isObjectWithTextString(it: unknown): it is ObjectWithText {\n return typeof it === 'object' && typeof (it as null | { text?: unknown })?.text === 'string';\n}\n\nexport type ObjectWithText = {\n text: string;\n [k: string]: unknown;\n};\n"],"names":[],"mappings":";;;;;;AA0CO,MAAM,MAAA,GAAS;AAqBf,SAAS,gBAAA,CAAiB,QAA4B,WAAA,EAAwD;AAInH,EAAA,IAAI,CAAC,WAAA,EAAa,OAAO,SAAA,CAAU,YAAA;AAInC,EAAA,MAAM,OAAA,GACJ,OAAO,WAAA,CAAY,IAAA,KAAS,QAAA,IAAY,WAAA,CAAY,IAAA,GAChD,WAAA,CAAY,IAAA,GACZ,4BAAA,CAA6B,WAAA,CAAY,IAAI,CAAA;AAEnD,EAAA,OAAO,CAAA,EAAG,SAAA,CAAU,YAAY,CAAA,CAAA,EAAI,OAAO,GAAG,MAAA,GAAS,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA;AAC1E;AAEO,SAAS,6BAA6B,SAAA,EAA2B;AAEtE,EAAA,MAAM,YAAA,GAAe,UAAU,IAAA,EAAK;AACpC,EAAA,MAAM,iBAAA,GAAoB,YAAA,CAAa,OAAA,CAAQ,GAAG,CAAA;AAClD,EAAA,IAAI,aAAa,iBAAA,KAAsB,EAAA,GAAK,eAAe,YAAA,CAAa,KAAA,CAAM,GAAG,iBAAiB,CAAA;AAClG,EAAA,UAAA,GAAa,WAAW,WAAA,EAAY;AAGpC,EAAA,OAAO,UAAA,CAAW,SAAS,GAAG,CAAA,GAAI,WAAW,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GAAI,UAAA;AAC9D;AAEO,SAAS,6BAA6B,gBAAA,EAAkC;AAC7E,EAAA,IAAI;AAEF,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,gBAAgB,CAAA;AAGpC,IAAA,GAAA,CAAI,QAAA,GAAW,EAAA;AACf,IAAA,GAAA,CAAI,QAAA,GAAW,EAAA;AAEf,IAAA,OAAO,IAAI,QAAA,EAAS;AAAA,EACtB,CAAA,CAAA,MAAQ;AAEN,IAAA,OAAO,8BAAA;AAAA,EACT;AACF;AAEO,SAAS,oBAAoB,MAAA,EAAgE;AAClG,EAAA,IAAI,kBAAA,IAAsB,MAAA,IAAU,MAAA,CAAO,gBAAA,EAAkB;AAC3D,IAAA,OAAO,4BAAA,CAA6B,OAAO,gBAAgB,CAAA;AAAA,EAC7D;AACA,EAAA,MAAM,IAAA,GAAO,OAAO,IAAA,IAAQ,WAAA;AAC5B,EAAA,MAAM,IAAA,GAAO,OAAO,IAAA,IAAQ,IAAA;AAC5B,EAAA,MAAM,QAAA,GAAW,OAAO,QAAA,IAAY,EAAA;AACpC,EAAA,OAAO,CAAA,aAAA,EAAgB,IAAI,CAAA,CAAA,EAAI,IAAI,IAAI,QAAQ,CAAA,CAAA;AACjD;AAEA,SAAS,QAAQ,IAAA,EAA8C;AAG7D,EAAA,IAAI,MAAA,CAAO,SAAA,CAAU,IAAI,CAAA,EAAG;AAC1B,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,oCAAoC,MAAA,EAAkD;AACpG,EAAA,OAAO;AAAA,IACL,CAAC,SAAS,GAAG,0BAAA;AAAA,IACb,CAAC,OAAO,GAAG,MAAA,CAAO,QAAA;AAAA,IAClB,CAAC,yBAAyB,GAAG,mBAAA,CAAoB,MAAM,CAAA;AAAA,IACvD,CAAC,OAAO,GAAG,MAAA,CAAO,IAAA;AAAA,IAClB,CAAC,aAAa,GAAG,MAAA,CAAO,IAAA;AAAA;AAAA,IACxB,CAAC,aAAa,GAAG,OAAA,CAAQ,OAAO,IAAI;AAAA,GACtC;AACF;AAEO,SAAS,wCAAwC,MAAA,EAA6C;AACnG,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,OAAO,gBAAA,GAAmB,IAAI,GAAA,CAAI,MAAA,CAAO,gBAAgB,CAAA,GAAI,KAAA,CAAA;AAAA,EACrE,CAAA,CAAA,MAAQ;AACN,IAAA,GAAA,GAAM,MAAA;AAAA,EACR;AAEA,EAAA,OAAO;AAAA,IACL,CAAC,cAAA,CAAe,mBAAmB,GAAG,MAAA,CAAO,iBAAA;AAAA,IAC7C,CAAC,cAAA,CAAe,UAAU,GAAG,MAAA,CAAO,SAAA;AAAA,IACpC,CAAC,SAAS,GAAG,0BAAA;AAAA,IACb,CAAC,OAAO,GAAG,GAAA,EAAK,SAAS,KAAA,CAAM,CAAC,KAAK,MAAA,CAAO,QAAA;AAAA,IAC5C,CAAC,yBAAyB,GAAG,mBAAA,CAAoB,MAAM,CAAA;AAAA,IACvD,CAAC,aAAa,GAAG,GAAA,EAAK,YAAY,MAAA,CAAO,IAAA;AAAA,IACzC,CAAC,aAAa,GAAG,MAAA,CAAO,KAAK,IAAI,CAAA,IAAK,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA;AAAA,IACzD,CAAC,OAAO,GAAG,GAAA,EAAK,YAAY,MAAA,CAAO;AAAA,GACrC;AACF;AAMO,SAAS,yBAAA,GAAqC;AACnD,EAAA,OAAO,eAAc,KAAM,MAAA;AAC7B;AAIO,SAAS,kBAEd,WAAA,EACM;AAEN,EAAA,MAAM,EAAE,sBAAqB,GAAI,IAAA;AACjC,EAAA,MAAM,SAAS,oBAAA,CAAqB,QAAA;AAEpC,EAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,MAAA,EAAQ,WAAW,CAAA;AACrD,EAAA,MAAM,OAAO,iBAAA,CAAkB;AAAA,IAC7B,IAAA,EAAM,QAAA;AAAA,IACN,MAAM,SAAA,CAAU,MAAA;AAAA,IAChB,UAAA,EAAY;AAAA,MACV,GAAG,oCAAoC,oBAAoB,CAAA;AAAA,MAC3D,CAAC,gCAAgC,GAAG;AAAA;AACtC,GACD,CAAA;AAED,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,IAAI,YAAY,IAAA,EAAM;AACpB,IAAA,IAAA,CAAK,YAAA,CAAa,YAAA,EAAc,WAAA,CAAY,IAAI,CAAA;AAAA,EAClD;AAGA,EAAA,IAAI,OAAO,WAAA,CAAY,IAAA,KAAS,QAAA,EAAU;AACxC,IAAA,IAAA,CAAK,YAAA,CAAa,cAAA,CAAe,OAAA,EAAS,WAAA,CAAY,IAAI,CAAA;AAAA,EAC5D;AAEA,EAAA,OAAO,IAAA;AACT;AAEO,SAAS,aAAA,CAAc,MAAY,EAAA,EAAwC;AAChF,EAAA,OAAO,SAAS,eAAA,CAAwC,GAAA,EAAY,GAAA,EAAa;AAC/E,IAAA,IAAI,GAAA,EAAK;AACP,MAAA,IAAA,CAAK,UAAU,EAAE,IAAA,EAAM,mBAAmB,OAAA,EAAS,GAAA,CAAI,SAAS,CAAA;AAAA,IAClE;AACA,IAAA,IAAA,CAAK,GAAA,EAAI;AACT,IAAA,EAAA,CAAG,IAAA,CAAK,IAAA,EAAM,GAAA,EAAK,GAAG,CAAA;AAAA,EACxB,CAAA;AACF;AAEO,SAAS,mBAAA,CAAoB,MAAY,EAAA,EAAoC;AAClF,EAAA,OAAO,SAAS,eAAA,CAAsC,GAAA,EAAY,GAAA,EAAa,IAAA,EAAW;AACxF,IAAA,IAAI,GAAA,EAAK;AACP,MAAA,IAAA,CAAK,UAAU,EAAE,IAAA,EAAM,mBAAmB,OAAA,EAAS,GAAA,CAAI,SAAS,CAAA;AAAA,IAClE;AACA,IAAA,IAAA,CAAK,GAAA,EAAI;AACT,IAAA,EAAA,CAAG,IAAA,CAAK,IAAA,EAAM,GAAA,EAAK,GAAA,EAAK,IAAI,CAAA;AAAA,EAC9B,CAAA;AACF;AAEO,SAAS,0BAAA,CAA2B,MAAY,EAAA,EAAgE;AACrH,EAAA,OAAO,SAAS,gCAAgD,IAAA,EAAiB;AAC/E,IAAA,MAAM,GAAA,GAAM,KAAK,CAAC,CAAA;AAClB,IAAA,IAAI,eAAe,KAAA,EAAO;AACxB,MAAA,IAAA,CAAK,UAAU,EAAE,IAAA,EAAM,mBAAmB,OAAA,EAAS,GAAA,CAAI,SAAS,CAAA;AAAA,IAClE;AACA,IAAA,IAAA,CAAK,GAAA,EAAI;AACT,IAAA,EAAA,CAAG,KAAA,CAAM,MAAM,IAAI,CAAA;AAAA,EACrB,CAAA;AACF;AAOO,SAAS,gBAAgB,CAAA,EAAgC;AAC9D,EAAA,OAAO,OAAO,CAAA,KAAM,QAAA,IAAY,CAAA,KAAM,IAAA,IAAQ,aAAa,CAAA,GACvD,MAAA,CAAQ,CAAA,CAA4B,OAAO,CAAA,GAC3C,MAAA;AACN;AAEO,SAAS,uBAAuB,EAAA,EAAmC;AACxE,EAAA,OAAO,OAAO,EAAA,KAAO,QAAA,IAAY,OAAQ,IAAkC,IAAA,KAAS,QAAA;AACtF;;;;"}
@@ -1,13 +1,14 @@
1
1
  import { trace, context } from '@opentelemetry/api';
2
2
  import { InstrumentationBase, InstrumentationNodeModuleDefinition, safeExecuteInTheMiddle } from '@opentelemetry/instrumentation';
3
3
  import { InstrumentationNodeModuleFile } from './InstrumentationNodeModuleFile.js';
4
- import { ATTR_DB_OPERATION_NAME, ATTR_DB_QUERY_TEXT, ATTR_DB_SYSTEM_NAME, ATTR_DB_RESPONSE_STATUS_CODE, ATTR_ERROR_TYPE } from '@opentelemetry/semantic-conventions';
4
+ import { DB_OPERATION_NAME, DB_QUERY_TEXT, DB_SYSTEM_NAME, ERROR_TYPE } from '@sentry/conventions/attributes';
5
5
  import { SDK_VERSION, debug, replaceExports, startSpanManual, SPAN_STATUS_ERROR, defineIntegration, instrumentPostgresJsSql } from '@sentry/core';
6
6
  import { generateInstrumentOnce, addOriginToSpan } from '@sentry/node-core';
7
7
  import { DEBUG_BUILD } from '../../debug-build.js';
8
8
 
9
9
  const INTEGRATION_NAME = "PostgresJs";
10
10
  const SUPPORTED_VERSIONS = [">=3.0.0 <4"];
11
+ const ATTR_DB_RESPONSE_STATUS_CODE = "db.response.status_code";
11
12
  const SQL_OPERATION_REGEX = /^(SELECT|INSERT|UPDATE|DELETE|CREATE|DROP|ALTER)/i;
12
13
  const QUERY_FROM_INSTRUMENTED_SQL = /* @__PURE__ */ Symbol.for("sentry.query.from.instrumented.sql");
13
14
  const instrumentPostgresJs = generateInstrumentOnce(
@@ -109,12 +110,12 @@ class PostgresJsInstrumentation extends InstrumentationBase {
109
110
  */
110
111
  _setOperationName(span, sanitizedQuery, command) {
111
112
  if (command) {
112
- span.setAttribute(ATTR_DB_OPERATION_NAME, command);
113
+ span.setAttribute(DB_OPERATION_NAME, command);
113
114
  return;
114
115
  }
115
116
  const operationMatch = sanitizedQuery?.match(SQL_OPERATION_REGEX);
116
117
  if (operationMatch?.[1]) {
117
- span.setAttribute(ATTR_DB_OPERATION_NAME, operationMatch[1].toUpperCase());
118
+ span.setAttribute(DB_OPERATION_NAME, operationMatch[1].toUpperCase());
118
119
  }
119
120
  }
120
121
  /**
@@ -173,8 +174,8 @@ class PostgresJsInstrumentation extends InstrumentationBase {
173
174
  (span) => {
174
175
  addOriginToSpan(span, "auto.db.postgresjs");
175
176
  span.setAttributes({
176
- [ATTR_DB_SYSTEM_NAME]: "postgres",
177
- [ATTR_DB_QUERY_TEXT]: sanitizedSqlQuery
177
+ [DB_SYSTEM_NAME]: "postgres",
178
+ [DB_QUERY_TEXT]: sanitizedSqlQuery
178
179
  });
179
180
  const config = self.getConfig();
180
181
  const { requestHook } = config;
@@ -211,7 +212,7 @@ class PostgresJsInstrumentation extends InstrumentationBase {
211
212
  message: rejectArgs?.[0]?.message || "unknown_error"
212
213
  });
213
214
  span.setAttribute(ATTR_DB_RESPONSE_STATUS_CODE, rejectArgs?.[0]?.code || "unknown");
214
- span.setAttribute(ATTR_ERROR_TYPE, rejectArgs?.[0]?.name || "unknown");
215
+ span.setAttribute(ERROR_TYPE, rejectArgs?.[0]?.name || "unknown");
215
216
  self._setOperationName(span, sanitizedSqlQuery);
216
217
  span.end();
217
218
  } catch (e) {
@@ -1 +1 @@
1
- {"version":3,"file":"postgresjs.js","sources":["../../../../src/integrations/tracing/postgresjs.ts"],"sourcesContent":["// Instrumentation for https://github.com/porsager/postgres\n\nimport { context, trace } from '@opentelemetry/api';\nimport type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport {\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n safeExecuteInTheMiddle,\n} from '@opentelemetry/instrumentation';\nimport { InstrumentationNodeModuleFile } from './InstrumentationNodeModuleFile';\nimport {\n ATTR_DB_OPERATION_NAME,\n ATTR_DB_QUERY_TEXT,\n ATTR_DB_RESPONSE_STATUS_CODE,\n ATTR_DB_SYSTEM_NAME,\n ATTR_ERROR_TYPE,\n} from '@opentelemetry/semantic-conventions';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n debug,\n defineIntegration,\n instrumentPostgresJsSql,\n replaceExports,\n SDK_VERSION,\n SPAN_STATUS_ERROR,\n startSpanManual,\n} from '@sentry/core';\nimport { addOriginToSpan, generateInstrumentOnce } from '@sentry/node-core';\nimport { DEBUG_BUILD } from '../../debug-build';\n\nconst INTEGRATION_NAME = 'PostgresJs' as const;\nconst SUPPORTED_VERSIONS = ['>=3.0.0 <4'];\nconst SQL_OPERATION_REGEX = /^(SELECT|INSERT|UPDATE|DELETE|CREATE|DROP|ALTER)/i;\n\ntype PostgresConnectionContext = {\n ATTR_DB_NAMESPACE?: string; // Database name\n ATTR_SERVER_ADDRESS?: string; // Hostname or IP address of the database server\n ATTR_SERVER_PORT?: string; // Port number of the database server\n};\n\n// Marker to track if a query was created from an instrumented sql instance\n// This prevents double-spanning when both wrapper and prototype patches are active\nconst QUERY_FROM_INSTRUMENTED_SQL = Symbol.for('sentry.query.from.instrumented.sql');\n\ntype PostgresJsInstrumentationConfig = InstrumentationConfig & {\n /**\n * Whether to require a parent span for the instrumentation.\n * If set to true, the instrumentation will only create spans if there is a parent span\n * available in the current scope.\n * @default true\n */\n requireParentSpan?: boolean;\n /**\n * Hook to modify the span before it is started.\n * This can be used to set additional attributes or modify the span in any way.\n */\n requestHook?: (span: Span, sanitizedSqlQuery: string, postgresConnectionContext?: PostgresConnectionContext) => void;\n};\n\nexport const instrumentPostgresJs = generateInstrumentOnce(\n INTEGRATION_NAME,\n (options?: PostgresJsInstrumentationConfig) =>\n new PostgresJsInstrumentation({\n requireParentSpan: options?.requireParentSpan ?? true,\n requestHook: options?.requestHook,\n }),\n);\n\n/**\n * Instrumentation for the [postgres](https://www.npmjs.com/package/postgres) library.\n * This instrumentation captures postgresjs queries and their attributes.\n *\n * Uses internal Sentry patching patterns to support both CommonJS and ESM environments.\n */\nexport class PostgresJsInstrumentation extends InstrumentationBase<PostgresJsInstrumentationConfig> {\n public constructor(config: PostgresJsInstrumentationConfig) {\n super('sentry-postgres-js', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by patching the postgres module.\n * Uses two complementary approaches:\n * 1. Main function wrapper: instruments sql instances created AFTER instrumentation is set up (CJS + ESM)\n * 2. Query.prototype patch: fallback for sql instances created BEFORE instrumentation (CJS only)\n */\n public init(): InstrumentationNodeModuleDefinition {\n const module = new InstrumentationNodeModuleDefinition(\n 'postgres',\n SUPPORTED_VERSIONS,\n exports => {\n try {\n return this._patchPostgres(exports);\n } catch (e) {\n DEBUG_BUILD && debug.error('Failed to patch postgres module:', e);\n return exports;\n }\n },\n exports => exports,\n );\n\n // Add fallback Query.prototype patching for pre-existing sql instances (CJS only)\n // This catches queries from sql instances created before Sentry was initialized\n ['src', 'cf/src', 'cjs/src'].forEach(path => {\n module.files.push(\n new InstrumentationNodeModuleFile(\n `postgres/${path}/query.js`,\n SUPPORTED_VERSIONS,\n this._patchQueryPrototype.bind(this),\n this._unpatchQueryPrototype.bind(this),\n ),\n );\n });\n\n return module;\n }\n\n /**\n * Patches the postgres module by wrapping the main export function.\n * This intercepts the creation of sql instances and instruments them.\n */\n private _patchPostgres(exports: { [key: string]: unknown }): { [key: string]: unknown } {\n // In CJS: exports is the function itself\n // In ESM: exports.default is the function\n const isFunction = typeof exports === 'function';\n const Original = isFunction ? exports : exports.default;\n\n if (typeof Original !== 'function') {\n DEBUG_BUILD && debug.warn('postgres module does not export a function. Skipping instrumentation.');\n return exports;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n const WrappedPostgres = function (this: unknown, ...args: unknown[]): unknown {\n const sql = Reflect.construct(Original as (...args: unknown[]) => unknown, args);\n\n // Validate that construction succeeded and returned a valid function object\n if (!sql || typeof sql !== 'function') {\n DEBUG_BUILD && debug.warn('postgres() did not return a valid instance');\n return sql;\n }\n\n // Delegate to the portable instrumentation from @sentry/core\n const config = self.getConfig();\n return instrumentPostgresJsSql(sql, {\n requireParentSpan: config.requireParentSpan,\n requestHook: config.requestHook,\n });\n };\n\n Object.setPrototypeOf(WrappedPostgres, Original);\n Object.setPrototypeOf(WrappedPostgres.prototype, (Original as { prototype: object }).prototype);\n\n for (const key of Object.getOwnPropertyNames(Original)) {\n if (!['length', 'name', 'prototype'].includes(key)) {\n const descriptor = Object.getOwnPropertyDescriptor(Original, key);\n if (descriptor) {\n Object.defineProperty(WrappedPostgres, key, descriptor);\n }\n }\n }\n\n // For CJS: the exports object IS the function, so return the wrapped function\n // For ESM: replace the default export\n if (isFunction) {\n return WrappedPostgres as unknown as { [key: string]: unknown };\n } else {\n replaceExports(exports, 'default', WrappedPostgres);\n return exports;\n }\n }\n\n /**\n * Determines whether a span should be created based on the current context.\n * If `requireParentSpan` is set to true in the configuration, a span will\n * only be created if there is a parent span available.\n */\n private _shouldCreateSpans(): boolean {\n const config = this.getConfig();\n const hasParentSpan = trace.getSpan(context.active()) !== undefined;\n return hasParentSpan || !config.requireParentSpan;\n }\n\n /**\n * Extracts DB operation name from SQL query and sets it on the span.\n */\n private _setOperationName(span: Span, sanitizedQuery: string | undefined, command?: string): void {\n if (command) {\n span.setAttribute(ATTR_DB_OPERATION_NAME, command);\n return;\n }\n // Fallback: extract operation from the SQL query\n const operationMatch = sanitizedQuery?.match(SQL_OPERATION_REGEX);\n if (operationMatch?.[1]) {\n span.setAttribute(ATTR_DB_OPERATION_NAME, operationMatch[1].toUpperCase());\n }\n }\n\n /**\n * Reconstructs the full SQL query from template strings with PostgreSQL placeholders.\n *\n * For sql`SELECT * FROM users WHERE id = ${123} AND name = ${'foo'}`:\n * strings = [\"SELECT * FROM users WHERE id = \", \" AND name = \", \"\"]\n * returns: \"SELECT * FROM users WHERE id = $1 AND name = $2\"\n */\n private _reconstructQuery(strings: string[] | undefined): string | undefined {\n if (!strings?.length) {\n return undefined;\n }\n if (strings.length === 1) {\n return strings[0] || undefined;\n }\n // Join template parts with PostgreSQL placeholders ($1, $2, etc.)\n return strings.reduce((acc, str, i) => (i === 0 ? str : `${acc}$${i}${str}`), '');\n }\n\n /**\n * Sanitize SQL query as per the OTEL semantic conventions\n * https://opentelemetry.io/docs/specs/semconv/database/database-spans/#sanitization-of-dbquerytext\n *\n * PostgreSQL $n placeholders are preserved per OTEL spec - they're parameterized queries,\n * not sensitive literals. Only actual values (strings, numbers, booleans) are sanitized.\n */\n private _sanitizeSqlQuery(sqlQuery: string | undefined): string {\n if (!sqlQuery) {\n return 'Unknown SQL Query';\n }\n\n return (\n sqlQuery\n // Remove comments first (they may contain newlines and extra spaces)\n .replace(/--.*$/gm, '') // Single line comments (multiline mode)\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '') // Multi-line comments\n .replace(/;\\s*$/, '') // Remove trailing semicolons\n // Collapse whitespace to a single space (after removing comments)\n .replace(/\\s+/g, ' ')\n .trim() // Remove extra spaces and trim\n // Sanitize hex/binary literals before string literals\n .replace(/\\bX'[0-9A-Fa-f]*'/gi, '?') // Hex string literals\n .replace(/\\bB'[01]*'/gi, '?') // Binary string literals\n // Sanitize string literals (handles escaped quotes)\n .replace(/'(?:[^']|'')*'/g, '?')\n // Sanitize hex numbers\n .replace(/\\b0x[0-9A-Fa-f]+/gi, '?')\n // Sanitize boolean literals\n .replace(/\\b(?:TRUE|FALSE)\\b/gi, '?')\n // Sanitize numeric literals (preserve $n placeholders via negative lookbehind)\n .replace(/-?\\b\\d+\\.?\\d*[eE][+-]?\\d+\\b/g, '?') // Scientific notation\n .replace(/-?\\b\\d+\\.\\d+\\b/g, '?') // Decimals\n .replace(/-?\\.\\d+\\b/g, '?') // Decimals starting with dot\n .replace(/(?<!\\$)-?\\b\\d+\\b/g, '?') // Integers (NOT $n placeholders)\n // Collapse IN clauses for cardinality (both ? and $n variants)\n .replace(/\\bIN\\b\\s*\\(\\s*\\?(?:\\s*,\\s*\\?)*\\s*\\)/gi, 'IN (?)')\n .replace(/\\bIN\\b\\s*\\(\\s*\\$\\d+(?:\\s*,\\s*\\$\\d+)*\\s*\\)/gi, 'IN ($?)')\n );\n }\n\n /**\n * Fallback patch for Query.prototype.handle to instrument queries from pre-existing sql instances.\n * This catches queries from sql instances created BEFORE Sentry was initialized (CJS only).\n *\n * Note: Queries from pre-existing instances won't have connection context (database, host, port)\n * because the sql instance wasn't created through our instrumented wrapper.\n */\n private _patchQueryPrototype(moduleExports: {\n Query: {\n prototype: {\n handle: ((...args: unknown[]) => Promise<unknown>) & {\n __sentry_original__?: (...args: unknown[]) => Promise<unknown>;\n };\n };\n };\n }): typeof moduleExports {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n const originalHandle = moduleExports.Query.prototype.handle;\n\n moduleExports.Query.prototype.handle = async function (\n this: {\n resolve: unknown;\n reject: unknown;\n strings?: string[];\n executed?: boolean;\n },\n ...args: unknown[]\n ): Promise<unknown> {\n // Skip if this query came from an instrumented sql instance (already handled by wrapper),\n // or if handle() was already called (postgres.js calls handle() from then/catch/finally —\n // only the first call executes SQL, subsequent calls are no-ops).\n if (this.executed || (this as Record<symbol, unknown>)[QUERY_FROM_INSTRUMENTED_SQL]) {\n return originalHandle.apply(this, args);\n }\n\n // Skip if we shouldn't create spans\n if (!self._shouldCreateSpans()) {\n return originalHandle.apply(this, args);\n }\n\n const fullQuery = self._reconstructQuery(this.strings);\n const sanitizedSqlQuery = self._sanitizeSqlQuery(fullQuery);\n\n return startSpanManual(\n {\n name: sanitizedSqlQuery || 'postgresjs.query',\n op: 'db',\n },\n (span: Span) => {\n addOriginToSpan(span, 'auto.db.postgresjs');\n\n span.setAttributes({\n [ATTR_DB_SYSTEM_NAME]: 'postgres',\n [ATTR_DB_QUERY_TEXT]: sanitizedSqlQuery,\n });\n\n // Note: No connection context available for pre-existing instances\n // because the sql instance wasn't created through our instrumented wrapper\n\n const config = self.getConfig();\n const { requestHook } = config;\n if (requestHook) {\n safeExecuteInTheMiddle(\n () => requestHook(span, sanitizedSqlQuery, undefined),\n e => {\n if (e) {\n span.setAttribute('sentry.hook.error', 'requestHook failed');\n DEBUG_BUILD && debug.error(`Error in requestHook for ${INTEGRATION_NAME} integration:`, e);\n }\n },\n true,\n );\n }\n\n // Wrap resolve to end span on success\n const originalResolve = this.resolve;\n this.resolve = new Proxy(originalResolve as (...args: unknown[]) => unknown, {\n apply: (resolveTarget, resolveThisArg, resolveArgs: [{ command?: string }]) => {\n try {\n self._setOperationName(span, sanitizedSqlQuery, resolveArgs?.[0]?.command);\n span.end();\n } catch (e) {\n DEBUG_BUILD && debug.error('Error ending span in resolve callback:', e);\n }\n return Reflect.apply(resolveTarget, resolveThisArg, resolveArgs);\n },\n });\n\n // Wrap reject to end span on error\n const originalReject = this.reject;\n this.reject = new Proxy(originalReject as (...args: unknown[]) => unknown, {\n apply: (rejectTarget, rejectThisArg, rejectArgs: { message?: string; code?: string; name?: string }[]) => {\n try {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n message: rejectArgs?.[0]?.message || 'unknown_error',\n });\n span.setAttribute(ATTR_DB_RESPONSE_STATUS_CODE, rejectArgs?.[0]?.code || 'unknown');\n span.setAttribute(ATTR_ERROR_TYPE, rejectArgs?.[0]?.name || 'unknown');\n self._setOperationName(span, sanitizedSqlQuery);\n span.end();\n } catch (e) {\n DEBUG_BUILD && debug.error('Error ending span in reject callback:', e);\n }\n return Reflect.apply(rejectTarget, rejectThisArg, rejectArgs);\n },\n });\n\n try {\n return originalHandle.apply(this, args);\n } catch (e) {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n message: e instanceof Error ? e.message : 'unknown_error',\n });\n span.end();\n throw e;\n }\n },\n );\n };\n\n // Store original for unpatch - must be set on the NEW patched function\n moduleExports.Query.prototype.handle.__sentry_original__ = originalHandle;\n\n return moduleExports;\n }\n\n /**\n * Restores the original Query.prototype.handle method.\n */\n private _unpatchQueryPrototype(moduleExports: {\n Query: {\n prototype: {\n handle: ((...args: unknown[]) => Promise<unknown>) & {\n __sentry_original__?: (...args: unknown[]) => Promise<unknown>;\n };\n };\n };\n }): typeof moduleExports {\n if (moduleExports.Query.prototype.handle.__sentry_original__) {\n moduleExports.Query.prototype.handle = moduleExports.Query.prototype.handle.__sentry_original__;\n }\n return moduleExports;\n }\n}\n\nconst _postgresJsIntegration = ((options?: PostgresJsInstrumentationConfig) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentPostgresJs(options);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the [postgres](https://www.npmjs.com/package/postgres) library.\n *\n * For more information, see the [`postgresIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/postgres/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.postgresJsIntegration()],\n * });\n * ```\n */\n\nexport const postgresJsIntegration = defineIntegration(_postgresJsIntegration);\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"postgresjs.js","sources":["../../../../src/integrations/tracing/postgresjs.ts"],"sourcesContent":["// Instrumentation for https://github.com/porsager/postgres\n\nimport { context, trace } from '@opentelemetry/api';\nimport type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport {\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n safeExecuteInTheMiddle,\n} from '@opentelemetry/instrumentation';\nimport { InstrumentationNodeModuleFile } from './InstrumentationNodeModuleFile';\nimport { DB_OPERATION_NAME, DB_QUERY_TEXT, DB_SYSTEM_NAME, ERROR_TYPE } from '@sentry/conventions/attributes';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n debug,\n defineIntegration,\n instrumentPostgresJsSql,\n replaceExports,\n SDK_VERSION,\n SPAN_STATUS_ERROR,\n startSpanManual,\n} from '@sentry/core';\nimport { addOriginToSpan, generateInstrumentOnce } from '@sentry/node-core';\nimport { DEBUG_BUILD } from '../../debug-build';\n\nconst INTEGRATION_NAME = 'PostgresJs' as const;\nconst SUPPORTED_VERSIONS = ['>=3.0.0 <4'];\n// Not part of `@sentry/conventions`, so we keep it inline.\nconst ATTR_DB_RESPONSE_STATUS_CODE = 'db.response.status_code';\nconst SQL_OPERATION_REGEX = /^(SELECT|INSERT|UPDATE|DELETE|CREATE|DROP|ALTER)/i;\n\ntype PostgresConnectionContext = {\n ATTR_DB_NAMESPACE?: string; // Database name\n ATTR_SERVER_ADDRESS?: string; // Hostname or IP address of the database server\n ATTR_SERVER_PORT?: string; // Port number of the database server\n};\n\n// Marker to track if a query was created from an instrumented sql instance\n// This prevents double-spanning when both wrapper and prototype patches are active\nconst QUERY_FROM_INSTRUMENTED_SQL = Symbol.for('sentry.query.from.instrumented.sql');\n\ntype PostgresJsInstrumentationConfig = InstrumentationConfig & {\n /**\n * Whether to require a parent span for the instrumentation.\n * If set to true, the instrumentation will only create spans if there is a parent span\n * available in the current scope.\n * @default true\n */\n requireParentSpan?: boolean;\n /**\n * Hook to modify the span before it is started.\n * This can be used to set additional attributes or modify the span in any way.\n */\n requestHook?: (span: Span, sanitizedSqlQuery: string, postgresConnectionContext?: PostgresConnectionContext) => void;\n};\n\nexport const instrumentPostgresJs = generateInstrumentOnce(\n INTEGRATION_NAME,\n (options?: PostgresJsInstrumentationConfig) =>\n new PostgresJsInstrumentation({\n requireParentSpan: options?.requireParentSpan ?? true,\n requestHook: options?.requestHook,\n }),\n);\n\n/**\n * Instrumentation for the [postgres](https://www.npmjs.com/package/postgres) library.\n * This instrumentation captures postgresjs queries and their attributes.\n *\n * Uses internal Sentry patching patterns to support both CommonJS and ESM environments.\n */\nexport class PostgresJsInstrumentation extends InstrumentationBase<PostgresJsInstrumentationConfig> {\n public constructor(config: PostgresJsInstrumentationConfig) {\n super('sentry-postgres-js', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by patching the postgres module.\n * Uses two complementary approaches:\n * 1. Main function wrapper: instruments sql instances created AFTER instrumentation is set up (CJS + ESM)\n * 2. Query.prototype patch: fallback for sql instances created BEFORE instrumentation (CJS only)\n */\n public init(): InstrumentationNodeModuleDefinition {\n const module = new InstrumentationNodeModuleDefinition(\n 'postgres',\n SUPPORTED_VERSIONS,\n exports => {\n try {\n return this._patchPostgres(exports);\n } catch (e) {\n DEBUG_BUILD && debug.error('Failed to patch postgres module:', e);\n return exports;\n }\n },\n exports => exports,\n );\n\n // Add fallback Query.prototype patching for pre-existing sql instances (CJS only)\n // This catches queries from sql instances created before Sentry was initialized\n ['src', 'cf/src', 'cjs/src'].forEach(path => {\n module.files.push(\n new InstrumentationNodeModuleFile(\n `postgres/${path}/query.js`,\n SUPPORTED_VERSIONS,\n this._patchQueryPrototype.bind(this),\n this._unpatchQueryPrototype.bind(this),\n ),\n );\n });\n\n return module;\n }\n\n /**\n * Patches the postgres module by wrapping the main export function.\n * This intercepts the creation of sql instances and instruments them.\n */\n private _patchPostgres(exports: { [key: string]: unknown }): { [key: string]: unknown } {\n // In CJS: exports is the function itself\n // In ESM: exports.default is the function\n const isFunction = typeof exports === 'function';\n const Original = isFunction ? exports : exports.default;\n\n if (typeof Original !== 'function') {\n DEBUG_BUILD && debug.warn('postgres module does not export a function. Skipping instrumentation.');\n return exports;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n const WrappedPostgres = function (this: unknown, ...args: unknown[]): unknown {\n const sql = Reflect.construct(Original as (...args: unknown[]) => unknown, args);\n\n // Validate that construction succeeded and returned a valid function object\n if (!sql || typeof sql !== 'function') {\n DEBUG_BUILD && debug.warn('postgres() did not return a valid instance');\n return sql;\n }\n\n // Delegate to the portable instrumentation from @sentry/core\n const config = self.getConfig();\n return instrumentPostgresJsSql(sql, {\n requireParentSpan: config.requireParentSpan,\n requestHook: config.requestHook,\n });\n };\n\n Object.setPrototypeOf(WrappedPostgres, Original);\n Object.setPrototypeOf(WrappedPostgres.prototype, (Original as { prototype: object }).prototype);\n\n for (const key of Object.getOwnPropertyNames(Original)) {\n if (!['length', 'name', 'prototype'].includes(key)) {\n const descriptor = Object.getOwnPropertyDescriptor(Original, key);\n if (descriptor) {\n Object.defineProperty(WrappedPostgres, key, descriptor);\n }\n }\n }\n\n // For CJS: the exports object IS the function, so return the wrapped function\n // For ESM: replace the default export\n if (isFunction) {\n return WrappedPostgres as unknown as { [key: string]: unknown };\n } else {\n replaceExports(exports, 'default', WrappedPostgres);\n return exports;\n }\n }\n\n /**\n * Determines whether a span should be created based on the current context.\n * If `requireParentSpan` is set to true in the configuration, a span will\n * only be created if there is a parent span available.\n */\n private _shouldCreateSpans(): boolean {\n const config = this.getConfig();\n const hasParentSpan = trace.getSpan(context.active()) !== undefined;\n return hasParentSpan || !config.requireParentSpan;\n }\n\n /**\n * Extracts DB operation name from SQL query and sets it on the span.\n */\n private _setOperationName(span: Span, sanitizedQuery: string | undefined, command?: string): void {\n if (command) {\n span.setAttribute(DB_OPERATION_NAME, command);\n return;\n }\n // Fallback: extract operation from the SQL query\n const operationMatch = sanitizedQuery?.match(SQL_OPERATION_REGEX);\n if (operationMatch?.[1]) {\n span.setAttribute(DB_OPERATION_NAME, operationMatch[1].toUpperCase());\n }\n }\n\n /**\n * Reconstructs the full SQL query from template strings with PostgreSQL placeholders.\n *\n * For sql`SELECT * FROM users WHERE id = ${123} AND name = ${'foo'}`:\n * strings = [\"SELECT * FROM users WHERE id = \", \" AND name = \", \"\"]\n * returns: \"SELECT * FROM users WHERE id = $1 AND name = $2\"\n */\n private _reconstructQuery(strings: string[] | undefined): string | undefined {\n if (!strings?.length) {\n return undefined;\n }\n if (strings.length === 1) {\n return strings[0] || undefined;\n }\n // Join template parts with PostgreSQL placeholders ($1, $2, etc.)\n return strings.reduce((acc, str, i) => (i === 0 ? str : `${acc}$${i}${str}`), '');\n }\n\n /**\n * Sanitize SQL query as per the OTEL semantic conventions\n * https://opentelemetry.io/docs/specs/semconv/database/database-spans/#sanitization-of-dbquerytext\n *\n * PostgreSQL $n placeholders are preserved per OTEL spec - they're parameterized queries,\n * not sensitive literals. Only actual values (strings, numbers, booleans) are sanitized.\n */\n private _sanitizeSqlQuery(sqlQuery: string | undefined): string {\n if (!sqlQuery) {\n return 'Unknown SQL Query';\n }\n\n return (\n sqlQuery\n // Remove comments first (they may contain newlines and extra spaces)\n .replace(/--.*$/gm, '') // Single line comments (multiline mode)\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '') // Multi-line comments\n .replace(/;\\s*$/, '') // Remove trailing semicolons\n // Collapse whitespace to a single space (after removing comments)\n .replace(/\\s+/g, ' ')\n .trim() // Remove extra spaces and trim\n // Sanitize hex/binary literals before string literals\n .replace(/\\bX'[0-9A-Fa-f]*'/gi, '?') // Hex string literals\n .replace(/\\bB'[01]*'/gi, '?') // Binary string literals\n // Sanitize string literals (handles escaped quotes)\n .replace(/'(?:[^']|'')*'/g, '?')\n // Sanitize hex numbers\n .replace(/\\b0x[0-9A-Fa-f]+/gi, '?')\n // Sanitize boolean literals\n .replace(/\\b(?:TRUE|FALSE)\\b/gi, '?')\n // Sanitize numeric literals (preserve $n placeholders via negative lookbehind)\n .replace(/-?\\b\\d+\\.?\\d*[eE][+-]?\\d+\\b/g, '?') // Scientific notation\n .replace(/-?\\b\\d+\\.\\d+\\b/g, '?') // Decimals\n .replace(/-?\\.\\d+\\b/g, '?') // Decimals starting with dot\n .replace(/(?<!\\$)-?\\b\\d+\\b/g, '?') // Integers (NOT $n placeholders)\n // Collapse IN clauses for cardinality (both ? and $n variants)\n .replace(/\\bIN\\b\\s*\\(\\s*\\?(?:\\s*,\\s*\\?)*\\s*\\)/gi, 'IN (?)')\n .replace(/\\bIN\\b\\s*\\(\\s*\\$\\d+(?:\\s*,\\s*\\$\\d+)*\\s*\\)/gi, 'IN ($?)')\n );\n }\n\n /**\n * Fallback patch for Query.prototype.handle to instrument queries from pre-existing sql instances.\n * This catches queries from sql instances created BEFORE Sentry was initialized (CJS only).\n *\n * Note: Queries from pre-existing instances won't have connection context (database, host, port)\n * because the sql instance wasn't created through our instrumented wrapper.\n */\n private _patchQueryPrototype(moduleExports: {\n Query: {\n prototype: {\n handle: ((...args: unknown[]) => Promise<unknown>) & {\n __sentry_original__?: (...args: unknown[]) => Promise<unknown>;\n };\n };\n };\n }): typeof moduleExports {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n const originalHandle = moduleExports.Query.prototype.handle;\n\n moduleExports.Query.prototype.handle = async function (\n this: {\n resolve: unknown;\n reject: unknown;\n strings?: string[];\n executed?: boolean;\n },\n ...args: unknown[]\n ): Promise<unknown> {\n // Skip if this query came from an instrumented sql instance (already handled by wrapper),\n // or if handle() was already called (postgres.js calls handle() from then/catch/finally —\n // only the first call executes SQL, subsequent calls are no-ops).\n if (this.executed || (this as Record<symbol, unknown>)[QUERY_FROM_INSTRUMENTED_SQL]) {\n return originalHandle.apply(this, args);\n }\n\n // Skip if we shouldn't create spans\n if (!self._shouldCreateSpans()) {\n return originalHandle.apply(this, args);\n }\n\n const fullQuery = self._reconstructQuery(this.strings);\n const sanitizedSqlQuery = self._sanitizeSqlQuery(fullQuery);\n\n return startSpanManual(\n {\n name: sanitizedSqlQuery || 'postgresjs.query',\n op: 'db',\n },\n (span: Span) => {\n addOriginToSpan(span, 'auto.db.postgresjs');\n\n span.setAttributes({\n [DB_SYSTEM_NAME]: 'postgres',\n [DB_QUERY_TEXT]: sanitizedSqlQuery,\n });\n\n // Note: No connection context available for pre-existing instances\n // because the sql instance wasn't created through our instrumented wrapper\n\n const config = self.getConfig();\n const { requestHook } = config;\n if (requestHook) {\n safeExecuteInTheMiddle(\n () => requestHook(span, sanitizedSqlQuery, undefined),\n e => {\n if (e) {\n span.setAttribute('sentry.hook.error', 'requestHook failed');\n DEBUG_BUILD && debug.error(`Error in requestHook for ${INTEGRATION_NAME} integration:`, e);\n }\n },\n true,\n );\n }\n\n // Wrap resolve to end span on success\n const originalResolve = this.resolve;\n this.resolve = new Proxy(originalResolve as (...args: unknown[]) => unknown, {\n apply: (resolveTarget, resolveThisArg, resolveArgs: [{ command?: string }]) => {\n try {\n self._setOperationName(span, sanitizedSqlQuery, resolveArgs?.[0]?.command);\n span.end();\n } catch (e) {\n DEBUG_BUILD && debug.error('Error ending span in resolve callback:', e);\n }\n return Reflect.apply(resolveTarget, resolveThisArg, resolveArgs);\n },\n });\n\n // Wrap reject to end span on error\n const originalReject = this.reject;\n this.reject = new Proxy(originalReject as (...args: unknown[]) => unknown, {\n apply: (rejectTarget, rejectThisArg, rejectArgs: { message?: string; code?: string; name?: string }[]) => {\n try {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n message: rejectArgs?.[0]?.message || 'unknown_error',\n });\n span.setAttribute(ATTR_DB_RESPONSE_STATUS_CODE, rejectArgs?.[0]?.code || 'unknown');\n span.setAttribute(ERROR_TYPE, rejectArgs?.[0]?.name || 'unknown');\n self._setOperationName(span, sanitizedSqlQuery);\n span.end();\n } catch (e) {\n DEBUG_BUILD && debug.error('Error ending span in reject callback:', e);\n }\n return Reflect.apply(rejectTarget, rejectThisArg, rejectArgs);\n },\n });\n\n try {\n return originalHandle.apply(this, args);\n } catch (e) {\n span.setStatus({\n code: SPAN_STATUS_ERROR,\n message: e instanceof Error ? e.message : 'unknown_error',\n });\n span.end();\n throw e;\n }\n },\n );\n };\n\n // Store original for unpatch - must be set on the NEW patched function\n moduleExports.Query.prototype.handle.__sentry_original__ = originalHandle;\n\n return moduleExports;\n }\n\n /**\n * Restores the original Query.prototype.handle method.\n */\n private _unpatchQueryPrototype(moduleExports: {\n Query: {\n prototype: {\n handle: ((...args: unknown[]) => Promise<unknown>) & {\n __sentry_original__?: (...args: unknown[]) => Promise<unknown>;\n };\n };\n };\n }): typeof moduleExports {\n if (moduleExports.Query.prototype.handle.__sentry_original__) {\n moduleExports.Query.prototype.handle = moduleExports.Query.prototype.handle.__sentry_original__;\n }\n return moduleExports;\n }\n}\n\nconst _postgresJsIntegration = ((options?: PostgresJsInstrumentationConfig) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentPostgresJs(options);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Adds Sentry tracing instrumentation for the [postgres](https://www.npmjs.com/package/postgres) library.\n *\n * For more information, see the [`postgresIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/postgres/).\n *\n * @example\n * ```javascript\n * const Sentry = require('@sentry/node');\n *\n * Sentry.init({\n * integrations: [Sentry.postgresJsIntegration()],\n * });\n * ```\n */\n\nexport const postgresJsIntegration = defineIntegration(_postgresJsIntegration);\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { trace, SpanKind, TraceFlags, context } from '@opentelemetry/api';
2
- import { defineIntegration, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, consoleSandbox } from '@sentry/core';
1
+ import { LRUMap, defineIntegration, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, debug, startInactiveSpan, SPAN_KIND } from '@sentry/core';
3
2
  import { generateInstrumentOnce } from '@sentry/node-core';
3
+ import { DEBUG_BUILD } from '../../../debug-build.js';
4
4
  import { PrismaInstrumentation } from './vendored/instrumentation.js';
5
5
 
6
6
  const INTEGRATION_NAME = "Prisma";
@@ -12,6 +12,44 @@ function getPrismaTracingHelper() {
12
12
  const prismaTracingHelper = prismaInstrumentationObject && typeof prismaInstrumentationObject === "object" && "helper" in prismaInstrumentationObject ? prismaInstrumentationObject.helper : void 0;
13
13
  return prismaTracingHelper;
14
14
  }
15
+ const MAX_TRACKED_PRISMA_SPANS = 1e3;
16
+ const prismaSpanRegistry = new LRUMap(MAX_TRACKED_PRISMA_SPANS);
17
+ const pendingEngineSpans = [];
18
+ function registerPrismaSpan(id, span) {
19
+ prismaSpanRegistry.set(id, span);
20
+ }
21
+ function createResolvedEngineSpans() {
22
+ let createdSpan = true;
23
+ while (createdSpan) {
24
+ createdSpan = false;
25
+ for (let i = pendingEngineSpans.length - 1; i >= 0; i--) {
26
+ const engineSpan = pendingEngineSpans[i];
27
+ const parentSpan = prismaSpanRegistry.get(engineSpan.parent_span_id);
28
+ if (!parentSpan) {
29
+ continue;
30
+ }
31
+ const span = startInactiveSpan({
32
+ name: engineSpan.name,
33
+ attributes: engineSpan.attributes,
34
+ kind: engineSpan.kind === "client" ? SPAN_KIND.CLIENT : SPAN_KIND.INTERNAL,
35
+ startTime: engineSpan.start_time,
36
+ parentSpan
37
+ });
38
+ registerPrismaSpan(engineSpan.span_id, span);
39
+ if (engineSpan.links) {
40
+ span.addLinks(
41
+ engineSpan.links.flatMap((link) => {
42
+ const linkedSpan = prismaSpanRegistry.get(link.span_id);
43
+ return linkedSpan ? [{ context: linkedSpan.spanContext() }] : [];
44
+ })
45
+ );
46
+ }
47
+ span.end(engineSpan.end_time);
48
+ pendingEngineSpans.splice(i, 1);
49
+ createdSpan = true;
50
+ }
51
+ }
52
+ }
15
53
  class SentryPrismaInteropInstrumentation extends PrismaInstrumentation {
16
54
  constructor(options) {
17
55
  super(options?.instrumentationConfig);
@@ -21,58 +59,12 @@ class SentryPrismaInteropInstrumentation extends PrismaInstrumentation {
21
59
  const prismaTracingHelper = getPrismaTracingHelper();
22
60
  if (isPrismaV6TracingHelper(prismaTracingHelper)) {
23
61
  prismaTracingHelper.createEngineSpan = (engineSpanEvent) => {
24
- const tracer = trace.getTracer("prismaV5Compatibility");
25
- const initialIdGenerator = tracer._idGenerator;
26
- if (!initialIdGenerator) {
27
- consoleSandbox(() => {
28
- console.warn(
29
- "[Sentry] Could not find _idGenerator on tracer, skipping Prisma v5 compatibility - some Prisma spans may be missing!"
30
- );
31
- });
32
- return;
33
- }
34
- try {
35
- engineSpanEvent.spans.forEach((engineSpan) => {
36
- const kind = engineSpan.kind === "client" ? SpanKind.CLIENT : SpanKind.INTERNAL;
37
- const parentSpanId = engineSpan.parent_span_id;
38
- const spanId = engineSpan.span_id;
39
- const traceId = engineSpan.trace_id;
40
- const links = engineSpan.links?.map((link) => {
41
- return {
42
- context: {
43
- traceId: link.trace_id,
44
- spanId: link.span_id,
45
- traceFlags: TraceFlags.SAMPLED
46
- }
47
- };
48
- });
49
- const ctx = trace.setSpanContext(context.active(), {
50
- traceId,
51
- spanId: parentSpanId,
52
- traceFlags: TraceFlags.SAMPLED
53
- });
54
- context.with(ctx, () => {
55
- const temporaryIdGenerator = {
56
- generateTraceId: () => {
57
- return traceId;
58
- },
59
- generateSpanId: () => {
60
- return spanId;
61
- }
62
- };
63
- tracer._idGenerator = temporaryIdGenerator;
64
- const span = tracer.startSpan(engineSpan.name, {
65
- kind,
66
- links,
67
- startTime: engineSpan.start_time,
68
- attributes: engineSpan.attributes
69
- });
70
- span.end(engineSpan.end_time);
71
- tracer._idGenerator = initialIdGenerator;
72
- });
73
- });
74
- } finally {
75
- tracer._idGenerator = initialIdGenerator;
62
+ pendingEngineSpans.push(...engineSpanEvent.spans);
63
+ createResolvedEngineSpans();
64
+ const overflow = pendingEngineSpans.length - MAX_TRACKED_PRISMA_SPANS;
65
+ if (overflow > 0) {
66
+ DEBUG_BUILD && debug.log(`[Prisma] Dropping ${overflow} unresolved v5 engine span(s) whose parent was never registered.`);
67
+ pendingEngineSpans.splice(0, overflow);
76
68
  }
77
69
  };
78
70
  }
@@ -95,6 +87,9 @@ const prismaIntegration = defineIntegration((options) => {
95
87
  const spanJSON = spanToJSON(span);
96
88
  if (spanJSON.description?.startsWith("prisma:")) {
97
89
  span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, "auto.db.otel.prisma");
90
+ if (spanJSON.description.startsWith("prisma:client:")) {
91
+ registerPrismaSpan(span.spanContext().spanId, span);
92
+ }
98
93
  }
99
94
  if ((spanJSON.description === "prisma:engine:db_query" || spanJSON.description === "prisma:client:db_query") && spanJSON.data["db.query.text"]) {
100
95
  span.updateName(spanJSON.data["db.query.text"]);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/prisma/index.ts"],"sourcesContent":["import type { Link, Tracer } from '@opentelemetry/api';\nimport { context, SpanKind, trace, TraceFlags } from '@opentelemetry/api';\nimport type { Instrumentation } from '@opentelemetry/instrumentation';\nimport type { IdGenerator } from '@opentelemetry/sdk-trace-base';\nimport { consoleSandbox, defineIntegration, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, spanToJSON } from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport { PrismaInstrumentation } from './vendored/instrumentation';\nimport type { PrismaV5TracingHelper } from './vendored/v5-tracing-helper';\nimport type { PrismaV6TracingHelper } from './vendored/v6-tracing-helper';\n\nconst INTEGRATION_NAME = 'Prisma' as const;\n\ntype CompatibilityLayerTraceHelper = PrismaV5TracingHelper & PrismaV6TracingHelper;\n\n// Vendored in from @prisma/instrumentation v5:\ntype V5EngineSpanEvent = {\n span: boolean;\n spans: V5EngineSpan[];\n};\n\ntype V5EngineSpanKind = 'client' | 'internal';\n\ntype V5EngineSpan = {\n span: boolean;\n name: string;\n trace_id: string;\n span_id: string;\n parent_span_id: string;\n start_time: [number, number];\n end_time: [number, number];\n attributes?: Record<string, string>;\n links?: { trace_id: string; span_id: string }[];\n kind: V5EngineSpanKind;\n};\n\nfunction isPrismaV6TracingHelper(helper: unknown): helper is PrismaV6TracingHelper {\n return !!helper && typeof helper === 'object' && 'dispatchEngineSpans' in helper;\n}\n\nfunction getPrismaTracingHelper(): unknown | undefined {\n const prismaInstrumentationObject = (globalThis as Record<string, unknown>).PRISMA_INSTRUMENTATION;\n const prismaTracingHelper =\n prismaInstrumentationObject &&\n typeof prismaInstrumentationObject === 'object' &&\n 'helper' in prismaInstrumentationObject\n ? prismaInstrumentationObject.helper\n : undefined;\n\n return prismaTracingHelper;\n}\n\ntype TracerWithIdGenerator = Tracer & {\n _idGenerator?: IdGenerator;\n};\n\ninterface PrismaOptions {\n /**\n * @deprecated This is no longer used, v5 works out of the box.\n */\n prismaInstrumentation?: Instrumentation;\n /**\n * Configuration passed through to the {@link PrismaInstrumentation} constructor.\n */\n instrumentationConfig?: ConstructorParameters<typeof PrismaInstrumentation>[0];\n}\n\nclass SentryPrismaInteropInstrumentation extends PrismaInstrumentation {\n public constructor(options?: PrismaOptions) {\n super(options?.instrumentationConfig);\n }\n\n public enable(): void {\n super.enable();\n\n // The PrismaIntegration (super class) defines a global variable `global[\"PRISMA_INSTRUMENTATION\"]` when `enable()` is called. This global variable holds a \"TracingHelper\" which Prisma uses internally to create tracing data. It's their way of not depending on OTEL with their main package. The sucky thing is, prisma broke the interface of the tracing helper with the v6 major update. This means that if you use Prisma 5 with the v6 instrumentation (or vice versa) Prisma just blows up, because tries to call methods on the helper that no longer exist.\n // Because we actually want to use the v6 instrumentation and not blow up in Prisma 5 user's faces, what we're doing here is backfilling the v5 method (`createEngineSpan`) with a noop so that no longer crashes when it attempts to call that function.\n const prismaTracingHelper = getPrismaTracingHelper();\n\n if (isPrismaV6TracingHelper(prismaTracingHelper)) {\n // Inspired & adjusted from https://github.com/prisma/prisma/tree/5.22.0/packages/instrumentation\n (prismaTracingHelper as CompatibilityLayerTraceHelper).createEngineSpan = (\n engineSpanEvent: V5EngineSpanEvent,\n ) => {\n const tracer = trace.getTracer('prismaV5Compatibility') as TracerWithIdGenerator;\n\n // Prisma v5 relies on being able to create spans with a specific span & trace ID\n // this is no longer possible in OTEL v2, there is no public API to do this anymore\n // So in order to kind of hack this possibility, we rely on the internal `_idGenerator` property\n // This is used to generate the random IDs, and we overwrite this temporarily to generate static IDs\n // This is flawed and may not work, e.g. if the code is bundled and the private property is renamed\n // in such cases, these spans will not be captured and some Prisma spans will be missing\n const initialIdGenerator = tracer._idGenerator;\n\n if (!initialIdGenerator) {\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn(\n '[Sentry] Could not find _idGenerator on tracer, skipping Prisma v5 compatibility - some Prisma spans may be missing!',\n );\n });\n\n return;\n }\n\n try {\n engineSpanEvent.spans.forEach(engineSpan => {\n const kind = engineSpan.kind === 'client' ? SpanKind.CLIENT : SpanKind.INTERNAL;\n\n const parentSpanId = engineSpan.parent_span_id;\n const spanId = engineSpan.span_id;\n const traceId = engineSpan.trace_id;\n\n const links: Link[] | undefined = engineSpan.links?.map(link => {\n return {\n context: {\n traceId: link.trace_id,\n spanId: link.span_id,\n traceFlags: TraceFlags.SAMPLED,\n },\n };\n });\n\n const ctx = trace.setSpanContext(context.active(), {\n traceId,\n spanId: parentSpanId,\n traceFlags: TraceFlags.SAMPLED,\n });\n\n context.with(ctx, () => {\n const temporaryIdGenerator: IdGenerator = {\n generateTraceId: () => {\n return traceId;\n },\n generateSpanId: () => {\n return spanId;\n },\n };\n\n tracer._idGenerator = temporaryIdGenerator;\n\n const span = tracer.startSpan(engineSpan.name, {\n kind,\n links,\n startTime: engineSpan.start_time,\n attributes: engineSpan.attributes,\n });\n\n span.end(engineSpan.end_time);\n\n tracer._idGenerator = initialIdGenerator;\n });\n });\n } finally {\n // Ensure we always restore this at the end, even if something errors\n tracer._idGenerator = initialIdGenerator;\n }\n };\n }\n }\n}\n\nexport const instrumentPrisma = generateInstrumentOnce<PrismaOptions>(INTEGRATION_NAME, options => {\n return new SentryPrismaInteropInstrumentation(options);\n});\n\n/**\n * Adds Sentry tracing instrumentation for the [prisma](https://www.npmjs.com/package/prisma) library.\n * For more information, see the [`prismaIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/prisma/).\n *\n * NOTE: This integration works out of the box with Prisma v6, and v7.\n * On Prisma versions prior to v6, add `previewFeatures = [\"tracing\"]` to the client generator block of your Prisma schema:\n *\n * ```\n * generator client {\n * provider = \"prisma-client-js\"\n * previewFeatures = [\"tracing\"]\n * }\n * ```\n */\nexport const prismaIntegration = defineIntegration((options?: PrismaOptions) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentPrisma(options);\n },\n setup(client) {\n // If no tracing helper exists, we skip any work here\n // this means that prisma is not being used\n if (!getPrismaTracingHelper()) {\n return;\n }\n\n // Prisma v5 engine spans are created via the `createEngineSpan` path above, which bypasses the\n // tracing helper, so this hook applies origin, the db_query rename, and the db.system backfill to\n // them. v6/v7 spans already get these from the helper; the guards are idempotent, so it's a no-op there.\n client.on('spanStart', span => {\n const spanJSON = spanToJSON(span);\n if (spanJSON.description?.startsWith('prisma:')) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.prisma');\n }\n\n // Make sure we use the query text as the span name, for ex. SELECT * FROM \"User\" WHERE \"id\" = $1.\n // v5/v6 emit `prisma:engine:db_query`; v7 inlined the engine and emits `prisma:client:db_query`.\n if (\n (spanJSON.description === 'prisma:engine:db_query' || spanJSON.description === 'prisma:client:db_query') &&\n spanJSON.data['db.query.text']\n ) {\n span.updateName(spanJSON.data['db.query.text'] as string);\n }\n\n // In Prisma v5.22+, the `db.system` attribute is automatically set\n // On older versions, this is missing, so we add it here\n if (spanJSON.description === 'prisma:engine:db_query' && !spanJSON.data['db.system']) {\n span.setAttribute('db.system', 'prisma');\n }\n });\n },\n };\n});\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../../../src/integrations/tracing/prisma/index.ts"],"sourcesContent":["import type { Instrumentation } from '@opentelemetry/instrumentation';\nimport type { Span } from '@sentry/core';\nimport {\n debug,\n defineIntegration,\n LRUMap,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_KIND,\n spanToJSON,\n startInactiveSpan,\n} from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node-core';\nimport { DEBUG_BUILD } from '../../../debug-build';\nimport { PrismaInstrumentation } from './vendored/instrumentation';\nimport type { PrismaV5TracingHelper } from './vendored/v5-tracing-helper';\nimport type { PrismaV6TracingHelper } from './vendored/v6-tracing-helper';\n\nconst INTEGRATION_NAME = 'Prisma' as const;\n\ntype CompatibilityLayerTraceHelper = PrismaV5TracingHelper & PrismaV6TracingHelper;\n\n// Vendored in from @prisma/instrumentation v5:\ntype V5EngineSpanEvent = {\n span: boolean;\n spans: V5EngineSpan[];\n};\n\ntype V5EngineSpanKind = 'client' | 'internal';\n\ntype V5EngineSpan = {\n span: boolean;\n name: string;\n trace_id: string;\n span_id: string;\n parent_span_id: string;\n start_time: [number, number];\n end_time: [number, number];\n attributes?: Record<string, string>;\n links?: { trace_id: string; span_id: string }[];\n kind: V5EngineSpanKind;\n};\n\nfunction isPrismaV6TracingHelper(helper: unknown): helper is PrismaV6TracingHelper {\n return !!helper && typeof helper === 'object' && 'dispatchEngineSpans' in helper;\n}\n\nfunction getPrismaTracingHelper(): unknown | undefined {\n const prismaInstrumentationObject = (globalThis as Record<string, unknown>).PRISMA_INSTRUMENTATION;\n const prismaTracingHelper =\n prismaInstrumentationObject &&\n typeof prismaInstrumentationObject === 'object' &&\n 'helper' in prismaInstrumentationObject\n ? prismaInstrumentationObject.helper\n : undefined;\n\n return prismaTracingHelper;\n}\n\n// Prisma v5 dispatches engine spans (`prisma:engine:*`, which carry the SQL `db.statement`) one batch\n// at a time, out of order, and detached from the active span, naming their parent only by id: a span\n// references either a client span (by the Sentry span id Prisma learned via `getTraceParent`) or a\n// sibling engine span (by the engine's own id), and a batch may not contain the parent it references.\n// By the time the engine reports them the client span may already have ended, so `getActiveSpan()`\n// can't be used to find it. `prismaSpanRegistry` maps span ids to their Sentry span, and an engine\n// span whose parent isn't registered yet waits in `pendingEngineSpans` until a later batch registers it.\nconst MAX_TRACKED_PRISMA_SPANS = 1000;\nconst prismaSpanRegistry = new LRUMap<string, Span>(MAX_TRACKED_PRISMA_SPANS);\nconst pendingEngineSpans: V5EngineSpan[] = [];\n\n/** Register a span so v5 engine spans can later resolve it as a parent by the id Prisma reports it under. */\nfunction registerPrismaSpan(id: string, span: Span): void {\n prismaSpanRegistry.set(id, span);\n}\n\n/**\n * Create every pending v5 engine span whose parent is now registered, repeating until no further span\n * resolves (so a child queued before its parent is created once the parent arrives in a later batch).\n * Each span is created under its resolved parent and registered by its engine id so its own children\n * can find it; origin, the `prisma:engine:db_query` to SQL rename, and the `db.system` backfill are\n * applied by the `spanStart` hook, exactly as for v6/v7 engine spans.\n */\nfunction createResolvedEngineSpans(): void {\n // Terminates: `createdSpan` is only set true right after a `splice`, so every pass that keeps the\n // loop going strictly shrinks the finite `pendingEngineSpans`; a pass that resolves nothing exits.\n let createdSpan = true;\n while (createdSpan) {\n createdSpan = false;\n for (let i = pendingEngineSpans.length - 1; i >= 0; i--) {\n const engineSpan = pendingEngineSpans[i]!;\n const parentSpan = prismaSpanRegistry.get(engineSpan.parent_span_id);\n if (!parentSpan) {\n continue;\n }\n\n const span = startInactiveSpan({\n name: engineSpan.name,\n attributes: engineSpan.attributes,\n kind: engineSpan.kind === 'client' ? SPAN_KIND.CLIENT : SPAN_KIND.INTERNAL,\n startTime: engineSpan.start_time,\n parentSpan,\n });\n registerPrismaSpan(engineSpan.span_id, span);\n\n // Engine links reference other engine spans by their engine id; re-point them at the Sentry spans\n // we minted (mirroring v6/v7's `dispatchEngineSpan`). Links must be added before the span ends,\n // since the SentryTracerProvider seals spans on end. Links to spans we haven't created are dropped.\n if (engineSpan.links) {\n span.addLinks(\n engineSpan.links.flatMap(link => {\n const linkedSpan = prismaSpanRegistry.get(link.span_id);\n return linkedSpan ? [{ context: linkedSpan.spanContext() }] : [];\n }),\n );\n }\n\n span.end(engineSpan.end_time);\n\n pendingEngineSpans.splice(i, 1);\n createdSpan = true;\n }\n }\n}\n\ninterface PrismaOptions {\n /**\n * @deprecated This is no longer used, v5 works out of the box.\n */\n prismaInstrumentation?: Instrumentation;\n /**\n * Configuration passed through to the {@link PrismaInstrumentation} constructor.\n */\n instrumentationConfig?: ConstructorParameters<typeof PrismaInstrumentation>[0];\n}\n\nclass SentryPrismaInteropInstrumentation extends PrismaInstrumentation {\n public constructor(options?: PrismaOptions) {\n super(options?.instrumentationConfig);\n }\n\n public enable(): void {\n super.enable();\n\n // The PrismaIntegration (super class) defines a global variable `global[\"PRISMA_INSTRUMENTATION\"]` when `enable()` is called. This global variable holds a \"TracingHelper\" which Prisma uses internally to create tracing data. It's their way of not depending on OTEL with their main package. The sucky thing is, prisma broke the interface of the tracing helper with the v6 major update. This means that if you use Prisma 5 with the v6 instrumentation (or vice versa) Prisma just blows up, because tries to call methods on the helper that no longer exist.\n // Because we actually want to use the v6/v7 instrumentation and not blow up in Prisma 5 users' faces, we backfill the v5-only `createEngineSpan` method so v5 engine spans are minted through Sentry's span APIs instead of crashing.\n const prismaTracingHelper = getPrismaTracingHelper();\n\n if (isPrismaV6TracingHelper(prismaTracingHelper)) {\n (prismaTracingHelper as CompatibilityLayerTraceHelper).createEngineSpan = (\n engineSpanEvent: V5EngineSpanEvent,\n ) => {\n pendingEngineSpans.push(...engineSpanEvent.spans);\n\n // Resolve before capping so a span is only ever dropped after a full resolution attempt, never\n // before it had a chance to find its parent. What remains are orphans whose parent was never\n // registered (e.g. evicted from the registry under sustained load); cap that backlog so it can't\n // grow without bound.\n createResolvedEngineSpans();\n\n const overflow = pendingEngineSpans.length - MAX_TRACKED_PRISMA_SPANS;\n if (overflow > 0) {\n DEBUG_BUILD &&\n debug.log(`[Prisma] Dropping ${overflow} unresolved v5 engine span(s) whose parent was never registered.`);\n pendingEngineSpans.splice(0, overflow);\n }\n };\n }\n }\n}\n\nexport const instrumentPrisma = generateInstrumentOnce<PrismaOptions>(INTEGRATION_NAME, options => {\n return new SentryPrismaInteropInstrumentation(options);\n});\n\n/**\n * Adds Sentry tracing instrumentation for the [prisma](https://www.npmjs.com/package/prisma) library.\n * For more information, see the [`prismaIntegration` documentation](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/prisma/).\n *\n * NOTE: This integration works out of the box with Prisma v6, and v7.\n * On Prisma versions prior to v6, add `previewFeatures = [\"tracing\"]` to the client generator block of your Prisma schema:\n *\n * ```\n * generator client {\n * provider = \"prisma-client-js\"\n * previewFeatures = [\"tracing\"]\n * }\n * ```\n */\nexport const prismaIntegration = defineIntegration((options?: PrismaOptions) => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentPrisma(options);\n },\n setup(client) {\n // If no tracing helper exists, we skip any work here\n // this means that prisma is not being used\n if (!getPrismaTracingHelper()) {\n return;\n }\n\n // Prisma v5 engine spans are created via the `createEngineSpan` path above, which bypasses the\n // tracing helper, so this hook applies origin, the db_query rename, and the db.system backfill to\n // them. v6/v7 spans already get these from the helper; the guards are idempotent, so it's a no-op there.\n client.on('spanStart', span => {\n const spanJSON = spanToJSON(span);\n if (spanJSON.description?.startsWith('prisma:')) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.prisma');\n\n // Register client spans so a v5 engine span (dispatched later, detached) can resolve one as a\n // parent by the Sentry span id Prisma reported via `getTraceParent` (see\n // `createResolvedEngineSpans`). Only client spans are referenced this way; engine spans\n // reference their parent by the engine's own id and are registered in `createResolvedEngineSpans`,\n // so registering them here too would just leave entries that are never looked up.\n if (spanJSON.description.startsWith('prisma:client:')) {\n registerPrismaSpan(span.spanContext().spanId, span);\n }\n }\n\n // Make sure we use the query text as the span name, for ex. SELECT * FROM \"User\" WHERE \"id\" = $1.\n // v5/v6 emit `prisma:engine:db_query`; v7 inlined the engine and emits `prisma:client:db_query`.\n if (\n (spanJSON.description === 'prisma:engine:db_query' || spanJSON.description === 'prisma:client:db_query') &&\n spanJSON.data['db.query.text']\n ) {\n span.updateName(spanJSON.data['db.query.text'] as string);\n }\n\n // In Prisma v5.22+, the `db.system` attribute is automatically set\n // On older versions, this is missing, so we add it here\n if (spanJSON.description === 'prisma:engine:db_query' && !spanJSON.data['db.system']) {\n span.setAttribute('db.system', 'prisma');\n }\n });\n },\n };\n});\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { spanToJSON, SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE, SEMANTIC_ATTRIBUTE_CACHE_HIT, SEMANTIC_ATTRIBUTE_CACHE_KEY, SEMANTIC_ATTRIBUTE_SENTRY_OP, truncate } from '@sentry/core';
2
+ import { getCacheKeySafely, getCacheOperation, shouldConsiderForCache, calculateCacheItemSize, isInCommands, GET_COMMANDS } from '../../../utils/redisCache.js';
3
+
4
+ let _redisOptions = {};
5
+ function setRedisOptions(options) {
6
+ _redisOptions = options;
7
+ }
8
+ const cacheResponseHook = (span, redisCommand, cmdArgs, response) => {
9
+ const safeKey = getCacheKeySafely(redisCommand, cmdArgs);
10
+ const cacheOperation = getCacheOperation(redisCommand);
11
+ if (!safeKey || !cacheOperation || !_redisOptions.cachePrefixes || !shouldConsiderForCache(redisCommand, safeKey, _redisOptions.cachePrefixes)) {
12
+ return;
13
+ }
14
+ const spanData = spanToJSON(span).data;
15
+ const networkPeerAddress = spanData["net.peer.name"] ?? spanData["server.address"];
16
+ const networkPeerPort = spanData["net.peer.port"] ?? spanData["server.port"];
17
+ if (networkPeerPort && networkPeerAddress) {
18
+ span.setAttributes({ "network.peer.address": networkPeerAddress, "network.peer.port": networkPeerPort });
19
+ }
20
+ const cacheItemSize = calculateCacheItemSize(response);
21
+ if (cacheItemSize) {
22
+ span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE, cacheItemSize);
23
+ }
24
+ if (isInCommands(GET_COMMANDS, redisCommand) && cacheItemSize !== void 0) {
25
+ span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, cacheItemSize > 0);
26
+ }
27
+ span.setAttributes({
28
+ [SEMANTIC_ATTRIBUTE_SENTRY_OP]: cacheOperation,
29
+ [SEMANTIC_ATTRIBUTE_CACHE_KEY]: safeKey
30
+ });
31
+ const spanDescription = safeKey.join(", ");
32
+ span.updateName(
33
+ _redisOptions.maxCacheKeyLength ? truncate(spanDescription, _redisOptions.maxCacheKeyLength) : spanDescription
34
+ );
35
+ };
36
+
37
+ export { _redisOptions, cacheResponseHook, setRedisOptions };
38
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sources":["../../../../../src/integrations/tracing/redis/cache.ts"],"sourcesContent":["import type { Span } from '@sentry/core';\nimport {\n SEMANTIC_ATTRIBUTE_CACHE_HIT,\n SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE,\n SEMANTIC_ATTRIBUTE_CACHE_KEY,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n spanToJSON,\n truncate,\n} from '@sentry/core';\nimport type { IORedisCommandArgs } from '../../../utils/redisCache';\nimport {\n calculateCacheItemSize,\n GET_COMMANDS,\n getCacheKeySafely,\n getCacheOperation,\n isInCommands,\n shouldConsiderForCache,\n} from '../../../utils/redisCache';\nimport type { IORedisResponseCustomAttributeFunction } from './vendored/types';\n\n// This module deliberately does NOT import the vendored OTel `IORedisInstrumentation`/\n// `RedisInstrumentation`, so the orchestrion opt-in can pull `cacheResponseHook`\n// without dragging the OTel redis instrumentation into its module graph.\n\nexport interface RedisOptions {\n /**\n * Define cache prefixes for cache keys that should be captured as a cache span.\n *\n * Setting this to, for example, `['user:']` will capture cache keys that start with `user:`.\n */\n cachePrefixes?: string[];\n /**\n * Maximum length of the cache key added to the span description. If the key exceeds this length, it will be truncated.\n *\n * Passing `0` will use the full cache key without truncation.\n *\n * By default, the full cache key is used.\n */\n maxCacheKeyLength?: number;\n}\n\n/* Only exported for testing purposes */\nexport let _redisOptions: RedisOptions = {};\n\n/** Set the options consumed by {@link cacheResponseHook}. */\nexport function setRedisOptions(options: RedisOptions): void {\n _redisOptions = options;\n}\n\n/* Only exported for testing purposes */\nexport const cacheResponseHook: IORedisResponseCustomAttributeFunction = (\n span: Span,\n redisCommand: string,\n cmdArgs: IORedisCommandArgs,\n response: unknown,\n) => {\n const safeKey = getCacheKeySafely(redisCommand, cmdArgs);\n const cacheOperation = getCacheOperation(redisCommand);\n\n if (\n !safeKey ||\n !cacheOperation ||\n !_redisOptions.cachePrefixes ||\n !shouldConsiderForCache(redisCommand, safeKey, _redisOptions.cachePrefixes)\n ) {\n // not relevant for cache\n return;\n }\n\n // otel/ioredis seems to be using the old standard, as there was a change to those params: https://github.com/open-telemetry/opentelemetry-specification/issues/3199\n // We are using params based on the docs: https://opentelemetry.io/docs/specs/semconv/attributes-registry/network/\n // Fall back to stable semconv attributes (server.address/server.port) when\n // old-semconv ones are absent, eg OTEL_SEMCONV_STABILITY_OPT_IN=database\n // set for node-redis v4/v5.\n const spanData = spanToJSON(span).data;\n const networkPeerAddress = spanData['net.peer.name'] ?? spanData['server.address'];\n const networkPeerPort = spanData['net.peer.port'] ?? spanData['server.port'];\n if (networkPeerPort && networkPeerAddress) {\n span.setAttributes({ 'network.peer.address': networkPeerAddress, 'network.peer.port': networkPeerPort });\n }\n\n const cacheItemSize = calculateCacheItemSize(response);\n\n if (cacheItemSize) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_ITEM_SIZE, cacheItemSize);\n }\n\n if (isInCommands(GET_COMMANDS, redisCommand) && cacheItemSize !== undefined) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, cacheItemSize > 0);\n }\n\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: cacheOperation,\n [SEMANTIC_ATTRIBUTE_CACHE_KEY]: safeKey,\n });\n\n // todo: change to string[] once EAP supports it\n const spanDescription = safeKey.join(', ');\n\n span.updateName(\n _redisOptions.maxCacheKeyLength ? truncate(spanDescription, _redisOptions.maxCacheKeyLength) : spanDescription,\n );\n};\n"],"names":[],"mappings":";;;AA0CO,IAAI,gBAA8B;AAGlC,SAAS,gBAAgB,OAAA,EAA6B;AAC3D,EAAA,aAAA,GAAgB,OAAA;AAClB;AAGO,MAAM,iBAAA,GAA4D,CACvE,IAAA,EACA,YAAA,EACA,SACA,QAAA,KACG;AACH,EAAA,MAAM,OAAA,GAAU,iBAAA,CAAkB,YAAA,EAAc,OAAO,CAAA;AACvD,EAAA,MAAM,cAAA,GAAiB,kBAAkB,YAAY,CAAA;AAErD,EAAA,IACE,CAAC,OAAA,IACD,CAAC,cAAA,IACD,CAAC,aAAA,CAAc,aAAA,IACf,CAAC,sBAAA,CAAuB,YAAA,EAAc,OAAA,EAAS,aAAA,CAAc,aAAa,CAAA,EAC1E;AAEA,IAAA;AAAA,EACF;AAOA,EAAA,MAAM,QAAA,GAAW,UAAA,CAAW,IAAI,CAAA,CAAE,IAAA;AAClC,EAAA,MAAM,kBAAA,GAAqB,QAAA,CAAS,eAAe,CAAA,IAAK,SAAS,gBAAgB,CAAA;AACjF,EAAA,MAAM,eAAA,GAAkB,QAAA,CAAS,eAAe,CAAA,IAAK,SAAS,aAAa,CAAA;AAC3E,EAAA,IAAI,mBAAmB,kBAAA,EAAoB;AACzC,IAAA,IAAA,CAAK,cAAc,EAAE,sBAAA,EAAwB,kBAAA,EAAoB,mBAAA,EAAqB,iBAAiB,CAAA;AAAA,EACzG;AAEA,EAAA,MAAM,aAAA,GAAgB,uBAAuB,QAAQ,CAAA;AAErD,EAAA,IAAI,aAAA,EAAe;AACjB,IAAA,IAAA,CAAK,YAAA,CAAa,oCAAoC,aAAa,CAAA;AAAA,EACrE;AAEA,EAAA,IAAI,YAAA,CAAa,YAAA,EAAc,YAAY,CAAA,IAAK,kBAAkB,MAAA,EAAW;AAC3E,IAAA,IAAA,CAAK,YAAA,CAAa,4BAAA,EAA8B,aAAA,GAAgB,CAAC,CAAA;AAAA,EACnE;AAEA,EAAA,IAAA,CAAK,aAAA,CAAc;AAAA,IACjB,CAAC,4BAA4B,GAAG,cAAA;AAAA,IAChC,CAAC,4BAA4B,GAAG;AAAA,GACjC,CAAA;AAGD,EAAA,MAAM,eAAA,GAAkB,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA;AAEzC,EAAA,IAAA,CAAK,UAAA;AAAA,IACH,cAAc,iBAAA,GAAoB,QAAA,CAAS,eAAA,EAAiB,aAAA,CAAc,iBAAiB,CAAA,GAAI;AAAA,GACjG;AACF;;;;"}