@geekmidas/telescope 10.0.0-alpha.99 → 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (480) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/README.md +18 -28
  3. package/dist/InMemoryMetricsStorage-BbKCL3YL.d.mts +47 -0
  4. package/dist/InMemoryMetricsStorage-BbKCL3YL.d.mts.map +1 -0
  5. package/dist/InMemoryMetricsStorage-C4drxT7G.mjs +247 -0
  6. package/dist/InMemoryMetricsStorage-C4drxT7G.mjs.map +1 -0
  7. package/dist/InMemoryMetricsStorage-D0njWUSi.cjs +252 -0
  8. package/dist/InMemoryMetricsStorage-D0njWUSi.cjs.map +1 -0
  9. package/dist/InMemoryMetricsStorage-TvPdZjL0.d.cts +47 -0
  10. package/dist/InMemoryMetricsStorage-TvPdZjL0.d.cts.map +1 -0
  11. package/dist/{MetricsAggregator-BJdIvfEv.d.mts → MetricsAggregator-4SqelGcG.d.cts} +6 -3
  12. package/dist/MetricsAggregator-4SqelGcG.d.cts.map +1 -0
  13. package/dist/MetricsAggregator-B7lUICdH.cjs +363 -0
  14. package/dist/MetricsAggregator-B7lUICdH.cjs.map +1 -0
  15. package/dist/{MetricsAggregator-CnC3oT5q.d.cts → MetricsAggregator-DZrW8ls6.d.mts} +6 -3
  16. package/dist/MetricsAggregator-DZrW8ls6.d.mts.map +1 -0
  17. package/dist/MetricsAggregator-S3DQWNas.mjs +357 -0
  18. package/dist/MetricsAggregator-S3DQWNas.mjs.map +1 -0
  19. package/dist/MetricsStorage-B86e4131.d.cts +60 -0
  20. package/dist/MetricsStorage-B86e4131.d.cts.map +1 -0
  21. package/dist/MetricsStorage-BWyP2_12.d.mts +60 -0
  22. package/dist/MetricsStorage-BWyP2_12.d.mts.map +1 -0
  23. package/dist/MetricsStorage-BypQXWiv.mjs +0 -0
  24. package/dist/MetricsStorage-Or8pVCe4.cjs +0 -0
  25. package/dist/Telescope-Cs3fv8jt.cjs +395 -0
  26. package/dist/Telescope-Cs3fv8jt.cjs.map +1 -0
  27. package/dist/{Telescope-BVfDvVvY.d.mts → Telescope-D4nmwDRA.d.cts} +7 -4
  28. package/dist/Telescope-D4nmwDRA.d.cts.map +1 -0
  29. package/dist/Telescope-Dh5av3FC.mjs +389 -0
  30. package/dist/Telescope-Dh5av3FC.mjs.map +1 -0
  31. package/dist/{Telescope-DeqSHfuB.d.cts → Telescope-Dl6VSfxd.d.mts} +7 -4
  32. package/dist/Telescope-Dl6VSfxd.d.mts.map +1 -0
  33. package/dist/Telescope.cjs +4 -385
  34. package/dist/Telescope.d.cts +3 -1
  35. package/dist/Telescope.d.mts +3 -1
  36. package/dist/Telescope.mjs +4 -384
  37. package/dist/adapters/index.d.cts +2 -2
  38. package/dist/adapters/index.d.mts +2 -2
  39. package/dist/adapters/index.mjs +0 -1
  40. package/dist/adapters/lambda.cjs +10 -9
  41. package/dist/adapters/lambda.cjs.map +1 -1
  42. package/dist/adapters/lambda.d.cts +13 -9
  43. package/dist/adapters/lambda.d.cts.map +1 -1
  44. package/dist/adapters/lambda.d.mts +13 -9
  45. package/dist/adapters/lambda.d.mts.map +1 -1
  46. package/dist/adapters/lambda.mjs +4 -3
  47. package/dist/adapters/lambda.mjs.map +1 -1
  48. package/dist/adapters/middy.cjs +4 -236
  49. package/dist/adapters/middy.d.cts +5 -60
  50. package/dist/adapters/middy.d.mts +5 -60
  51. package/dist/adapters/middy.mjs +3 -234
  52. package/dist/adapters/types.d.cts +2 -162
  53. package/dist/adapters/types.d.mts +2 -162
  54. package/dist/adapters/types.mjs +0 -1
  55. package/dist/{rolldown-runtime-VH7oDXx4.cjs → chunk-CUT6urMc.cjs} +10 -8
  56. package/dist/core--quSp5Qr.d.mts +78 -0
  57. package/dist/core--quSp5Qr.d.mts.map +1 -0
  58. package/dist/core-B4Jpia5H.d.cts +78 -0
  59. package/dist/core-B4Jpia5H.d.cts.map +1 -0
  60. package/dist/core-CtVHRJGv.cjs +199 -0
  61. package/dist/core-CtVHRJGv.cjs.map +1 -0
  62. package/dist/core-D6hJ6exL.mjs +139 -0
  63. package/dist/core-D6hJ6exL.mjs.map +1 -0
  64. package/dist/core.cjs +22 -22
  65. package/dist/core.d.cts +4 -4
  66. package/dist/core.d.mts +4 -4
  67. package/dist/core.mjs +4 -3
  68. package/dist/hono--uKQ7Jgi.d.mts +71 -0
  69. package/dist/hono--uKQ7Jgi.d.mts.map +1 -0
  70. package/dist/hono-C4EgpbKQ.cjs +160 -0
  71. package/dist/hono-C4EgpbKQ.cjs.map +1 -0
  72. package/dist/hono-CemCKU87.d.cts +71 -0
  73. package/dist/hono-CemCKU87.d.cts.map +1 -0
  74. package/dist/hono-DxhvnVbF.mjs +136 -0
  75. package/dist/hono-DxhvnVbF.mjs.map +1 -0
  76. package/dist/http-BiNtg85L.d.mts +107 -0
  77. package/dist/http-BiNtg85L.d.mts.map +1 -0
  78. package/dist/http-DQzgLczm.mjs +159 -0
  79. package/dist/http-DQzgLczm.mjs.map +1 -0
  80. package/dist/http-D_Z8sYXZ.cjs +219 -0
  81. package/dist/http-D_Z8sYXZ.cjs.map +1 -0
  82. package/dist/http-Dvca6fC3.d.cts +107 -0
  83. package/dist/http-Dvca6fC3.d.cts.map +1 -0
  84. package/dist/index-BL32-cvv.d.cts +1 -0
  85. package/dist/index-CsuikFeJ.d.mts +1 -0
  86. package/dist/index.cjs +9 -8
  87. package/dist/index.d.cts +6 -5
  88. package/dist/index.d.mts +6 -5
  89. package/dist/index.mjs +7 -5
  90. package/dist/instrumentation/core.cjs +11 -147
  91. package/dist/instrumentation/core.d.cts +3 -74
  92. package/dist/instrumentation/core.d.mts +3 -74
  93. package/dist/instrumentation/core.mjs +2 -137
  94. package/dist/instrumentation/hono.cjs +6 -174
  95. package/dist/instrumentation/hono.d.cts +2 -86
  96. package/dist/instrumentation/hono.d.mts +2 -86
  97. package/dist/instrumentation/hono.mjs +3 -170
  98. package/dist/instrumentation/http.cjs +11 -189
  99. package/dist/instrumentation/http.d.cts +2 -119
  100. package/dist/instrumentation/http.d.mts +2 -119
  101. package/dist/instrumentation/http.mjs +2 -178
  102. package/dist/instrumentation/index.cjs +47 -56
  103. package/dist/instrumentation/index.d.cts +9 -11
  104. package/dist/instrumentation/index.d.mts +9 -11
  105. package/dist/instrumentation/index.mjs +9 -10
  106. package/dist/instrumentation/middleware.cjs +6 -164
  107. package/dist/instrumentation/middleware.d.cts +2 -83
  108. package/dist/instrumentation/middleware.d.mts +2 -83
  109. package/dist/instrumentation/middleware.mjs +3 -160
  110. package/dist/instrumentation/otel.cjs +3 -137
  111. package/dist/instrumentation/otel.d.cts +2 -97
  112. package/dist/instrumentation/otel.d.mts +2 -97
  113. package/dist/instrumentation/otel.mjs +3 -136
  114. package/dist/instrumentation/setup.cjs +4 -142
  115. package/dist/instrumentation/setup.d.cts +3 -139
  116. package/dist/instrumentation/setup.d.mts +3 -139
  117. package/dist/instrumentation/setup.mjs +3 -139
  118. package/dist/instrumentation/tracing.cjs +10 -114
  119. package/dist/instrumentation/tracing.d.cts +2 -49
  120. package/dist/instrumentation/tracing.d.mts +2 -49
  121. package/dist/instrumentation/tracing.mjs +2 -105
  122. package/dist/logger/console.cjs +12 -18
  123. package/dist/logger/console.cjs.map +1 -1
  124. package/dist/logger/console.d.cts +10 -7
  125. package/dist/logger/console.d.cts.map +1 -1
  126. package/dist/logger/console.d.mts +10 -7
  127. package/dist/logger/console.d.mts.map +1 -1
  128. package/dist/logger/console.mjs +11 -17
  129. package/dist/logger/console.mjs.map +1 -1
  130. package/dist/logger/pino.cjs +5 -6
  131. package/dist/logger/pino.cjs.map +1 -1
  132. package/dist/logger/pino.d.cts +10 -6
  133. package/dist/logger/pino.d.cts.map +1 -1
  134. package/dist/logger/pino.d.mts +10 -6
  135. package/dist/logger/pino.d.mts.map +1 -1
  136. package/dist/logger/pino.mjs +3 -2
  137. package/dist/logger/pino.mjs.map +1 -1
  138. package/dist/memory--BK4iWiv.d.cts +40 -0
  139. package/dist/memory--BK4iWiv.d.cts.map +1 -0
  140. package/dist/memory-6S9H-IF5.mjs +123 -0
  141. package/dist/memory-6S9H-IF5.mjs.map +1 -0
  142. package/dist/memory-B0d_n1g5.cjs +129 -0
  143. package/dist/memory-B0d_n1g5.cjs.map +1 -0
  144. package/dist/memory-DCirEVFW.d.mts +40 -0
  145. package/dist/memory-DCirEVFW.d.mts.map +1 -0
  146. package/dist/metrics/MetricsAggregator.cjs +2 -354
  147. package/dist/metrics/MetricsAggregator.d.cts +2 -1
  148. package/dist/metrics/MetricsAggregator.d.mts +2 -1
  149. package/dist/metrics/MetricsAggregator.mjs +2 -353
  150. package/dist/metrics/index.cjs +4 -3
  151. package/dist/metrics/index.d.cts +4 -2
  152. package/dist/metrics/index.d.mts +4 -2
  153. package/dist/metrics/index.mjs +4 -2
  154. package/dist/metrics/storage/InMemoryMetricsStorage.cjs +3 -240
  155. package/dist/metrics/storage/InMemoryMetricsStorage.d.cts +4 -43
  156. package/dist/metrics/storage/InMemoryMetricsStorage.d.mts +4 -43
  157. package/dist/metrics/storage/InMemoryMetricsStorage.mjs +3 -239
  158. package/dist/metrics/storage/MetricsStorage.cjs +1 -0
  159. package/dist/metrics/storage/MetricsStorage.d.cts +3 -56
  160. package/dist/metrics/storage/MetricsStorage.d.mts +3 -56
  161. package/dist/metrics/storage/MetricsStorage.mjs +1 -1
  162. package/dist/metrics/storage/index.cjs +6 -6
  163. package/dist/metrics/storage/index.d.cts +3 -3
  164. package/dist/metrics/storage/index.d.mts +3 -3
  165. package/dist/metrics/storage/index.mjs +5 -4
  166. package/dist/metrics/storage/types.cjs +2 -34
  167. package/dist/metrics/storage/types.d.cts +2 -207
  168. package/dist/metrics/storage/types.d.mts +2 -207
  169. package/dist/metrics/storage/types.mjs +2 -33
  170. package/dist/metrics-D5YT-Rnq.mjs +0 -0
  171. package/dist/metrics-fhD3l3C3.cjs +0 -0
  172. package/dist/middleware-B2jFUukM.cjs +184 -0
  173. package/dist/middleware-B2jFUukM.cjs.map +1 -0
  174. package/dist/middleware-BTDncHwm.mjs +160 -0
  175. package/dist/middleware-BTDncHwm.mjs.map +1 -0
  176. package/dist/middleware-CA84nsNN.d.cts +74 -0
  177. package/dist/middleware-CA84nsNN.d.cts.map +1 -0
  178. package/dist/middleware-DAceVpfw.d.mts +74 -0
  179. package/dist/middleware-DAceVpfw.d.mts.map +1 -0
  180. package/dist/middy-B6Btl8XE.d.mts +64 -0
  181. package/dist/middy-B6Btl8XE.d.mts.map +1 -0
  182. package/dist/middy-BTR3cyvk.mjs +236 -0
  183. package/dist/middy-BTR3cyvk.mjs.map +1 -0
  184. package/dist/middy-Bq0defVg.d.cts +64 -0
  185. package/dist/middy-Bq0defVg.d.cts.map +1 -0
  186. package/dist/middy-y5Zp27eG.cjs +247 -0
  187. package/dist/middy-y5Zp27eG.cjs.map +1 -0
  188. package/dist/otel-1bJPb2Z7.d.mts +101 -0
  189. package/dist/otel-1bJPb2Z7.d.mts.map +1 -0
  190. package/dist/otel-C1HqHA2O.cjs +136 -0
  191. package/dist/otel-C1HqHA2O.cjs.map +1 -0
  192. package/dist/otel-SBVoVEHr.d.cts +101 -0
  193. package/dist/otel-SBVoVEHr.d.cts.map +1 -0
  194. package/dist/otel-wulj5B-X.mjs +130 -0
  195. package/dist/otel-wulj5B-X.mjs.map +1 -0
  196. package/dist/otlp/hono.cjs +15 -9
  197. package/dist/otlp/hono.cjs.map +1 -1
  198. package/dist/otlp/hono.d.cts +13 -3
  199. package/dist/otlp/hono.d.cts.map +1 -1
  200. package/dist/otlp/hono.d.mts +13 -3
  201. package/dist/otlp/hono.d.mts.map +1 -1
  202. package/dist/otlp/hono.mjs +11 -5
  203. package/dist/otlp/hono.mjs.map +1 -1
  204. package/dist/otlp/index.cjs +11 -11
  205. package/dist/otlp/index.d.cts +7 -4
  206. package/dist/otlp/index.d.mts +7 -4
  207. package/dist/otlp/index.mjs +5 -4
  208. package/dist/otlp/receiver.cjs +4 -88
  209. package/dist/otlp/receiver.d.cts +7 -59
  210. package/dist/otlp/receiver.d.mts +7 -59
  211. package/dist/otlp/receiver.mjs +4 -87
  212. package/dist/otlp/transformer.cjs +5 -214
  213. package/dist/otlp/transformer.d.cts +3 -1
  214. package/dist/otlp/transformer.d.mts +3 -1
  215. package/dist/otlp/transformer.mjs +3 -211
  216. package/dist/otlp/types.cjs +5 -57
  217. package/dist/otlp/types.d.cts +1 -1
  218. package/dist/otlp/types.d.mts +1 -1
  219. package/dist/otlp/types.mjs +2 -53
  220. package/dist/receiver-Cj1lbAOO.cjs +94 -0
  221. package/dist/receiver-Cj1lbAOO.cjs.map +1 -0
  222. package/dist/receiver-CxVd_9CB.mjs +89 -0
  223. package/dist/receiver-CxVd_9CB.mjs.map +1 -0
  224. package/dist/receiver-DLICx5uU.d.cts +63 -0
  225. package/dist/receiver-DLICx5uU.d.cts.map +1 -0
  226. package/dist/receiver-UeZT-H8u.d.mts +63 -0
  227. package/dist/receiver-UeZT-H8u.d.mts.map +1 -0
  228. package/dist/redact-BzkITCNW.mjs +83 -0
  229. package/dist/redact-BzkITCNW.mjs.map +1 -0
  230. package/dist/redact-DVaSSPZT.cjs +95 -0
  231. package/dist/redact-DVaSSPZT.cjs.map +1 -0
  232. package/dist/redact.cjs +3 -84
  233. package/dist/redact.d.cts +8 -4
  234. package/dist/redact.d.cts.map +1 -1
  235. package/dist/redact.d.mts +8 -4
  236. package/dist/redact.d.mts.map +1 -1
  237. package/dist/redact.mjs +2 -80
  238. package/dist/server/hono.cjs +54 -33
  239. package/dist/server/hono.cjs.map +1 -1
  240. package/dist/server/hono.d.cts +14 -19
  241. package/dist/server/hono.d.cts.map +1 -1
  242. package/dist/server/hono.d.mts +14 -19
  243. package/dist/server/hono.d.mts.map +1 -1
  244. package/dist/server/hono.mjs +52 -31
  245. package/dist/server/hono.mjs.map +1 -1
  246. package/dist/setup-B9jM77Qk.mjs +98 -0
  247. package/dist/setup-B9jM77Qk.mjs.map +1 -0
  248. package/dist/setup-Bkxm4g6b.d.mts +87 -0
  249. package/dist/setup-Bkxm4g6b.d.mts.map +1 -0
  250. package/dist/setup-CYpff5B9.cjs +110 -0
  251. package/dist/setup-CYpff5B9.cjs.map +1 -0
  252. package/dist/setup-D58N1f9O.d.cts +87 -0
  253. package/dist/setup-D58N1f9O.d.cts.map +1 -0
  254. package/dist/storage/kysely.cjs +70 -82
  255. package/dist/storage/kysely.cjs.map +1 -1
  256. package/dist/storage/kysely.d.cts +20 -36
  257. package/dist/storage/kysely.d.cts.map +1 -1
  258. package/dist/storage/kysely.d.mts +20 -36
  259. package/dist/storage/kysely.d.mts.map +1 -1
  260. package/dist/storage/kysely.mjs +69 -81
  261. package/dist/storage/kysely.mjs.map +1 -1
  262. package/dist/storage/memory.cjs +2 -122
  263. package/dist/storage/memory.d.cts +3 -36
  264. package/dist/storage/memory.d.mts +3 -36
  265. package/dist/storage/memory.mjs +2 -121
  266. package/dist/tracing-BX8uY2nR.d.cts +53 -0
  267. package/dist/tracing-BX8uY2nR.d.cts.map +1 -0
  268. package/dist/tracing-Bt1zWRlb.cjs +167 -0
  269. package/dist/tracing-Bt1zWRlb.cjs.map +1 -0
  270. package/dist/tracing-Cijm_5NI.mjs +113 -0
  271. package/dist/tracing-Cijm_5NI.mjs.map +1 -0
  272. package/dist/tracing-PnECEbEu.d.mts +53 -0
  273. package/dist/tracing-PnECEbEu.d.mts.map +1 -0
  274. package/dist/transformer-BXQPhzql.mjs +215 -0
  275. package/dist/transformer-BXQPhzql.mjs.map +1 -0
  276. package/dist/transformer-CLGZ0EQc.cjs +232 -0
  277. package/dist/transformer-CLGZ0EQc.cjs.map +1 -0
  278. package/dist/{transformer-BtqjAs0b.d.cts → transformer-CTGsaVfV.d.mts} +8 -4
  279. package/dist/transformer-CTGsaVfV.d.mts.map +1 -0
  280. package/dist/{transformer-DI6t8-YA.d.mts → transformer-ICEbxpFf.d.cts} +8 -4
  281. package/dist/transformer-ICEbxpFf.d.cts.map +1 -0
  282. package/dist/{types-BVujq4zd.d.mts → types-B1EIa_cQ.d.mts} +4 -3
  283. package/dist/types-B1EIa_cQ.d.mts.map +1 -0
  284. package/dist/types-BRzW1NM8.d.cts +166 -0
  285. package/dist/types-BRzW1NM8.d.cts.map +1 -0
  286. package/dist/types-BS3Rx8Sk.d.cts +209 -0
  287. package/dist/types-BS3Rx8Sk.d.cts.map +1 -0
  288. package/dist/types-Bwm_jNU7.mjs +54 -0
  289. package/dist/types-Bwm_jNU7.mjs.map +1 -0
  290. package/dist/types-BzQ78Efw.d.mts +166 -0
  291. package/dist/types-BzQ78Efw.d.mts.map +1 -0
  292. package/dist/types-CbNGXnJE.d.mts +209 -0
  293. package/dist/types-CbNGXnJE.d.mts.map +1 -0
  294. package/dist/{types-DVETVdpa.d.cts → types-CmOB7CLO.d.cts} +7 -6
  295. package/dist/types-CmOB7CLO.d.cts.map +1 -0
  296. package/dist/{types-DVETVdpa.d.mts → types-DBc0q5KD.d.mts} +7 -6
  297. package/dist/types-DBc0q5KD.d.mts.map +1 -0
  298. package/dist/types-Dsh-DIO_.cjs +78 -0
  299. package/dist/types-Dsh-DIO_.cjs.map +1 -0
  300. package/dist/types-ZW-nfWf6.cjs +40 -0
  301. package/dist/types-ZW-nfWf6.cjs.map +1 -0
  302. package/dist/{types-BVujq4zd.d.cts → types-l7Rlb5Mg.d.cts} +4 -3
  303. package/dist/types-l7Rlb5Mg.d.cts.map +1 -0
  304. package/dist/types-ojhnLdwz.mjs +34 -0
  305. package/dist/types-ojhnLdwz.mjs.map +1 -0
  306. package/dist/types.d.cts +1 -1
  307. package/dist/types.d.mts +1 -1
  308. package/dist/types.mjs +0 -1
  309. package/dist/ui-assets-BEXqOQLe.cjs +48 -0
  310. package/dist/ui-assets-BEXqOQLe.cjs.map +1 -0
  311. package/dist/ui-assets-BhTDUsrM.mjs +30 -0
  312. package/dist/ui-assets-BhTDUsrM.mjs.map +1 -0
  313. package/dist/ui-assets.cjs +5 -0
  314. package/dist/ui-assets.d.cts +13 -0
  315. package/dist/ui-assets.d.cts.map +1 -0
  316. package/dist/ui-assets.d.mts +13 -0
  317. package/dist/ui-assets.d.mts.map +1 -0
  318. package/dist/ui-assets.mjs +3 -0
  319. package/package.json +46 -46
  320. package/src/Telescope.ts +561 -0
  321. package/src/__tests__/Telescope.spec.ts +438 -0
  322. package/src/__tests__/pino-transport.spec.ts +115 -0
  323. package/src/__tests__/redact.spec.ts +336 -0
  324. package/src/adapters/__tests__/lambda.spec.ts +318 -0
  325. package/src/adapters/__tests__/middy.spec.ts +741 -0
  326. package/src/adapters/index.ts +22 -0
  327. package/src/adapters/lambda.ts +432 -0
  328. package/src/adapters/middy.ts +402 -0
  329. package/src/adapters/types.ts +181 -0
  330. package/src/core.ts +51 -0
  331. package/src/index.ts +34 -0
  332. package/src/instrumentation/__tests__/core.spec.ts +248 -0
  333. package/src/instrumentation/__tests__/hono.spec.ts +348 -0
  334. package/src/instrumentation/__tests__/middleware.spec.ts +528 -0
  335. package/src/instrumentation/__tests__/otel.spec.ts +291 -0
  336. package/src/instrumentation/__tests__/tracing.spec.ts +208 -0
  337. package/src/instrumentation/core.ts +228 -0
  338. package/src/instrumentation/hono.ts +270 -0
  339. package/src/instrumentation/http.ts +306 -0
  340. package/src/instrumentation/index.ts +90 -0
  341. package/src/instrumentation/middleware.ts +297 -0
  342. package/src/instrumentation/otel.ts +271 -0
  343. package/src/instrumentation/setup.ts +246 -0
  344. package/src/instrumentation/tracing.ts +145 -0
  345. package/src/logger/__tests__/console.spec.ts +366 -0
  346. package/src/logger/__tests__/pino.spec.ts +217 -0
  347. package/src/logger/console.ts +230 -0
  348. package/src/logger/pino.ts +201 -0
  349. package/src/metrics/MetricsAggregator.ts +555 -0
  350. package/src/metrics/__tests__/MetricsAggregator.spec.ts +298 -0
  351. package/src/metrics/index.ts +2 -0
  352. package/src/metrics/storage/InMemoryMetricsStorage.ts +380 -0
  353. package/src/metrics/storage/MetricsStorage.ts +74 -0
  354. package/src/metrics/storage/index.ts +3 -0
  355. package/src/metrics/storage/types.ts +243 -0
  356. package/src/otlp/__tests__/receiver.spec.ts +367 -0
  357. package/src/otlp/__tests__/transformer.spec.ts +455 -0
  358. package/src/otlp/hono.ts +120 -0
  359. package/src/otlp/index.ts +22 -0
  360. package/src/otlp/receiver.ts +162 -0
  361. package/src/otlp/transformer.ts +367 -0
  362. package/src/otlp/types.ts +364 -0
  363. package/src/redact.ts +116 -0
  364. package/src/server/__tests__/hono.spec.ts +814 -0
  365. package/src/server/hono.ts +442 -0
  366. package/src/storage/__tests__/kysely.spec.ts +715 -0
  367. package/src/storage/__tests__/memory.spec.ts +694 -0
  368. package/src/storage/kysely.ts +599 -0
  369. package/src/storage/memory.ts +204 -0
  370. package/src/types.ts +447 -0
  371. package/src/ui-assets.ts +40 -0
  372. package/tsconfig.json +9 -0
  373. package/ui/CHANGELOG.md +7 -0
  374. package/ui/index.html +12 -0
  375. package/ui/node_modules/.bin/tsc +21 -0
  376. package/ui/node_modules/.bin/tsserver +21 -0
  377. package/ui/node_modules/.bin/vite +21 -0
  378. package/ui/package.json +24 -0
  379. package/ui/src/App.tsx +595 -0
  380. package/ui/src/api.ts +88 -0
  381. package/ui/src/components/ExceptionDetail.tsx +100 -0
  382. package/ui/src/components/FilterBar.tsx +162 -0
  383. package/ui/src/components/LogDetail.tsx +91 -0
  384. package/ui/src/components/RequestDetail.tsx +143 -0
  385. package/ui/src/main.tsx +10 -0
  386. package/ui/src/styles.css +11 -0
  387. package/ui/src/types.ts +63 -0
  388. package/ui/src/vite-env.d.ts +1 -0
  389. package/ui/src/vite-plugin-gkm-config.ts +54 -0
  390. package/ui/tsconfig.json +20 -0
  391. package/ui/tsconfig.tsbuildinfo +1 -0
  392. package/ui/vite.config.ts +13 -0
  393. package/dist/MetricsAggregator-BJdIvfEv.d.mts.map +0 -1
  394. package/dist/MetricsAggregator-CnC3oT5q.d.cts.map +0 -1
  395. package/dist/Telescope-BVfDvVvY.d.mts.map +0 -1
  396. package/dist/Telescope-DeqSHfuB.d.cts.map +0 -1
  397. package/dist/Telescope.cjs.map +0 -1
  398. package/dist/Telescope.mjs.map +0 -1
  399. package/dist/adapters/middy.cjs.map +0 -1
  400. package/dist/adapters/middy.d.cts.map +0 -1
  401. package/dist/adapters/middy.d.mts.map +0 -1
  402. package/dist/adapters/middy.mjs.map +0 -1
  403. package/dist/adapters/types.d.cts.map +0 -1
  404. package/dist/adapters/types.d.mts.map +0 -1
  405. package/dist/instrumentation/core.cjs.map +0 -1
  406. package/dist/instrumentation/core.d.cts.map +0 -1
  407. package/dist/instrumentation/core.d.mts.map +0 -1
  408. package/dist/instrumentation/core.mjs.map +0 -1
  409. package/dist/instrumentation/hono.cjs.map +0 -1
  410. package/dist/instrumentation/hono.d.cts.map +0 -1
  411. package/dist/instrumentation/hono.d.mts.map +0 -1
  412. package/dist/instrumentation/hono.mjs.map +0 -1
  413. package/dist/instrumentation/http.cjs.map +0 -1
  414. package/dist/instrumentation/http.d.cts.map +0 -1
  415. package/dist/instrumentation/http.d.mts.map +0 -1
  416. package/dist/instrumentation/http.mjs.map +0 -1
  417. package/dist/instrumentation/middleware.cjs.map +0 -1
  418. package/dist/instrumentation/middleware.d.cts.map +0 -1
  419. package/dist/instrumentation/middleware.d.mts.map +0 -1
  420. package/dist/instrumentation/middleware.mjs.map +0 -1
  421. package/dist/instrumentation/otel.cjs.map +0 -1
  422. package/dist/instrumentation/otel.d.cts.map +0 -1
  423. package/dist/instrumentation/otel.d.mts.map +0 -1
  424. package/dist/instrumentation/otel.mjs.map +0 -1
  425. package/dist/instrumentation/sampler.cjs +0 -54
  426. package/dist/instrumentation/sampler.cjs.map +0 -1
  427. package/dist/instrumentation/sampler.d.cts +0 -38
  428. package/dist/instrumentation/sampler.d.cts.map +0 -1
  429. package/dist/instrumentation/sampler.d.mts +0 -38
  430. package/dist/instrumentation/sampler.d.mts.map +0 -1
  431. package/dist/instrumentation/sampler.mjs +0 -52
  432. package/dist/instrumentation/sampler.mjs.map +0 -1
  433. package/dist/instrumentation/setup.cjs.map +0 -1
  434. package/dist/instrumentation/setup.d.cts.map +0 -1
  435. package/dist/instrumentation/setup.d.mts.map +0 -1
  436. package/dist/instrumentation/setup.mjs.map +0 -1
  437. package/dist/instrumentation/tracing.cjs.map +0 -1
  438. package/dist/instrumentation/tracing.d.cts.map +0 -1
  439. package/dist/instrumentation/tracing.d.mts.map +0 -1
  440. package/dist/instrumentation/tracing.mjs.map +0 -1
  441. package/dist/instrumentation/trust.cjs +0 -107
  442. package/dist/instrumentation/trust.cjs.map +0 -1
  443. package/dist/instrumentation/trust.d.cts +0 -57
  444. package/dist/instrumentation/trust.d.cts.map +0 -1
  445. package/dist/instrumentation/trust.d.mts +0 -57
  446. package/dist/instrumentation/trust.d.mts.map +0 -1
  447. package/dist/instrumentation/trust.mjs +0 -104
  448. package/dist/instrumentation/trust.mjs.map +0 -1
  449. package/dist/metrics/MetricsAggregator.cjs.map +0 -1
  450. package/dist/metrics/MetricsAggregator.mjs.map +0 -1
  451. package/dist/metrics/storage/InMemoryMetricsStorage.cjs.map +0 -1
  452. package/dist/metrics/storage/InMemoryMetricsStorage.d.cts.map +0 -1
  453. package/dist/metrics/storage/InMemoryMetricsStorage.d.mts.map +0 -1
  454. package/dist/metrics/storage/InMemoryMetricsStorage.mjs.map +0 -1
  455. package/dist/metrics/storage/MetricsStorage.d.cts.map +0 -1
  456. package/dist/metrics/storage/MetricsStorage.d.mts.map +0 -1
  457. package/dist/metrics/storage/types.cjs.map +0 -1
  458. package/dist/metrics/storage/types.d.cts.map +0 -1
  459. package/dist/metrics/storage/types.d.mts.map +0 -1
  460. package/dist/metrics/storage/types.mjs.map +0 -1
  461. package/dist/otlp/receiver.cjs.map +0 -1
  462. package/dist/otlp/receiver.d.cts.map +0 -1
  463. package/dist/otlp/receiver.d.mts.map +0 -1
  464. package/dist/otlp/receiver.mjs.map +0 -1
  465. package/dist/otlp/transformer.cjs.map +0 -1
  466. package/dist/otlp/transformer.mjs.map +0 -1
  467. package/dist/otlp/types.cjs.map +0 -1
  468. package/dist/otlp/types.mjs.map +0 -1
  469. package/dist/redact.cjs.map +0 -1
  470. package/dist/redact.mjs.map +0 -1
  471. package/dist/storage/memory.cjs.map +0 -1
  472. package/dist/storage/memory.d.cts.map +0 -1
  473. package/dist/storage/memory.d.mts.map +0 -1
  474. package/dist/storage/memory.mjs.map +0 -1
  475. package/dist/transformer-BtqjAs0b.d.cts.map +0 -1
  476. package/dist/transformer-DI6t8-YA.d.mts.map +0 -1
  477. package/dist/types-BVujq4zd.d.cts.map +0 -1
  478. package/dist/types-BVujq4zd.d.mts.map +0 -1
  479. package/dist/types-DVETVdpa.d.cts.map +0 -1
  480. package/dist/types-DVETVdpa.d.mts.map +0 -1
