@geekmidas/telescope 10.0.0-alpha.98 → 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
@@ -1 +1 @@
1
- {"version":3,"file":"hono.cjs","names":["Hono"],"sources":["../../src/server/hono.ts"],"sourcesContent":["import type { Context, MiddlewareHandler, Next } from 'hono';\nimport { Hono } from 'hono';\nimport type {\n\tHonoAdapterConfig,\n\tTelescopeHonoContext,\n} from '../adapters/types';\nimport type { Telescope } from '../Telescope';\nimport type { MetricsQueryOptions, QueryOptions } from '../types';\n\n// Lazy-loaded telemetry flush function (only loads @opentelemetry/* when actually used)\nlet _flushTelemetry: (() => Promise<void>) | null = null;\nasync function getFlushTelemetry(): Promise<() => Promise<void>> {\n\tif (!_flushTelemetry) {\n\t\tconst { flushTelemetry } = await import('../instrumentation/core');\n\t\t_flushTelemetry = flushTelemetry;\n\t}\n\treturn _flushTelemetry;\n}\n\nconst CONTEXT_KEY = 'telescope-context';\n\n/** Default Hono adapter configuration */\nconst _DEFAULT_CONFIG: HonoAdapterConfig = {\n\tenvironment: 'server',\n};\n\n/**\n * Options for the Telescope Hono middleware\n */\nexport interface TelescopeMiddlewareOptions {\n\t/**\n\t * Whether to flush telemetry after each request.\n\t * Enable this for serverless environments (Lambda, Edge).\n\t * @default false\n\t */\n\tflushOnResponse?: boolean;\n}\n\n/**\n * Create Hono middleware that captures requests and responses\n */\nexport function createMiddleware(\n\ttelescope: Telescope,\n\toptions: TelescopeMiddlewareOptions = {},\n): MiddlewareHandler {\n\tconst { flushOnResponse = false } = options;\n\n\treturn async (c: Context, next: Next) => {\n\t\tif (!telescope.enabled) {\n\t\t\treturn next();\n\t\t}\n\n\t\tif (telescope.shouldIgnore(c.req.path)) {\n\t\t\treturn next();\n\t\t}\n\n\t\tconst startTime = performance.now();\n\n\t\t// Capture request data\n\t\tconst headers: Record<string, string> = {};\n\t\tc.req.raw.headers.forEach((value, key) => {\n\t\t\theaders[key] = value;\n\t\t});\n\n\t\tconst url = new URL(c.req.url);\n\t\tconst query: Record<string, string> = {};\n\t\turl.searchParams.forEach((value, key) => {\n\t\t\tquery[key] = value;\n\t\t});\n\n\t\tlet body: unknown;\n\t\tlet requestSize: number | undefined;\n\n\t\t// Get request size from Content-Length header\n\t\tconst contentLength = c.req.header('content-length');\n\t\tif (contentLength) {\n\t\t\trequestSize = parseInt(contentLength, 10);\n\t\t}\n\n\t\tif (\n\t\t\ttelescope.recordBody &&\n\t\t\t['POST', 'PUT', 'PATCH'].includes(c.req.method)\n\t\t) {\n\t\t\ttry {\n\t\t\t\tconst contentType = c.req.header('content-type') || '';\n\t\t\t\t// Clone the request to avoid consuming the body stream\n\t\t\t\tconst clonedRequest = c.req.raw.clone();\n\t\t\t\tif (contentType.includes('application/json')) {\n\t\t\t\t\tbody = await clonedRequest.json();\n\t\t\t\t} else if (contentType.includes('application/x-www-form-urlencoded')) {\n\t\t\t\t\tbody = Object.fromEntries((await clonedRequest.formData()).entries());\n\t\t\t\t} else if (contentType.includes('text/')) {\n\t\t\t\t\tbody = await clonedRequest.text();\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Ignore body parsing errors\n\t\t\t}\n\t\t}\n\n\t\tconst ip = c.req.header('x-forwarded-for') || c.req.header('x-real-ip');\n\n\t\ttry {\n\t\t\tawait next();\n\n\t\t\t// Capture response data\n\t\t\tconst duration = performance.now() - startTime;\n\n\t\t\tconst responseHeaders: Record<string, string> = {};\n\t\t\tc.res.headers.forEach((value, key) => {\n\t\t\t\tresponseHeaders[key] = value;\n\t\t\t});\n\n\t\t\tlet responseBody: unknown;\n\t\t\tlet responseSize: number | undefined;\n\n\t\t\t// Get response size - prefer Content-Length header, fallback to body size\n\t\t\tconst responseContentLength = c.res.headers.get('content-length');\n\t\t\tif (responseContentLength) {\n\t\t\t\tresponseSize = parseInt(responseContentLength, 10);\n\t\t\t}\n\n\t\t\tif (telescope.recordBody) {\n\t\t\t\ttry {\n\t\t\t\t\tconst contentType = c.res.headers.get('content-type') || '';\n\t\t\t\t\tif (contentType.includes('application/json')) {\n\t\t\t\t\t\tconst cloned = c.res.clone();\n\t\t\t\t\t\tconst text = await cloned.text();\n\t\t\t\t\t\tresponseSize ??= Buffer.byteLength(text, 'utf8');\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponseBody = JSON.parse(text);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tresponseBody = text;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore body parsing errors\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst requestId = await telescope.recordRequest({\n\t\t\t\tmethod: c.req.method,\n\t\t\t\tpath: c.req.path,\n\t\t\t\turl: c.req.url,\n\t\t\t\theaders,\n\t\t\t\tbody,\n\t\t\t\tquery,\n\t\t\t\tstatus: c.res.status,\n\t\t\t\tresponseHeaders,\n\t\t\t\tresponseBody,\n\t\t\t\tduration,\n\t\t\t\tip,\n\t\t\t\trequestSize,\n\t\t\t\tresponseSize,\n\t\t\t});\n\n\t\t\t// Store context for access by other middleware\n\t\t\tconst ctx: TelescopeHonoContext = {\n\t\t\t\trequestId,\n\t\t\t\tstartTime,\n\t\t\t};\n\t\t\tc.set(CONTEXT_KEY, ctx);\n\n\t\t\t// Flush telemetry for serverless environments\n\t\t\tif (flushOnResponse) {\n\t\t\t\tconst flushTelemetry = await getFlushTelemetry();\n\t\t\t\tawait flushTelemetry();\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait telescope.exception(error as Error);\n\t\t\tthrow error;\n\t\t}\n\t};\n}\n\n/**\n * Parse query options from Hono context\n */\nfunction parseQueryOptions(c: Context): QueryOptions {\n\tconst limit = parseInt(c.req.query('limit') || '50', 10);\n\tconst offset = parseInt(c.req.query('offset') || '0', 10);\n\tconst search = c.req.query('search');\n\tconst before = c.req.query('before');\n\tconst after = c.req.query('after');\n\tconst tags = c.req.query('tags')?.split(',').filter(Boolean);\n\tconst method = c.req.query('method');\n\tconst status = c.req.query('status');\n\tconst level = c.req.query('level') as\n\t\t| 'debug'\n\t\t| 'info'\n\t\t| 'warn'\n\t\t| 'error'\n\t\t| undefined;\n\n\treturn {\n\t\tlimit: Math.min(limit, 100),\n\t\toffset,\n\t\tsearch,\n\t\tbefore: before ? new Date(before) : undefined,\n\t\tafter: after ? new Date(after) : undefined,\n\t\ttags,\n\t\tmethod: method || undefined,\n\t\tstatus: status || undefined,\n\t\tlevel: level || undefined,\n\t};\n}\n\n/**\n * Parse metrics query options from Hono context\n */\nfunction parseMetricsQueryOptions(c: Context): MetricsQueryOptions {\n\tconst start = c.req.query('start');\n\tconst end = c.req.query('end');\n\tconst bucketSize = c.req.query('bucketSize');\n\tconst limit = c.req.query('limit');\n\n\treturn {\n\t\trange:\n\t\t\tstart && end ? { start: new Date(start), end: new Date(end) } : undefined,\n\t\tbucketSize: bucketSize ? parseInt(bucketSize, 10) : undefined,\n\t\tlimit: limit ? parseInt(limit, 10) : undefined,\n\t};\n}\n\n/**\n * Telescope's JSON API: requests, exceptions, logs, stats and metrics under\n * `/api/*`. Headless — there is no dashboard; anything can be built on the\n * JSON, and live updates come from the WebSocket feed (`setupWebSocket`).\n *\n * @example\n * ```typescript\n * app.route('/__telescope', createApi(telescope));\n * // GET /__telescope/api/requests\n * ```\n */\nexport function createApi(telescope: Telescope): Hono {\n\tconst app = new Hono();\n\n\t// API routes\n\tapp.get('/api/requests', async (c) => {\n\t\tconst options = parseQueryOptions(c);\n\t\tconst requests = await telescope.getRequests(options);\n\t\treturn c.json(requests);\n\t});\n\n\tapp.get('/api/requests/:id', async (c) => {\n\t\tconst request = await telescope.getRequest(c.req.param('id'));\n\t\tif (!request) {\n\t\t\treturn c.json({ error: 'Request not found' }, 404);\n\t\t}\n\t\treturn c.json(request);\n\t});\n\n\tapp.get('/api/exceptions', async (c) => {\n\t\tconst options = parseQueryOptions(c);\n\t\tconst exceptions = await telescope.getExceptions(options);\n\t\treturn c.json(exceptions);\n\t});\n\n\tapp.get('/api/exceptions/:id', async (c) => {\n\t\tconst exception = await telescope.getException(c.req.param('id'));\n\t\tif (!exception) {\n\t\t\treturn c.json({ error: 'Exception not found' }, 404);\n\t\t}\n\t\treturn c.json(exception);\n\t});\n\n\tapp.get('/api/logs', async (c) => {\n\t\tconst options = parseQueryOptions(c);\n\t\tconst logs = await telescope.getLogs(options);\n\t\treturn c.json(logs);\n\t});\n\n\tapp.get('/api/stats', async (c) => {\n\t\tconst stats = await telescope.getStats();\n\t\treturn c.json(stats);\n\t});\n\n\t// Metrics API\n\tapp.get('/api/metrics', (c) => {\n\t\tconst options = parseMetricsQueryOptions(c);\n\t\tconst metrics = telescope.getMetrics(options);\n\t\treturn c.json(metrics);\n\t});\n\n\tapp.get('/api/metrics/endpoints', (c) => {\n\t\tconst options = parseMetricsQueryOptions(c);\n\t\tconst endpoints = telescope.getEndpointMetrics(options);\n\t\treturn c.json(endpoints);\n\t});\n\n\t// Endpoint details - method and path are query params to avoid URL encoding issues\n\tapp.get('/api/metrics/endpoint', (c) => {\n\t\tconst method = c.req.query('method');\n\t\tconst path = c.req.query('path');\n\n\t\tif (!method || !path) {\n\t\t\treturn c.json({ error: 'method and path are required' }, 400);\n\t\t}\n\n\t\tconst options = parseMetricsQueryOptions(c);\n\t\tconst details = telescope.getEndpointDetails(method, path, options);\n\n\t\tif (!details) {\n\t\t\treturn c.json({ error: 'Endpoint not found' }, 404);\n\t\t}\n\n\t\treturn c.json(details);\n\t});\n\n\tapp.get('/api/metrics/status', (c) => {\n\t\tconst options = parseMetricsQueryOptions(c);\n\t\tconst distribution = telescope.getStatusDistribution(options);\n\t\treturn c.json(distribution);\n\t});\n\n\tapp.delete('/api/metrics', (c) => {\n\t\ttelescope.resetMetrics();\n\t\treturn c.json({ success: true });\n\t});\n\n\treturn app;\n}\n\n/**\n * Options for setupWebSocket\n */\nexport interface WebSocketOptions {\n\t/**\n\t * Enable real-time metrics broadcasting (default: true)\n\t */\n\tbroadcastMetrics?: boolean;\n\t/**\n\t * Metrics broadcast interval in milliseconds (default: 5000)\n\t */\n\tmetricsBroadcastInterval?: number;\n}\n\n/**\n * Set up WebSocket routes for real-time updates.\n * Requires @hono/node-ws for Node.js or Bun's built-in WebSocket.\n */\nexport function setupWebSocket(\n\tapp: Hono,\n\ttelescope: Telescope,\n\tupgradeWebSocket: (handler: any) => any,\n\toptions: WebSocketOptions = {},\n): void {\n\tconst { broadcastMetrics = true, metricsBroadcastInterval = 5000 } = options;\n\n\t// Start metrics broadcast if enabled\n\tif (broadcastMetrics) {\n\t\ttelescope.startMetricsBroadcast(metricsBroadcastInterval);\n\t}\n\n\tapp.get(\n\t\t'/ws',\n\t\tupgradeWebSocket(() => ({\n\t\t\tonOpen: (_event: Event, ws: WebSocket) => {\n\t\t\t\ttelescope.addWsClient(ws);\n\t\t\t},\n\t\t\tonClose: (_event: Event, ws: WebSocket) => {\n\t\t\t\ttelescope.removeWsClient(ws);\n\t\t\t},\n\t\t\tonMessage: (event: MessageEvent, ws: WebSocket) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst data = JSON.parse(event.data);\n\t\t\t\t\tif (data.type === 'ping') {\n\t\t\t\t\t\tws.send(JSON.stringify({ type: 'pong' }));\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore invalid messages\n\t\t\t\t}\n\t\t\t},\n\t\t})),\n\t);\n}\n\n/**\n * Get the Telescope context from Hono context (set by middleware)\n */\nexport function getTelescopeContext(\n\tc: Context,\n): TelescopeHonoContext | undefined {\n\treturn c.get(CONTEXT_KEY);\n}\n\n/**\n * Get the request ID from Hono context (set by middleware)\n */\nexport function getRequestId(c: Context): string | undefined {\n\treturn getTelescopeContext(c)?.requestId;\n}\n\n// Re-export types and utilities\nexport type { Telescope };\nexport type {\n\tHonoAdapterConfig,\n\tTelescopeHonoContext,\n} from '../adapters/types';\n\n/**\n * Get the flushTelemetry function (lazy-loaded to avoid requiring @opentelemetry/* at import time).\n * Use this for serverless environments where you need to flush telemetry before the process freezes.\n *\n * @example\n * ```typescript\n * const flushTelemetry = await getFlushTelemetryFn();\n * await flushTelemetry();\n * ```\n */\nexport { getFlushTelemetry as getFlushTelemetryFn };\n"],"mappings":"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"}
1
+ {"version":3,"file":"hono.cjs","names":["_flushTelemetry: (() => Promise<void>) | null","telescope: Telescope","options: TelescopeMiddlewareOptions","c: Context","next: Next","headers: Record<string, string>","query: Record<string, string>","body: unknown","requestSize: number | undefined","responseHeaders: Record<string, string>","responseBody: unknown","responseSize: number | undefined","ctx: TelescopeHonoContext","Hono","app: Hono","upgradeWebSocket: (handler: any) => any","options: WebSocketOptions","_event: Event","ws: WebSocket","event: MessageEvent"],"sources":["../../src/server/hono.ts"],"sourcesContent":["import type { Context, MiddlewareHandler, Next } from 'hono';\nimport { Hono } from 'hono';\nimport type {\n\tHonoAdapterConfig,\n\tTelescopeHonoContext,\n} from '../adapters/types';\nimport type { Telescope } from '../Telescope';\nimport type { MetricsQueryOptions, QueryOptions } from '../types';\nimport { getAsset, getIndexHtml } from '../ui-assets';\n\n// Lazy-loaded telemetry flush function (only loads @opentelemetry/* when actually used)\nlet _flushTelemetry: (() => Promise<void>) | null = null;\nasync function getFlushTelemetry(): Promise<() => Promise<void>> {\n\tif (!_flushTelemetry) {\n\t\tconst { flushTelemetry } = await import('../instrumentation/core');\n\t\t_flushTelemetry = flushTelemetry;\n\t}\n\treturn _flushTelemetry;\n}\n\nconst CONTEXT_KEY = 'telescope-context';\n\n/** Default Hono adapter configuration */\nconst _DEFAULT_CONFIG: HonoAdapterConfig = {\n\tenvironment: 'server',\n};\n\n/**\n * Options for the Telescope Hono middleware\n */\nexport interface TelescopeMiddlewareOptions {\n\t/**\n\t * Whether to flush telemetry after each request.\n\t * Enable this for serverless environments (Lambda, Edge).\n\t * @default false\n\t */\n\tflushOnResponse?: boolean;\n}\n\n/**\n * Create Hono middleware that captures requests and responses\n */\nexport function createMiddleware(\n\ttelescope: Telescope,\n\toptions: TelescopeMiddlewareOptions = {},\n): MiddlewareHandler {\n\tconst { flushOnResponse = false } = options;\n\n\treturn async (c: Context, next: Next) => {\n\t\tif (!telescope.enabled) {\n\t\t\treturn next();\n\t\t}\n\n\t\tif (telescope.shouldIgnore(c.req.path)) {\n\t\t\treturn next();\n\t\t}\n\n\t\tconst startTime = performance.now();\n\n\t\t// Capture request data\n\t\tconst headers: Record<string, string> = {};\n\t\tc.req.raw.headers.forEach((value, key) => {\n\t\t\theaders[key] = value;\n\t\t});\n\n\t\tconst url = new URL(c.req.url);\n\t\tconst query: Record<string, string> = {};\n\t\turl.searchParams.forEach((value, key) => {\n\t\t\tquery[key] = value;\n\t\t});\n\n\t\tlet body: unknown;\n\t\tlet requestSize: number | undefined;\n\n\t\t// Get request size from Content-Length header\n\t\tconst contentLength = c.req.header('content-length');\n\t\tif (contentLength) {\n\t\t\trequestSize = parseInt(contentLength, 10);\n\t\t}\n\n\t\tif (\n\t\t\ttelescope.recordBody &&\n\t\t\t['POST', 'PUT', 'PATCH'].includes(c.req.method)\n\t\t) {\n\t\t\ttry {\n\t\t\t\tconst contentType = c.req.header('content-type') || '';\n\t\t\t\t// Clone the request to avoid consuming the body stream\n\t\t\t\tconst clonedRequest = c.req.raw.clone();\n\t\t\t\tif (contentType.includes('application/json')) {\n\t\t\t\t\tbody = await clonedRequest.json();\n\t\t\t\t} else if (contentType.includes('application/x-www-form-urlencoded')) {\n\t\t\t\t\tbody = Object.fromEntries((await clonedRequest.formData()).entries());\n\t\t\t\t} else if (contentType.includes('text/')) {\n\t\t\t\t\tbody = await clonedRequest.text();\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Ignore body parsing errors\n\t\t\t}\n\t\t}\n\n\t\tconst ip = c.req.header('x-forwarded-for') || c.req.header('x-real-ip');\n\n\t\ttry {\n\t\t\tawait next();\n\n\t\t\t// Capture response data\n\t\t\tconst duration = performance.now() - startTime;\n\n\t\t\tconst responseHeaders: Record<string, string> = {};\n\t\t\tc.res.headers.forEach((value, key) => {\n\t\t\t\tresponseHeaders[key] = value;\n\t\t\t});\n\n\t\t\tlet responseBody: unknown;\n\t\t\tlet responseSize: number | undefined;\n\n\t\t\t// Get response size - prefer Content-Length header, fallback to body size\n\t\t\tconst responseContentLength = c.res.headers.get('content-length');\n\t\t\tif (responseContentLength) {\n\t\t\t\tresponseSize = parseInt(responseContentLength, 10);\n\t\t\t}\n\n\t\t\tif (telescope.recordBody) {\n\t\t\t\ttry {\n\t\t\t\t\tconst contentType = c.res.headers.get('content-type') || '';\n\t\t\t\t\tif (contentType.includes('application/json')) {\n\t\t\t\t\t\tconst cloned = c.res.clone();\n\t\t\t\t\t\tconst text = await cloned.text();\n\t\t\t\t\t\tresponseSize ??= Buffer.byteLength(text, 'utf8');\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponseBody = JSON.parse(text);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tresponseBody = text;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore body parsing errors\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst requestId = await telescope.recordRequest({\n\t\t\t\tmethod: c.req.method,\n\t\t\t\tpath: c.req.path,\n\t\t\t\turl: c.req.url,\n\t\t\t\theaders,\n\t\t\t\tbody,\n\t\t\t\tquery,\n\t\t\t\tstatus: c.res.status,\n\t\t\t\tresponseHeaders,\n\t\t\t\tresponseBody,\n\t\t\t\tduration,\n\t\t\t\tip,\n\t\t\t\trequestSize,\n\t\t\t\tresponseSize,\n\t\t\t});\n\n\t\t\t// Store context for access by other middleware\n\t\t\tconst ctx: TelescopeHonoContext = {\n\t\t\t\trequestId,\n\t\t\t\tstartTime,\n\t\t\t};\n\t\t\tc.set(CONTEXT_KEY, ctx);\n\n\t\t\t// Flush telemetry for serverless environments\n\t\t\tif (flushOnResponse) {\n\t\t\t\tconst flushTelemetry = await getFlushTelemetry();\n\t\t\t\tawait flushTelemetry();\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait telescope.exception(error as Error);\n\t\t\tthrow error;\n\t\t}\n\t};\n}\n\n/**\n * Parse query options from Hono context\n */\nfunction parseQueryOptions(c: Context): QueryOptions {\n\tconst limit = parseInt(c.req.query('limit') || '50', 10);\n\tconst offset = parseInt(c.req.query('offset') || '0', 10);\n\tconst search = c.req.query('search');\n\tconst before = c.req.query('before');\n\tconst after = c.req.query('after');\n\tconst tags = c.req.query('tags')?.split(',').filter(Boolean);\n\tconst method = c.req.query('method');\n\tconst status = c.req.query('status');\n\tconst level = c.req.query('level') as\n\t\t| 'debug'\n\t\t| 'info'\n\t\t| 'warn'\n\t\t| 'error'\n\t\t| undefined;\n\n\treturn {\n\t\tlimit: Math.min(limit, 100),\n\t\toffset,\n\t\tsearch,\n\t\tbefore: before ? new Date(before) : undefined,\n\t\tafter: after ? new Date(after) : undefined,\n\t\ttags,\n\t\tmethod: method || undefined,\n\t\tstatus: status || undefined,\n\t\tlevel: level || undefined,\n\t};\n}\n\n/**\n * Parse metrics query options from Hono context\n */\nfunction parseMetricsQueryOptions(c: Context): MetricsQueryOptions {\n\tconst start = c.req.query('start');\n\tconst end = c.req.query('end');\n\tconst bucketSize = c.req.query('bucketSize');\n\tconst limit = c.req.query('limit');\n\n\treturn {\n\t\trange:\n\t\t\tstart && end ? { start: new Date(start), end: new Date(end) } : undefined,\n\t\tbucketSize: bucketSize ? parseInt(bucketSize, 10) : undefined,\n\t\tlimit: limit ? parseInt(limit, 10) : undefined,\n\t};\n}\n\n/**\n * Create Hono app with dashboard UI and API routes\n */\nexport function createUI(telescope: Telescope): Hono {\n\tconst app = new Hono();\n\n\t// API routes\n\tapp.get('/api/requests', async (c) => {\n\t\tconst options = parseQueryOptions(c);\n\t\tconst requests = await telescope.getRequests(options);\n\t\treturn c.json(requests);\n\t});\n\n\tapp.get('/api/requests/:id', async (c) => {\n\t\tconst request = await telescope.getRequest(c.req.param('id'));\n\t\tif (!request) {\n\t\t\treturn c.json({ error: 'Request not found' }, 404);\n\t\t}\n\t\treturn c.json(request);\n\t});\n\n\tapp.get('/api/exceptions', async (c) => {\n\t\tconst options = parseQueryOptions(c);\n\t\tconst exceptions = await telescope.getExceptions(options);\n\t\treturn c.json(exceptions);\n\t});\n\n\tapp.get('/api/exceptions/:id', async (c) => {\n\t\tconst exception = await telescope.getException(c.req.param('id'));\n\t\tif (!exception) {\n\t\t\treturn c.json({ error: 'Exception not found' }, 404);\n\t\t}\n\t\treturn c.json(exception);\n\t});\n\n\tapp.get('/api/logs', async (c) => {\n\t\tconst options = parseQueryOptions(c);\n\t\tconst logs = await telescope.getLogs(options);\n\t\treturn c.json(logs);\n\t});\n\n\tapp.get('/api/stats', async (c) => {\n\t\tconst stats = await telescope.getStats();\n\t\treturn c.json(stats);\n\t});\n\n\t// Metrics API\n\tapp.get('/api/metrics', (c) => {\n\t\tconst options = parseMetricsQueryOptions(c);\n\t\tconst metrics = telescope.getMetrics(options);\n\t\treturn c.json(metrics);\n\t});\n\n\tapp.get('/api/metrics/endpoints', (c) => {\n\t\tconst options = parseMetricsQueryOptions(c);\n\t\tconst endpoints = telescope.getEndpointMetrics(options);\n\t\treturn c.json(endpoints);\n\t});\n\n\t// Endpoint details - method and path are query params to avoid URL encoding issues\n\tapp.get('/api/metrics/endpoint', (c) => {\n\t\tconst method = c.req.query('method');\n\t\tconst path = c.req.query('path');\n\n\t\tif (!method || !path) {\n\t\t\treturn c.json({ error: 'method and path are required' }, 400);\n\t\t}\n\n\t\tconst options = parseMetricsQueryOptions(c);\n\t\tconst details = telescope.getEndpointDetails(method, path, options);\n\n\t\tif (!details) {\n\t\t\treturn c.json({ error: 'Endpoint not found' }, 404);\n\t\t}\n\n\t\treturn c.json(details);\n\t});\n\n\tapp.get('/api/metrics/status', (c) => {\n\t\tconst options = parseMetricsQueryOptions(c);\n\t\tconst distribution = telescope.getStatusDistribution(options);\n\t\treturn c.json(distribution);\n\t});\n\n\tapp.delete('/api/metrics', (c) => {\n\t\ttelescope.resetMetrics();\n\t\treturn c.json({ success: true });\n\t});\n\n\t// Static assets\n\tapp.get('/assets/:filename', (c) => {\n\t\tconst filename = c.req.param('filename');\n\t\tconst assetPath = `assets/${filename}`;\n\t\tconst asset = getAsset(assetPath);\n\t\tif (asset) {\n\t\t\treturn c.body(asset.content, 200, {\n\t\t\t\t'Content-Type': asset.contentType,\n\t\t\t\t'Cache-Control': 'public, max-age=31536000, immutable',\n\t\t\t});\n\t\t}\n\t\treturn c.notFound();\n\t});\n\n\t// Dashboard UI - serve React app\n\tapp.get('/', (c) => {\n\t\tconst html = getIndexHtml();\n\t\tif (!html) {\n\t\t\treturn c.text(\n\t\t\t\t'Telescope UI not available. Run \"pnpm build:ui\" first.',\n\t\t\t\t500,\n\t\t\t);\n\t\t}\n\t\treturn c.html(html);\n\t});\n\n\tapp.get('/*', (c) => {\n\t\t// SPA fallback - serve index.html for client-side routing\n\t\tconst html = getIndexHtml();\n\t\tif (!html) {\n\t\t\treturn c.text(\n\t\t\t\t'Telescope UI not available. Run \"pnpm build:ui\" first.',\n\t\t\t\t500,\n\t\t\t);\n\t\t}\n\t\treturn c.html(html);\n\t});\n\n\treturn app;\n}\n\n/**\n * Options for setupWebSocket\n */\nexport interface WebSocketOptions {\n\t/**\n\t * Enable real-time metrics broadcasting (default: true)\n\t */\n\tbroadcastMetrics?: boolean;\n\t/**\n\t * Metrics broadcast interval in milliseconds (default: 5000)\n\t */\n\tmetricsBroadcastInterval?: number;\n}\n\n/**\n * Set up WebSocket routes for real-time updates.\n * Requires @hono/node-ws for Node.js or Bun's built-in WebSocket.\n */\nexport function setupWebSocket(\n\tapp: Hono,\n\ttelescope: Telescope,\n\tupgradeWebSocket: (handler: any) => any,\n\toptions: WebSocketOptions = {},\n): void {\n\tconst { broadcastMetrics = true, metricsBroadcastInterval = 5000 } = options;\n\n\t// Start metrics broadcast if enabled\n\tif (broadcastMetrics) {\n\t\ttelescope.startMetricsBroadcast(metricsBroadcastInterval);\n\t}\n\n\tapp.get(\n\t\t'/ws',\n\t\tupgradeWebSocket(() => ({\n\t\t\tonOpen: (_event: Event, ws: WebSocket) => {\n\t\t\t\ttelescope.addWsClient(ws);\n\t\t\t},\n\t\t\tonClose: (_event: Event, ws: WebSocket) => {\n\t\t\t\ttelescope.removeWsClient(ws);\n\t\t\t},\n\t\t\tonMessage: (event: MessageEvent, ws: WebSocket) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst data = JSON.parse(event.data);\n\t\t\t\t\tif (data.type === 'ping') {\n\t\t\t\t\t\tws.send(JSON.stringify({ type: 'pong' }));\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore invalid messages\n\t\t\t\t}\n\t\t\t},\n\t\t})),\n\t);\n}\n\n/**\n * Get the Telescope context from Hono context (set by middleware)\n */\nexport function getTelescopeContext(\n\tc: Context,\n): TelescopeHonoContext | undefined {\n\treturn c.get(CONTEXT_KEY);\n}\n\n/**\n * Get the request ID from Hono context (set by middleware)\n */\nexport function getRequestId(c: Context): string | undefined {\n\treturn getTelescopeContext(c)?.requestId;\n}\n\n// Re-export types and utilities\nexport type { Telescope };\nexport type {\n\tHonoAdapterConfig,\n\tTelescopeHonoContext,\n} from '../adapters/types';\n\n/**\n * Get the flushTelemetry function (lazy-loaded to avoid requiring @opentelemetry/* at import time).\n * Use this for serverless environments where you need to flush telemetry before the process freezes.\n *\n * @example\n * ```typescript\n * const flushTelemetry = await getFlushTelemetryFn();\n * await flushTelemetry();\n * ```\n */\nexport { getFlushTelemetry as getFlushTelemetryFn };\n"],"mappings":"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"}
@@ -1,12 +1,15 @@
1
- import { t as Telescope } from "../Telescope-DeqSHfuB.cjs";
2
- import { HonoAdapterConfig, TelescopeHonoContext } from "../adapters/types.cjs";
1
+ import "../types-l7Rlb5Mg.cjs";
2
+ import "../MetricsAggregator-4SqelGcG.cjs";
3
+ import { Telescope } from "../Telescope-D4nmwDRA.cjs";
4
+ import { HonoAdapterConfig, TelescopeHonoContext } from "../types-BRzW1NM8.cjs";
3
5
  import { Context, Hono, MiddlewareHandler } from "hono";
