@geekmidas/telescope 10.0.0-alpha.99 → 10.0.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 (480) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/README.md +18 -28
  3. package/dist/InMemoryMetricsStorage-BbKCL3YL.d.mts +47 -0
  4. package/dist/InMemoryMetricsStorage-BbKCL3YL.d.mts.map +1 -0
  5. package/dist/InMemoryMetricsStorage-C4drxT7G.mjs +247 -0
  6. package/dist/InMemoryMetricsStorage-C4drxT7G.mjs.map +1 -0
  7. package/dist/InMemoryMetricsStorage-D0njWUSi.cjs +252 -0
  8. package/dist/InMemoryMetricsStorage-D0njWUSi.cjs.map +1 -0
  9. package/dist/InMemoryMetricsStorage-TvPdZjL0.d.cts +47 -0
  10. package/dist/InMemoryMetricsStorage-TvPdZjL0.d.cts.map +1 -0
  11. package/dist/{MetricsAggregator-BJdIvfEv.d.mts → MetricsAggregator-4SqelGcG.d.cts} +6 -3
  12. package/dist/MetricsAggregator-4SqelGcG.d.cts.map +1 -0
  13. package/dist/MetricsAggregator-B7lUICdH.cjs +363 -0
  14. package/dist/MetricsAggregator-B7lUICdH.cjs.map +1 -0
  15. package/dist/{MetricsAggregator-CnC3oT5q.d.cts → MetricsAggregator-DZrW8ls6.d.mts} +6 -3
  16. package/dist/MetricsAggregator-DZrW8ls6.d.mts.map +1 -0
  17. package/dist/MetricsAggregator-S3DQWNas.mjs +357 -0
  18. package/dist/MetricsAggregator-S3DQWNas.mjs.map +1 -0
  19. package/dist/MetricsStorage-B86e4131.d.cts +60 -0
  20. package/dist/MetricsStorage-B86e4131.d.cts.map +1 -0
  21. package/dist/MetricsStorage-BWyP2_12.d.mts +60 -0
  22. package/dist/MetricsStorage-BWyP2_12.d.mts.map +1 -0
  23. package/dist/MetricsStorage-BypQXWiv.mjs +0 -0
  24. package/dist/MetricsStorage-Or8pVCe4.cjs +0 -0
  25. package/dist/Telescope-Cs3fv8jt.cjs +395 -0
  26. package/dist/Telescope-Cs3fv8jt.cjs.map +1 -0
  27. package/dist/{Telescope-BVfDvVvY.d.mts → Telescope-D4nmwDRA.d.cts} +7 -4
  28. package/dist/Telescope-D4nmwDRA.d.cts.map +1 -0
  29. package/dist/Telescope-Dh5av3FC.mjs +389 -0
  30. package/dist/Telescope-Dh5av3FC.mjs.map +1 -0
  31. package/dist/{Telescope-DeqSHfuB.d.cts → Telescope-Dl6VSfxd.d.mts} +7 -4
  32. package/dist/Telescope-Dl6VSfxd.d.mts.map +1 -0
  33. package/dist/Telescope.cjs +4 -385
  34. package/dist/Telescope.d.cts +3 -1
  35. package/dist/Telescope.d.mts +3 -1
  36. package/dist/Telescope.mjs +4 -384
  37. package/dist/adapters/index.d.cts +2 -2
  38. package/dist/adapters/index.d.mts +2 -2
  39. package/dist/adapters/index.mjs +0 -1
  40. package/dist/adapters/lambda.cjs +10 -9
  41. package/dist/adapters/lambda.cjs.map +1 -1
  42. package/dist/adapters/lambda.d.cts +13 -9
  43. package/dist/adapters/lambda.d.cts.map +1 -1
  44. package/dist/adapters/lambda.d.mts +13 -9
  45. package/dist/adapters/lambda.d.mts.map +1 -1
  46. package/dist/adapters/lambda.mjs +4 -3
  47. package/dist/adapters/lambda.mjs.map +1 -1
  48. package/dist/adapters/middy.cjs +4 -236
  49. package/dist/adapters/middy.d.cts +5 -60
  50. package/dist/adapters/middy.d.mts +5 -60
  51. package/dist/adapters/middy.mjs +3 -234
  52. package/dist/adapters/types.d.cts +2 -162
  53. package/dist/adapters/types.d.mts +2 -162
  54. package/dist/adapters/types.mjs +0 -1
  55. package/dist/{rolldown-runtime-VH7oDXx4.cjs → chunk-CUT6urMc.cjs} +10 -8
  56. package/dist/core--quSp5Qr.d.mts +78 -0
  57. package/dist/core--quSp5Qr.d.mts.map +1 -0
  58. package/dist/core-B4Jpia5H.d.cts +78 -0
  59. package/dist/core-B4Jpia5H.d.cts.map +1 -0
  60. package/dist/core-CtVHRJGv.cjs +199 -0
  61. package/dist/core-CtVHRJGv.cjs.map +1 -0
  62. package/dist/core-D6hJ6exL.mjs +139 -0
  63. package/dist/core-D6hJ6exL.mjs.map +1 -0
  64. package/dist/core.cjs +22 -22
  65. package/dist/core.d.cts +4 -4
  66. package/dist/core.d.mts +4 -4
  67. package/dist/core.mjs +4 -3
  68. package/dist/hono--uKQ7Jgi.d.mts +71 -0
  69. package/dist/hono--uKQ7Jgi.d.mts.map +1 -0
  70. package/dist/hono-C4EgpbKQ.cjs +160 -0
  71. package/dist/hono-C4EgpbKQ.cjs.map +1 -0
  72. package/dist/hono-CemCKU87.d.cts +71 -0
  73. package/dist/hono-CemCKU87.d.cts.map +1 -0
  74. package/dist/hono-DxhvnVbF.mjs +136 -0
  75. package/dist/hono-DxhvnVbF.mjs.map +1 -0
  76. package/dist/http-BiNtg85L.d.mts +107 -0
  77. package/dist/http-BiNtg85L.d.mts.map +1 -0
  78. package/dist/http-DQzgLczm.mjs +159 -0
  79. package/dist/http-DQzgLczm.mjs.map +1 -0
  80. package/dist/http-D_Z8sYXZ.cjs +219 -0
  81. package/dist/http-D_Z8sYXZ.cjs.map +1 -0
  82. package/dist/http-Dvca6fC3.d.cts +107 -0
  83. package/dist/http-Dvca6fC3.d.cts.map +1 -0
  84. package/dist/index-BL32-cvv.d.cts +1 -0
  85. package/dist/index-CsuikFeJ.d.mts +1 -0
  86. package/dist/index.cjs +9 -8
  87. package/dist/index.d.cts +6 -5
  88. package/dist/index.d.mts +6 -5
  89. package/dist/index.mjs +7 -5
  90. package/dist/instrumentation/core.cjs +11 -147
  91. package/dist/instrumentation/core.d.cts +3 -74
  92. package/dist/instrumentation/core.d.mts +3 -74
  93. package/dist/instrumentation/core.mjs +2 -137
  94. package/dist/instrumentation/hono.cjs +6 -174
  95. package/dist/instrumentation/hono.d.cts +2 -86
  96. package/dist/instrumentation/hono.d.mts +2 -86
  97. package/dist/instrumentation/hono.mjs +3 -170
  98. package/dist/instrumentation/http.cjs +11 -189
  99. package/dist/instrumentation/http.d.cts +2 -119
  100. package/dist/instrumentation/http.d.mts +2 -119
  101. package/dist/instrumentation/http.mjs +2 -178
  102. package/dist/instrumentation/index.cjs +47 -56
  103. package/dist/instrumentation/index.d.cts +9 -11
  104. package/dist/instrumentation/index.d.mts +9 -11
  105. package/dist/instrumentation/index.mjs +9 -10
  106. package/dist/instrumentation/middleware.cjs +6 -164
  107. package/dist/instrumentation/middleware.d.cts +2 -83
  108. package/dist/instrumentation/middleware.d.mts +2 -83
  109. package/dist/instrumentation/middleware.mjs +3 -160
  110. package/dist/instrumentation/otel.cjs +3 -137
  111. package/dist/instrumentation/otel.d.cts +2 -97
  112. package/dist/instrumentation/otel.d.mts +2 -97
  113. package/dist/instrumentation/otel.mjs +3 -136
  114. package/dist/instrumentation/setup.cjs +4 -142
  115. package/dist/instrumentation/setup.d.cts +3 -139
  116. package/dist/instrumentation/setup.d.mts +3 -139
  117. package/dist/instrumentation/setup.mjs +3 -139
  118. package/dist/instrumentation/tracing.cjs +10 -114
  119. package/dist/instrumentation/tracing.d.cts +2 -49
  120. package/dist/instrumentation/tracing.d.mts +2 -49
  121. package/dist/instrumentation/tracing.mjs +2 -105
  122. package/dist/logger/console.cjs +12 -18
  123. package/dist/logger/console.cjs.map +1 -1
  124. package/dist/logger/console.d.cts +10 -7
  125. package/dist/logger/console.d.cts.map +1 -1
  126. package/dist/logger/console.d.mts +10 -7
  127. package/dist/logger/console.d.mts.map +1 -1
  128. package/dist/logger/console.mjs +11 -17
  129. package/dist/logger/console.mjs.map +1 -1
  130. package/dist/logger/pino.cjs +5 -6
  131. package/dist/logger/pino.cjs.map +1 -1
  132. package/dist/logger/pino.d.cts +10 -6
  133. package/dist/logger/pino.d.cts.map +1 -1
  134. package/dist/logger/pino.d.mts +10 -6
  135. package/dist/logger/pino.d.mts.map +1 -1
  136. package/dist/logger/pino.mjs +3 -2
  137. package/dist/logger/pino.mjs.map +1 -1
  138. package/dist/memory--BK4iWiv.d.cts +40 -0
  139. package/dist/memory--BK4iWiv.d.cts.map +1 -0
  140. package/dist/memory-6S9H-IF5.mjs +123 -0
  141. package/dist/memory-6S9H-IF5.mjs.map +1 -0
  142. package/dist/memory-B0d_n1g5.cjs +129 -0
  143. package/dist/memory-B0d_n1g5.cjs.map +1 -0
  144. package/dist/memory-DCirEVFW.d.mts +40 -0
  145. package/dist/memory-DCirEVFW.d.mts.map +1 -0
  146. package/dist/metrics/MetricsAggregator.cjs +2 -354
  147. package/dist/metrics/MetricsAggregator.d.cts +2 -1
  148. package/dist/metrics/MetricsAggregator.d.mts +2 -1
  149. package/dist/metrics/MetricsAggregator.mjs +2 -353
  150. package/dist/metrics/index.cjs +4 -3
  151. package/dist/metrics/index.d.cts +4 -2
  152. package/dist/metrics/index.d.mts +4 -2
  153. package/dist/metrics/index.mjs +4 -2
  154. package/dist/metrics/storage/InMemoryMetricsStorage.cjs +3 -240
  155. package/dist/metrics/storage/InMemoryMetricsStorage.d.cts +4 -43
  156. package/dist/metrics/storage/InMemoryMetricsStorage.d.mts +4 -43
  157. package/dist/metrics/storage/InMemoryMetricsStorage.mjs +3 -239
  158. package/dist/metrics/storage/MetricsStorage.cjs +1 -0
  159. package/dist/metrics/storage/MetricsStorage.d.cts +3 -56
  160. package/dist/metrics/storage/MetricsStorage.d.mts +3 -56
  161. package/dist/metrics/storage/MetricsStorage.mjs +1 -1
  162. package/dist/metrics/storage/index.cjs +6 -6
  163. package/dist/metrics/storage/index.d.cts +3 -3
  164. package/dist/metrics/storage/index.d.mts +3 -3
  165. package/dist/metrics/storage/index.mjs +5 -4
  166. package/dist/metrics/storage/types.cjs +2 -34
  167. package/dist/metrics/storage/types.d.cts +2 -207
  168. package/dist/metrics/storage/types.d.mts +2 -207
  169. package/dist/metrics/storage/types.mjs +2 -33
  170. package/dist/metrics-D5YT-Rnq.mjs +0 -0
  171. package/dist/metrics-fhD3l3C3.cjs +0 -0
  172. package/dist/middleware-B2jFUukM.cjs +184 -0
  173. package/dist/middleware-B2jFUukM.cjs.map +1 -0
  174. package/dist/middleware-BTDncHwm.mjs +160 -0
  175. package/dist/middleware-BTDncHwm.mjs.map +1 -0
  176. package/dist/middleware-CA84nsNN.d.cts +74 -0
  177. package/dist/middleware-CA84nsNN.d.cts.map +1 -0
  178. package/dist/middleware-DAceVpfw.d.mts +74 -0
  179. package/dist/middleware-DAceVpfw.d.mts.map +1 -0
  180. package/dist/middy-B6Btl8XE.d.mts +64 -0
  181. package/dist/middy-B6Btl8XE.d.mts.map +1 -0
  182. package/dist/middy-BTR3cyvk.mjs +236 -0
  183. package/dist/middy-BTR3cyvk.mjs.map +1 -0
  184. package/dist/middy-Bq0defVg.d.cts +64 -0
  185. package/dist/middy-Bq0defVg.d.cts.map +1 -0
  186. package/dist/middy-y5Zp27eG.cjs +247 -0
  187. package/dist/middy-y5Zp27eG.cjs.map +1 -0
  188. package/dist/otel-1bJPb2Z7.d.mts +101 -0
  189. package/dist/otel-1bJPb2Z7.d.mts.map +1 -0
  190. package/dist/otel-C1HqHA2O.cjs +136 -0
  191. package/dist/otel-C1HqHA2O.cjs.map +1 -0
  192. package/dist/otel-SBVoVEHr.d.cts +101 -0
  193. package/dist/otel-SBVoVEHr.d.cts.map +1 -0
  194. package/dist/otel-wulj5B-X.mjs +130 -0
  195. package/dist/otel-wulj5B-X.mjs.map +1 -0
  196. package/dist/otlp/hono.cjs +15 -9
  197. package/dist/otlp/hono.cjs.map +1 -1
  198. package/dist/otlp/hono.d.cts +13 -3
  199. package/dist/otlp/hono.d.cts.map +1 -1
  200. package/dist/otlp/hono.d.mts +13 -3
  201. package/dist/otlp/hono.d.mts.map +1 -1
  202. package/dist/otlp/hono.mjs +11 -5
  203. package/dist/otlp/hono.mjs.map +1 -1
  204. package/dist/otlp/index.cjs +11 -11
  205. package/dist/otlp/index.d.cts +7 -4
  206. package/dist/otlp/index.d.mts +7 -4
  207. package/dist/otlp/index.mjs +5 -4
  208. package/dist/otlp/receiver.cjs +4 -88
  209. package/dist/otlp/receiver.d.cts +7 -59
  210. package/dist/otlp/receiver.d.mts +7 -59
  211. package/dist/otlp/receiver.mjs +4 -87
  212. package/dist/otlp/transformer.cjs +5 -214
  213. package/dist/otlp/transformer.d.cts +3 -1
  214. package/dist/otlp/transformer.d.mts +3 -1
  215. package/dist/otlp/transformer.mjs +3 -211
  216. package/dist/otlp/types.cjs +5 -57
  217. package/dist/otlp/types.d.cts +1 -1
  218. package/dist/otlp/types.d.mts +1 -1
  219. package/dist/otlp/types.mjs +2 -53
  220. package/dist/receiver-Cj1lbAOO.cjs +94 -0
  221. package/dist/receiver-Cj1lbAOO.cjs.map +1 -0
  222. package/dist/receiver-CxVd_9CB.mjs +89 -0
  223. package/dist/receiver-CxVd_9CB.mjs.map +1 -0
  224. package/dist/receiver-DLICx5uU.d.cts +63 -0
  225. package/dist/receiver-DLICx5uU.d.cts.map +1 -0
  226. package/dist/receiver-UeZT-H8u.d.mts +63 -0
  227. package/dist/receiver-UeZT-H8u.d.mts.map +1 -0
  228. package/dist/redact-BzkITCNW.mjs +83 -0
  229. package/dist/redact-BzkITCNW.mjs.map +1 -0
  230. package/dist/redact-DVaSSPZT.cjs +95 -0
  231. package/dist/redact-DVaSSPZT.cjs.map +1 -0
  232. package/dist/redact.cjs +3 -84
  233. package/dist/redact.d.cts +8 -4
  234. package/dist/redact.d.cts.map +1 -1
  235. package/dist/redact.d.mts +8 -4
  236. package/dist/redact.d.mts.map +1 -1
  237. package/dist/redact.mjs +2 -80
  238. package/dist/server/hono.cjs +54 -33
  239. package/dist/server/hono.cjs.map +1 -1
  240. package/dist/server/hono.d.cts +14 -19
  241. package/dist/server/hono.d.cts.map +1 -1
  242. package/dist/server/hono.d.mts +14 -19
  243. package/dist/server/hono.d.mts.map +1 -1
  244. package/dist/server/hono.mjs +52 -31
  245. package/dist/server/hono.mjs.map +1 -1
  246. package/dist/setup-B9jM77Qk.mjs +98 -0
  247. package/dist/setup-B9jM77Qk.mjs.map +1 -0
  248. package/dist/setup-Bkxm4g6b.d.mts +87 -0
  249. package/dist/setup-Bkxm4g6b.d.mts.map +1 -0
  250. package/dist/setup-CYpff5B9.cjs +110 -0
  251. package/dist/setup-CYpff5B9.cjs.map +1 -0
  252. package/dist/setup-D58N1f9O.d.cts +87 -0
  253. package/dist/setup-D58N1f9O.d.cts.map +1 -0
  254. package/dist/storage/kysely.cjs +70 -82
  255. package/dist/storage/kysely.cjs.map +1 -1
  256. package/dist/storage/kysely.d.cts +20 -36
  257. package/dist/storage/kysely.d.cts.map +1 -1
  258. package/dist/storage/kysely.d.mts +20 -36
  259. package/dist/storage/kysely.d.mts.map +1 -1
  260. package/dist/storage/kysely.mjs +69 -81
  261. package/dist/storage/kysely.mjs.map +1 -1
  262. package/dist/storage/memory.cjs +2 -122
  263. package/dist/storage/memory.d.cts +3 -36
  264. package/dist/storage/memory.d.mts +3 -36
  265. package/dist/storage/memory.mjs +2 -121
  266. package/dist/tracing-BX8uY2nR.d.cts +53 -0
  267. package/dist/tracing-BX8uY2nR.d.cts.map +1 -0
  268. package/dist/tracing-Bt1zWRlb.cjs +167 -0
  269. package/dist/tracing-Bt1zWRlb.cjs.map +1 -0
  270. package/dist/tracing-Cijm_5NI.mjs +113 -0
  271. package/dist/tracing-Cijm_5NI.mjs.map +1 -0
  272. package/dist/tracing-PnECEbEu.d.mts +53 -0
  273. package/dist/tracing-PnECEbEu.d.mts.map +1 -0
  274. package/dist/transformer-BXQPhzql.mjs +215 -0
  275. package/dist/transformer-BXQPhzql.mjs.map +1 -0
  276. package/dist/transformer-CLGZ0EQc.cjs +232 -0
  277. package/dist/transformer-CLGZ0EQc.cjs.map +1 -0
  278. package/dist/{transformer-BtqjAs0b.d.cts → transformer-CTGsaVfV.d.mts} +8 -4
  279. package/dist/transformer-CTGsaVfV.d.mts.map +1 -0
  280. package/dist/{transformer-DI6t8-YA.d.mts → transformer-ICEbxpFf.d.cts} +8 -4
  281. package/dist/transformer-ICEbxpFf.d.cts.map +1 -0
  282. package/dist/{types-BVujq4zd.d.mts → types-B1EIa_cQ.d.mts} +4 -3
  283. package/dist/types-B1EIa_cQ.d.mts.map +1 -0
  284. package/dist/types-BRzW1NM8.d.cts +166 -0
  285. package/dist/types-BRzW1NM8.d.cts.map +1 -0
  286. package/dist/types-BS3Rx8Sk.d.cts +209 -0
  287. package/dist/types-BS3Rx8Sk.d.cts.map +1 -0
  288. package/dist/types-Bwm_jNU7.mjs +54 -0
  289. package/dist/types-Bwm_jNU7.mjs.map +1 -0
  290. package/dist/types-BzQ78Efw.d.mts +166 -0
  291. package/dist/types-BzQ78Efw.d.mts.map +1 -0
  292. package/dist/types-CbNGXnJE.d.mts +209 -0
  293. package/dist/types-CbNGXnJE.d.mts.map +1 -0
  294. package/dist/{types-DVETVdpa.d.cts → types-CmOB7CLO.d.cts} +7 -6
  295. package/dist/types-CmOB7CLO.d.cts.map +1 -0
  296. package/dist/{types-DVETVdpa.d.mts → types-DBc0q5KD.d.mts} +7 -6
  297. package/dist/types-DBc0q5KD.d.mts.map +1 -0
  298. package/dist/types-Dsh-DIO_.cjs +78 -0
  299. package/dist/types-Dsh-DIO_.cjs.map +1 -0
  300. package/dist/types-ZW-nfWf6.cjs +40 -0
  301. package/dist/types-ZW-nfWf6.cjs.map +1 -0
  302. package/dist/{types-BVujq4zd.d.cts → types-l7Rlb5Mg.d.cts} +4 -3
  303. package/dist/types-l7Rlb5Mg.d.cts.map +1 -0
  304. package/dist/types-ojhnLdwz.mjs +34 -0
  305. package/dist/types-ojhnLdwz.mjs.map +1 -0
  306. package/dist/types.d.cts +1 -1
  307. package/dist/types.d.mts +1 -1
  308. package/dist/types.mjs +0 -1
  309. package/dist/ui-assets-BEXqOQLe.cjs +48 -0
  310. package/dist/ui-assets-BEXqOQLe.cjs.map +1 -0
  311. package/dist/ui-assets-BhTDUsrM.mjs +30 -0
  312. package/dist/ui-assets-BhTDUsrM.mjs.map +1 -0
  313. package/dist/ui-assets.cjs +5 -0
  314. package/dist/ui-assets.d.cts +13 -0
  315. package/dist/ui-assets.d.cts.map +1 -0
  316. package/dist/ui-assets.d.mts +13 -0
  317. package/dist/ui-assets.d.mts.map +1 -0
  318. package/dist/ui-assets.mjs +3 -0
  319. package/package.json +46 -46
  320. package/src/Telescope.ts +561 -0
  321. package/src/__tests__/Telescope.spec.ts +438 -0
  322. package/src/__tests__/pino-transport.spec.ts +115 -0
  323. package/src/__tests__/redact.spec.ts +336 -0
  324. package/src/adapters/__tests__/lambda.spec.ts +318 -0
  325. package/src/adapters/__tests__/middy.spec.ts +741 -0
  326. package/src/adapters/index.ts +22 -0
  327. package/src/adapters/lambda.ts +432 -0
  328. package/src/adapters/middy.ts +402 -0
  329. package/src/adapters/types.ts +181 -0
  330. package/src/core.ts +51 -0
  331. package/src/index.ts +34 -0
  332. package/src/instrumentation/__tests__/core.spec.ts +248 -0
  333. package/src/instrumentation/__tests__/hono.spec.ts +348 -0
  334. package/src/instrumentation/__tests__/middleware.spec.ts +528 -0
  335. package/src/instrumentation/__tests__/otel.spec.ts +291 -0
  336. package/src/instrumentation/__tests__/tracing.spec.ts +208 -0
  337. package/src/instrumentation/core.ts +228 -0
  338. package/src/instrumentation/hono.ts +270 -0
  339. package/src/instrumentation/http.ts +306 -0
  340. package/src/instrumentation/index.ts +90 -0
  341. package/src/instrumentation/middleware.ts +297 -0
  342. package/src/instrumentation/otel.ts +271 -0
  343. package/src/instrumentation/setup.ts +246 -0
  344. package/src/instrumentation/tracing.ts +145 -0
  345. package/src/logger/__tests__/console.spec.ts +366 -0
  346. package/src/logger/__tests__/pino.spec.ts +217 -0
  347. package/src/logger/console.ts +230 -0
  348. package/src/logger/pino.ts +201 -0
  349. package/src/metrics/MetricsAggregator.ts +555 -0
  350. package/src/metrics/__tests__/MetricsAggregator.spec.ts +298 -0
  351. package/src/metrics/index.ts +2 -0
  352. package/src/metrics/storage/InMemoryMetricsStorage.ts +380 -0
  353. package/src/metrics/storage/MetricsStorage.ts +74 -0
  354. package/src/metrics/storage/index.ts +3 -0
  355. package/src/metrics/storage/types.ts +243 -0
  356. package/src/otlp/__tests__/receiver.spec.ts +367 -0
  357. package/src/otlp/__tests__/transformer.spec.ts +455 -0
  358. package/src/otlp/hono.ts +120 -0
  359. package/src/otlp/index.ts +22 -0
  360. package/src/otlp/receiver.ts +162 -0
  361. package/src/otlp/transformer.ts +367 -0
  362. package/src/otlp/types.ts +364 -0
  363. package/src/redact.ts +116 -0
  364. package/src/server/__tests__/hono.spec.ts +814 -0
  365. package/src/server/hono.ts +442 -0
  366. package/src/storage/__tests__/kysely.spec.ts +715 -0
  367. package/src/storage/__tests__/memory.spec.ts +694 -0
  368. package/src/storage/kysely.ts +599 -0
  369. package/src/storage/memory.ts +204 -0
  370. package/src/types.ts +447 -0
  371. package/src/ui-assets.ts +40 -0
  372. package/tsconfig.json +9 -0
  373. package/ui/CHANGELOG.md +7 -0
  374. package/ui/index.html +12 -0
  375. package/ui/node_modules/.bin/tsc +21 -0
  376. package/ui/node_modules/.bin/tsserver +21 -0
  377. package/ui/node_modules/.bin/vite +21 -0
  378. package/ui/package.json +24 -0
  379. package/ui/src/App.tsx +595 -0
  380. package/ui/src/api.ts +88 -0
  381. package/ui/src/components/ExceptionDetail.tsx +100 -0
  382. package/ui/src/components/FilterBar.tsx +162 -0
  383. package/ui/src/components/LogDetail.tsx +91 -0
  384. package/ui/src/components/RequestDetail.tsx +143 -0
  385. package/ui/src/main.tsx +10 -0
  386. package/ui/src/styles.css +11 -0
  387. package/ui/src/types.ts +63 -0
  388. package/ui/src/vite-env.d.ts +1 -0
  389. package/ui/src/vite-plugin-gkm-config.ts +54 -0
  390. package/ui/tsconfig.json +20 -0
  391. package/ui/tsconfig.tsbuildinfo +1 -0
  392. package/ui/vite.config.ts +13 -0
  393. package/dist/MetricsAggregator-BJdIvfEv.d.mts.map +0 -1
  394. package/dist/MetricsAggregator-CnC3oT5q.d.cts.map +0 -1
  395. package/dist/Telescope-BVfDvVvY.d.mts.map +0 -1
  396. package/dist/Telescope-DeqSHfuB.d.cts.map +0 -1
  397. package/dist/Telescope.cjs.map +0 -1
  398. package/dist/Telescope.mjs.map +0 -1
  399. package/dist/adapters/middy.cjs.map +0 -1
  400. package/dist/adapters/middy.d.cts.map +0 -1
  401. package/dist/adapters/middy.d.mts.map +0 -1
  402. package/dist/adapters/middy.mjs.map +0 -1
  403. package/dist/adapters/types.d.cts.map +0 -1
  404. package/dist/adapters/types.d.mts.map +0 -1
  405. package/dist/instrumentation/core.cjs.map +0 -1
  406. package/dist/instrumentation/core.d.cts.map +0 -1
  407. package/dist/instrumentation/core.d.mts.map +0 -1
  408. package/dist/instrumentation/core.mjs.map +0 -1
  409. package/dist/instrumentation/hono.cjs.map +0 -1
  410. package/dist/instrumentation/hono.d.cts.map +0 -1
  411. package/dist/instrumentation/hono.d.mts.map +0 -1
  412. package/dist/instrumentation/hono.mjs.map +0 -1
  413. package/dist/instrumentation/http.cjs.map +0 -1
  414. package/dist/instrumentation/http.d.cts.map +0 -1
  415. package/dist/instrumentation/http.d.mts.map +0 -1
  416. package/dist/instrumentation/http.mjs.map +0 -1
  417. package/dist/instrumentation/middleware.cjs.map +0 -1
  418. package/dist/instrumentation/middleware.d.cts.map +0 -1
  419. package/dist/instrumentation/middleware.d.mts.map +0 -1
  420. package/dist/instrumentation/middleware.mjs.map +0 -1
  421. package/dist/instrumentation/otel.cjs.map +0 -1
  422. package/dist/instrumentation/otel.d.cts.map +0 -1
  423. package/dist/instrumentation/otel.d.mts.map +0 -1
  424. package/dist/instrumentation/otel.mjs.map +0 -1
  425. package/dist/instrumentation/sampler.cjs +0 -54
  426. package/dist/instrumentation/sampler.cjs.map +0 -1
  427. package/dist/instrumentation/sampler.d.cts +0 -38
  428. package/dist/instrumentation/sampler.d.cts.map +0 -1
  429. package/dist/instrumentation/sampler.d.mts +0 -38
  430. package/dist/instrumentation/sampler.d.mts.map +0 -1
  431. package/dist/instrumentation/sampler.mjs +0 -52
  432. package/dist/instrumentation/sampler.mjs.map +0 -1
  433. package/dist/instrumentation/setup.cjs.map +0 -1
  434. package/dist/instrumentation/setup.d.cts.map +0 -1
  435. package/dist/instrumentation/setup.d.mts.map +0 -1
  436. package/dist/instrumentation/setup.mjs.map +0 -1
  437. package/dist/instrumentation/tracing.cjs.map +0 -1
  438. package/dist/instrumentation/tracing.d.cts.map +0 -1
  439. package/dist/instrumentation/tracing.d.mts.map +0 -1
  440. package/dist/instrumentation/tracing.mjs.map +0 -1
  441. package/dist/instrumentation/trust.cjs +0 -107
  442. package/dist/instrumentation/trust.cjs.map +0 -1
  443. package/dist/instrumentation/trust.d.cts +0 -57
  444. package/dist/instrumentation/trust.d.cts.map +0 -1
  445. package/dist/instrumentation/trust.d.mts +0 -57
  446. package/dist/instrumentation/trust.d.mts.map +0 -1
  447. package/dist/instrumentation/trust.mjs +0 -104
  448. package/dist/instrumentation/trust.mjs.map +0 -1
  449. package/dist/metrics/MetricsAggregator.cjs.map +0 -1
  450. package/dist/metrics/MetricsAggregator.mjs.map +0 -1
  451. package/dist/metrics/storage/InMemoryMetricsStorage.cjs.map +0 -1
  452. package/dist/metrics/storage/InMemoryMetricsStorage.d.cts.map +0 -1
  453. package/dist/metrics/storage/InMemoryMetricsStorage.d.mts.map +0 -1
  454. package/dist/metrics/storage/InMemoryMetricsStorage.mjs.map +0 -1
  455. package/dist/metrics/storage/MetricsStorage.d.cts.map +0 -1
  456. package/dist/metrics/storage/MetricsStorage.d.mts.map +0 -1
  457. package/dist/metrics/storage/types.cjs.map +0 -1
  458. package/dist/metrics/storage/types.d.cts.map +0 -1
  459. package/dist/metrics/storage/types.d.mts.map +0 -1
  460. package/dist/metrics/storage/types.mjs.map +0 -1
  461. package/dist/otlp/receiver.cjs.map +0 -1
  462. package/dist/otlp/receiver.d.cts.map +0 -1
  463. package/dist/otlp/receiver.d.mts.map +0 -1
  464. package/dist/otlp/receiver.mjs.map +0 -1
  465. package/dist/otlp/transformer.cjs.map +0 -1
  466. package/dist/otlp/transformer.mjs.map +0 -1
  467. package/dist/otlp/types.cjs.map +0 -1
  468. package/dist/otlp/types.mjs.map +0 -1
  469. package/dist/redact.cjs.map +0 -1
  470. package/dist/redact.mjs.map +0 -1
  471. package/dist/storage/memory.cjs.map +0 -1
  472. package/dist/storage/memory.d.cts.map +0 -1
  473. package/dist/storage/memory.d.mts.map +0 -1
  474. package/dist/storage/memory.mjs.map +0 -1
  475. package/dist/transformer-BtqjAs0b.d.cts.map +0 -1
  476. package/dist/transformer-DI6t8-YA.d.mts.map +0 -1
  477. package/dist/types-BVujq4zd.d.cts.map +0 -1
  478. package/dist/types-BVujq4zd.d.mts.map +0 -1
  479. package/dist/types-DVETVdpa.d.cts.map +0 -1
  480. package/dist/types-DVETVdpa.d.mts.map +0 -1