package/ui/src/App.tsx ADDED
@@ -0,0 +1,595 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+ import * as api from './api';
3
+ import { ExceptionDetail } from './components/ExceptionDetail';
4
+ import {
5
+ type ExceptionFilters,
6
+ FilterBar,
7
+ type LogFilters,
8
+ type RequestFilters,
9
+ } from './components/FilterBar';
10
+ import { LogDetail } from './components/LogDetail';
11
+ import { RequestDetail } from './components/RequestDetail';
12
+ import type {
13
+ ExceptionEntry,
14
+ LogEntry,
15
+ RequestEntry,
16
+ Tab,
17
+ TelescopeStats,
18
+ WebSocketMessage,
19
+ } from './types';
20
+
21
+ const DEFAULT_REQUEST_FILTERS: RequestFilters = {
22
+ search: '',
23
+ method: '',
24
+ status: '',
25
+ };
26
+
27
+ const DEFAULT_LOG_FILTERS: LogFilters = {
28
+ search: '',
29
+ level: '',
30
+ };
31
+
32
+ const DEFAULT_EXCEPTION_FILTERS: ExceptionFilters = {
33
+ search: '',
34
+ };
35
+
36
+ export function App() {
37
+ const [activeTab, setActiveTab] = useState<Tab>('requests');
38
+ const [stats, setStats] = useState<TelescopeStats | null>(null);
39
+ const [requests, setRequests] = useState<RequestEntry[]>([]);
40
+ const [exceptions, setExceptions] = useState<ExceptionEntry[]>([]);
41
+ const [logs, setLogs] = useState<LogEntry[]>([]);
42
+ const [loading, setLoading] = useState(true);
43
+ const [connected, setConnected] = useState(false);
44
+ const [selectedRequest, setSelectedRequest] = useState<RequestEntry | null>(
45
+ null,
46
+ );
47
+ const [selectedException, setSelectedException] =
48
+ useState<ExceptionEntry | null>(null);
49
+ const [selectedLog, setSelectedLog] = useState<LogEntry | null>(null);
50
+
51
+ // Filter state
52
+ const [requestFilters, setRequestFilters] = useState<RequestFilters>(
53
+ DEFAULT_REQUEST_FILTERS,
54
+ );
55
+ const [logFilters, setLogFilters] = useState<LogFilters>(DEFAULT_LOG_FILTERS);
56
+ const [exceptionFilters, setExceptionFilters] = useState<ExceptionFilters>(
57
+ DEFAULT_EXCEPTION_FILTERS,
58
+ );
59
+
60
+ // Track if we have active filters to show filtered count
61
+ const hasRequestFilters =
62
+ requestFilters.search || requestFilters.method || requestFilters.status;
63
+ const hasLogFilters = logFilters.search || logFilters.level;
64
+ const hasExceptionFilters = exceptionFilters.search;
65
+
66
+ // Debounce timer ref
67
+ const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
68
+
69
+ // Load initial data and stats
70
+ const loadInitialData = useCallback(async () => {
71
+ try {
72
+ const [statsData, requestsData, exceptionsData, logsData] =
73
+ await Promise.all([
74
+ api.getStats(),
75
+ api.getRequests({ limit: 100 }),
76
+ api.getExceptions({ limit: 100 }),
77
+ api.getLogs({ limit: 100 }),
78
+ ]);
79
+
80
+ setStats(statsData);
81
+ setRequests(requestsData);
82
+ setExceptions(exceptionsData);
83
+ setLogs(logsData);
84
+ } catch (_error) {
85
+ } finally {
86
+ setLoading(false);
87
+ }
88
+ }, []);
89
+
90
+ useEffect(() => {
91
+ loadInitialData();
92
+ }, [loadInitialData]);
93
+
94
+ // Fetch requests with filters
95
+ const fetchRequests = useCallback(async (filters: RequestFilters) => {
96
+ try {
97
+ const data = await api.getRequests({
98
+ limit: 100,
99
+ search: filters.search || undefined,
100
+ method: filters.method || undefined,
101
+ status: filters.status || undefined,
102
+ });
103
+ setRequests(data);
104
+ } catch (_error) {}
105
+ }, []);
106
+
107
+ // Fetch logs with filters
108
+ const fetchLogs = useCallback(async (filters: LogFilters) => {
109
+ try {
110
+ const data = await api.getLogs({
111
+ limit: 100,
112
+ search: filters.search || undefined,
113
+ level: filters.level || undefined,
114
+ });
115
+ setLogs(data);
116
+ } catch (_error) {}
117
+ }, []);
118
+
119
+ // Fetch exceptions with filters
120
+ const fetchExceptions = useCallback(async (filters: ExceptionFilters) => {
121
+ try {
122
+ const data = await api.getExceptions({
123
+ limit: 100,
124
+ search: filters.search || undefined,
125
+ });
126
+ setExceptions(data);
127
+ } catch (_error) {}
128
+ }, []);
129
+
130
+ // Handle request filter changes with debounce
131
+ const handleRequestFiltersChange = useCallback(
132
+ (filters: RequestFilters) => {
133
+ setRequestFilters(filters);
134
+
135
+ if (debounceRef.current) {
136
+ clearTimeout(debounceRef.current);
137
+ }
138
+
139
+ debounceRef.current = setTimeout(() => {
140
+ fetchRequests(filters);
141
+ }, 300);
142
+ },
143
+ [fetchRequests],
144
+ );
145
+
146
+ // Handle log filter changes with debounce
147
+ const handleLogFiltersChange = useCallback(
148
+ (filters: LogFilters) => {
149
+ setLogFilters(filters);
150
+
151
+ if (debounceRef.current) {
152
+ clearTimeout(debounceRef.current);
153
+ }
154
+
155
+ debounceRef.current = setTimeout(() => {
156
+ fetchLogs(filters);
157
+ }, 300);
158
+ },
159
+ [fetchLogs],
160
+ );
161
+
162
+ // Handle exception filter changes with debounce
163
+ const handleExceptionFiltersChange = useCallback(
164
+ (filters: ExceptionFilters) => {
165
+ setExceptionFilters(filters);
166
+
167
+ if (debounceRef.current) {
168
+ clearTimeout(debounceRef.current);
169
+ }
170
+
171
+ debounceRef.current = setTimeout(() => {
172
+ fetchExceptions(filters);
173
+ }, 300);
174
+ },
175
+ [fetchExceptions],
176
+ );
177
+
178
+ // Clear filters and reload
179
+ const clearFilters = useCallback(() => {
180
+ setRequestFilters(DEFAULT_REQUEST_FILTERS);
181
+ setLogFilters(DEFAULT_LOG_FILTERS);
182
+ setExceptionFilters(DEFAULT_EXCEPTION_FILTERS);
183
+
184
+ // Reload without filters
185
+ fetchRequests(DEFAULT_REQUEST_FILTERS);
186
+ fetchLogs(DEFAULT_LOG_FILTERS);
187
+ fetchExceptions(DEFAULT_EXCEPTION_FILTERS);
188
+ }, [fetchRequests, fetchLogs, fetchExceptions]);
189
+
190
+ // Helper to check if a new WebSocket entry matches current filters
191
+ const matchesRequestFilters = useCallback(
192
+ (request: RequestEntry, filters: RequestFilters) => {
193
+ if (
194
+ filters.search &&
195
+ !request.path.toLowerCase().includes(filters.search.toLowerCase())
196
+ ) {
197
+ return false;
198
+ }
199
+ if (filters.method && request.method !== filters.method) {
200
+ return false;
201
+ }
202
+ if (filters.status) {
203
+ const statusCategory = Math.floor(request.status / 100);
204
+ const filterCategory = parseInt(filters.status[0], 10);
205
+ if (statusCategory !== filterCategory) {
206
+ return false;
207
+ }
208
+ }
209
+ return true;
210
+ },
211
+ [],
212
+ );
213
+
214
+ const matchesLogFilters = useCallback(
215
+ (log: LogEntry, filters: LogFilters) => {
216
+ if (
217
+ filters.search &&
218
+ !log.message.toLowerCase().includes(filters.search.toLowerCase())
219
+ ) {
220
+ return false;
221
+ }
222
+ if (filters.level && log.level !== filters.level) {
223
+ return false;
224
+ }
225
+ return true;
226
+ },
227
+ [],
228
+ );
229
+
230
+ const matchesExceptionFilters = useCallback(
231
+ (exception: ExceptionEntry, filters: ExceptionFilters) => {
232
+ if (filters.search) {
233
+ const searchLower = filters.search.toLowerCase();
234
+ if (
235
+ !exception.name.toLowerCase().includes(searchLower) &&
236
+ !exception.message.toLowerCase().includes(searchLower)
237
+ ) {
238
+ return false;
239
+ }
240
+ }
241
+ return true;
242
+ },
243
+ [],
244
+ );
245
+
246
+ // WebSocket connection for real-time updates
247
+ useEffect(() => {
248
+ let ws: WebSocket | null = null;
249
+ let reconnectTimeout: ReturnType<typeof setTimeout>;
250
+
251
+ function connect() {
252
+ try {
253
+ ws = api.createWebSocket();
254
+
255
+ ws.onopen = () => {
256
+ setConnected(true);
257
+ };
258
+
259
+ ws.onclose = () => {
260
+ setConnected(false);
261
+ reconnectTimeout = setTimeout(connect, 3000);
262
+ };
263
+
264
+ ws.onerror = () => {
265
+ ws?.close();
266
+ };
267
+
268
+ ws.onmessage = (event) => {
269
+ try {
270
+ const message: WebSocketMessage = JSON.parse(event.data);
271
+
272
+ switch (message.type) {
273
+ case 'request': {
274
+ const newRequest = message.payload as RequestEntry;
275
+ setStats((prev) =>
276
+ prev ? { ...prev, requests: prev.requests + 1 } : prev,
277
+ );
278
+ // Only add to list if it matches current filters
279
+ setRequestFilters((currentFilters) => {
280
+ if (matchesRequestFilters(newRequest, currentFilters)) {
281
+ setRequests((prev) => [newRequest, ...prev].slice(0, 100));
282
+ }
283
+ return currentFilters;
284
+ });
285
+ break;
286
+ }
287
+ case 'exception': {
288
+ const newException = message.payload as ExceptionEntry;
289
+ setStats((prev) =>
290
+ prev ? { ...prev, exceptions: prev.exceptions + 1 } : prev,
291
+ );
292
+ setExceptionFilters((currentFilters) => {
293
+ if (matchesExceptionFilters(newException, currentFilters)) {
294
+ setExceptions((prev) =>
295
+ [newException, ...prev].slice(0, 100),
296
+ );
297
+ }
298
+ return currentFilters;
299
+ });
300
+ break;
301
+ }
302
+ case 'log': {
303
+ const newLog = message.payload as LogEntry;
304
+ setStats((prev) =>
305
+ prev ? { ...prev, logs: prev.logs + 1 } : prev,
306
+ );
307
+ setLogFilters((currentFilters) => {
308
+ if (matchesLogFilters(newLog, currentFilters)) {
309
+ setLogs((prev) => [newLog, ...prev].slice(0, 100));
310
+ }
311
+ return currentFilters;
312
+ });
313
+ break;
314
+ }
315
+ }
316
+ } catch {
317
+ // Ignore parse errors
318
+ }
319
+ };
320
+ } catch {
321
+ reconnectTimeout = setTimeout(connect, 3000);
322
+ }
323
+ }
324
+
325
+ connect();
326
+
327
+ return () => {
328
+ clearTimeout(reconnectTimeout);
329
+ ws?.close();
330
+ };
331
+ }, [matchesRequestFilters, matchesLogFilters, matchesExceptionFilters]);
332
+
333
+ const formatTime = (timestamp: string) => {
334
+ return new Date(timestamp).toLocaleTimeString();
335
+ };
336
+
337
+ const formatDuration = (ms: number) => {
338
+ if (ms < 1) return '<1ms';
339
+ if (ms < 1000) return `${Math.round(ms)}ms`;
340
+ return `${(ms / 1000).toFixed(2)}s`;
341
+ };
342
+
343
+ const getMethodColor = (method: string) => {
344
+ const colors: Record<string, string> = {
345
+ GET: 'bg-green-500/20 text-green-400',
346
+ POST: 'bg-blue-500/20 text-blue-400',
347
+ PUT: 'bg-amber-500/20 text-amber-400',
348
+ PATCH: 'bg-purple-500/20 text-purple-400',
349
+ DELETE: 'bg-red-500/20 text-red-400',
350
+ };
351
+ return colors[method] || 'bg-slate-500/20 text-slate-400';
352
+ };
353
+
354
+ const getStatusColor = (status: number) => {
355
+ if (status >= 500) return 'bg-red-500/20 text-red-400';
356
+ if (status >= 400) return 'bg-amber-500/20 text-amber-400';
357
+ if (status >= 300) return 'bg-blue-500/20 text-blue-400';
358
+ return 'bg-green-500/20 text-green-400';
359
+ };
360
+
361
+ const getLogLevelColor = (level: string) => {
362
+ const colors: Record<string, string> = {
363
+ debug: 'bg-slate-500/20 text-slate-400',
364
+ info: 'bg-blue-500/20 text-blue-400',
365
+ warn: 'bg-amber-500/20 text-amber-400',
366
+ error: 'bg-red-500/20 text-red-400',
367
+ };
368
+ return colors[level] || 'bg-slate-500/20 text-slate-400';
369
+ };
370
+
371
+ const closeDetail = () => {
372
+ setSelectedRequest(null);
373
+ setSelectedException(null);
374
+ setSelectedLog(null);
375
+ };
376
+
377
+ return (
378
+ <div className="flex flex-col min-h-screen bg-bg-primary font-mono text-slate-100">
379
+ {/* Header */}
380
+ <header className="bg-bg-secondary border-b border-border px-6 py-4 flex items-center justify-between">
381
+ <h1 className="text-xl font-semibold flex items-center gap-2">
382
+ <span className="text-blue-400">&#128301;</span> Telescope
383
+ </h1>
384
+ <div className="flex items-center gap-6">
385
+ {stats && (
386
+ <>
387
+ <div className="text-sm text-slate-400">
388
+ <span className="font-semibold text-slate-100">
389
+ {stats.requests}
390
+ </span>{' '}
391
+ requests
392
+ </div>
393
+ <div className="text-sm text-slate-400">
394
+ <span className="font-semibold text-slate-100">
395
+ {stats.exceptions}
396
+ </span>{' '}
397
+ exceptions
398
+ </div>
399
+ <div className="text-sm text-slate-400">
400
+ <span className="font-semibold text-slate-100">
401
+ {stats.logs}
402
+ </span>{' '}
403
+ logs
404
+ </div>
405
+ </>
406
+ )}
407
+ <div className="flex items-center gap-2 text-xs text-slate-500">
408
+ <span
409
+ className={`w-2 h-2 rounded-full ${connected ? 'bg-green-500' : 'bg-red-500'}`}
410
+ />
411
+ {connected ? 'Live' : 'Disconnected'}
412
+ </div>
413
+ </div>
414
+ </header>
415
+
416
+ {/* Main */}
417
+ <main className="flex-1 flex flex-col">
418
+ {/* Tabs */}
419
+ <div className="flex bg-bg-secondary border-b border-border">
420
+ {(['requests', 'exceptions', 'logs'] as Tab[]).map((tab) => (
421
+ <button
422
+ key={tab}
423
+ className={`px-6 py-3 text-sm capitalize border-b-2 transition-colors ${
424
+ activeTab === tab
425
+ ? 'text-blue-400 border-blue-400'
426
+ : 'text-slate-400 border-transparent hover:text-slate-100 hover:bg-bg-tertiary'
427
+ }`}
428
+ onClick={() => setActiveTab(tab)}
429
+ >
430
+ {tab}
431
+ {tab === 'requests' && hasRequestFilters && (
432
+ <span className="ml-2 text-xs text-slate-500">
433
+ ({requests.length})
434
+ </span>
435
+ )}
436
+ {tab === 'logs' && hasLogFilters && (
437
+ <span className="ml-2 text-xs text-slate-500">
438
+ ({logs.length})
439
+ </span>
440
+ )}
441
+ {tab === 'exceptions' && hasExceptionFilters && (
442
+ <span className="ml-2 text-xs text-slate-500">
443
+ ({exceptions.length})
444
+ </span>
445
+ )}
446
+ </button>
447
+ ))}
448
+ </div>
449
+
450
+ {/* Filter Bar */}
451
+ <FilterBar
452
+ tab={activeTab}
453
+ requestFilters={requestFilters}
454
+ logFilters={logFilters}
455
+ exceptionFilters={exceptionFilters}
456
+ onRequestFiltersChange={handleRequestFiltersChange}
457
+ onLogFiltersChange={handleLogFiltersChange}
458
+ onExceptionFiltersChange={handleExceptionFiltersChange}
459
+ onClear={clearFilters}
460
+ />
461
+
462
+ {/* Content */}
463
+ <div className="flex-1 p-4 overflow-y-auto">
464
+ {loading ? (
465
+ <div className="flex items-center justify-center py-16 text-slate-500">
466
+ Loading...
467
+ </div>
468
+ ) : activeTab === 'requests' ? (
469
+ requests.length === 0 ? (
470
+ <div className="flex flex-col items-center justify-center py-16 text-slate-500 text-center">
471
+ <h3 className="text-lg mb-2">
472
+ {hasRequestFilters
473
+ ? 'No matching requests'
474
+ : 'No requests yet'}
475
+ </h3>
476
+ <p className="text-sm">
477
+ {hasRequestFilters
478
+ ? 'Try adjusting your filters.'
479
+ : 'Requests will appear here as they are captured.'}
480
+ </p>
481
+ </div>
482
+ ) : (
483
+ <div className="flex flex-col gap-2">
484
+ {requests.map((request) => (
485
+ <div
486
+ key={request.id}
487
+ className="bg-bg-secondary border border-border rounded-lg p-4 cursor-pointer transition-colors hover:border-blue-500 hover:bg-bg-tertiary flex items-center gap-4"
488
+ onClick={() => setSelectedRequest(request)}
489
+ >
490
+ <span
491
+ className={`font-semibold px-2 py-1 rounded text-xs min-w-16 text-center ${getMethodColor(request.method)}`}
492
+ >
493
+ {request.method}
494
+ </span>
495
+ <span className="flex-1 truncate">{request.path}</span>
496
+ <span
497
+ className={`text-sm px-2 py-1 rounded ${getStatusColor(request.status)}`}
498
+ >
499
+ {request.status}
500
+ </span>
501
+ <span className="text-xs text-slate-500 min-w-16 text-right">
502
+ {formatDuration(request.duration)}
503
+ </span>
504
+ <span className="text-xs text-slate-500 min-w-20 text-right">
505
+ {formatTime(request.timestamp)}
506
+ </span>
507
+ </div>
508
+ ))}
509
+ </div>
510
+ )
511
+ ) : activeTab === 'exceptions' ? (
512
+ exceptions.length === 0 ? (
513
+ <div className="flex flex-col items-center justify-center py-16 text-slate-500 text-center">
514
+ <h3 className="text-lg mb-2">
515
+ {hasExceptionFilters
516
+ ? 'No matching exceptions'
517
+ : 'No exceptions'}
518
+ </h3>
519
+ <p className="text-sm">
520
+ {hasExceptionFilters
521
+ ? 'Try adjusting your filters.'
522
+ : 'Exceptions will appear here when they occur.'}
523
+ </p>
524
+ </div>
525
+ ) : (
526
+ <div className="flex flex-col gap-2">
527
+ {exceptions.map((exception) => (
528
+ <div
529
+ key={exception.id}
530
+ className="bg-bg-secondary border border-border rounded-lg p-4 cursor-pointer transition-colors hover:border-blue-500 hover:bg-bg-tertiary"
531
+ onClick={() => setSelectedException(exception)}
532
+ >
533
+ <div className="flex justify-between items-center mb-1">
534
+ <span className="font-semibold text-red-400">
535
+ {exception.name}
536
+ </span>
537
+ <span className="text-xs text-slate-500">
538
+ {formatTime(exception.timestamp)}
539
+ </span>
540
+ </div>
541
+ <span className="text-sm text-slate-400 truncate block">
542
+ {exception.message}
543
+ </span>
544
+ </div>
545
+ ))}
546
+ </div>
547
+ )
548
+ ) : logs.length === 0 ? (
549
+ <div className="flex flex-col items-center justify-center py-16 text-slate-500 text-center">
550
+ <h3 className="text-lg mb-2">
551
+ {hasLogFilters ? 'No matching logs' : 'No logs yet'}
552
+ </h3>
553
+ <p className="text-sm">
554
+ {hasLogFilters
555
+ ? 'Try adjusting your filters.'
556
+ : 'Log entries will appear here as they are recorded.'}
557
+ </p>
558
+ </div>
559
+ ) : (
560
+ <div className="flex flex-col gap-2">
561
+ {logs.map((log) => (
562
+ <div
563
+ key={log.id}
564
+ className="bg-bg-secondary border border-border rounded-lg p-4 cursor-pointer transition-colors hover:border-blue-500 hover:bg-bg-tertiary flex items-start gap-4"
565
+ onClick={() => setSelectedLog(log)}
566
+ >
567
+ <span
568
+ className={`font-semibold px-2 py-1 rounded text-xs min-w-14 text-center ${getLogLevelColor(log.level)}`}
569
+ >
570
+ {log.level}
571
+ </span>
572
+ <span className="flex-1 wrap-break-word">{log.message}</span>
573
+ <span className="text-xs text-slate-500 min-w-20 text-right">
574
+ {formatTime(log.timestamp)}
575
+ </span>
576
+ </div>
577
+ ))}
578
+ </div>
579
+ )}
580
+ </div>
581
+ </main>
582
+
583
+ {/* Detail Panels */}
584
+ {selectedRequest && (
585
+ <RequestDetail request={selectedRequest} onClose={closeDetail} />
586
+ )}
587
+
588
+ {selectedException && (
589
+ <ExceptionDetail exception={selectedException} onClose={closeDetail} />
590
+ )}
591
+
592
+ {selectedLog && <LogDetail log={selectedLog} onClose={closeDetail} />}
593
+ </div>
594
+ );
595
+ }
package/ui/src/api.ts ADDED
@@ -0,0 +1,88 @@
1
+ import type {
2
+ ExceptionEntry,
3
+ LogEntry,
4
+ RequestEntry,
5
+ TelescopeStats,
6
+ } from './types';
7
+
8
+ const BASE_URL = '/__telescope/api';
9
+
10
+ export interface FilterOptions {
11
+ limit?: number;
12
+ offset?: number;
13
+ search?: string;
14
+ before?: string;
15
+ after?: string;
16
+ tags?: string[];
17
+ method?: string;
18
+ status?: string;
19
+ level?: string;
20
+ }
21
+
22
+ async function fetchJson<T>(path: string): Promise<T> {
23
+ const response = await fetch(`${BASE_URL}${path}`);
24
+ if (!response.ok) {
25
+ throw new Error(`HTTP error! status: ${response.status}`);
26
+ }
27
+ return response.json();
28
+ }
29
+
30
+ function buildQueryString(options?: FilterOptions): string {
31
+ if (!options) return '';
32
+
33
+ const params = new URLSearchParams();
34
+ if (options.limit) params.set('limit', String(options.limit));
35
+ if (options.offset) params.set('offset', String(options.offset));
36
+ if (options.search) params.set('search', options.search);
37
+ if (options.before) params.set('before', options.before);
38
+ if (options.after) params.set('after', options.after);
39
+ if (options.tags?.length) params.set('tags', options.tags.join(','));
40
+ if (options.method) params.set('method', options.method);
41
+ if (options.status) params.set('status', options.status);
42
+ if (options.level) params.set('level', options.level);
43
+
44
+ const query = params.toString();
45
+ return query ? `?${query}` : '';
46
+ }
47
+
48
+ export async function getRequests(
49
+ options?: FilterOptions,
50
+ ): Promise<RequestEntry[]> {
51
+ return fetchJson(`/requests${buildQueryString(options)}`);
52
+ }
53
+
54
+ export async function getRequest(id: string): Promise<RequestEntry | null> {
55
+ try {
56
+ return await fetchJson(`/requests/${id}`);
57
+ } catch {
58
+ return null;
59
+ }
60
+ }
61
+
62
+ export async function getExceptions(
63
+ options?: FilterOptions,
64
+ ): Promise<ExceptionEntry[]> {
65
+ return fetchJson(`/exceptions${buildQueryString(options)}`);
66
+ }
67
+
68
+ export async function getException(id: string): Promise<ExceptionEntry | null> {
69
+ try {
70
+ return await fetchJson(`/exceptions/${id}`);
71
+ } catch {
72
+ return null;
73
+ }
74
+ }
75
+
76
+ export async function getLogs(options?: FilterOptions): Promise<LogEntry[]> {
77
+ return fetchJson(`/logs${buildQueryString(options)}`);
78
+ }
79
+
80
+ export async function getStats(): Promise<TelescopeStats> {
81
+ return fetchJson('/stats');
82
+ }
83
+
84
+ export function createWebSocket(): WebSocket {
85
+ const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
86
+ const host = window.location.host;
87
+ return new WebSocket(`${protocol}//${host}/__telescope/ws`);
88
+ }