6
+
4
7
  //#region src/server/hono.d.ts
5
8
  declare function getFlushTelemetry(): Promise<() => Promise<void>>;
6
9
  /**
7
10
  * Options for the Telescope Hono middleware
8
11
  */
9
- export interface TelescopeMiddlewareOptions {
12
+ interface TelescopeMiddlewareOptions {
10
13
  /**
11
14
  * Whether to flush telemetry after each request.
12
15
  * Enable this for serverless environments (Lambda, Edge).
@@ -17,23 +20,15 @@ export interface TelescopeMiddlewareOptions {
17
20
  /**
18
21
  * Create Hono middleware that captures requests and responses
19
22
  */
20
- export declare function createMiddleware(telescope: Telescope, options?: TelescopeMiddlewareOptions): MiddlewareHandler;
23
+ declare function createMiddleware(telescope: Telescope, options?: TelescopeMiddlewareOptions): MiddlewareHandler;
21
24
  /**
22
- * Telescope's JSON API: requests, exceptions, logs, stats and metrics under
23
- * `/api/*`. Headless — there is no dashboard; anything can be built on the
24
- * JSON, and live updates come from the WebSocket feed (`setupWebSocket`).
25
- *
26
- * @example
27
- * ```typescript
28
- * app.route('/__telescope', createApi(telescope));
29
- * // GET /__telescope/api/requests
30
- * ```
25
+ * Create Hono app with dashboard UI and API routes
31
26
  */
32
- export declare function createApi(telescope: Telescope): Hono;
27
+ declare function createUI(telescope: Telescope): Hono;
33
28
  /**
34
29
  * Options for setupWebSocket
35
30
  */
36
- export interface WebSocketOptions {
31
+ interface WebSocketOptions {
37
32
  /**
38
33
  * Enable real-time metrics broadcasting (default: true)
39
34
  */
@@ -47,15 +42,15 @@ export interface WebSocketOptions {
47
42
  * Set up WebSocket routes for real-time updates.
48
43
  * Requires @hono/node-ws for Node.js or Bun's built-in WebSocket.
49
44
  */
50
- export declare function setupWebSocket(app: Hono, telescope: Telescope, upgradeWebSocket: (handler: any) => any, options?: WebSocketOptions): void;
45
+ declare function setupWebSocket(app: Hono, telescope: Telescope, upgradeWebSocket: (handler: any) => any, options?: WebSocketOptions): void;
51
46
  /**
52
47
  * Get the Telescope context from Hono context (set by middleware)
53
48
  */
54
- export declare function getTelescopeContext(c: Context): TelescopeHonoContext | undefined;
49
+ declare function getTelescopeContext(c: Context): TelescopeHonoContext | undefined;
55
50
  /**
56
51
  * Get the request ID from Hono context (set by middleware)
57
52
  */
58
- export declare function getRequestId(c: Context): string | undefined;
53
+ declare function getRequestId(c: Context): string | undefined;
59
54
  //#endregion
60
- export { type HonoAdapterConfig, type Telescope, type TelescopeHonoContext, getFlushTelemetry as getFlushTelemetryFn };
55
+ export { HonoAdapterConfig, Telescope, TelescopeHonoContext, TelescopeMiddlewareOptions, WebSocketOptions, createMiddleware, createUI, getFlushTelemetry as getFlushTelemetryFn, getRequestId, getTelescopeContext, setupWebSocket };
61
56
  //# sourceMappingURL=hono.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hono.d.cts","names":[],"sources":["../../src/server/hono.ts"],"mappings":";;;;iBAWe,qBAAqB,cAAc;;;;iBAkBjC;;;;;;EAMhB;;;;;wBAMe,iBACf,WAAW,WACX,UAAS,6BACP;;;;;;;;;;;;wBA8La,UAAU,WAAW,YAAY;;;;iBA4FhC;;;;EAIhB;;;;EAIA;;;;;;wBAOe,eACf,KAAK,MACL,WAAW,WACX,mBAAmB,sBACnB,UAAS;;;;wBAmCM,oBACf,GAAG,UACD;;;;wBAOa,aAAa,GAAG"}
1
+ {"version":3,"file":"hono.d.cts","names":[],"sources":["../../src/server/hono.ts"],"sourcesContent":[],"mappings":";;;;;;;iBAYe,iBAAA,CAAA,GAAqB,cAAc;;;AANJ;AAMd,UAkBf,0BAAA,CAlBe;EAAA;;AAAW;AAkB3C;AAYA;EAAgC,eAAA,CAAA,EAAA,OAAA;;;;AAGZ;AAsLJ,iBAzLA,gBAAA,CAyLQ,SAAA,EAxLZ,SAwLY,EAAA,OAAA,CAAA,EAvLd,0BAuLc,CAAA,EAtLrB,iBAsLqB;;;;AAA4B,iBAApC,QAAA,CAAoC,SAAA,EAAhB,SAAgB,CAAA,EAAJ,IAAI;AAkIpD;AAeA;;AACM,UAhBW,gBAAA,CAgBX;EAAI;;AAGqB;EAmCf,gBAAA,CAAA,EAAA,OAAmB;EAAA;;;EAEZ,wBAAA,CAAA,EAAA,MAAA;AAOvB;;;;;iBAhDgB,cAAA,MACV,iBACM,8DAEF;;;;iBAmCM,mBAAA,IACZ,UACD;;;;iBAOa,YAAA,IAAgB"}
@@ -1,12 +1,15 @@
1
- import { t as Telescope } from "../Telescope-BVfDvVvY.mjs";
2
- import { HonoAdapterConfig, TelescopeHonoContext } from "../adapters/types.mjs";
1
+ import "../types-B1EIa_cQ.mjs";
2
+ import "../MetricsAggregator-DZrW8ls6.mjs";
3
+ import { Telescope } from "../Telescope-Dl6VSfxd.mjs";
4
+ import { HonoAdapterConfig, TelescopeHonoContext } from "../types-BzQ78Efw.mjs";
3
5
  import { Context, Hono, MiddlewareHandler } from "hono";
6
+
4
7
  //#region src/server/hono.d.ts
5
8
  declare function getFlushTelemetry(): Promise<() => Promise<void>>;
6
9
  /**
7
10
  * Options for the Telescope Hono middleware
8
11
  */
9
- export interface TelescopeMiddlewareOptions {
12
+ interface TelescopeMiddlewareOptions {
10
13
  /**
11
14
  * Whether to flush telemetry after each request.
12
15
  * Enable this for serverless environments (Lambda, Edge).
@@ -17,23 +20,15 @@ export interface TelescopeMiddlewareOptions {
17
20
  /**
18
21
  * Create Hono middleware that captures requests and responses
19
22
  */
20
- export declare function createMiddleware(telescope: Telescope, options?: TelescopeMiddlewareOptions): MiddlewareHandler;
23
+ declare function createMiddleware(telescope: Telescope, options?: TelescopeMiddlewareOptions): MiddlewareHandler;
21
24
  /**
22
- * Telescope's JSON API: requests, exceptions, logs, stats and metrics under
23
- * `/api/*`. Headless — there is no dashboard; anything can be built on the
24
- * JSON, and live updates come from the WebSocket feed (`setupWebSocket`).
25
- *
26
- * @example
27
- * ```typescript
28
- * app.route('/__telescope', createApi(telescope));
29
- * // GET /__telescope/api/requests
30
- * ```
25
+ * Create Hono app with dashboard UI and API routes
31
26
  */
32
- export declare function createApi(telescope: Telescope): Hono;
27
+ declare function createUI(telescope: Telescope): Hono;
33
28
  /**
34
29
  * Options for setupWebSocket
35
30
  */
36
- export interface WebSocketOptions {
31
+ interface WebSocketOptions {
37
32
  /**
38
33
  * Enable real-time metrics broadcasting (default: true)
39
34
  */
@@ -47,15 +42,15 @@ export interface WebSocketOptions {
47
42
  * Set up WebSocket routes for real-time updates.
48
43
  * Requires @hono/node-ws for Node.js or Bun's built-in WebSocket.
49
44
  */
50
- export declare function setupWebSocket(app: Hono, telescope: Telescope, upgradeWebSocket: (handler: any) => any, options?: WebSocketOptions): void;
45
+ declare function setupWebSocket(app: Hono, telescope: Telescope, upgradeWebSocket: (handler: any) => any, options?: WebSocketOptions): void;
51
46
  /**
52
47
  * Get the Telescope context from Hono context (set by middleware)
53
48
  */
54
- export declare function getTelescopeContext(c: Context): TelescopeHonoContext | undefined;
49
+ declare function getTelescopeContext(c: Context): TelescopeHonoContext | undefined;
55
50
  /**
56
51
  * Get the request ID from Hono context (set by middleware)
57
52
  */
58
- export declare function getRequestId(c: Context): string | undefined;
53
+ declare function getRequestId(c: Context): string | undefined;
59
54
  //#endregion
60
- export { type HonoAdapterConfig, type Telescope, type TelescopeHonoContext, getFlushTelemetry as getFlushTelemetryFn };
55
+ export { HonoAdapterConfig, Telescope, TelescopeHonoContext, TelescopeMiddlewareOptions, WebSocketOptions, createMiddleware, createUI, getFlushTelemetry as getFlushTelemetryFn, getRequestId, getTelescopeContext, setupWebSocket };
61
56
  //# sourceMappingURL=hono.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hono.d.mts","names":[],"sources":["../../src/server/hono.ts"],"mappings":";;;;iBAWe,qBAAqB,cAAc;;;;iBAkBjC;;;;;;EAMhB;;;;;wBAMe,iBACf,WAAW,WACX,UAAS,6BACP;;;;;;;;;;;;wBA8La,UAAU,WAAW,YAAY;;;;iBA4FhC;;;;EAIhB;;;;EAIA;;;;;;wBAOe,eACf,KAAK,MACL,WAAW,WACX,mBAAmB,sBACnB,UAAS;;;;wBAmCM,oBACf,GAAG,UACD;;;;wBAOa,aAAa,GAAG"}
1
+ {"version":3,"file":"hono.d.mts","names":[],"sources":["../../src/server/hono.ts"],"sourcesContent":[],"mappings":";;;;;;;iBAYe,iBAAA,CAAA,GAAqB,cAAc;;;AANJ;AAMd,UAkBf,0BAAA,CAlBe;EAAA;;AAAW;AAkB3C;AAYA;EAAgC,eAAA,CAAA,EAAA,OAAA;;;;AAGZ;AAsLJ,iBAzLA,gBAAA,CAyLQ,SAAA,EAxLZ,SAwLY,EAAA,OAAA,CAAA,EAvLd,0BAuLc,CAAA,EAtLrB,iBAsLqB;;;;AAA4B,iBAApC,QAAA,CAAoC,SAAA,EAAhB,SAAgB,CAAA,EAAJ,IAAI;AAkIpD;AAeA;;AACM,UAhBW,gBAAA,CAgBX;EAAI;;AAGqB;EAmCf,gBAAA,CAAA,EAAA,OAAmB;EAAA;;;EAEZ,wBAAA,CAAA,EAAA,MAAA;AAOvB;;;;;iBAhDgB,cAAA,MACV,iBACM,8DAEF;;;;iBAmCM,mBAAA,IACZ,UACD;;;;iBAOa,YAAA,IAAgB"}
@@ -1,4 +1,6 @@
1
+ import { getAsset, getIndexHtml } from "../ui-assets-BhTDUsrM.mjs";
1
2
  import { Hono } from "hono";
3
+
2
4
  //#region src/server/hono.ts
3
5
  let _flushTelemetry = null;
4
6
  async function getFlushTelemetry() {
@@ -55,8 +57,10 @@ function createMiddleware(telescope, options = {}) {
55
57
  const responseContentLength = c.res.headers.get("content-length");
56
58
  if (responseContentLength) responseSize = parseInt(responseContentLength, 10);
57
59
  if (telescope.recordBody) try {
58
- if ((c.res.headers.get("content-type") || "").includes("application/json")) {
59
- const text = await c.res.clone().text();
60
+ const contentType = c.res.headers.get("content-type") || "";
61
+ if (contentType.includes("application/json")) {
62
+ const cloned = c.res.clone();
63
+ const text = await cloned.text();
60
64
  responseSize ??= Buffer.byteLength(text, "utf8");
61
65
  try {
62
66
  responseBody = JSON.parse(text);
@@ -65,26 +69,30 @@ function createMiddleware(telescope, options = {}) {
65
69
  }
66
70
  }
67
71
  } catch {}
72
+ const requestId = await telescope.recordRequest({
73
+ method: c.req.method,
74
+ path: c.req.path,
75
+ url: c.req.url,
76
+ headers,
77
+ body,
78
+ query,
79
+ status: c.res.status,
80
+ responseHeaders,
81
+ responseBody,
82
+ duration,
83
+ ip,
84
+ requestSize,
85
+ responseSize
86
+ });
68
87
  const ctx = {
69
- requestId: await telescope.recordRequest({
70
- method: c.req.method,
71
- path: c.req.path,
72
- url: c.req.url,
73
- headers,
74
- body,
75
- query,
76
- status: c.res.status,
77
- responseHeaders,
78
- responseBody,
79
- duration,
80
- ip,
81
- requestSize,
82
- responseSize
83
- }),
88
+ requestId,
84
89
  startTime
85
90
  };
86
91
  c.set(CONTEXT_KEY, ctx);
87
- if (flushOnResponse) await (await getFlushTelemetry())();
92
+ if (flushOnResponse) {
93
+ const flushTelemetry = await getFlushTelemetry();
94
+ await flushTelemetry();
95
+ }
88
96
  } catch (error) {
89
97
  await telescope.exception(error);
90
98
  throw error;
@@ -134,17 +142,9 @@ function parseMetricsQueryOptions(c) {
134
142
  };
135
143
  }
136
144
  /**
137
- * Telescope's JSON API: requests, exceptions, logs, stats and metrics under
138
- * `/api/*`. Headless — there is no dashboard; anything can be built on the
139
- * JSON, and live updates come from the WebSocket feed (`setupWebSocket`).
140
- *
141
- * @example
142
- * ```typescript
143
- * app.route('/__telescope', createApi(telescope));
144
- * // GET /__telescope/api/requests
145
- * ```
145
+ * Create Hono app with dashboard UI and API routes
146
146
  */
147
- function createApi(telescope) {
147
+ function createUI(telescope) {
148
148
  const app = new Hono();
149
149
  app.get("/api/requests", async (c) => {
150
150
  const options = parseQueryOptions(c);
@@ -203,6 +203,26 @@ function createApi(telescope) {
203
203
  telescope.resetMetrics();
204
204
  return c.json({ success: true });
205
205
  });
206
+ app.get("/assets/:filename", (c) => {
207
+ const filename = c.req.param("filename");
208
+ const assetPath = `assets/${filename}`;
209
+ const asset = getAsset(assetPath);
210
+ if (asset) return c.body(asset.content, 200, {
211
+ "Content-Type": asset.contentType,
212
+ "Cache-Control": "public, max-age=31536000, immutable"
213
+ });
214
+ return c.notFound();
215
+ });
216
+ app.get("/", (c) => {
217
+ const html = getIndexHtml();
218
+ if (!html) return c.text("Telescope UI not available. Run \"pnpm build:ui\" first.", 500);
219
+ return c.html(html);
220
+ });
221
+ app.get("/*", (c) => {
222
+ const html = getIndexHtml();
223
+ if (!html) return c.text("Telescope UI not available. Run \"pnpm build:ui\" first.", 500);
224
+ return c.html(html);
225
+ });
206
226
  return app;
207
227
  }
208
228
  /**
@@ -221,7 +241,8 @@ function setupWebSocket(app, telescope, upgradeWebSocket, options = {}) {
221
241
  },
222
242
  onMessage: (event, ws) => {
223
243
  try {
224
- if (JSON.parse(event.data).type === "ping") ws.send(JSON.stringify({ type: "pong" }));
244
+ const data = JSON.parse(event.data);
245
+ if (data.type === "ping") ws.send(JSON.stringify({ type: "pong" }));
225
246
  } catch {}
226
247
  }
227
248
  })));
@@ -238,7 +259,7 @@ function getTelescopeContext(c) {
238
259
  function getRequestId(c) {
239
260
  return getTelescopeContext(c)?.requestId;
240
261
  }
241
- //#endregion
242
- export { createApi, createMiddleware, getFlushTelemetry as getFlushTelemetryFn, getRequestId, getTelescopeContext, setupWebSocket };
243
262
 
263
+ //#endregion
264
+ export { createMiddleware, createUI, getFlushTelemetry as getFlushTelemetryFn, getRequestId, getTelescopeContext, setupWebSocket };
244
265
  //# sourceMappingURL=hono.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"hono.mjs","names":[],"sources":["../../src/server/hono.ts"],"sourcesContent":["import type { Context, MiddlewareHandler, Next } from 'hono';\nimport { Hono } from 'hono';\nimport type {\n\tHonoAdapterConfig,\n\tTelescopeHonoContext,\n} from '../adapters/types';\nimport type { Telescope } from '../Telescope';\nimport type { MetricsQueryOptions, QueryOptions } from '../types';\n\n// Lazy-loaded telemetry flush function (only loads @opentelemetry/* when actually used)\nlet _flushTelemetry: (() => Promise<void>) | null = null;\nasync function getFlushTelemetry(): Promise<() => Promise<void>> {\n\tif (!_flushTelemetry) {\n\t\tconst { flushTelemetry } = await import('../instrumentation/core');\n\t\t_flushTelemetry = flushTelemetry;\n\t}\n\treturn _flushTelemetry;\n}\n\nconst CONTEXT_KEY = 'telescope-context';\n\n/** Default Hono adapter configuration */\nconst _DEFAULT_CONFIG: HonoAdapterConfig = {\n\tenvironment: 'server',\n};\n\n/**\n * Options for the Telescope Hono middleware\n */\nexport interface TelescopeMiddlewareOptions {\n\t/**\n\t * Whether to flush telemetry after each request.\n\t * Enable this for serverless environments (Lambda, Edge).\n\t * @default false\n\t */\n\tflushOnResponse?: boolean;\n}\n\n/**\n * Create Hono middleware that captures requests and responses\n */\nexport function createMiddleware(\n\ttelescope: Telescope,\n\toptions: TelescopeMiddlewareOptions = {},\n): MiddlewareHandler {\n\tconst { flushOnResponse = false } = options;\n\n\treturn async (c: Context, next: Next) => {\n\t\tif (!telescope.enabled) {\n\t\t\treturn next();\n\t\t}\n\n\t\tif (telescope.shouldIgnore(c.req.path)) {\n\t\t\treturn next();\n\t\t}\n\n\t\tconst startTime = performance.now();\n\n\t\t// Capture request data\n\t\tconst headers: Record<string, string> = {};\n\t\tc.req.raw.headers.forEach((value, key) => {\n\t\t\theaders[key] = value;\n\t\t});\n\n\t\tconst url = new URL(c.req.url);\n\t\tconst query: Record<string, string> = {};\n\t\turl.searchParams.forEach((value, key) => {\n\t\t\tquery[key] = value;\n\t\t});\n\n\t\tlet body: unknown;\n\t\tlet requestSize: number | undefined;\n\n\t\t// Get request size from Content-Length header\n\t\tconst contentLength = c.req.header('content-length');\n\t\tif (contentLength) {\n\t\t\trequestSize = parseInt(contentLength, 10);\n\t\t}\n\n\t\tif (\n\t\t\ttelescope.recordBody &&\n\t\t\t['POST', 'PUT', 'PATCH'].includes(c.req.method)\n\t\t) {\n\t\t\ttry {\n\t\t\t\tconst contentType = c.req.header('content-type') || '';\n\t\t\t\t// Clone the request to avoid consuming the body stream\n\t\t\t\tconst clonedRequest = c.req.raw.clone();\n\t\t\t\tif (contentType.includes('application/json')) {\n\t\t\t\t\tbody = await clonedRequest.json();\n\t\t\t\t} else if (contentType.includes('application/x-www-form-urlencoded')) {\n\t\t\t\t\tbody = Object.fromEntries((await clonedRequest.formData()).entries());\n\t\t\t\t} else if (contentType.includes('text/')) {\n\t\t\t\t\tbody = await clonedRequest.text();\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Ignore body parsing errors\n\t\t\t}\n\t\t}\n\n\t\tconst ip = c.req.header('x-forwarded-for') || c.req.header('x-real-ip');\n\n\t\ttry {\n\t\t\tawait next();\n\n\t\t\t// Capture response data\n\t\t\tconst duration = performance.now() - startTime;\n\n\t\t\tconst responseHeaders: Record<string, string> = {};\n\t\t\tc.res.headers.forEach((value, key) => {\n\t\t\t\tresponseHeaders[key] = value;\n\t\t\t});\n\n\t\t\tlet responseBody: unknown;\n\t\t\tlet responseSize: number | undefined;\n\n\t\t\t// Get response size - prefer Content-Length header, fallback to body size\n\t\t\tconst responseContentLength = c.res.headers.get('content-length');\n\t\t\tif (responseContentLength) {\n\t\t\t\tresponseSize = parseInt(responseContentLength, 10);\n\t\t\t}\n\n\t\t\tif (telescope.recordBody) {\n\t\t\t\ttry {\n\t\t\t\t\tconst contentType = c.res.headers.get('content-type') || '';\n\t\t\t\t\tif (contentType.includes('application/json')) {\n\t\t\t\t\t\tconst cloned = c.res.clone();\n\t\t\t\t\t\tconst text = await cloned.text();\n\t\t\t\t\t\tresponseSize ??= Buffer.byteLength(text, 'utf8');\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponseBody = JSON.parse(text);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tresponseBody = text;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore body parsing errors\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst requestId = await telescope.recordRequest({\n\t\t\t\tmethod: c.req.method,\n\t\t\t\tpath: c.req.path,\n\t\t\t\turl: c.req.url,\n\t\t\t\theaders,\n\t\t\t\tbody,\n\t\t\t\tquery,\n\t\t\t\tstatus: c.res.status,\n\t\t\t\tresponseHeaders,\n\t\t\t\tresponseBody,\n\t\t\t\tduration,\n\t\t\t\tip,\n\t\t\t\trequestSize,\n\t\t\t\tresponseSize,\n\t\t\t});\n\n\t\t\t// Store context for access by other middleware\n\t\t\tconst ctx: TelescopeHonoContext = {\n\t\t\t\trequestId,\n\t\t\t\tstartTime,\n\t\t\t};\n\t\t\tc.set(CONTEXT_KEY, ctx);\n\n\t\t\t// Flush telemetry for serverless environments\n\t\t\tif (flushOnResponse) {\n\t\t\t\tconst flushTelemetry = await getFlushTelemetry();\n\t\t\t\tawait flushTelemetry();\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait telescope.exception(error as Error);\n\t\t\tthrow error;\n\t\t}\n\t};\n}\n\n/**\n * Parse query options from Hono context\n */\nfunction parseQueryOptions(c: Context): QueryOptions {\n\tconst limit = parseInt(c.req.query('limit') || '50', 10);\n\tconst offset = parseInt(c.req.query('offset') || '0', 10);\n\tconst search = c.req.query('search');\n\tconst before = c.req.query('before');\n\tconst after = c.req.query('after');\n\tconst tags = c.req.query('tags')?.split(',').filter(Boolean);\n\tconst method = c.req.query('method');\n\tconst status = c.req.query('status');\n\tconst level = c.req.query('level') as\n\t\t| 'debug'\n\t\t| 'info'\n\t\t| 'warn'\n\t\t| 'error'\n\t\t| undefined;\n\n\treturn {\n\t\tlimit: Math.min(limit, 100),\n\t\toffset,\n\t\tsearch,\n\t\tbefore: before ? new Date(before) : undefined,\n\t\tafter: after ? new Date(after) : undefined,\n\t\ttags,\n\t\tmethod: method || undefined,\n\t\tstatus: status || undefined,\n\t\tlevel: level || undefined,\n\t};\n}\n\n/**\n * Parse metrics query options from Hono context\n */\nfunction parseMetricsQueryOptions(c: Context): MetricsQueryOptions {\n\tconst start = c.req.query('start');\n\tconst end = c.req.query('end');\n\tconst bucketSize = c.req.query('bucketSize');\n\tconst limit = c.req.query('limit');\n\n\treturn {\n\t\trange:\n\t\t\tstart && end ? { start: new Date(start), end: new Date(end) } : undefined,\n\t\tbucketSize: bucketSize ? parseInt(bucketSize, 10) : undefined,\n\t\tlimit: limit ? parseInt(limit, 10) : undefined,\n\t};\n}\n\n/**\n * Telescope's JSON API: requests, exceptions, logs, stats and metrics under\n * `/api/*`. Headless — there is no dashboard; anything can be built on the\n * JSON, and live updates come from the WebSocket feed (`setupWebSocket`).\n *\n * @example\n * ```typescript\n * app.route('/__telescope', createApi(telescope));\n * // GET /__telescope/api/requests\n * ```\n */\nexport function createApi(telescope: Telescope): Hono {\n\tconst app = new Hono();\n\n\t// API routes\n\tapp.get('/api/requests', async (c) => {\n\t\tconst options = parseQueryOptions(c);\n\t\tconst requests = await telescope.getRequests(options);\n\t\treturn c.json(requests);\n\t});\n\n\tapp.get('/api/requests/:id', async (c) => {\n\t\tconst request = await telescope.getRequest(c.req.param('id'));\n\t\tif (!request) {\n\t\t\treturn c.json({ error: 'Request not found' }, 404);\n\t\t}\n\t\treturn c.json(request);\n\t});\n\n\tapp.get('/api/exceptions', async (c) => {\n\t\tconst options = parseQueryOptions(c);\n\t\tconst exceptions = await telescope.getExceptions(options);\n\t\treturn c.json(exceptions);\n\t});\n\n\tapp.get('/api/exceptions/:id', async (c) => {\n\t\tconst exception = await telescope.getException(c.req.param('id'));\n\t\tif (!exception) {\n\t\t\treturn c.json({ error: 'Exception not found' }, 404);\n\t\t}\n\t\treturn c.json(exception);\n\t});\n\n\tapp.get('/api/logs', async (c) => {\n\t\tconst options = parseQueryOptions(c);\n\t\tconst logs = await telescope.getLogs(options);\n\t\treturn c.json(logs);\n\t});\n\n\tapp.get('/api/stats', async (c) => {\n\t\tconst stats = await telescope.getStats();\n\t\treturn c.json(stats);\n\t});\n\n\t// Metrics API\n\tapp.get('/api/metrics', (c) => {\n\t\tconst options = parseMetricsQueryOptions(c);\n\t\tconst metrics = telescope.getMetrics(options);\n\t\treturn c.json(metrics);\n\t});\n\n\tapp.get('/api/metrics/endpoints', (c) => {\n\t\tconst options = parseMetricsQueryOptions(c);\n\t\tconst endpoints = telescope.getEndpointMetrics(options);\n\t\treturn c.json(endpoints);\n\t});\n\n\t// Endpoint details - method and path are query params to avoid URL encoding issues\n\tapp.get('/api/metrics/endpoint', (c) => {\n\t\tconst method = c.req.query('method');\n\t\tconst path = c.req.query('path');\n\n\t\tif (!method || !path) {\n\t\t\treturn c.json({ error: 'method and path are required' }, 400);\n\t\t}\n\n\t\tconst options = parseMetricsQueryOptions(c);\n\t\tconst details = telescope.getEndpointDetails(method, path, options);\n\n\t\tif (!details) {\n\t\t\treturn c.json({ error: 'Endpoint not found' }, 404);\n\t\t}\n\n\t\treturn c.json(details);\n\t});\n\n\tapp.get('/api/metrics/status', (c) => {\n\t\tconst options = parseMetricsQueryOptions(c);\n\t\tconst distribution = telescope.getStatusDistribution(options);\n\t\treturn c.json(distribution);\n\t});\n\n\tapp.delete('/api/metrics', (c) => {\n\t\ttelescope.resetMetrics();\n\t\treturn c.json({ success: true });\n\t});\n\n\treturn app;\n}\n\n/**\n * Options for setupWebSocket\n */\nexport interface WebSocketOptions {\n\t/**\n\t * Enable real-time metrics broadcasting (default: true)\n\t */\n\tbroadcastMetrics?: boolean;\n\t/**\n\t * Metrics broadcast interval in milliseconds (default: 5000)\n\t */\n\tmetricsBroadcastInterval?: number;\n}\n\n/**\n * Set up WebSocket routes for real-time updates.\n * Requires @hono/node-ws for Node.js or Bun's built-in WebSocket.\n */\nexport function setupWebSocket(\n\tapp: Hono,\n\ttelescope: Telescope,\n\tupgradeWebSocket: (handler: any) => any,\n\toptions: WebSocketOptions = {},\n): void {\n\tconst { broadcastMetrics = true, metricsBroadcastInterval = 5000 } = options;\n\n\t// Start metrics broadcast if enabled\n\tif (broadcastMetrics) {\n\t\ttelescope.startMetricsBroadcast(metricsBroadcastInterval);\n\t}\n\n\tapp.get(\n\t\t'/ws',\n\t\tupgradeWebSocket(() => ({\n\t\t\tonOpen: (_event: Event, ws: WebSocket) => {\n\t\t\t\ttelescope.addWsClient(ws);\n\t\t\t},\n\t\t\tonClose: (_event: Event, ws: WebSocket) => {\n\t\t\t\ttelescope.removeWsClient(ws);\n\t\t\t},\n\t\t\tonMessage: (event: MessageEvent, ws: WebSocket) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst data = JSON.parse(event.data);\n\t\t\t\t\tif (data.type === 'ping') {\n\t\t\t\t\t\tws.send(JSON.stringify({ type: 'pong' }));\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore invalid messages\n\t\t\t\t}\n\t\t\t},\n\t\t})),\n\t);\n}\n\n/**\n * Get the Telescope context from Hono context (set by middleware)\n */\nexport function getTelescopeContext(\n\tc: Context,\n): TelescopeHonoContext | undefined {\n\treturn c.get(CONTEXT_KEY);\n}\n\n/**\n * Get the request ID from Hono context (set by middleware)\n */\nexport function getRequestId(c: Context): string | undefined {\n\treturn getTelescopeContext(c)?.requestId;\n}\n\n// Re-export types and utilities\nexport type { Telescope };\nexport type {\n\tHonoAdapterConfig,\n\tTelescopeHonoContext,\n} from '../adapters/types';\n\n/**\n * Get the flushTelemetry function (lazy-loaded to avoid requiring @opentelemetry/* at import time).\n * Use this for serverless environments where you need to flush telemetry before the process freezes.\n *\n * @example\n * ```typescript\n * const flushTelemetry = await getFlushTelemetryFn();\n * await flushTelemetry();\n * ```\n */\nexport { getFlushTelemetry as getFlushTelemetryFn };\n"],"mappings":"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"}
1
+ {"version":3,"file":"hono.mjs","names":["_flushTelemetry: (() => Promise<void>) | null","telescope: Telescope","options: TelescopeMiddlewareOptions","c: Context","next: Next","headers: Record<string, string>","query: Record<string, string>","body: unknown","requestSize: number | undefined","responseHeaders: Record<string, string>","responseBody: unknown","responseSize: number | undefined","ctx: TelescopeHonoContext","app: Hono","upgradeWebSocket: (handler: any) => any","options: WebSocketOptions","_event: Event","ws: WebSocket","event: MessageEvent"],"sources":["../../src/server/hono.ts"],"sourcesContent":["import type { Context, MiddlewareHandler, Next } from 'hono';\nimport { Hono } from 'hono';\nimport type {\n\tHonoAdapterConfig,\n\tTelescopeHonoContext,\n} from '../adapters/types';\nimport type { Telescope } from '../Telescope';\nimport type { MetricsQueryOptions, QueryOptions } from '../types';\nimport { getAsset, getIndexHtml } from '../ui-assets';\n\n// Lazy-loaded telemetry flush function (only loads @opentelemetry/* when actually used)\nlet _flushTelemetry: (() => Promise<void>) | null = null;\nasync function getFlushTelemetry(): Promise<() => Promise<void>> {\n\tif (!_flushTelemetry) {\n\t\tconst { flushTelemetry } = await import('../instrumentation/core');\n\t\t_flushTelemetry = flushTelemetry;\n\t}\n\treturn _flushTelemetry;\n}\n\nconst CONTEXT_KEY = 'telescope-context';\n\n/** Default Hono adapter configuration */\nconst _DEFAULT_CONFIG: HonoAdapterConfig = {\n\tenvironment: 'server',\n};\n\n/**\n * Options for the Telescope Hono middleware\n */\nexport interface TelescopeMiddlewareOptions {\n\t/**\n\t * Whether to flush telemetry after each request.\n\t * Enable this for serverless environments (Lambda, Edge).\n\t * @default false\n\t */\n\tflushOnResponse?: boolean;\n}\n\n/**\n * Create Hono middleware that captures requests and responses\n */\nexport function createMiddleware(\n\ttelescope: Telescope,\n\toptions: TelescopeMiddlewareOptions = {},\n): MiddlewareHandler {\n\tconst { flushOnResponse = false } = options;\n\n\treturn async (c: Context, next: Next) => {\n\t\tif (!telescope.enabled) {\n\t\t\treturn next();\n\t\t}\n\n\t\tif (telescope.shouldIgnore(c.req.path)) {\n\t\t\treturn next();\n\t\t}\n\n\t\tconst startTime = performance.now();\n\n\t\t// Capture request data\n\t\tconst headers: Record<string, string> = {};\n\t\tc.req.raw.headers.forEach((value, key) => {\n\t\t\theaders[key] = value;\n\t\t});\n\n\t\tconst url = new URL(c.req.url);\n\t\tconst query: Record<string, string> = {};\n\t\turl.searchParams.forEach((value, key) => {\n\t\t\tquery[key] = value;\n\t\t});\n\n\t\tlet body: unknown;\n\t\tlet requestSize: number | undefined;\n\n\t\t// Get request size from Content-Length header\n\t\tconst contentLength = c.req.header('content-length');\n\t\tif (contentLength) {\n\t\t\trequestSize = parseInt(contentLength, 10);\n\t\t}\n\n\t\tif (\n\t\t\ttelescope.recordBody &&\n\t\t\t['POST', 'PUT', 'PATCH'].includes(c.req.method)\n\t\t) {\n\t\t\ttry {\n\t\t\t\tconst contentType = c.req.header('content-type') || '';\n\t\t\t\t// Clone the request to avoid consuming the body stream\n\t\t\t\tconst clonedRequest = c.req.raw.clone();\n\t\t\t\tif (contentType.includes('application/json')) {\n\t\t\t\t\tbody = await clonedRequest.json();\n\t\t\t\t} else if (contentType.includes('application/x-www-form-urlencoded')) {\n\t\t\t\t\tbody = Object.fromEntries((await clonedRequest.formData()).entries());\n\t\t\t\t} else if (contentType.includes('text/')) {\n\t\t\t\t\tbody = await clonedRequest.text();\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Ignore body parsing errors\n\t\t\t}\n\t\t}\n\n\t\tconst ip = c.req.header('x-forwarded-for') || c.req.header('x-real-ip');\n\n\t\ttry {\n\t\t\tawait next();\n\n\t\t\t// Capture response data\n\t\t\tconst duration = performance.now() - startTime;\n\n\t\t\tconst responseHeaders: Record<string, string> = {};\n\t\t\tc.res.headers.forEach((value, key) => {\n\t\t\t\tresponseHeaders[key] = value;\n\t\t\t});\n\n\t\t\tlet responseBody: unknown;\n\t\t\tlet responseSize: number | undefined;\n\n\t\t\t// Get response size - prefer Content-Length header, fallback to body size\n\t\t\tconst responseContentLength = c.res.headers.get('content-length');\n\t\t\tif (responseContentLength) {\n\t\t\t\tresponseSize = parseInt(responseContentLength, 10);\n\t\t\t}\n\n\t\t\tif (telescope.recordBody) {\n\t\t\t\ttry {\n\t\t\t\t\tconst contentType = c.res.headers.get('content-type') || '';\n\t\t\t\t\tif (contentType.includes('application/json')) {\n\t\t\t\t\t\tconst cloned = c.res.clone();\n\t\t\t\t\t\tconst text = await cloned.text();\n\t\t\t\t\t\tresponseSize ??= Buffer.byteLength(text, 'utf8');\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponseBody = JSON.parse(text);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tresponseBody = text;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore body parsing errors\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst requestId = await telescope.recordRequest({\n\t\t\t\tmethod: c.req.method,\n\t\t\t\tpath: c.req.path,\n\t\t\t\turl: c.req.url,\n\t\t\t\theaders,\n\t\t\t\tbody,\n\t\t\t\tquery,\n\t\t\t\tstatus: c.res.status,\n\t\t\t\tresponseHeaders,\n\t\t\t\tresponseBody,\n\t\t\t\tduration,\n\t\t\t\tip,\n\t\t\t\trequestSize,\n\t\t\t\tresponseSize,\n\t\t\t});\n\n\t\t\t// Store context for access by other middleware\n\t\t\tconst ctx: TelescopeHonoContext = {\n\t\t\t\trequestId,\n\t\t\t\tstartTime,\n\t\t\t};\n\t\t\tc.set(CONTEXT_KEY, ctx);\n\n\t\t\t// Flush telemetry for serverless environments\n\t\t\tif (flushOnResponse) {\n\t\t\t\tconst flushTelemetry = await getFlushTelemetry();\n\t\t\t\tawait flushTelemetry();\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait telescope.exception(error as Error);\n\t\t\tthrow error;\n\t\t}\n\t};\n}\n\n/**\n * Parse query options from Hono context\n */\nfunction parseQueryOptions(c: Context): QueryOptions {\n\tconst limit = parseInt(c.req.query('limit') || '50', 10);\n\tconst offset = parseInt(c.req.query('offset') || '0', 10);\n\tconst search = c.req.query('search');\n\tconst before = c.req.query('before');\n\tconst after = c.req.query('after');\n\tconst tags = c.req.query('tags')?.split(',').filter(Boolean);\n\tconst method = c.req.query('method');\n\tconst status = c.req.query('status');\n\tconst level = c.req.query('level') as\n\t\t| 'debug'\n\t\t| 'info'\n\t\t| 'warn'\n\t\t| 'error'\n\t\t| undefined;\n\n\treturn {\n\t\tlimit: Math.min(limit, 100),\n\t\toffset,\n\t\tsearch,\n\t\tbefore: before ? new Date(before) : undefined,\n\t\tafter: after ? new Date(after) : undefined,\n\t\ttags,\n\t\tmethod: method || undefined,\n\t\tstatus: status || undefined,\n\t\tlevel: level || undefined,\n\t};\n}\n\n/**\n * Parse metrics query options from Hono context\n */\nfunction parseMetricsQueryOptions(c: Context): MetricsQueryOptions {\n\tconst start = c.req.query('start');\n\tconst end = c.req.query('end');\n\tconst bucketSize = c.req.query('bucketSize');\n\tconst limit = c.req.query('limit');\n\n\treturn {\n\t\trange:\n\t\t\tstart && end ? { start: new Date(start), end: new Date(end) } : undefined,\n\t\tbucketSize: bucketSize ? parseInt(bucketSize, 10) : undefined,\n\t\tlimit: limit ? parseInt(limit, 10) : undefined,\n\t};\n}\n\n/**\n * Create Hono app with dashboard UI and API routes\n */\nexport function createUI(telescope: Telescope): Hono {\n\tconst app = new Hono();\n\n\t// API routes\n\tapp.get('/api/requests', async (c) => {\n\t\tconst options = parseQueryOptions(c);\n\t\tconst requests = await telescope.getRequests(options);\n\t\treturn c.json(requests);\n\t});\n\n\tapp.get('/api/requests/:id', async (c) => {\n\t\tconst request = await telescope.getRequest(c.req.param('id'));\n\t\tif (!request) {\n\t\t\treturn c.json({ error: 'Request not found' }, 404);\n\t\t}\n\t\treturn c.json(request);\n\t});\n\n\tapp.get('/api/exceptions', async (c) => {\n\t\tconst options = parseQueryOptions(c);\n\t\tconst exceptions = await telescope.getExceptions(options);\n\t\treturn c.json(exceptions);\n\t});\n\n\tapp.get('/api/exceptions/:id', async (c) => {\n\t\tconst exception = await telescope.getException(c.req.param('id'));\n\t\tif (!exception) {\n\t\t\treturn c.json({ error: 'Exception not found' }, 404);\n\t\t}\n\t\treturn c.json(exception);\n\t});\n\n\tapp.get('/api/logs', async (c) => {\n\t\tconst options = parseQueryOptions(c);\n\t\tconst logs = await telescope.getLogs(options);\n\t\treturn c.json(logs);\n\t});\n\n\tapp.get('/api/stats', async (c) => {\n\t\tconst stats = await telescope.getStats();\n\t\treturn c.json(stats);\n\t});\n\n\t// Metrics API\n\tapp.get('/api/metrics', (c) => {\n\t\tconst options = parseMetricsQueryOptions(c);\n\t\tconst metrics = telescope.getMetrics(options);\n\t\treturn c.json(metrics);\n\t});\n\n\tapp.get('/api/metrics/endpoints', (c) => {\n\t\tconst options = parseMetricsQueryOptions(c);\n\t\tconst endpoints = telescope.getEndpointMetrics(options);\n\t\treturn c.json(endpoints);\n\t});\n\n\t// Endpoint details - method and path are query params to avoid URL encoding issues\n\tapp.get('/api/metrics/endpoint', (c) => {\n\t\tconst method = c.req.query('method');\n\t\tconst path = c.req.query('path');\n\n\t\tif (!method || !path) {\n\t\t\treturn c.json({ error: 'method and path are required' }, 400);\n\t\t}\n\n\t\tconst options = parseMetricsQueryOptions(c);\n\t\tconst details = telescope.getEndpointDetails(method, path, options);\n\n\t\tif (!details) {\n\t\t\treturn c.json({ error: 'Endpoint not found' }, 404);\n\t\t}\n\n\t\treturn c.json(details);\n\t});\n\n\tapp.get('/api/metrics/status', (c) => {\n\t\tconst options = parseMetricsQueryOptions(c);\n\t\tconst distribution = telescope.getStatusDistribution(options);\n\t\treturn c.json(distribution);\n\t});\n\n\tapp.delete('/api/metrics', (c) => {\n\t\ttelescope.resetMetrics();\n\t\treturn c.json({ success: true });\n\t});\n\n\t// Static assets\n\tapp.get('/assets/:filename', (c) => {\n\t\tconst filename = c.req.param('filename');\n\t\tconst assetPath = `assets/${filename}`;\n\t\tconst asset = getAsset(assetPath);\n\t\tif (asset) {\n\t\t\treturn c.body(asset.content, 200, {\n\t\t\t\t'Content-Type': asset.contentType,\n\t\t\t\t'Cache-Control': 'public, max-age=31536000, immutable',\n\t\t\t});\n\t\t}\n\t\treturn c.notFound();\n\t});\n\n\t// Dashboard UI - serve React app\n\tapp.get('/', (c) => {\n\t\tconst html = getIndexHtml();\n\t\tif (!html) {\n\t\t\treturn c.text(\n\t\t\t\t'Telescope UI not available. Run \"pnpm build:ui\" first.',\n\t\t\t\t500,\n\t\t\t);\n\t\t}\n\t\treturn c.html(html);\n\t});\n\n\tapp.get('/*', (c) => {\n\t\t// SPA fallback - serve index.html for client-side routing\n\t\tconst html = getIndexHtml();\n\t\tif (!html) {\n\t\t\treturn c.text(\n\t\t\t\t'Telescope UI not available. Run \"pnpm build:ui\" first.',\n\t\t\t\t500,\n\t\t\t);\n\t\t}\n\t\treturn c.html(html);\n\t});\n\n\treturn app;\n}\n\n/**\n * Options for setupWebSocket\n */\nexport interface WebSocketOptions {\n\t/**\n\t * Enable real-time metrics broadcasting (default: true)\n\t */\n\tbroadcastMetrics?: boolean;\n\t/**\n\t * Metrics broadcast interval in milliseconds (default: 5000)\n\t */\n\tmetricsBroadcastInterval?: number;\n}\n\n/**\n * Set up WebSocket routes for real-time updates.\n * Requires @hono/node-ws for Node.js or Bun's built-in WebSocket.\n */\nexport function setupWebSocket(\n\tapp: Hono,\n\ttelescope: Telescope,\n\tupgradeWebSocket: (handler: any) => any,\n\toptions: WebSocketOptions = {},\n): void {\n\tconst { broadcastMetrics = true, metricsBroadcastInterval = 5000 } = options;\n\n\t// Start metrics broadcast if enabled\n\tif (broadcastMetrics) {\n\t\ttelescope.startMetricsBroadcast(metricsBroadcastInterval);\n\t}\n\n\tapp.get(\n\t\t'/ws',\n\t\tupgradeWebSocket(() => ({\n\t\t\tonOpen: (_event: Event, ws: WebSocket) => {\n\t\t\t\ttelescope.addWsClient(ws);\n\t\t\t},\n\t\t\tonClose: (_event: Event, ws: WebSocket) => {\n\t\t\t\ttelescope.removeWsClient(ws);\n\t\t\t},\n\t\t\tonMessage: (event: MessageEvent, ws: WebSocket) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst data = JSON.parse(event.data);\n\t\t\t\t\tif (data.type === 'ping') {\n\t\t\t\t\t\tws.send(JSON.stringify({ type: 'pong' }));\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore invalid messages\n\t\t\t\t}\n\t\t\t},\n\t\t})),\n\t);\n}\n\n/**\n * Get the Telescope context from Hono context (set by middleware)\n */\nexport function getTelescopeContext(\n\tc: Context,\n): TelescopeHonoContext | undefined {\n\treturn c.get(CONTEXT_KEY);\n}\n\n/**\n * Get the request ID from Hono context (set by middleware)\n */\nexport function getRequestId(c: Context): string | undefined {\n\treturn getTelescopeContext(c)?.requestId;\n}\n\n// Re-export types and utilities\nexport type { Telescope };\nexport type {\n\tHonoAdapterConfig,\n\tTelescopeHonoContext,\n} from '../adapters/types';\n\n/**\n * Get the flushTelemetry function (lazy-loaded to avoid requiring @opentelemetry/* at import time).\n * Use this for serverless environments where you need to flush telemetry before the process freezes.\n *\n * @example\n * ```typescript\n * const flushTelemetry = await getFlushTelemetryFn();\n * await flushTelemetry();\n * ```\n */\nexport { getFlushTelemetry as getFlushTelemetryFn };\n"],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ import { createSpanProcessor, getRecommendedStrategy, setGlobalLogProcessor, setGlobalSpanProcessor } from "./core-D6hJ6exL.mjs";
2
+ import { DiagConsoleLogger, DiagLogLevel, diag } from "@opentelemetry/api";
3
+ import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
4
+ import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
5
+ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
6
+ import { PinoInstrumentation } from "@opentelemetry/instrumentation-pino";
7
+ import { Resource } from "@opentelemetry/resources";
8
+ import { BatchLogRecordProcessor, LoggerProvider } from "@opentelemetry/sdk-logs";
9
+ import { NodeSDK } from "@opentelemetry/sdk-node";
10
+ import { ConsoleSpanExporter } from "@opentelemetry/sdk-trace-node";
11
+ import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from "@opentelemetry/semantic-conventions";
12
+
13
+ //#region src/instrumentation/setup.ts
14
+ let sdk = null;
15
+ /**
16
+ * Set up OpenTelemetry instrumentation.
17
+ * Call this BEFORE importing your application code.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * // instrumentation.ts (create this file)
22
+ * import { setupTelemetry } from '@geekmidas/telescope/instrumentation';
23
+ *
24
+ * setupTelemetry({
25
+ * serviceName: 'my-api',
26
+ * endpoint: 'http://localhost:3000/__telescope/v1',
27
+ * });
28
+ *
29
+ * // Then in your entry point:
30
+ * // import './instrumentation';
31
+ * // import { app } from './app';
32
+ * ```
33
+ */
34
+ function setupTelemetry(options) {
35
+ if (sdk) return;
36
+ const { serviceName, serviceVersion = "1.0.0", endpoint, instrumentPino = true, autoInstrument = true, debug = false, resourceAttributes = {}, headers = {}, spanProcessorStrategy, environment = "server" } = options;
37
+ if (debug) diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG);
38
+ const resource = new Resource({
39
+ [ATTR_SERVICE_NAME]: serviceName,
40
+ [ATTR_SERVICE_VERSION]: serviceVersion,
41
+ ...resourceAttributes
42
+ });
43
+ const instrumentations = [];
44
+ if (instrumentPino) instrumentations.push(new PinoInstrumentation({ logHook: (span, record) => {
45
+ record.trace_id = span.spanContext().traceId;
46
+ record.span_id = span.spanContext().spanId;
47
+ record.trace_flags = span.spanContext().traceFlags;
48
+ } }));
49
+ if (autoInstrument) instrumentations.push(getNodeAutoInstrumentations({
50
+ "@opentelemetry/instrumentation-fs": { enabled: false },
51
+ "@opentelemetry/instrumentation-http": { ignoreIncomingRequestHook: (request) => {
52
+ const path = request.url || "";
53
+ return path.includes("/__health") || path.includes("/__telescope") || path.includes("/favicon");
54
+ } }
55
+ }));
56
+ let traceExporter;
57
+ if (endpoint) traceExporter = new OTLPTraceExporter({
58
+ url: `${endpoint}/traces`,
59
+ headers
60
+ });
61
+ else traceExporter = new ConsoleSpanExporter();
62
+ const strategy = spanProcessorStrategy ?? getRecommendedStrategy(environment);
63
+ const spanProcessor = createSpanProcessor(traceExporter, { strategy });
64
+ setGlobalSpanProcessor(spanProcessor);
65
+ sdk = new NodeSDK({
66
+ resource,
67
+ traceExporter,
68
+ spanProcessors: [spanProcessor],
69
+ instrumentations
70
+ });
71
+ if (endpoint) {
72
+ const logExporter = new OTLPLogExporter({
73
+ url: `${endpoint}/logs`,
74
+ headers
75
+ });
76
+ const loggerProvider = new LoggerProvider({ resource });
77
+ const logProcessor = new BatchLogRecordProcessor(logExporter);
78
+ loggerProvider.addLogRecordProcessor(logProcessor);
79
+ setGlobalLogProcessor(logProcessor);
80
+ }
81
+ sdk.start();
82
+ process.on("SIGTERM", () => {
83
+ sdk?.shutdown().then(() => {}).catch((_error) => {}).finally(() => process.exit(0));
84
+ });
85
+ }
86
+ /**
87
+ * Shut down telemetry (for testing or graceful shutdown)
88
+ */
89
+ async function shutdownTelemetry() {
90
+ if (sdk) {
91
+ await sdk.shutdown();
92
+ sdk = null;
93
+ }
94
+ }
95
+
96
+ //#endregion
97
+ export { setupTelemetry, shutdownTelemetry };
98
+ //# sourceMappingURL=setup-B9jM77Qk.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-B9jM77Qk.mjs","names":["sdk: NodeSDK | null","options: TelemetryOptions","traceExporter: SpanExporter"],"sources":["../src/instrumentation/setup.ts"],"sourcesContent":["import { DiagConsoleLogger, DiagLogLevel, diag } from '@opentelemetry/api';\nimport { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';\nimport { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\nimport { PinoInstrumentation } from '@opentelemetry/instrumentation-pino';\nimport { Resource } from '@opentelemetry/resources';\nimport {\n\tBatchLogRecordProcessor,\n\tLoggerProvider,\n} from '@opentelemetry/sdk-logs';\nimport { NodeSDK } from '@opentelemetry/sdk-node';\nimport {\n\tConsoleSpanExporter,\n\ttype SpanExporter,\n} from '@opentelemetry/sdk-trace-node';\nimport {\n\tATTR_SERVICE_NAME,\n\tATTR_SERVICE_VERSION,\n} from '@opentelemetry/semantic-conventions';\nimport type { SpanProcessorStrategy } from '../adapters/types';\nimport {\n\tcreateSpanProcessor,\n\tgetRecommendedStrategy,\n\tsetGlobalLogProcessor,\n\tsetGlobalSpanProcessor,\n} from './core';\n\n/**\n * Options for configuring telemetry\n */\nexport interface TelemetryOptions {\n\t/**\n\t * Service name for resource identification\n\t */\n\tserviceName: string;\n\n\t/**\n\t * Service version\n\t */\n\tserviceVersion?: string;\n\n\t/**\n\t * OTLP endpoint URL (e.g., 'http://localhost:3000/__telescope/v1')\n\t * If not provided, traces will be logged to console\n\t */\n\tendpoint?: string;\n\n\t/**\n\t * Whether to instrument Pino for log correlation\n\t * @default true\n\t */\n\tinstrumentPino?: boolean;\n\n\t/**\n\t * Whether to enable auto-instrumentation for common libraries\n\t * (http, fetch, express, etc.)\n\t * @default true\n\t */\n\tautoInstrument?: boolean;\n\n\t/**\n\t * Enable debug logging for OTel SDK\n\t * @default false\n\t */\n\tdebug?: boolean;\n\n\t/**\n\t * Additional resource attributes\n\t */\n\tresourceAttributes?: Record<string, string>;\n\n\t/**\n\t * Headers to send with OTLP requests\n\t */\n\theaders?: Record<string, string>;\n\n\t/**\n\t * Span processor strategy.\n\t * - 'batch': Efficient batching for long-running servers (default)\n\t * - 'simple': Immediate export for serverless environments (Lambda, Edge)\n\t *\n\t * If not specified, automatically selected based on environment detection.\n\t */\n\tspanProcessorStrategy?: SpanProcessorStrategy;\n\n\t/**\n\t * Environment type for automatic configuration\n\t * @default 'server'\n\t */\n\tenvironment?: 'server' | 'lambda' | 'edge' | 'custom';\n}\n\nlet sdk: NodeSDK | null = null;\n\n/**\n * Set up OpenTelemetry instrumentation.\n * Call this BEFORE importing your application code.\n *\n * @example\n * ```typescript\n * // instrumentation.ts (create this file)\n * import { setupTelemetry } from '@geekmidas/telescope/instrumentation';\n *\n * setupTelemetry({\n * serviceName: 'my-api',\n * endpoint: 'http://localhost:3000/__telescope/v1',\n * });\n *\n * // Then in your entry point:\n * // import './instrumentation';\n * // import { app } from './app';\n * ```\n */\nexport function setupTelemetry(options: TelemetryOptions): void {\n\tif (sdk) {\n\t\treturn;\n\t}\n\n\tconst {\n\t\tserviceName,\n\t\tserviceVersion = '1.0.0',\n\t\tendpoint,\n\t\tinstrumentPino = true,\n\t\tautoInstrument = true,\n\t\tdebug = false,\n\t\tresourceAttributes = {},\n\t\theaders = {},\n\t\tspanProcessorStrategy,\n\t\tenvironment = 'server',\n\t} = options;\n\n\t// Enable debug logging if requested\n\tif (debug) {\n\t\tdiag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG);\n\t}\n\n\t// Create resource\n\tconst resource = new Resource({\n\t\t[ATTR_SERVICE_NAME]: serviceName,\n\t\t[ATTR_SERVICE_VERSION]: serviceVersion,\n\t\t...resourceAttributes,\n\t});\n\n\t// Build instrumentations list\n\tconst instrumentations = [];\n\n\t// Add Pino instrumentation for log correlation\n\tif (instrumentPino) {\n\t\tinstrumentations.push(\n\t\t\tnew PinoInstrumentation({\n\t\t\t\t// Inject trace context into log records\n\t\t\t\tlogHook: (span, record) => {\n\t\t\t\t\trecord.trace_id = span.spanContext().traceId;\n\t\t\t\t\trecord.span_id = span.spanContext().spanId;\n\t\t\t\t\trecord.trace_flags = span.spanContext().traceFlags;\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\t}\n\n\t// Add auto-instrumentations for common libraries\n\tif (autoInstrument) {\n\t\tinstrumentations.push(\n\t\t\tgetNodeAutoInstrumentations({\n\t\t\t\t// Disable file system instrumentation (too noisy)\n\t\t\t\t'@opentelemetry/instrumentation-fs': { enabled: false },\n\t\t\t\t// Configure HTTP instrumentation\n\t\t\t\t'@opentelemetry/instrumentation-http': {\n\t\t\t\t\tignoreIncomingRequestHook: (request) => {\n\t\t\t\t\t\t// Ignore health checks and internal routes\n\t\t\t\t\t\tconst path = request.url || '';\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\tpath.includes('/__health') ||\n\t\t\t\t\t\t\tpath.includes('/__telescope') ||\n\t\t\t\t\t\t\tpath.includes('/favicon')\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\t}\n\n\t// Create exporters\n\tlet traceExporter: SpanExporter;\n\tif (endpoint) {\n\t\ttraceExporter = new OTLPTraceExporter({\n\t\t\turl: `${endpoint}/traces`,\n\t\t\theaders,\n\t\t});\n\t} else {\n\t\t// Fall back to console exporter for debugging\n\t\ttraceExporter = new ConsoleSpanExporter();\n\t}\n\n\t// Determine span processor strategy\n\tconst strategy = spanProcessorStrategy ?? getRecommendedStrategy(environment);\n\tconst spanProcessor = createSpanProcessor(traceExporter, { strategy });\n\n\t// Register globally for flush operations\n\tsetGlobalSpanProcessor(spanProcessor);\n\n\t// Create and configure SDK\n\tsdk = new NodeSDK({\n\t\tresource,\n\t\ttraceExporter,\n\t\tspanProcessors: [spanProcessor],\n\t\tinstrumentations,\n\t});\n\n\t// Set up log exporter if endpoint is provided\n\tif (endpoint) {\n\t\tconst logExporter = new OTLPLogExporter({\n\t\t\turl: `${endpoint}/logs`,\n\t\t\theaders,\n\t\t});\n\n\t\tconst loggerProvider = new LoggerProvider({ resource });\n\t\tconst logProcessor = new BatchLogRecordProcessor(logExporter);\n\t\tloggerProvider.addLogRecordProcessor(logProcessor);\n\n\t\t// Register for flush operations\n\t\tsetGlobalLogProcessor(logProcessor);\n\t}\n\n\t// Start the SDK\n\tsdk.start();\n\n\t// Graceful shutdown\n\tprocess.on('SIGTERM', () => {\n\t\tsdk\n\t\t\t?.shutdown()\n\t\t\t.then(() => {})\n\t\t\t.catch((_error) => {})\n\t\t\t.finally(() => process.exit(0));\n\t});\n}\n\n/**\n * Shut down telemetry (for testing or graceful shutdown)\n */\nexport async function shutdownTelemetry(): Promise<void> {\n\tif (sdk) {\n\t\tawait sdk.shutdown();\n\t\tsdk = null;\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;AA4FA,IAAIA,MAAsB;;;;;;;;;;;;;;;;;;;;AAqB1B,SAAgB,eAAeC,SAAiC;AAC/D,KAAI,IACH;CAGD,MAAM,EACL,aACA,iBAAiB,SACjB,UACA,iBAAiB,MACjB,iBAAiB,MACjB,QAAQ,OACR,qBAAqB,CAAE,GACvB,UAAU,CAAE,GACZ,uBACA,cAAc,UACd,GAAG;AAGJ,KAAI,MACH,MAAK,UAAU,IAAI,qBAAqB,aAAa,MAAM;CAI5D,MAAM,WAAW,IAAI,SAAS;GAC5B,oBAAoB;GACpB,uBAAuB;EACxB,GAAG;CACH;CAGD,MAAM,mBAAmB,CAAE;AAG3B,KAAI,eACH,kBAAiB,KAChB,IAAI,oBAAoB,EAEvB,SAAS,CAAC,MAAM,WAAW;AAC1B,SAAO,WAAW,KAAK,aAAa,CAAC;AACrC,SAAO,UAAU,KAAK,aAAa,CAAC;AACpC,SAAO,cAAc,KAAK,aAAa,CAAC;CACxC,EACD,GACD;AAIF,KAAI,eACH,kBAAiB,KAChB,4BAA4B;EAE3B,qCAAqC,EAAE,SAAS,MAAO;EAEvD,uCAAuC,EACtC,2BAA2B,CAAC,YAAY;GAEvC,MAAM,OAAO,QAAQ,OAAO;AAC5B,UACC,KAAK,SAAS,YAAY,IAC1B,KAAK,SAAS,eAAe,IAC7B,KAAK,SAAS,WAAW;EAE1B,EACD;CACD,EAAC,CACF;CAIF,IAAIC;AACJ,KAAI,SACH,iBAAgB,IAAI,kBAAkB;EACrC,MAAM,EAAE,SAAS;EACjB;CACA;KAGD,iBAAgB,IAAI;CAIrB,MAAM,WAAW,yBAAyB,uBAAuB,YAAY;CAC7E,MAAM,gBAAgB,oBAAoB,eAAe,EAAE,SAAU,EAAC;AAGtE,wBAAuB,cAAc;AAGrC,OAAM,IAAI,QAAQ;EACjB;EACA;EACA,gBAAgB,CAAC,aAAc;EAC/B;CACA;AAGD,KAAI,UAAU;EACb,MAAM,cAAc,IAAI,gBAAgB;GACvC,MAAM,EAAE,SAAS;GACjB;EACA;EAED,MAAM,iBAAiB,IAAI,eAAe,EAAE,SAAU;EACtD,MAAM,eAAe,IAAI,wBAAwB;AACjD,iBAAe,sBAAsB,aAAa;AAGlD,wBAAsB,aAAa;CACnC;AAGD,KAAI,OAAO;AAGX,SAAQ,GAAG,WAAW,MAAM;AAC3B,OACG,UAAU,CACX,KAAK,MAAM,CAAE,EAAC,CACd,MAAM,CAAC,WAAW,CAAE,EAAC,CACrB,QAAQ,MAAM,QAAQ,KAAK,EAAE,CAAC;CAChC,EAAC;AACF;;;;AAKD,eAAsB,oBAAmC;AACxD,KAAI,KAAK;AACR,QAAM,IAAI,UAAU;AACpB,QAAM;CACN;AACD"}