@@ -0,0 +1,741 @@
1
+ import type {
2
+ APIGatewayProxyEvent,
3
+ APIGatewayProxyEventV2,
4
+ Context,
5
+ } from 'aws-lambda';
6
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
7
+ import { InMemoryStorage } from '../../storage/memory';
8
+ import { Telescope } from '../../Telescope';
9
+ import { createTelescopeHandler, telescopeMiddleware } from '../middy';
10
+
11
+ describe('Telescope Middy Middleware', () => {
12
+ let telescope: Telescope;
13
+ let storage: InMemoryStorage;
14
+ let mockContext: Context;
15
+
16
+ beforeEach(() => {
17
+ storage = new InMemoryStorage();
18
+ telescope = new Telescope({ storage });
19
+
20
+ mockContext = {
21
+ callbackWaitsForEmptyEventLoop: true,
22
+ functionName: 'test-function',
23
+ functionVersion: '1',
24
+ invokedFunctionArn: 'arn:aws:lambda:us-east-1:123456789:function:test',
25
+ memoryLimitInMB: '128',
26
+ awsRequestId: 'test-request-id',
27
+ logGroupName: '/aws/lambda/test',
28
+ logStreamName: '2024/01/01/[$LATEST]abc123',
29
+ getRemainingTimeInMillis: () => 10000,
30
+ done: vi.fn(),
31
+ fail: vi.fn(),
32
+ succeed: vi.fn(),
33
+ };
34
+ });
35
+
36
+ afterEach(() => {
37
+ telescope.destroy();
38
+ });
39
+
40
+ describe('telescopeMiddleware', () => {
41
+ describe('before hook', () => {
42
+ it('should set callbackWaitsForEmptyEventLoop to false', async () => {
43
+ const middleware = telescopeMiddleware(telescope);
44
+ const request = {
45
+ event: createV2Event(),
46
+ context: mockContext,
47
+ response: null,
48
+ error: null,
49
+ internal: {},
50
+ };
51
+
52
+ await middleware.before?.(request as any);
53
+
54
+ expect(request.context.callbackWaitsForEmptyEventLoop).toBe(false);
55
+ });
56
+
57
+ it('should store start time on request', async () => {
58
+ const middleware = telescopeMiddleware(telescope);
59
+ const request = {
60
+ event: createV2Event(),
61
+ context: mockContext,
62
+ response: null,
63
+ error: null,
64
+ internal: {},
65
+ };
66
+
67
+ await middleware.before?.(request as any);
68
+
69
+ expect((request as any).__telescopeStartTime).toBeDefined();
70
+ expect(typeof (request as any).__telescopeStartTime).toBe('number');
71
+ });
72
+ });
73
+
74
+ describe('after hook', () => {
75
+ it('should record request to Telescope for v2 events', async () => {
76
+ const middleware = telescopeMiddleware(telescope);
77
+ const event = createV2Event({
78
+ method: 'POST',
79
+ path: '/api/users',
80
+ body: JSON.stringify({ name: 'John' }),
81
+ });
82
+ const request = {
83
+ event,
84
+ context: mockContext,
85
+ response: { statusCode: 201, body: JSON.stringify({ id: '123' }) },
86
+ error: null,
87
+ internal: {},
88
+ __telescopeStartTime: Date.now() - 100,
89
+ };
90
+
91
+ await middleware.after?.(request as any);
92
+
93
+ const requests = await storage.getRequests();
94
+ expect(requests).toHaveLength(1);
95
+ expect(requests[0].method).toBe('POST');
96
+ expect(requests[0].path).toBe('/api/users');
97
+ expect(requests[0].status).toBe(201);
98
+ expect(requests[0].duration).toBeGreaterThanOrEqual(100);
99
+ });
100
+
101
+ it('should record request to Telescope for v1 events', async () => {
102
+ const middleware = telescopeMiddleware(telescope);
103
+ const event = createV1Event({
104
+ method: 'GET',
105
+ path: '/api/items',
106
+ query: { page: '1' },
107
+ });
108
+ const request = {
109
+ event,
110
+ context: mockContext,
111
+ response: { statusCode: 200, body: JSON.stringify({ items: [] }) },
112
+ error: null,
113
+ internal: {},
114
+ __telescopeStartTime: Date.now() - 50,
115
+ };
116
+
117
+ await middleware.after?.(request as any);
118
+
119
+ const requests = await storage.getRequests();
120
+ expect(requests).toHaveLength(1);
121
+ expect(requests[0].method).toBe('GET');
122
+ expect(requests[0].path).toBe('/api/items');
123
+ expect(requests[0].status).toBe(200);
124
+ });
125
+
126
+ it('should respect recordBody option when false', async () => {
127
+ const middleware = telescopeMiddleware(telescope, {
128
+ recordBody: false,
129
+ });
130
+ const event = createV2Event({
131
+ method: 'POST',
132
+ path: '/api/users',
133
+ body: JSON.stringify({ secret: 'password123' }),
134
+ });
135
+ const request = {
136
+ event,
137
+ context: mockContext,
138
+ response: {
139
+ statusCode: 200,
140
+ body: JSON.stringify({ token: 'secret-token' }),
141
+ },
142
+ error: null,
143
+ internal: {},
144
+ __telescopeStartTime: Date.now(),
145
+ };
146
+
147
+ await middleware.after?.(request as any);
148
+
149
+ const requests = await storage.getRequests();
150
+ expect(requests).toHaveLength(1);
151
+ expect(requests[0].body).toBeUndefined();
152
+ expect(requests[0].responseBody).toBeUndefined();
153
+ });
154
+
155
+ it('should include body when recordBody is true (default)', async () => {
156
+ const middleware = telescopeMiddleware(telescope);
157
+ const event = createV2Event({
158
+ method: 'POST',
159
+ path: '/api/users',
160
+ body: JSON.stringify({ name: 'Test' }),
161
+ });
162
+ const request = {
163
+ event,
164
+ context: mockContext,
165
+ response: { statusCode: 200, body: JSON.stringify({ id: '1' }) },
166
+ error: null,
167
+ internal: {},
168
+ __telescopeStartTime: Date.now(),
169
+ };
170
+
171
+ await middleware.after?.(request as any);
172
+
173
+ const requests = await storage.getRequests();
174
+ expect(requests[0].body).toEqual({ name: 'Test' });
175
+ expect(requests[0].responseBody).toEqual({ id: '1' });
176
+ });
177
+
178
+ it('should extract IP from v2 event', async () => {
179
+ const middleware = telescopeMiddleware(telescope);
180
+ const event = createV2Event({ ip: '192.168.1.1' });
181
+ const request = {
182
+ event,
183
+ context: mockContext,
184
+ response: { statusCode: 200 },
185
+ error: null,
186
+ internal: {},
187
+ __telescopeStartTime: Date.now(),
188
+ };
189
+
190
+ await middleware.after?.(request as any);
191
+
192
+ const requests = await storage.getRequests();
193
+ expect(requests[0].ip).toBe('192.168.1.1');
194
+ });
195
+
196
+ it('should extract IP from v1 event', async () => {
197
+ const middleware = telescopeMiddleware(telescope);
198
+ const event = createV1Event({ ip: '10.0.0.1' });
199
+ const request = {
200
+ event,
201
+ context: mockContext,
202
+ response: { statusCode: 200 },
203
+ error: null,
204
+ internal: {},
205
+ __telescopeStartTime: Date.now(),
206
+ };
207
+
208
+ await middleware.after?.(request as any);
209
+
210
+ const requests = await storage.getRequests();
211
+ expect(requests[0].ip).toBe('10.0.0.1');
212
+ });
213
+ });
214
+
215
+ describe('onError hook', () => {
216
+ it('should record exception to Telescope', async () => {
217
+ const middleware = telescopeMiddleware(telescope);
218
+ const error = new Error('Something went wrong');
219
+ const request = {
220
+ event: createV2Event({ path: '/api/error' }),
221
+ context: mockContext,
222
+ response: null,
223
+ error,
224
+ internal: {},
225
+ __telescopeStartTime: Date.now(),
226
+ };
227
+
228
+ await middleware.onError?.(request as any);
229
+
230
+ const exceptions = await storage.getExceptions();
231
+ expect(exceptions).toHaveLength(1);
232
+ expect(exceptions[0].message).toBe('Something went wrong');
233
+ });
234
+
235
+ it('should record failed request with 500 status', async () => {
236
+ const middleware = telescopeMiddleware(telescope);
237
+ const error = new Error('Database connection failed');
238
+ const request = {
239
+ event: createV2Event({ method: 'POST', path: '/api/data' }),
240
+ context: mockContext,
241
+ response: null,
242
+ error,
243
+ internal: {},
244
+ __telescopeStartTime: Date.now() - 200,
245
+ };
246
+
247
+ await middleware.onError?.(request as any);
248
+
249
+ const requests = await storage.getRequests();
250
+ expect(requests).toHaveLength(1);
251
+ expect(requests[0].status).toBe(500);
252
+ expect(requests[0].path).toBe('/api/data');
253
+ expect(requests[0].responseBody).toEqual({
254
+ error: 'Database connection failed',
255
+ });
256
+ });
257
+ });
258
+ });
259
+
260
+ describe('createTelescopeHandler', () => {
261
+ it('should wrap handler and record successful request', async () => {
262
+ const baseHandler = async () => ({
263
+ statusCode: 200,
264
+ body: JSON.stringify({ success: true }),
265
+ });
266
+
267
+ const handler = createTelescopeHandler(telescope, baseHandler);
268
+ const event = createV2Event({ method: 'GET', path: '/api/health' });
269
+
270
+ const result = await handler(event, mockContext);
271
+
272
+ expect(result).toEqual({
273
+ statusCode: 200,
274
+ body: JSON.stringify({ success: true }),
275
+ });
276
+
277
+ const requests = await storage.getRequests();
278
+ expect(requests).toHaveLength(1);
279
+ expect(requests[0].method).toBe('GET');
280
+ expect(requests[0].path).toBe('/api/health');
281
+ expect(requests[0].status).toBe(200);
282
+ });
283
+
284
+ it('should set callbackWaitsForEmptyEventLoop to false', async () => {
285
+ const baseHandler = async () => ({ statusCode: 200 });
286
+ const handler = createTelescopeHandler(telescope, baseHandler);
287
+ const event = createV2Event();
288
+
289
+ await handler(event, mockContext);
290
+
291
+ expect(mockContext.callbackWaitsForEmptyEventLoop).toBe(false);
292
+ });
293
+
294
+ it('should record exception on error and rethrow', async () => {
295
+ const error = new Error('Handler failed');
296
+ const baseHandler = async () => {
297
+ throw error;
298
+ };
299
+ const handler = createTelescopeHandler(telescope, baseHandler);
300
+ const event = createV2Event({ path: '/api/failing' });
301
+
302
+ await expect(handler(event, mockContext)).rejects.toThrow(
303
+ 'Handler failed',
304
+ );
305
+
306
+ const exceptions = await storage.getExceptions();
307
+ expect(exceptions).toHaveLength(1);
308
+ expect(exceptions[0].message).toBe('Handler failed');
309
+ });
310
+
311
+ it('should respect recordBody option', async () => {
312
+ const baseHandler = async () => ({
313
+ statusCode: 200,
314
+ body: JSON.stringify({ token: 'secret' }),
315
+ });
316
+
317
+ const handler = createTelescopeHandler(telescope, baseHandler, {
318
+ recordBody: false,
319
+ });
320
+ const event = createV2Event({
321
+ method: 'POST',
322
+ body: JSON.stringify({ password: 'secret' }),
323
+ });
324
+
325
+ await handler(event, mockContext);
326
+
327
+ const requests = await storage.getRequests();
328
+ expect(requests[0].body).toBeUndefined();
329
+ expect(requests[0].responseBody).toBeUndefined();
330
+ });
331
+
332
+ it('should calculate duration correctly', async () => {
333
+ const baseHandler = async () => {
334
+ await new Promise((resolve) => setTimeout(resolve, 50));
335
+ return { statusCode: 200 };
336
+ };
337
+
338
+ const handler = createTelescopeHandler(telescope, baseHandler);
339
+ const event = createV2Event();
340
+
341
+ await handler(event, mockContext);
342
+
343
+ const requests = await storage.getRequests();
344
+ // Use 45ms threshold to account for setTimeout timing imprecision
345
+ expect(requests[0].duration).toBeGreaterThanOrEqual(45);
346
+ });
347
+ });
348
+
349
+ describe('request data extraction', () => {
350
+ it('should handle base64 encoded body', async () => {
351
+ const middleware = telescopeMiddleware(telescope);
352
+ const bodyContent = { data: 'test' };
353
+ const base64Body = Buffer.from(JSON.stringify(bodyContent)).toString(
354
+ 'base64',
355
+ );
356
+
357
+ const event: APIGatewayProxyEventV2 = {
358
+ ...createV2Event(),
359
+ body: base64Body,
360
+ isBase64Encoded: true,
361
+ };
362
+
363
+ const request = {
364
+ event,
365
+ context: mockContext,
366
+ response: { statusCode: 200 },
367
+ error: null,
368
+ internal: {},
369
+ __telescopeStartTime: Date.now(),
370
+ };
371
+
372
+ await middleware.after?.(request as any);
373
+
374
+ const requests = await storage.getRequests();
375
+ expect(requests[0].body).toEqual({ data: 'test' });
376
+ });
377
+
378
+ it('should handle non-JSON body gracefully', async () => {
379
+ const middleware = telescopeMiddleware(telescope);
380
+ const event = createV2Event({ body: 'plain text body' });
381
+ const request = {
382
+ event,
383
+ context: mockContext,
384
+ response: { statusCode: 200 },
385
+ error: null,
386
+ internal: {},
387
+ __telescopeStartTime: Date.now(),
388
+ };
389
+
390
+ await middleware.after?.(request as any);
391
+
392
+ const requests = await storage.getRequests();
393
+ expect(requests[0].body).toBe('plain text body');
394
+ });
395
+
396
+ it('should handle null body', async () => {
397
+ const middleware = telescopeMiddleware(telescope);
398
+ const event = createV2Event({ body: null });
399
+ const request = {
400
+ event,
401
+ context: mockContext,
402
+ response: { statusCode: 200 },
403
+ error: null,
404
+ internal: {},
405
+ __telescopeStartTime: Date.now(),
406
+ };
407
+
408
+ await middleware.after?.(request as any);
409
+
410
+ const requests = await storage.getRequests();
411
+ expect(requests[0].body).toBeUndefined();
412
+ });
413
+
414
+ it('should construct URL with query string for v2 events', async () => {
415
+ const middleware = telescopeMiddleware(telescope);
416
+ const event = createV2Event({
417
+ path: '/api/search',
418
+ queryString: 'q=test&page=1',
419
+ });
420
+ const request = {
421
+ event,
422
+ context: mockContext,
423
+ response: { statusCode: 200 },
424
+ error: null,
425
+ internal: {},
426
+ __telescopeStartTime: Date.now(),
427
+ };
428
+
429
+ await middleware.after?.(request as any);
430
+
431
+ const requests = await storage.getRequests();
432
+ expect(requests[0].url).toBe('/api/search?q=test&page=1');
433
+ });
434
+
435
+ it('should normalize headers to lowercase', async () => {
436
+ const middleware = telescopeMiddleware(telescope);
437
+ const event = createV2Event();
438
+ event.headers = {
439
+ 'Content-Type': 'application/json',
440
+ 'X-Custom-Header': 'value',
441
+ Authorization: 'Bearer token',
442
+ };
443
+ const request = {
444
+ event,
445
+ context: mockContext,
446
+ response: { statusCode: 200 },
447
+ error: null,
448
+ internal: {},
449
+ __telescopeStartTime: Date.now(),
450
+ };
451
+
452
+ await middleware.after?.(request as any);
453
+
454
+ const requests = await storage.getRequests();
455
+ expect(requests[0].headers).toEqual({
456
+ 'content-type': 'application/json',
457
+ 'x-custom-header': 'value',
458
+ authorization: 'Bearer token',
459
+ });
460
+ });
461
+ });
462
+
463
+ describe('response data extraction', () => {
464
+ it('should handle response without statusCode', async () => {
465
+ const middleware = telescopeMiddleware(telescope);
466
+ const request = {
467
+ event: createV2Event(),
468
+ context: mockContext,
469
+ response: { data: 'raw response' }, // No statusCode
470
+ error: null,
471
+ internal: {},
472
+ __telescopeStartTime: Date.now(),
473
+ };
474
+
475
+ await middleware.after?.(request as any);
476
+
477
+ const requests = await storage.getRequests();
478
+ expect(requests[0].status).toBe(200); // Default status
479
+ });
480
+
481
+ it('should parse JSON response body', async () => {
482
+ const middleware = telescopeMiddleware(telescope);
483
+ const request = {
484
+ event: createV2Event(),
485
+ context: mockContext,
486
+ response: {
487
+ statusCode: 200,
488
+ body: JSON.stringify({ items: [1, 2, 3] }),
489
+ },
490
+ error: null,
491
+ internal: {},
492
+ __telescopeStartTime: Date.now(),
493
+ };
494
+
495
+ await middleware.after?.(request as any);
496
+
497
+ const requests = await storage.getRequests();
498
+ expect(requests[0].responseBody).toEqual({ items: [1, 2, 3] });
499
+ });
500
+
501
+ it('should handle non-JSON response body', async () => {
502
+ const middleware = telescopeMiddleware(telescope);
503
+ const request = {
504
+ event: createV2Event(),
505
+ context: mockContext,
506
+ response: {
507
+ statusCode: 200,
508
+ body: '<html>Hello</html>',
509
+ },
510
+ error: null,
511
+ internal: {},
512
+ __telescopeStartTime: Date.now(),
513
+ };
514
+
515
+ await middleware.after?.(request as any);
516
+
517
+ const requests = await storage.getRequests();
518
+ expect(requests[0].responseBody).toBe('<html>Hello</html>');
519
+ });
520
+ });
521
+
522
+ describe('size tracking', () => {
523
+ it('should capture request size from Content-Length header', async () => {
524
+ const middleware = telescopeMiddleware(telescope);
525
+ const body = JSON.stringify({ name: 'John', data: 'test payload' });
526
+ const event = createV2Event({
527
+ method: 'POST',
528
+ path: '/api/data',
529
+ body,
530
+ headers: { 'content-length': String(Buffer.byteLength(body)) },
531
+ });
532
+ const request = {
533
+ event,
534
+ context: mockContext,
535
+ response: { statusCode: 200, body: '{"ok":true}' },
536
+ error: null,
537
+ internal: {},
538
+ __telescopeStartTime: Date.now(),
539
+ };
540
+
541
+ await middleware.after?.(request as any);
542
+
543
+ const requests = await storage.getRequests();
544
+ expect(requests[0].requestSize).toBe(Buffer.byteLength(body));
545
+ });
546
+
547
+ it('should capture response size from Content-Length header', async () => {
548
+ const middleware = telescopeMiddleware(telescope);
549
+ const responseBody = JSON.stringify({ users: ['alice', 'bob'] });
550
+ const event = createV2Event({ method: 'GET', path: '/api/users' });
551
+ const request = {
552
+ event,
553
+ context: mockContext,
554
+ response: {
555
+ statusCode: 200,
556
+ headers: {
557
+ 'Content-Length': String(Buffer.byteLength(responseBody)),
558
+ },
559
+ body: responseBody,
560
+ },
561
+ error: null,
562
+ internal: {},
563
+ __telescopeStartTime: Date.now(),
564
+ };
565
+
566
+ await middleware.after?.(request as any);
567
+
568
+ const requests = await storage.getRequests();
569
+ expect(requests[0].responseSize).toBe(Buffer.byteLength(responseBody));
570
+ });
571
+
572
+ it('should calculate response size from body when Content-Length not set', async () => {
573
+ const middleware = telescopeMiddleware(telescope);
574
+ const responseBody = JSON.stringify({ items: [1, 2, 3, 4, 5] });
575
+ const event = createV2Event({ method: 'GET', path: '/api/items' });
576
+ const request = {
577
+ event,
578
+ context: mockContext,
579
+ response: {
580
+ statusCode: 200,
581
+ body: responseBody,
582
+ },
583
+ error: null,
584
+ internal: {},
585
+ __telescopeStartTime: Date.now(),
586
+ };
587
+
588
+ await middleware.after?.(request as any);
589
+
590
+ const requests = await storage.getRequests();
591
+ expect(requests[0].responseSize).toBe(Buffer.byteLength(responseBody));
592
+ });
593
+
594
+ it('should handle multi-byte characters in response size', async () => {
595
+ const middleware = telescopeMiddleware(telescope);
596
+ const responseBody = JSON.stringify({ message: '你好世界' });
597
+ const event = createV2Event({ method: 'GET', path: '/api/unicode' });
598
+ const request = {
599
+ event,
600
+ context: mockContext,
601
+ response: {
602
+ statusCode: 200,
603
+ body: responseBody,
604
+ },
605
+ error: null,
606
+ internal: {},
607
+ __telescopeStartTime: Date.now(),
608
+ };
609
+
610
+ await middleware.after?.(request as any);
611
+
612
+ const requests = await storage.getRequests();
613
+ // UTF-8 bytes for Chinese characters are more than string length
614
+ expect(requests[0].responseSize).toBe(
615
+ Buffer.byteLength(responseBody, 'utf8'),
616
+ );
617
+ });
618
+
619
+ it('should track request size for v1 events', async () => {
620
+ const middleware = telescopeMiddleware(telescope);
621
+ const body = JSON.stringify({ data: 'v1 payload' });
622
+ const event = createV1Event({
623
+ method: 'POST',
624
+ path: '/api/v1/data',
625
+ body,
626
+ headers: { 'content-length': String(Buffer.byteLength(body)) },
627
+ });
628
+ const request = {
629
+ event,
630
+ context: mockContext,
631
+ response: { statusCode: 201, body: '{"id":"123"}' },
632
+ error: null,
633
+ internal: {},
634
+ __telescopeStartTime: Date.now(),
635
+ };
636
+
637
+ await middleware.after?.(request as any);
638
+
639
+ const requests = await storage.getRequests();
640
+ expect(requests[0].requestSize).toBe(Buffer.byteLength(body));
641
+ });
642
+ });
643
+ });
644
+
645
+ // Helper functions to create mock events
646
+
647
+ function createV2Event(
648
+ options: {
649
+ method?: string;
650
+ path?: string;
651
+ body?: string | null;
652
+ query?: Record<string, string>;
653
+ queryString?: string;
654
+ ip?: string;
655
+ headers?: Record<string, string>;
656
+ } = {},
657
+ ): APIGatewayProxyEventV2 {
658
+ return {
659
+ version: '2.0',
660
+ routeKey: `${options.method || 'GET'} ${options.path || '/'}`,
661
+ rawPath: options.path || '/',
662
+ rawQueryString: options.queryString || '',
663
+ headers: options.headers || {},
664
+ queryStringParameters: options.query || {},
665
+ body: options.body ?? null,
666
+ isBase64Encoded: false,
667
+ requestContext: {
668
+ accountId: '123456789',
669
+ apiId: 'api123',
670
+ domainName: 'api.example.com',
671
+ domainPrefix: 'api',
672
+ http: {
673
+ method: options.method || 'GET',
674
+ path: options.path || '/',
675
+ protocol: 'HTTP/1.1',
676
+ sourceIp: options.ip || '127.0.0.1',
677
+ userAgent: 'test-agent',
678
+ },
679
+ requestId: 'test-request-id',
680
+ routeKey: `${options.method || 'GET'} ${options.path || '/'}`,
681
+ stage: '$default',
682
+ time: '01/Jan/2024:00:00:00 +0000',
683
+ timeEpoch: Date.now(),
684
+ },
685
+ };
686
+ }
687
+
688
+ function createV1Event(
689
+ options: {
690
+ method?: string;
691
+ path?: string;
692
+ body?: string | null;
693
+ query?: Record<string, string>;
694
+ ip?: string;
695
+ headers?: Record<string, string>;
696
+ } = {},
697
+ ): APIGatewayProxyEvent {
698
+ return {
699
+ httpMethod: options.method || 'GET',
700
+ path: options.path || '/',
701
+ headers: options.headers || {},
702
+ multiValueHeaders: {},
703
+ queryStringParameters: options.query || null,
704
+ multiValueQueryStringParameters: null,
705
+ pathParameters: null,
706
+ stageVariables: null,
707
+ body: options.body ?? null,
708
+ isBase64Encoded: false,
709
+ resource: options.path || '/',
710
+ requestContext: {
711
+ accountId: '123456789',
712
+ apiId: 'api123',
713
+ authorizer: null,
714
+ httpMethod: options.method || 'GET',
715
+ identity: {
716
+ accessKey: null,
717
+ accountId: null,
718
+ apiKey: null,
719
+ apiKeyId: null,
720
+ caller: null,
721
+ clientCert: null,
722
+ cognitoAuthenticationProvider: null,
723
+ cognitoAuthenticationType: null,
724
+ cognitoIdentityId: null,
725
+ cognitoIdentityPoolId: null,
726
+ principalOrgId: null,
727
+ sourceIp: options.ip || '127.0.0.1',
728
+ user: null,
729
+ userAgent: 'test-agent',
730
+ userArn: null,
731
+ },
732
+ path: options.path || '/',
733
+ protocol: 'HTTP/1.1',
734
+ requestId: 'test-request-id',
735
+ requestTimeEpoch: Date.now(),
736
+ resourceId: 'resource123',
737
+ resourcePath: options.path || '/',
738
+ stage: 'test',
739
+ },
740
+ };
741
+ }