adonisjs-server-stats 1.5.4 → 1.6.2

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 (527) hide show
  1. package/README.md +351 -171
  2. package/dist/configure.d.ts.map +1 -1
  3. package/dist/core/api-client.d.ts +73 -0
  4. package/dist/core/api-client.d.ts.map +1 -0
  5. package/dist/core/config-utils.d.ts +109 -0
  6. package/dist/core/config-utils.d.ts.map +1 -0
  7. package/dist/core/constants.d.ts +11 -0
  8. package/dist/core/constants.d.ts.map +1 -0
  9. package/dist/core/dashboard-api.d.ts +65 -0
  10. package/dist/core/dashboard-api.d.ts.map +1 -0
  11. package/dist/core/dashboard-data-controller.d.ts +157 -0
  12. package/dist/core/dashboard-data-controller.d.ts.map +1 -0
  13. package/dist/core/debug-data-controller.d.ts +89 -0
  14. package/dist/core/debug-data-controller.d.ts.map +1 -0
  15. package/dist/core/feature-detect.d.ts +67 -0
  16. package/dist/core/feature-detect.d.ts.map +1 -0
  17. package/dist/core/formatters.d.ts +189 -0
  18. package/dist/core/formatters.d.ts.map +1 -0
  19. package/dist/core/history-buffer.d.ts +23 -0
  20. package/dist/core/history-buffer.d.ts.map +1 -0
  21. package/dist/core/icons.d.ts +36 -0
  22. package/dist/core/icons.d.ts.map +1 -0
  23. package/dist/core/index.d.ts +39 -0
  24. package/dist/core/index.d.ts.map +1 -0
  25. package/dist/core/index.js +1961 -0
  26. package/dist/core/internals-utils.d.ts +71 -0
  27. package/dist/core/internals-utils.d.ts.map +1 -0
  28. package/dist/core/job-utils.d.ts +45 -0
  29. package/dist/core/job-utils.d.ts.map +1 -0
  30. package/dist/core/log-utils.d.ts +34 -0
  31. package/dist/core/log-utils.d.ts.map +1 -0
  32. package/dist/core/metrics.d.ts +41 -0
  33. package/dist/core/metrics.d.ts.map +1 -0
  34. package/dist/core/pagination.d.ts +128 -0
  35. package/dist/core/pagination.d.ts.map +1 -0
  36. package/dist/core/query-utils.d.ts +35 -0
  37. package/dist/core/query-utils.d.ts.map +1 -0
  38. package/dist/core/resizable-columns.d.ts +18 -0
  39. package/dist/core/resizable-columns.d.ts.map +1 -0
  40. package/dist/core/routes.d.ts +12 -0
  41. package/dist/core/routes.d.ts.map +1 -0
  42. package/dist/core/server-stats-controller.d.ts +106 -0
  43. package/dist/core/server-stats-controller.d.ts.map +1 -0
  44. package/dist/core/sparkline.d.ts +80 -0
  45. package/dist/core/sparkline.d.ts.map +1 -0
  46. package/dist/core/theme.d.ts +42 -0
  47. package/dist/core/theme.d.ts.map +1 -0
  48. package/dist/core/trace-utils.d.ts +62 -0
  49. package/dist/core/trace-utils.d.ts.map +1 -0
  50. package/dist/core/transmit-adapter.d.ts +59 -0
  51. package/dist/core/transmit-adapter.d.ts.map +1 -0
  52. package/dist/core/types.d.ts +619 -0
  53. package/dist/core/types.d.ts.map +1 -0
  54. package/dist/react/CacheSection-DGxMDlWK.js +146 -0
  55. package/dist/react/CacheTab-CnVW5PLs.js +123 -0
  56. package/dist/react/ConfigContent-CnsEI4j3.js +397 -0
  57. package/dist/react/ConfigSection-DPcrfqXY.js +11 -0
  58. package/dist/react/ConfigTab-BSWq_o2p.js +15 -0
  59. package/dist/react/CustomPaneTab-xjkYwTvH.js +104 -0
  60. package/dist/react/DataTable-YyShr5B-.js +55 -0
  61. package/dist/react/EmailsSection-CSyTg1aX.js +262 -0
  62. package/dist/react/EmailsTab-Dh2YSa_f.js +131 -0
  63. package/dist/react/EventsSection-C1pbJDfW.js +86 -0
  64. package/dist/react/EventsTab-eCh02cdd.js +63 -0
  65. package/dist/react/FilterBar-DQRXpWrb.js +50 -0
  66. package/dist/react/InternalsContent-DBzsI0CG.js +346 -0
  67. package/dist/react/InternalsSection-t7ihcWO-.js +32 -0
  68. package/dist/react/InternalsTab-Oij0A2fN.js +30 -0
  69. package/dist/react/JobsSection-CLAin5vU.js +187 -0
  70. package/dist/react/JobsTab-Dl5nrj2z.js +141 -0
  71. package/dist/react/LogsSection-C1p81fXO.js +212 -0
  72. package/dist/react/LogsTab-D-kR7PjX.js +88 -0
  73. package/dist/react/OverviewSection-nm3xdACz.js +539 -0
  74. package/dist/react/Pagination-BkmzUDY8.js +64 -0
  75. package/dist/react/QueriesSection-DB12HMfQ.js +461 -0
  76. package/dist/react/QueriesTab-fyBB1u_Y.js +90 -0
  77. package/dist/react/RequestsSection-DTqB81ac.js +209 -0
  78. package/dist/react/RoutesSection-DJWa4NPV.js +74 -0
  79. package/dist/react/RoutesTab-D3l8TOpu.js +74 -0
  80. package/dist/react/TimelineSection-C4d-jRX1.js +158 -0
  81. package/dist/react/TimelineTab-C5TFaSmQ.js +193 -0
  82. package/dist/react/WaterfallChart-Cj73WdfM.js +100 -0
  83. package/dist/react/core/api-client.d.ts +73 -0
  84. package/dist/react/core/api-client.d.ts.map +1 -0
  85. package/dist/react/core/config-utils.d.ts +109 -0
  86. package/dist/react/core/config-utils.d.ts.map +1 -0
  87. package/dist/react/core/constants.d.ts +11 -0
  88. package/dist/react/core/constants.d.ts.map +1 -0
  89. package/dist/react/core/dashboard-api.d.ts +65 -0
  90. package/dist/react/core/dashboard-api.d.ts.map +1 -0
  91. package/dist/react/core/dashboard-data-controller.d.ts +157 -0
  92. package/dist/react/core/dashboard-data-controller.d.ts.map +1 -0
  93. package/dist/react/core/debug-data-controller.d.ts +89 -0
  94. package/dist/react/core/debug-data-controller.d.ts.map +1 -0
  95. package/dist/react/core/feature-detect.d.ts +67 -0
  96. package/dist/react/core/feature-detect.d.ts.map +1 -0
  97. package/dist/react/core/formatters.d.ts +189 -0
  98. package/dist/react/core/formatters.d.ts.map +1 -0
  99. package/dist/react/core/history-buffer.d.ts +23 -0
  100. package/dist/react/core/history-buffer.d.ts.map +1 -0
  101. package/dist/react/core/icons.d.ts +36 -0
  102. package/dist/react/core/icons.d.ts.map +1 -0
  103. package/dist/react/core/index.d.ts +39 -0
  104. package/dist/react/core/index.d.ts.map +1 -0
  105. package/dist/react/core/internals-utils.d.ts +71 -0
  106. package/dist/react/core/internals-utils.d.ts.map +1 -0
  107. package/dist/react/core/job-utils.d.ts +45 -0
  108. package/dist/react/core/job-utils.d.ts.map +1 -0
  109. package/dist/react/core/log-utils.d.ts +34 -0
  110. package/dist/react/core/log-utils.d.ts.map +1 -0
  111. package/dist/react/core/metrics.d.ts +41 -0
  112. package/dist/react/core/metrics.d.ts.map +1 -0
  113. package/dist/react/core/pagination.d.ts +128 -0
  114. package/dist/react/core/pagination.d.ts.map +1 -0
  115. package/dist/react/core/query-utils.d.ts +35 -0
  116. package/dist/react/core/query-utils.d.ts.map +1 -0
  117. package/dist/react/core/resizable-columns.d.ts +18 -0
  118. package/dist/react/core/resizable-columns.d.ts.map +1 -0
  119. package/dist/react/core/routes.d.ts +12 -0
  120. package/dist/react/core/routes.d.ts.map +1 -0
  121. package/dist/react/core/server-stats-controller.d.ts +106 -0
  122. package/dist/react/core/server-stats-controller.d.ts.map +1 -0
  123. package/dist/react/core/sparkline.d.ts +80 -0
  124. package/dist/react/core/sparkline.d.ts.map +1 -0
  125. package/dist/react/core/theme.d.ts +42 -0
  126. package/dist/react/core/theme.d.ts.map +1 -0
  127. package/dist/react/core/trace-utils.d.ts +62 -0
  128. package/dist/react/core/trace-utils.d.ts.map +1 -0
  129. package/dist/react/core/transmit-adapter.d.ts +59 -0
  130. package/dist/react/core/transmit-adapter.d.ts.map +1 -0
  131. package/dist/react/core/types.d.ts +619 -0
  132. package/dist/react/core/types.d.ts.map +1 -0
  133. package/dist/react/index-UdTfSvtO.js +1074 -0
  134. package/dist/react/index.js +18 -0
  135. package/dist/react/react/components/Dashboard/DashboardPage.d.ts +17 -0
  136. package/dist/react/react/components/Dashboard/DashboardPage.d.ts.map +1 -0
  137. package/dist/react/react/components/Dashboard/sections/CacheSection.d.ts +7 -0
  138. package/dist/react/react/components/Dashboard/sections/CacheSection.d.ts.map +1 -0
  139. package/dist/react/react/components/Dashboard/sections/ConfigSection.d.ts +7 -0
  140. package/dist/react/react/components/Dashboard/sections/ConfigSection.d.ts.map +1 -0
  141. package/dist/react/react/components/Dashboard/sections/EmailsSection.d.ts +7 -0
  142. package/dist/react/react/components/Dashboard/sections/EmailsSection.d.ts.map +1 -0
  143. package/dist/react/react/components/Dashboard/sections/EventsSection.d.ts +7 -0
  144. package/dist/react/react/components/Dashboard/sections/EventsSection.d.ts.map +1 -0
  145. package/dist/react/react/components/Dashboard/sections/InternalsSection.d.ts +14 -0
  146. package/dist/react/react/components/Dashboard/sections/InternalsSection.d.ts.map +1 -0
  147. package/dist/react/react/components/Dashboard/sections/JobsSection.d.ts +7 -0
  148. package/dist/react/react/components/Dashboard/sections/JobsSection.d.ts.map +1 -0
  149. package/dist/react/react/components/Dashboard/sections/LogsSection.d.ts +7 -0
  150. package/dist/react/react/components/Dashboard/sections/LogsSection.d.ts.map +1 -0
  151. package/dist/react/react/components/Dashboard/sections/OverviewSection.d.ts +7 -0
  152. package/dist/react/react/components/Dashboard/sections/OverviewSection.d.ts.map +1 -0
  153. package/dist/react/react/components/Dashboard/sections/QueriesSection.d.ts +7 -0
  154. package/dist/react/react/components/Dashboard/sections/QueriesSection.d.ts.map +1 -0
  155. package/dist/react/react/components/Dashboard/sections/RequestsSection.d.ts +7 -0
  156. package/dist/react/react/components/Dashboard/sections/RequestsSection.d.ts.map +1 -0
  157. package/dist/react/react/components/Dashboard/sections/RoutesSection.d.ts +7 -0
  158. package/dist/react/react/components/Dashboard/sections/RoutesSection.d.ts.map +1 -0
  159. package/dist/react/react/components/Dashboard/sections/TimelineSection.d.ts +9 -0
  160. package/dist/react/react/components/Dashboard/sections/TimelineSection.d.ts.map +1 -0
  161. package/dist/react/react/components/Dashboard/shared/DataTable.d.ts +27 -0
  162. package/dist/react/react/components/Dashboard/shared/DataTable.d.ts.map +1 -0
  163. package/dist/react/react/components/Dashboard/shared/FilterBar.d.ts +17 -0
  164. package/dist/react/react/components/Dashboard/shared/FilterBar.d.ts.map +1 -0
  165. package/dist/react/react/components/Dashboard/shared/Pagination.d.ts +13 -0
  166. package/dist/react/react/components/Dashboard/shared/Pagination.d.ts.map +1 -0
  167. package/dist/react/react/components/Dashboard/shared/TimeRangeSelector.d.ts +12 -0
  168. package/dist/react/react/components/Dashboard/shared/TimeRangeSelector.d.ts.map +1 -0
  169. package/dist/react/react/components/Dashboard/shared/WaterfallChart.d.ts +16 -0
  170. package/dist/react/react/components/Dashboard/shared/WaterfallChart.d.ts.map +1 -0
  171. package/dist/react/react/components/DebugPanel/DebugPanel.d.ts +16 -0
  172. package/dist/react/react/components/DebugPanel/DebugPanel.d.ts.map +1 -0
  173. package/dist/react/react/components/DebugPanel/tabs/CacheTab.d.ts +8 -0
  174. package/dist/react/react/components/DebugPanel/tabs/CacheTab.d.ts.map +1 -0
  175. package/dist/react/react/components/DebugPanel/tabs/ConfigTab.d.ts +8 -0
  176. package/dist/react/react/components/DebugPanel/tabs/ConfigTab.d.ts.map +1 -0
  177. package/dist/react/react/components/DebugPanel/tabs/CustomPaneTab.d.ts +14 -0
  178. package/dist/react/react/components/DebugPanel/tabs/CustomPaneTab.d.ts.map +1 -0
  179. package/dist/react/react/components/DebugPanel/tabs/EmailsTab.d.ts +7 -0
  180. package/dist/react/react/components/DebugPanel/tabs/EmailsTab.d.ts.map +1 -0
  181. package/dist/react/react/components/DebugPanel/tabs/EventsTab.d.ts +7 -0
  182. package/dist/react/react/components/DebugPanel/tabs/EventsTab.d.ts.map +1 -0
  183. package/dist/react/react/components/DebugPanel/tabs/InternalsTab.d.ts +12 -0
  184. package/dist/react/react/components/DebugPanel/tabs/InternalsTab.d.ts.map +1 -0
  185. package/dist/react/react/components/DebugPanel/tabs/JobsTab.d.ts +9 -0
  186. package/dist/react/react/components/DebugPanel/tabs/JobsTab.d.ts.map +1 -0
  187. package/dist/react/react/components/DebugPanel/tabs/LogsTab.d.ts +7 -0
  188. package/dist/react/react/components/DebugPanel/tabs/LogsTab.d.ts.map +1 -0
  189. package/dist/react/react/components/DebugPanel/tabs/QueriesTab.d.ts +7 -0
  190. package/dist/react/react/components/DebugPanel/tabs/QueriesTab.d.ts.map +1 -0
  191. package/dist/react/react/components/DebugPanel/tabs/RoutesTab.d.ts +8 -0
  192. package/dist/react/react/components/DebugPanel/tabs/RoutesTab.d.ts.map +1 -0
  193. package/dist/react/react/components/DebugPanel/tabs/TimelineTab.d.ts +7 -0
  194. package/dist/react/react/components/DebugPanel/tabs/TimelineTab.d.ts.map +1 -0
  195. package/dist/react/react/components/StatsBar/MetricCard.d.ts +21 -0
  196. package/dist/react/react/components/StatsBar/MetricCard.d.ts.map +1 -0
  197. package/dist/react/react/components/StatsBar/Sparkline.d.ts +15 -0
  198. package/dist/react/react/components/StatsBar/Sparkline.d.ts.map +1 -0
  199. package/dist/react/react/components/StatsBar/StatsBar.d.ts +22 -0
  200. package/dist/react/react/components/StatsBar/StatsBar.d.ts.map +1 -0
  201. package/dist/react/react/components/shared/Badge.d.ts +32 -0
  202. package/dist/react/react/components/shared/Badge.d.ts.map +1 -0
  203. package/dist/react/react/components/shared/ConfigContent.d.ts +13 -0
  204. package/dist/react/react/components/shared/ConfigContent.d.ts.map +1 -0
  205. package/dist/react/react/components/shared/InternalsContent.d.ts +10 -0
  206. package/dist/react/react/components/shared/InternalsContent.d.ts.map +1 -0
  207. package/dist/react/react/components/shared/JsonViewer.d.ts +12 -0
  208. package/dist/react/react/components/shared/JsonViewer.d.ts.map +1 -0
  209. package/dist/react/react/components/shared/ThemeToggle.d.ts +13 -0
  210. package/dist/react/react/components/shared/ThemeToggle.d.ts.map +1 -0
  211. package/dist/react/react/components/shared/Tooltip.d.ts +16 -0
  212. package/dist/react/react/components/shared/Tooltip.d.ts.map +1 -0
  213. package/dist/react/react/hooks/useApiClient.d.ts +10 -0
  214. package/dist/react/react/hooks/useApiClient.d.ts.map +1 -0
  215. package/dist/react/react/hooks/useDashboardApiBase.d.ts +19 -0
  216. package/dist/react/react/hooks/useDashboardApiBase.d.ts.map +1 -0
  217. package/dist/react/react/hooks/useDashboardData.d.ts +27 -0
  218. package/dist/react/react/hooks/useDashboardData.d.ts.map +1 -0
  219. package/dist/react/react/hooks/useDebugData.d.ts +17 -0
  220. package/dist/react/react/hooks/useDebugData.d.ts.map +1 -0
  221. package/dist/react/react/hooks/useFeatures.d.ts +13 -0
  222. package/dist/react/react/hooks/useFeatures.d.ts.map +1 -0
  223. package/dist/react/react/hooks/useResizableTable.d.ts +13 -0
  224. package/dist/react/react/hooks/useResizableTable.d.ts.map +1 -0
  225. package/dist/react/react/hooks/useServerStats.d.ts +21 -0
  226. package/dist/react/react/hooks/useServerStats.d.ts.map +1 -0
  227. package/dist/react/react/hooks/useTheme.d.ts +12 -0
  228. package/dist/react/react/hooks/useTheme.d.ts.map +1 -0
  229. package/dist/react/react/index.d.ts +14 -0
  230. package/dist/react/react/index.d.ts.map +1 -0
  231. package/dist/react/style.css +1 -0
  232. package/dist/react/useApiClient-BVtNCmnL.js +9 -0
  233. package/dist/react/useDashboardApiBase-Bi36pJ2L.js +14 -0
  234. package/dist/react/useResizableTable-CNJmACdt.js +13 -0
  235. package/dist/src/collectors/app_collector.d.ts.map +1 -1
  236. package/dist/src/collectors/app_collector.js +30 -2
  237. package/dist/src/collectors/auto_detect.d.ts +31 -0
  238. package/dist/src/collectors/auto_detect.d.ts.map +1 -0
  239. package/dist/src/collectors/auto_detect.js +120 -0
  240. package/dist/src/collectors/collector.d.ts +17 -0
  241. package/dist/src/collectors/collector.d.ts.map +1 -1
  242. package/dist/src/collectors/db_pool_collector.d.ts.map +1 -1
  243. package/dist/src/collectors/db_pool_collector.js +35 -1
  244. package/dist/src/collectors/http_collector.d.ts +4 -3
  245. package/dist/src/collectors/http_collector.d.ts.map +1 -1
  246. package/dist/src/collectors/http_collector.js +28 -11
  247. package/dist/src/collectors/index.d.ts +2 -0
  248. package/dist/src/collectors/index.d.ts.map +1 -1
  249. package/dist/src/collectors/index.js +1 -0
  250. package/dist/src/collectors/log_collector.d.ts +11 -4
  251. package/dist/src/collectors/log_collector.d.ts.map +1 -1
  252. package/dist/src/collectors/log_collector.js +51 -5
  253. package/dist/src/collectors/process_collector.d.ts.map +1 -1
  254. package/dist/src/collectors/process_collector.js +4 -0
  255. package/dist/src/collectors/queue_collector.d.ts.map +1 -1
  256. package/dist/src/collectors/queue_collector.js +55 -1
  257. package/dist/src/collectors/redis_collector.d.ts.map +1 -1
  258. package/dist/src/collectors/redis_collector.js +42 -3
  259. package/dist/src/collectors/system_collector.d.ts.map +1 -1
  260. package/dist/src/collectors/system_collector.js +4 -0
  261. package/dist/src/controller/api_controller.d.ts +101 -0
  262. package/dist/src/controller/api_controller.d.ts.map +1 -0
  263. package/dist/src/controller/api_controller.js +131 -0
  264. package/dist/src/controller/debug_controller.d.ts +19 -10
  265. package/dist/src/controller/debug_controller.d.ts.map +1 -1
  266. package/dist/src/controller/debug_controller.js +118 -101
  267. package/dist/src/core/theme.d.ts +42 -0
  268. package/dist/src/core/theme.d.ts.map +1 -0
  269. package/dist/src/core/theme.js +115 -0
  270. package/dist/src/dashboard/chart_aggregator.d.ts.map +1 -1
  271. package/dist/src/dashboard/chart_aggregator.js +3 -2
  272. package/dist/src/dashboard/dashboard_controller.d.ts +10 -14
  273. package/dist/src/dashboard/dashboard_controller.d.ts.map +1 -1
  274. package/dist/src/dashboard/dashboard_controller.js +132 -250
  275. package/dist/src/dashboard/dashboard_store.d.ts +62 -19
  276. package/dist/src/dashboard/dashboard_store.d.ts.map +1 -1
  277. package/dist/src/dashboard/dashboard_store.js +242 -53
  278. package/dist/src/dashboard/integrations/cache_inspector.d.ts +19 -1
  279. package/dist/src/dashboard/integrations/cache_inspector.d.ts.map +1 -1
  280. package/dist/src/dashboard/integrations/config_inspector.d.ts +1 -1
  281. package/dist/src/dashboard/integrations/config_inspector.d.ts.map +1 -1
  282. package/dist/src/dashboard/integrations/config_inspector.js +3 -2
  283. package/dist/src/dashboard/integrations/queue_inspector.d.ts +55 -10
  284. package/dist/src/dashboard/integrations/queue_inspector.d.ts.map +1 -1
  285. package/dist/src/dashboard/integrations/queue_inspector.js +70 -24
  286. package/dist/src/dashboard/migrator.d.ts +5 -0
  287. package/dist/src/dashboard/migrator.d.ts.map +1 -1
  288. package/dist/src/dashboard/migrator.js +44 -9
  289. package/dist/src/dashboard/models/stats_event.d.ts +1 -1
  290. package/dist/src/dashboard/models/stats_event.d.ts.map +1 -1
  291. package/dist/src/dashboard/models/stats_log.d.ts +1 -1
  292. package/dist/src/dashboard/models/stats_log.d.ts.map +1 -1
  293. package/dist/src/dashboard/models/stats_query.d.ts +1 -1
  294. package/dist/src/dashboard/models/stats_query.d.ts.map +1 -1
  295. package/dist/src/dashboard/models/stats_saved_filter.d.ts +1 -1
  296. package/dist/src/dashboard/models/stats_saved_filter.d.ts.map +1 -1
  297. package/dist/src/dashboard/models/stats_trace.d.ts +2 -1
  298. package/dist/src/dashboard/models/stats_trace.d.ts.map +1 -1
  299. package/dist/src/data/data_access.d.ts +105 -0
  300. package/dist/src/data/data_access.d.ts.map +1 -0
  301. package/dist/src/data/data_access.js +310 -0
  302. package/dist/src/data/index.d.ts +3 -0
  303. package/dist/src/data/index.d.ts.map +1 -0
  304. package/dist/src/data/index.js +1 -0
  305. package/dist/src/debug/debug_store.d.ts +20 -1
  306. package/dist/src/debug/debug_store.d.ts.map +1 -1
  307. package/dist/src/debug/debug_store.js +43 -15
  308. package/dist/src/debug/email_collector.d.ts +6 -2
  309. package/dist/src/debug/email_collector.d.ts.map +1 -1
  310. package/dist/src/debug/email_collector.js +3 -0
  311. package/dist/src/debug/event_collector.d.ts +6 -2
  312. package/dist/src/debug/event_collector.d.ts.map +1 -1
  313. package/dist/src/debug/event_collector.js +12 -8
  314. package/dist/src/debug/query_collector.d.ts +6 -2
  315. package/dist/src/debug/query_collector.d.ts.map +1 -1
  316. package/dist/src/debug/query_collector.js +3 -0
  317. package/dist/src/debug/ring_buffer.d.ts +1 -0
  318. package/dist/src/debug/ring_buffer.d.ts.map +1 -1
  319. package/dist/src/debug/ring_buffer.js +5 -2
  320. package/dist/src/debug/route_inspector.d.ts +2 -2
  321. package/dist/src/debug/route_inspector.d.ts.map +1 -1
  322. package/dist/src/debug/route_inspector.js +4 -3
  323. package/dist/src/debug/trace_collector.d.ts +7 -3
  324. package/dist/src/debug/trace_collector.d.ts.map +1 -1
  325. package/dist/src/debug/trace_collector.js +7 -5
  326. package/dist/src/debug/types.d.ts +107 -2
  327. package/dist/src/debug/types.d.ts.map +1 -1
  328. package/dist/src/debug/types.js +1 -1
  329. package/dist/src/define_config.d.ts +49 -5
  330. package/dist/src/define_config.d.ts.map +1 -1
  331. package/dist/src/define_config.js +361 -4
  332. package/dist/src/edge/bootstrap.d.ts +17 -0
  333. package/dist/src/edge/bootstrap.d.ts.map +1 -0
  334. package/dist/src/edge/bootstrap.js +29 -0
  335. package/dist/src/edge/client/dashboard.js +2 -3619
  336. package/dist/src/edge/client/debug-panel-deferred.js +1 -0
  337. package/dist/src/edge/client/debug-panel.js +1 -2140
  338. package/dist/src/edge/client/stats-bar.js +1 -801
  339. package/dist/src/edge/client-vue/dashboard.js +5 -0
  340. package/dist/src/edge/client-vue/debug-panel-deferred.js +4 -0
  341. package/dist/src/edge/client-vue/debug-panel.js +4 -0
  342. package/dist/src/edge/client-vue/stats-bar.js +4 -0
  343. package/dist/src/edge/plugin.d.ts +35 -2
  344. package/dist/src/edge/plugin.d.ts.map +1 -1
  345. package/dist/src/edge/plugin.js +30 -66
  346. package/dist/src/edge/types.d.ts +46 -0
  347. package/dist/src/edge/types.d.ts.map +1 -0
  348. package/dist/src/edge/types.js +4 -0
  349. package/dist/src/edge/views/dashboard.edge +1 -358
  350. package/dist/src/edge/views/debug-panel.edge +2 -154
  351. package/dist/src/edge/views/stats-bar.edge +15 -48
  352. package/dist/src/engine/stats_engine.d.ts +18 -0
  353. package/dist/src/engine/stats_engine.d.ts.map +1 -1
  354. package/dist/src/engine/stats_engine.js +45 -2
  355. package/dist/src/index.d.ts +1 -1
  356. package/dist/src/index.d.ts.map +1 -1
  357. package/dist/src/log_stream/log_stream_provider.d.ts.map +1 -1
  358. package/dist/src/log_stream/log_stream_provider.js +21 -4
  359. package/dist/src/log_stream/log_stream_service.d.ts +8 -1
  360. package/dist/src/log_stream/log_stream_service.d.ts.map +1 -1
  361. package/dist/src/log_stream/log_stream_service.js +27 -3
  362. package/dist/src/middleware/request_tracking_middleware.d.ts +1 -1
  363. package/dist/src/middleware/request_tracking_middleware.d.ts.map +1 -1
  364. package/dist/src/middleware/request_tracking_middleware.js +21 -6
  365. package/dist/src/prometheus/prometheus_collector.d.ts +2 -1
  366. package/dist/src/prometheus/prometheus_collector.d.ts.map +1 -1
  367. package/dist/src/provider/server_stats_provider.d.ts +100 -0
  368. package/dist/src/provider/server_stats_provider.d.ts.map +1 -1
  369. package/dist/src/provider/server_stats_provider.js +460 -104
  370. package/dist/src/routes/access_middleware.d.ts +2 -1
  371. package/dist/src/routes/access_middleware.d.ts.map +1 -1
  372. package/dist/src/routes/access_middleware.js +7 -1
  373. package/dist/src/routes/index.d.ts +4 -0
  374. package/dist/src/routes/index.d.ts.map +1 -0
  375. package/dist/src/routes/index.js +1 -0
  376. package/dist/src/routes/register_routes.d.ts +103 -0
  377. package/dist/src/routes/register_routes.d.ts.map +1 -0
  378. package/dist/src/routes/register_routes.js +356 -0
  379. package/dist/src/routes/router_types.d.ts +29 -0
  380. package/dist/src/routes/router_types.d.ts.map +1 -0
  381. package/dist/src/routes/router_types.js +1 -0
  382. package/dist/src/stubs/config.stub +12 -32
  383. package/dist/src/styles/components.css +1048 -0
  384. package/dist/src/{edge/client → styles}/dashboard.css +299 -736
  385. package/dist/src/{edge/client → styles}/debug-panel.css +117 -633
  386. package/dist/src/{edge/client → styles}/stats-bar.css +28 -10
  387. package/dist/src/styles/tokens.css +153 -0
  388. package/dist/src/styles/utilities.css +75 -0
  389. package/dist/src/types.d.ts +119 -16
  390. package/dist/src/types.d.ts.map +1 -1
  391. package/dist/src/utils/app_import.d.ts +23 -0
  392. package/dist/src/utils/app_import.d.ts.map +1 -0
  393. package/dist/src/utils/app_import.js +44 -0
  394. package/dist/src/utils/json_helpers.d.ts +2 -2
  395. package/dist/src/utils/json_helpers.d.ts.map +1 -1
  396. package/dist/src/utils/logger.d.ts +17 -0
  397. package/dist/src/utils/logger.d.ts.map +1 -0
  398. package/dist/src/utils/logger.js +27 -0
  399. package/dist/src/utils/mail_helpers.d.ts +1 -1
  400. package/dist/src/utils/mail_helpers.d.ts.map +1 -1
  401. package/dist/src/utils/mail_helpers.js +1 -1
  402. package/dist/vue/CacheSection-C788Yfai.js +149 -0
  403. package/dist/vue/CacheTab-BPisYYiQ.js +104 -0
  404. package/dist/vue/ConfigSection-CRzYxqW2.js +576 -0
  405. package/dist/vue/ConfigTab-C8cafGUj.js +361 -0
  406. package/dist/vue/CustomPaneTab-BJxT5Dp7.js +172 -0
  407. package/dist/vue/EmailsSection-C8JFMtW7.js +206 -0
  408. package/dist/vue/EmailsTab-DhFhoNmU.js +157 -0
  409. package/dist/vue/EventsSection-C4wXUgxG.js +107 -0
  410. package/dist/vue/EventsTab-DQ4Nd6AK.js +97 -0
  411. package/dist/vue/FilterBar.vue_vue_type_script_setup_true_lang-ClJ37hhT.js +62 -0
  412. package/dist/vue/InternalsSection-BJUXE-5F.js +468 -0
  413. package/dist/vue/InternalsTab-DEMjqtlw.js +471 -0
  414. package/dist/vue/JobsSection-CsKWTjgN.js +187 -0
  415. package/dist/vue/JobsTab-BCvhOARO.js +117 -0
  416. package/dist/vue/JsonViewer.vue_vue_type_script_setup_true_lang-Vsqar1zx.js +67 -0
  417. package/dist/vue/LogsSection-BFVjSZ24.js +227 -0
  418. package/dist/vue/LogsTab-DpEQ7euu.js +122 -0
  419. package/dist/vue/OverviewSection-CbMdAido.js +849 -0
  420. package/dist/vue/PaginationControls.vue_vue_type_script_setup_true_lang-CuN7g_8Z.js +50 -0
  421. package/dist/vue/QueriesSection-BPiv7u3r.js +429 -0
  422. package/dist/vue/QueriesTab-C8_7oprC.js +107 -0
  423. package/dist/vue/RequestsSection-LtImH4rD.js +243 -0
  424. package/dist/vue/RoutesSection-CrxOxmzx.js +106 -0
  425. package/dist/vue/RoutesTab-Dz0MkZuF.js +80 -0
  426. package/dist/vue/TimelineSection-DLxMW2J_.js +186 -0
  427. package/dist/vue/TimelineTab-Db6lKKsD.js +250 -0
  428. package/dist/vue/WaterfallChart.vue_vue_type_script_setup_true_lang-tZ13cNj1.js +118 -0
  429. package/dist/vue/components/Dashboard/DashboardPage.vue.d.ts +18 -0
  430. package/dist/vue/components/Dashboard/DashboardPage.vue.d.ts.map +1 -0
  431. package/dist/vue/components/Dashboard/sections/CacheSection.vue.d.ts +5 -0
  432. package/dist/vue/components/Dashboard/sections/CacheSection.vue.d.ts.map +1 -0
  433. package/dist/vue/components/Dashboard/sections/ConfigSection.vue.d.ts +3 -0
  434. package/dist/vue/components/Dashboard/sections/ConfigSection.vue.d.ts.map +1 -0
  435. package/dist/vue/components/Dashboard/sections/EmailsSection.vue.d.ts +5 -0
  436. package/dist/vue/components/Dashboard/sections/EmailsSection.vue.d.ts.map +1 -0
  437. package/dist/vue/components/Dashboard/sections/EventsSection.vue.d.ts +5 -0
  438. package/dist/vue/components/Dashboard/sections/EventsSection.vue.d.ts.map +1 -0
  439. package/dist/vue/components/Dashboard/sections/InternalsSection.vue.d.ts +3 -0
  440. package/dist/vue/components/Dashboard/sections/InternalsSection.vue.d.ts.map +1 -0
  441. package/dist/vue/components/Dashboard/sections/JobsSection.vue.d.ts +5 -0
  442. package/dist/vue/components/Dashboard/sections/JobsSection.vue.d.ts.map +1 -0
  443. package/dist/vue/components/Dashboard/sections/LogsSection.vue.d.ts +3 -0
  444. package/dist/vue/components/Dashboard/sections/LogsSection.vue.d.ts.map +1 -0
  445. package/dist/vue/components/Dashboard/sections/OverviewSection.vue.d.ts +5 -0
  446. package/dist/vue/components/Dashboard/sections/OverviewSection.vue.d.ts.map +1 -0
  447. package/dist/vue/components/Dashboard/sections/QueriesSection.vue.d.ts +45 -0
  448. package/dist/vue/components/Dashboard/sections/QueriesSection.vue.d.ts.map +1 -0
  449. package/dist/vue/components/Dashboard/sections/RequestsSection.vue.d.ts +5 -0
  450. package/dist/vue/components/Dashboard/sections/RequestsSection.vue.d.ts.map +1 -0
  451. package/dist/vue/components/Dashboard/sections/RoutesSection.vue.d.ts +5 -0
  452. package/dist/vue/components/Dashboard/sections/RoutesSection.vue.d.ts.map +1 -0
  453. package/dist/vue/components/Dashboard/sections/TimelineSection.vue.d.ts +11 -0
  454. package/dist/vue/components/Dashboard/sections/TimelineSection.vue.d.ts.map +1 -0
  455. package/dist/vue/components/Dashboard/shared/FilterBar.vue.d.ts +29 -0
  456. package/dist/vue/components/Dashboard/shared/FilterBar.vue.d.ts.map +1 -0
  457. package/dist/vue/components/Dashboard/shared/PaginationControls.vue.d.ts +12 -0
  458. package/dist/vue/components/Dashboard/shared/PaginationControls.vue.d.ts.map +1 -0
  459. package/dist/vue/components/Dashboard/shared/TimeRangeSelector.vue.d.ts +11 -0
  460. package/dist/vue/components/Dashboard/shared/TimeRangeSelector.vue.d.ts.map +1 -0
  461. package/dist/vue/components/Dashboard/shared/WaterfallChart.vue.d.ts +10 -0
  462. package/dist/vue/components/Dashboard/shared/WaterfallChart.vue.d.ts.map +1 -0
  463. package/dist/vue/components/DebugPanel/DebugPanel.vue.d.ts +21 -0
  464. package/dist/vue/components/DebugPanel/DebugPanel.vue.d.ts.map +1 -0
  465. package/dist/vue/components/DebugPanel/tabs/CacheTab.vue.d.ts +12 -0
  466. package/dist/vue/components/DebugPanel/tabs/CacheTab.vue.d.ts.map +1 -0
  467. package/dist/vue/components/DebugPanel/tabs/ConfigTab.vue.d.ts +11 -0
  468. package/dist/vue/components/DebugPanel/tabs/ConfigTab.vue.d.ts.map +1 -0
  469. package/dist/vue/components/DebugPanel/tabs/CustomPaneTab.vue.d.ts +11 -0
  470. package/dist/vue/components/DebugPanel/tabs/CustomPaneTab.vue.d.ts.map +1 -0
  471. package/dist/vue/components/DebugPanel/tabs/EmailsTab.vue.d.ts +12 -0
  472. package/dist/vue/components/DebugPanel/tabs/EmailsTab.vue.d.ts.map +1 -0
  473. package/dist/vue/components/DebugPanel/tabs/EventsTab.vue.d.ts +12 -0
  474. package/dist/vue/components/DebugPanel/tabs/EventsTab.vue.d.ts.map +1 -0
  475. package/dist/vue/components/DebugPanel/tabs/InternalsTab.vue.d.ts +11 -0
  476. package/dist/vue/components/DebugPanel/tabs/InternalsTab.vue.d.ts.map +1 -0
  477. package/dist/vue/components/DebugPanel/tabs/JobsTab.vue.d.ts +13 -0
  478. package/dist/vue/components/DebugPanel/tabs/JobsTab.vue.d.ts.map +1 -0
  479. package/dist/vue/components/DebugPanel/tabs/LogsTab.vue.d.ts +15 -0
  480. package/dist/vue/components/DebugPanel/tabs/LogsTab.vue.d.ts.map +1 -0
  481. package/dist/vue/components/DebugPanel/tabs/QueriesTab.vue.d.ts +12 -0
  482. package/dist/vue/components/DebugPanel/tabs/QueriesTab.vue.d.ts.map +1 -0
  483. package/dist/vue/components/DebugPanel/tabs/RoutesTab.vue.d.ts +12 -0
  484. package/dist/vue/components/DebugPanel/tabs/RoutesTab.vue.d.ts.map +1 -0
  485. package/dist/vue/components/DebugPanel/tabs/TimelineTab.vue.d.ts +15 -0
  486. package/dist/vue/components/DebugPanel/tabs/TimelineTab.vue.d.ts.map +1 -0
  487. package/dist/vue/components/StatsBar/MetricCard.vue.d.ts +19 -0
  488. package/dist/vue/components/StatsBar/MetricCard.vue.d.ts.map +1 -0
  489. package/dist/vue/components/StatsBar/Sparkline.vue.d.ts +17 -0
  490. package/dist/vue/components/StatsBar/Sparkline.vue.d.ts.map +1 -0
  491. package/dist/vue/components/StatsBar/StatsBar.vue.d.ts +22 -0
  492. package/dist/vue/components/StatsBar/StatsBar.vue.d.ts.map +1 -0
  493. package/dist/vue/components/shared/JsonViewer.vue.d.ts +13 -0
  494. package/dist/vue/components/shared/JsonViewer.vue.d.ts.map +1 -0
  495. package/dist/vue/components/shared/ThemeToggle.vue.d.ts +8 -0
  496. package/dist/vue/components/shared/ThemeToggle.vue.d.ts.map +1 -0
  497. package/dist/vue/composables/useApiClient.d.ts +9 -0
  498. package/dist/vue/composables/useApiClient.d.ts.map +1 -0
  499. package/dist/vue/composables/useDashboardData.d.ts +53 -0
  500. package/dist/vue/composables/useDashboardData.d.ts.map +1 -0
  501. package/dist/vue/composables/useDebugData.d.ts +25 -0
  502. package/dist/vue/composables/useDebugData.d.ts.map +1 -0
  503. package/dist/vue/composables/useFeatures.d.ts +80 -0
  504. package/dist/vue/composables/useFeatures.d.ts.map +1 -0
  505. package/dist/vue/composables/useResizableTable.d.ts +16 -0
  506. package/dist/vue/composables/useResizableTable.d.ts.map +1 -0
  507. package/dist/vue/composables/useServerStats.d.ts +104 -0
  508. package/dist/vue/composables/useServerStats.d.ts.map +1 -0
  509. package/dist/vue/composables/useTheme.d.ts +6 -0
  510. package/dist/vue/composables/useTheme.d.ts.map +1 -0
  511. package/dist/vue/index-qCQpBftQ.js +1233 -0
  512. package/dist/vue/index.d.ts +10 -0
  513. package/dist/vue/index.d.ts.map +1 -0
  514. package/dist/vue/index.js +11 -0
  515. package/dist/vue/style.css +1 -0
  516. package/dist/vue/useApiClient-BQQ9CF-q.js +10 -0
  517. package/dist/vue/useResizableTable-BoivAevK.js +17 -0
  518. package/package.json +72 -10
  519. package/dist/src/dashboard/dashboard_routes.d.ts +0 -16
  520. package/dist/src/dashboard/dashboard_routes.d.ts.map +0 -1
  521. package/dist/src/dashboard/dashboard_routes.js +0 -77
  522. package/dist/src/routes/debug_routes.d.ts +0 -14
  523. package/dist/src/routes/debug_routes.d.ts.map +0 -1
  524. package/dist/src/routes/debug_routes.js +0 -42
  525. package/dist/src/routes/stats_routes.d.ts +0 -14
  526. package/dist/src/routes/stats_routes.d.ts.map +0 -1
  527. package/dist/src/routes/stats_routes.js +0 -27
@@ -1,12 +1,11 @@
1
1
  import { readFileSync } from 'node:fs';
2
- import { registerDashboardRoutes } from '../dashboard/dashboard_routes.js';
3
- import { DashboardStore } from '../dashboard/dashboard_store.js';
2
+ import { getLogStreamService } from '../collectors/log_collector.js';
4
3
  import { DebugStore } from '../debug/debug_store.js';
5
4
  import { StatsEngine } from '../engine/stats_engine.js';
6
5
  import { LogStreamService } from '../log_stream/log_stream_service.js';
7
6
  import { setShouldShow, setTraceCollector, setDashboardPath, setExcludedPrefixes, setOnRequestComplete, } from '../middleware/request_tracking_middleware.js';
8
- import { registerDebugRoutes } from '../routes/debug_routes.js';
9
- import { registerStatsRoutes } from '../routes/stats_routes.js';
7
+ import { registerAllRoutes } from '../routes/register_routes.js';
8
+ import { log, dim, bold } from '../utils/logger.js';
10
9
  export default class ServerStatsProvider {
11
10
  app;
12
11
  intervalId = null;
@@ -21,13 +20,39 @@ export default class ServerStatsProvider {
21
20
  flushTimer = null;
22
21
  statsController = null;
23
22
  debugController = null;
23
+ apiController = null;
24
+ // Dashboard dependency check (set in boot, read in ready)
25
+ dashboardDepsAvailable = true;
26
+ // Diagnostics tracking
27
+ pinoHookActive = false;
28
+ edgePluginActive = false;
29
+ prometheusActive = false;
30
+ transmitAvailable = false;
31
+ transmitChannels = [];
32
+ resolvedConfig = null;
33
+ resolvedCollectors = [];
24
34
  constructor(app) {
25
35
  this.app = app;
26
36
  }
27
37
  async boot() {
38
+ try {
39
+ await this.initializeBoot();
40
+ }
41
+ catch (err) {
42
+ log.warn(`boot failed: ${err?.message ?? err}\n` +
43
+ ` ${dim('The server will continue without server-stats.')}`);
44
+ if (err?.stack) {
45
+ console.error(err.stack);
46
+ }
47
+ }
48
+ }
49
+ async initializeBoot() {
28
50
  const config = this.app.config.get('server_stats');
29
- if (!config)
51
+ if (!config) {
52
+ log.warn('no config found — is config/server_stats.ts set up?');
30
53
  return;
54
+ }
55
+ log.info('booting...');
31
56
  // Wire up the per-request shouldShow callback
32
57
  if (config.shouldShow) {
33
58
  setShouldShow(config.shouldShow);
@@ -41,55 +66,95 @@ export default class ServerStatsProvider {
41
66
  }
42
67
  if (router && !this.app.inProduction) {
43
68
  const registeredPaths = [];
44
- // ── Auto-register stats bar endpoint ───────────────────────
45
- if (typeof config.endpoint === 'string') {
46
- registerStatsRoutes(router, config.endpoint, () => this.statsController, config.shouldShow);
47
- registeredPaths.push(config.endpoint);
48
- }
49
- // ── Auto-register debug toolbar routes ─────────────────────
69
+ const r = router;
50
70
  const toolbarConfig = config.devToolbar;
51
- if (toolbarConfig?.enabled) {
52
- const debugEndpoint = toolbarConfig.debugEndpoint ?? '/admin/api/debug';
53
- registerDebugRoutes(router, debugEndpoint, () => this.debugController, config.shouldShow);
54
- registeredPaths.push(debugEndpoint + '/*');
55
- // ── Auto-register dashboard routes ─────────────────────────
56
- if (toolbarConfig.dashboard) {
57
- const dashPath = toolbarConfig.dashboardPath ?? '/__stats';
58
- registerDashboardRoutes(router, dashPath, () => this.dashboardController, config.shouldShow);
59
- registeredPaths.push(dashPath + '/*');
71
+ // Derive endpoint paths for route registration
72
+ const statsEndpoint = typeof config.endpoint === 'string' ? config.endpoint : false;
73
+ const debugEndpoint = toolbarConfig?.enabled
74
+ ? (toolbarConfig.debugEndpoint ?? '/admin/api/debug')
75
+ : undefined;
76
+ // Check dashboard dependencies before registering dashboard routes.
77
+ // Must use appImport bare import() resolves to this package's
78
+ // devDeps when symlinked, not the app's actual dependencies.
79
+ if (toolbarConfig?.enabled && toolbarConfig.dashboard) {
80
+ const { appImport } = await import('../utils/app_import.js');
81
+ const missing = [];
82
+ try {
83
+ await appImport('knex');
60
84
  }
85
+ catch {
86
+ missing.push('knex');
87
+ }
88
+ try {
89
+ await appImport('better-sqlite3');
90
+ }
91
+ catch {
92
+ missing.push('better-sqlite3');
93
+ }
94
+ if (missing.length > 0) {
95
+ this.dashboardDepsAvailable = false;
96
+ log.block(`Dashboard requires ${missing.join(' and ')}. Install with:`, [
97
+ '',
98
+ bold(`npm install ${missing.join(' ')}`),
99
+ '',
100
+ dim('Dashboard routes have been skipped for now.'),
101
+ dim('Everything else (stats bar, debug panel) works without it.'),
102
+ ]);
103
+ }
104
+ }
105
+ const dashboardPath = toolbarConfig?.enabled && toolbarConfig.dashboard && this.dashboardDepsAvailable
106
+ ? (toolbarConfig.dashboardPath ?? '/__stats')
107
+ : undefined;
108
+ // ── Register all routes via the unified registrar ──────────
109
+ registerAllRoutes({
110
+ router: r,
111
+ getApiController: () => this.apiController,
112
+ getStatsController: () => this.statsController,
113
+ getDebugController: () => this.debugController,
114
+ getDashboardController: () => this.dashboardController,
115
+ statsEndpoint,
116
+ debugEndpoint,
117
+ dashboardPath,
118
+ shouldShow: config.shouldShow,
119
+ });
120
+ // Track which paths were registered for logging
121
+ if (typeof statsEndpoint === 'string') {
122
+ registeredPaths.push(statsEndpoint);
123
+ }
124
+ if (debugEndpoint) {
125
+ registeredPaths.push(debugEndpoint + '/*');
126
+ }
127
+ if (dashboardPath) {
128
+ registeredPaths.push(dashboardPath + '/*');
61
129
  }
62
130
  // Log registered routes
63
131
  if (registeredPaths.length > 0) {
64
- const tag = '\x1b[36m[ \x1b[1m🔍 server-stats\x1b[0m\x1b[36m ]\x1b[0m';
65
- const dim = (s) => `\x1b[2m${s}\x1b[0m`;
66
- const bold = (s) => `\x1b[1m${s}\x1b[0m`;
67
- console.log(`\n${tag} routes registered:\n` +
68
- registeredPaths.map((p) => ` ${dim('→')} ${bold(p)}`).join('\n'));
132
+ log.list('routes auto-registered (no manual setup needed):', registeredPaths);
69
133
  // Only warn about global auth middleware if:
70
134
  // 1. shouldShow is NOT configured (user hasn't set up access control)
71
135
  // 2. There IS auth middleware in server.use() or router.use()
72
136
  if (!config.shouldShow) {
73
137
  const authMiddleware = this.detectGlobalAuthMiddleware();
74
138
  if (authMiddleware.length > 0) {
75
- console.log(`\n${tag} ${bold('found global auth middleware that will run on every poll:')}\n` +
76
- authMiddleware.map((m) => ` ${dim('→')} ${m}`).join('\n') +
77
- '\n\n' +
78
- ` ${dim('these routes get polled every ~3s, so auth middleware will')}\n` +
79
- ` ${dim('trigger a DB query on each poll. here are two ways to fix it:')}\n` +
80
- '\n' +
81
- ` ${bold('option 1:')} add a shouldShow callback to your config:\n` +
82
- '\n' +
83
- ` ${dim('// config/server_stats.ts')}\n` +
84
- ` ${dim("shouldShow: (ctx) => ctx.auth?.user?.role === 'admin'")}\n` +
85
- '\n' +
86
- ` ${bold('option 2:')} move auth middleware from router.use() to a route group:\n` +
87
- '\n' +
88
- ` ${dim('// start/kernel.ts — remove from router.use()')}\n` +
89
- ` ${dim("// () => import('#middleware/silent_auth_middleware')")}\n` +
90
- '\n' +
91
- ` ${dim('// start/routes.ts — add to your route groups instead')}\n` +
92
- ` ${dim("router.group(() => { ... }).use(middleware.silentAuth())")}\n`);
139
+ log.block(bold('found global auth middleware that will run on every poll:'), [
140
+ ...authMiddleware.map((m) => `${dim('→')} ${m}`),
141
+ '',
142
+ dim('these routes get polled every ~3s, so auth middleware will'),
143
+ dim('trigger a DB query on each poll. here are two ways to fix it:'),
144
+ '',
145
+ `${bold('option 1:')} add a shouldShow callback to your config:`,
146
+ '',
147
+ dim('// config/server_stats.ts'),
148
+ dim("shouldShow: (ctx) => ctx.auth?.user?.role === 'admin'"),
149
+ '',
150
+ `${bold('option 2:')} move auth middleware from router.use() to a route group:`,
151
+ '',
152
+ dim('// start/kernel.ts — remove from router.use()'),
153
+ dim("// () => import('#middleware/silent_auth_middleware')"),
154
+ '',
155
+ dim('// start/routes.ts — add to your route groups instead'),
156
+ dim('router.group(() => { ... }).use(middleware.silentAuth())'),
157
+ ]);
93
158
  }
94
159
  }
95
160
  }
@@ -97,12 +162,18 @@ export default class ServerStatsProvider {
97
162
  if (!this.app.usingEdgeJS)
98
163
  return;
99
164
  try {
100
- const edge = await import('edge.js');
165
+ // Must use appImport for edge.js — when this package is symlinked,
166
+ // bare import('edge.js') resolves to the package's devDep copy,
167
+ // which is a different singleton than the app's Edge instance.
168
+ const { appImport } = await import('../utils/app_import.js');
169
+ const edge = await appImport('edge.js');
101
170
  const { edgePluginServerStats } = await import('../edge/plugin.js');
102
171
  edge.default.use(edgePluginServerStats(config));
172
+ this.edgePluginActive = true;
103
173
  }
104
- catch {
105
- // Edge not available skip tag registration
174
+ catch (err) {
175
+ log.warn('could not register Edge plugin@serverStats() tag will not work: ' +
176
+ err?.message);
106
177
  }
107
178
  }
108
179
  /**
@@ -155,36 +226,115 @@ export default class ServerStatsProvider {
155
226
  }
156
227
  return found;
157
228
  }
229
+ /**
230
+ * Hook into the AdonisJS logger's Pino stream to feed log entries
231
+ * directly into the LogStreamService — no file path needed.
232
+ *
233
+ * Uses `Symbol.for('pino.stream')` (documented Pino API) to access
234
+ * the underlying destination stream, then wraps its `write` method
235
+ * to tee entries into the log collector.
236
+ */
237
+ async hookPinoLogger() {
238
+ const logStream = getLogStreamService();
239
+ if (!logStream)
240
+ return; // logCollector() not in the config
241
+ let logger;
242
+ try {
243
+ logger = await this.app.container.make('logger');
244
+ }
245
+ catch {
246
+ // Logger not available
247
+ }
248
+ const pino = logger?.pino;
249
+ if (!pino)
250
+ return;
251
+ const streamSym = Symbol.for('pino.stream');
252
+ const rawStream = pino[streamSym];
253
+ if (!rawStream || typeof rawStream.write !== 'function')
254
+ return;
255
+ const stream = rawStream;
256
+ const originalWrite = stream.write.bind(stream);
257
+ stream.write = function (chunk, ...args) {
258
+ try {
259
+ const str = typeof chunk === 'string' ? chunk : chunk.toString();
260
+ const entry = JSON.parse(str);
261
+ if (entry && typeof entry.level === 'number') {
262
+ logStream.ingest(entry);
263
+ }
264
+ }
265
+ catch {
266
+ // Not valid JSON — ignore (e.g. pino-pretty output)
267
+ }
268
+ return originalWrite(chunk, ...args);
269
+ };
270
+ this.pinoHookActive = true;
271
+ log.info('log collector hooked into AdonisJS logger (zero-config)');
272
+ }
158
273
  async ready() {
159
274
  const config = this.app.config.get('server_stats');
160
275
  if (!config)
161
276
  return;
162
277
  if (this.app.inTest && config.skipInTest !== false)
163
278
  return;
164
- this.engine = new StatsEngine(config.collectors);
279
+ // Defer the entire initialization to setImmediate so ready() returns
280
+ // immediately. AdonisJS waits for all provider ready() hooks before
281
+ // processing HTTP requests — blocking here would hang the server.
282
+ // Routes use lazy controller getters that return 503 until init completes.
283
+ setImmediate(() => {
284
+ this.initializeServerStats(config).catch((err) => {
285
+ log.warn(`failed to initialize: ${err?.message ?? err}\n` +
286
+ ` ${dim('The server will continue without server-stats.')}`);
287
+ if (err?.stack) {
288
+ console.error(err.stack);
289
+ }
290
+ });
291
+ });
292
+ }
293
+ async initializeServerStats(config) {
294
+ this.resolvedConfig = config;
295
+ let collectors;
296
+ if (!config.collectors || config.collectors === 'auto') {
297
+ const { autoDetectCollectors } = await import('../collectors/auto_detect.js');
298
+ const result = await autoDetectCollectors();
299
+ collectors = result.collectors;
300
+ log.info(`${bold(String(result.active))} of ${bold(String(result.total))} collectors active`);
301
+ }
302
+ else {
303
+ collectors = config.collectors;
304
+ }
305
+ this.resolvedCollectors = collectors;
306
+ this.engine = new StatsEngine(collectors);
165
307
  this.app.container.singleton('server_stats.engine', () => this.engine);
166
308
  await this.engine.start();
309
+ // Auto-hook log collector into the AdonisJS Pino logger (zero-config)
310
+ await this.hookPinoLogger();
167
311
  // Create the stats controller (makes the stats route functional)
168
312
  const StatsControllerClass = (await import('../controller/server_stats_controller.js')).default;
169
313
  this.statsController = new StatsControllerClass(this.engine);
170
314
  // Dev toolbar setup
171
315
  const toolbarConfig = config.devToolbar;
172
316
  if (toolbarConfig?.enabled && !this.app.inProduction) {
173
- await this.setupDevToolbar({
174
- enabled: true,
175
- maxQueries: toolbarConfig.maxQueries ?? 500,
176
- maxEvents: toolbarConfig.maxEvents ?? 200,
177
- maxEmails: toolbarConfig.maxEmails ?? 100,
178
- slowQueryThresholdMs: toolbarConfig.slowQueryThresholdMs ?? 100,
179
- persistDebugData: toolbarConfig.persistDebugData ?? false,
180
- tracing: toolbarConfig.tracing ?? false,
181
- maxTraces: toolbarConfig.maxTraces ?? 200,
182
- dashboard: toolbarConfig.dashboard ?? false,
183
- dashboardPath: toolbarConfig.dashboardPath ?? '/__stats',
184
- retentionDays: toolbarConfig.retentionDays ?? 7,
185
- dbPath: toolbarConfig.dbPath ?? '.adonisjs/server-stats/dashboard.sqlite3',
186
- debugEndpoint: toolbarConfig.debugEndpoint ?? '/admin/api/debug',
187
- });
317
+ try {
318
+ await this.setupDevToolbar({
319
+ enabled: true,
320
+ maxQueries: toolbarConfig.maxQueries ?? 500,
321
+ maxEvents: toolbarConfig.maxEvents ?? 200,
322
+ maxEmails: toolbarConfig.maxEmails ?? 100,
323
+ slowQueryThresholdMs: toolbarConfig.slowQueryThresholdMs ?? 100,
324
+ persistDebugData: toolbarConfig.persistDebugData ?? false,
325
+ tracing: toolbarConfig.tracing ?? false,
326
+ maxTraces: toolbarConfig.maxTraces ?? 200,
327
+ dashboard: toolbarConfig.dashboard ?? false,
328
+ dashboardPath: toolbarConfig.dashboardPath ?? '/__stats',
329
+ retentionDays: toolbarConfig.retentionDays ?? 7,
330
+ dbPath: toolbarConfig.dbPath ?? '.adonisjs/server-stats/dashboard.sqlite3',
331
+ debugEndpoint: toolbarConfig.debugEndpoint ?? '/admin/api/debug',
332
+ });
333
+ }
334
+ catch (err) {
335
+ log.warn(`dev toolbar setup failed: ${err?.message ?? err}\n` +
336
+ ` ${dim('Stats bar will still work, but debug panel may be unavailable.')}`);
337
+ }
188
338
  // Exclude the stats endpoint and user-specified prefixes from tracing
189
339
  // so the debug panel's own polling doesn't flood the timeline
190
340
  const debugEndpoint = toolbarConfig.debugEndpoint ?? '/admin/api/debug';
@@ -196,31 +346,67 @@ export default class ServerStatsProvider {
196
346
  if (prefixes.length > 0) {
197
347
  setExcludedPrefixes(prefixes);
198
348
  }
349
+ // Create the unified ApiController now that debug store is available.
350
+ // Dashboard store is passed as a getter so it picks up the reference
351
+ // once setupDashboard() completes asynchronously.
352
+ if (this.debugStore) {
353
+ const logPath = this.app.makePath('logs', 'adonisjs.log');
354
+ const { DataAccess: DataAccessClass } = await import('../data/data_access.js');
355
+ const dataAccess = new DataAccessClass(this.debugStore, () => this.dashboardStore, logPath);
356
+ const { ApiController: ApiControllerClass } = await import('../controller/api_controller.js');
357
+ this.apiController = new ApiControllerClass(dataAccess);
358
+ }
199
359
  }
360
+ // ── Stats collection interval + transmit (lightweight, set up inline) ──
361
+ this.setupStatsInterval(config);
362
+ log.info('ready');
363
+ }
364
+ /**
365
+ * Set up the stats collection interval, transmit broadcasting,
366
+ * and Prometheus integration. Extracted from initializeServerStats
367
+ * so the ready log fires promptly.
368
+ */
369
+ setupStatsInterval(config) {
200
370
  let transmit = null;
201
- if (config.transport === 'transmit') {
371
+ let prometheusCollector = null;
372
+ // Resolve transmit + prometheus asynchronously but don't block ready()
373
+ const resolveIntegrations = async () => {
374
+ if (config.transport === 'transmit') {
375
+ try {
376
+ transmit = await this.app.container.make('transmit');
377
+ if (transmit) {
378
+ this.transmitAvailable = true;
379
+ if (config.channelName) {
380
+ this.transmitChannels.push(config.channelName);
381
+ }
382
+ }
383
+ }
384
+ catch {
385
+ log.info('transport is "transmit" but @adonisjs/transmit is not installed — falling back to polling');
386
+ }
387
+ }
202
388
  try {
203
- transmit = await this.app.container.make('transmit');
389
+ const mod = await import('../prometheus/prometheus_collector.js');
390
+ prometheusCollector = mod.ServerStatsCollector.instance;
204
391
  }
205
392
  catch {
206
- // Transmit not installed — skip broadcasting
393
+ // Prometheus not installed — skip (optional dependency)
207
394
  }
208
- }
209
- let prometheusCollector = null;
210
- try {
211
- const mod = await import('../prometheus/prometheus_collector.js');
212
- prometheusCollector = mod.ServerStatsCollector.instance;
213
- }
214
- catch {
215
- // Prometheus not installed — skip
216
- }
395
+ if (prometheusCollector) {
396
+ this.prometheusActive = true;
397
+ log.info('Prometheus integration active');
398
+ }
399
+ };
400
+ resolveIntegrations().catch(() => { });
217
401
  this.intervalId = setInterval(async () => {
218
402
  try {
219
403
  const stats = await this.engine.collect();
220
404
  if (transmit && config.channelName) {
405
+ ;
221
406
  transmit.broadcast(config.channelName, JSON.parse(JSON.stringify(stats)));
222
407
  }
223
408
  if (prometheusCollector) {
409
+ ;
224
410
  prometheusCollector.update(stats);
225
411
  }
226
412
  config.onStats?.(stats);
@@ -247,7 +433,7 @@ export default class ServerStatsProvider {
247
433
  emitter = await this.app.container.make('emitter');
248
434
  }
249
435
  catch {
250
- // Emitter not available
436
+ log.warn('AdonisJS emitter not available — query and event collection will be disabled');
251
437
  }
252
438
  // Get the router
253
439
  let router = null;
@@ -259,9 +445,14 @@ export default class ServerStatsProvider {
259
445
  }
260
446
  await this.debugStore.start(emitter, router);
261
447
  // Create the debug controller (makes the debug routes functional)
262
- const logPath = this.app.makePath('logs', 'adonisjs.log');
448
+ const serverConfig = this.app.config.get('server_stats');
263
449
  const DebugControllerClass = (await import('../controller/debug_controller.js')).default;
264
- this.debugController = new DebugControllerClass(this.debugStore, logPath);
450
+ this.debugController = new DebugControllerClass(this.debugStore, serverConfig, {
451
+ getEngine: () => this.engine,
452
+ getDashboardStore: () => this.dashboardStore,
453
+ getProviderDiagnostics: () => this.getDiagnostics(),
454
+ getApp: () => this.app,
455
+ });
265
456
  // Wire trace collector into the request tracking middleware
266
457
  if (this.debugStore.traces) {
267
458
  setTraceCollector(this.debugStore.traces);
@@ -286,7 +477,11 @@ export default class ServerStatsProvider {
286
477
  // Transmit not installed — debug panel will use polling
287
478
  }
288
479
  if (debugTransmit) {
480
+ this.transmitAvailable = true;
289
481
  const debugChannel = 'server-stats/debug';
482
+ if (!this.transmitChannels.includes(debugChannel)) {
483
+ this.transmitChannels.push(debugChannel);
484
+ }
290
485
  const pendingTypes = new Set();
291
486
  this.debugStore.onNewItem((type) => {
292
487
  // Debounce: coalesce rapid events into a single broadcast
@@ -298,6 +493,7 @@ export default class ServerStatsProvider {
298
493
  const types = Array.from(pendingTypes);
299
494
  pendingTypes.clear();
300
495
  try {
496
+ ;
301
497
  debugTransmit.broadcast(debugChannel, { types });
302
498
  }
303
499
  catch {
@@ -306,9 +502,17 @@ export default class ServerStatsProvider {
306
502
  }, 200);
307
503
  });
308
504
  }
309
- // Full-page dashboard setup (routes already registered in boot)
310
- if (toolbarConfig.dashboard) {
311
- await this.setupDashboard(toolbarConfig, emitter);
505
+ // Full-page dashboard setup deferred with setImmediate so it runs
506
+ // AFTER the current event-loop cycle completes. This guarantees
507
+ // ready() returns and AdonisJS can process HTTP requests while the
508
+ // SQLite store initializes in the background.
509
+ if (toolbarConfig.dashboard && this.dashboardDepsAvailable) {
510
+ setImmediate(() => {
511
+ this.setupDashboard(toolbarConfig, emitter).catch((err) => {
512
+ log.warn(`dashboard setup failed: ${err?.message ?? err}\n` +
513
+ ` ${dim('Everything else continues to work.')}`);
514
+ });
515
+ });
312
516
  }
313
517
  }
314
518
  /**
@@ -319,42 +523,99 @@ export default class ServerStatsProvider {
319
523
  * This method creates the controller so those routes become functional.
320
524
  */
321
525
  async setupDashboard(toolbarConfig, emitter) {
322
- // Create and start the DashboardStore
323
- this.dashboardStore = new DashboardStore(toolbarConfig);
526
+ log.info('dashboard: initializing SQLite store...');
527
+ // Dynamically import DashboardStore so knex/better-sqlite3 are truly optional
528
+ const { DashboardStore: DashboardStoreClass } = await import('../dashboard/dashboard_store.js');
529
+ this.dashboardStore = new DashboardStoreClass(toolbarConfig);
324
530
  const appRoot = this.app.makePath('');
325
531
  try {
326
- await this.dashboardStore.start(null, emitter, appRoot);
532
+ // Timeout safety net: if SQLite init hangs (e.g. wrong native binary
533
+ // loaded via symlink), abort after 15s instead of freezing forever.
534
+ const TIMEOUT_MS = 15_000;
535
+ const startPromise = this.dashboardStore.start(null, emitter, appRoot);
536
+ const timeoutPromise = new Promise((_, reject) => {
537
+ setTimeout(() => reject(new Error(`Dashboard SQLite initialization timed out after ${TIMEOUT_MS / 1000}s`)), TIMEOUT_MS);
538
+ });
539
+ await Promise.race([startPromise, timeoutPromise]);
540
+ log.info('dashboard: SQLite store ready');
327
541
  }
328
542
  catch (err) {
329
543
  const msg = err?.message || '';
330
- if (msg.includes('better-sqlite3') || msg.includes('Cannot find module')) {
331
- console.warn('[server-stats] Dashboard requires better-sqlite3. Install it with:\n' +
332
- ' npm install better-sqlite3\n' +
333
- 'Dashboard has been disabled for this session.');
334
- this.dashboardStore = null;
335
- return;
544
+ const code = err?.code || '';
545
+ const isMissingDep = msg.includes('better-sqlite3') ||
546
+ msg.includes('knex') ||
547
+ msg.includes('Cannot find module') ||
548
+ msg.includes('Cannot find package') ||
549
+ code === 'ERR_MODULE_NOT_FOUND' ||
550
+ code === 'MODULE_NOT_FOUND';
551
+ const isTimeout = msg.includes('timed out');
552
+ if (isMissingDep) {
553
+ log.block('Dashboard could not start — missing dependencies. Install with:', [
554
+ '',
555
+ bold('npm install knex better-sqlite3'),
556
+ '',
557
+ dim('Dashboard has been disabled for this session.'),
558
+ dim('Everything else (stats bar, debug panel) works without it.'),
559
+ ]);
560
+ }
561
+ else if (isTimeout) {
562
+ log.block('Dashboard initialization timed out', [
563
+ dim('SQLite setup took too long — this usually means a wrong native'),
564
+ dim('binary was loaded (common with symlinked/file: dependencies).'),
565
+ '',
566
+ dim('Try running:'),
567
+ ` ${bold('npm install knex better-sqlite3')}`,
568
+ dim('in your app directory to ensure the correct copies are used.'),
569
+ '',
570
+ dim('Dashboard has been disabled for this session.'),
571
+ dim('Everything else (stats bar, debug panel) works without it.'),
572
+ ]);
573
+ }
574
+ else {
575
+ log.warn(`Dashboard could not start: ${msg}\n` +
576
+ ` ${dim('Dashboard has been disabled for this session.')}`);
577
+ if (err?.stack) {
578
+ console.error(err.stack);
579
+ }
336
580
  }
337
- throw err;
581
+ this.dashboardStore = null;
582
+ return;
338
583
  }
339
- // Bind to container
340
- ;
584
+ log.info('dashboard: binding to container...');
341
585
  this.app.container.singleton('dashboard.store', () => this.dashboardStore);
342
586
  // Set dashboard path in middleware for self-exclusion
343
587
  setDashboardPath(toolbarConfig.dashboardPath);
344
588
  // Create the controller — this makes the routes registered in boot() functional
589
+ log.info('dashboard: creating controller...');
345
590
  const DashboardControllerClass = (await import('../dashboard/dashboard_controller.js')).default;
346
- this.dashboardController = new DashboardControllerClass(this.dashboardStore, this.debugStore, this.app);
591
+ this.dashboardController = new DashboardControllerClass(this.dashboardStore, this.app);
347
592
  // ── Log piping ────────────────────────────────────────────────
348
- const logPath = this.app.makePath('logs', 'adonisjs.log');
349
- this.dashboardLogStream = new LogStreamService(logPath, (entry) => {
350
- this.dashboardStore?.recordLog(entry);
351
- });
352
- await this.dashboardLogStream.start();
593
+ // If the log collector is already hooked into Pino (zero-config mode),
594
+ // piggyback on it instead of creating a separate file poller.
595
+ log.info('dashboard: setting up log piping...');
596
+ const existingLogStream = getLogStreamService();
597
+ if (existingLogStream && !existingLogStream['logPath']) {
598
+ // Stream mode — add a listener for dashboard persistence
599
+ const origOnEntry = existingLogStream['onEntry'];
600
+ existingLogStream['onEntry'] = (entry) => {
601
+ origOnEntry?.(entry);
602
+ this.dashboardStore?.recordLog(entry);
603
+ };
604
+ }
605
+ else {
606
+ // File-based fallback
607
+ const logPath = this.app.makePath('logs', 'adonisjs.log');
608
+ this.dashboardLogStream = new LogStreamService(logPath, (entry) => {
609
+ this.dashboardStore?.recordLog(entry);
610
+ });
611
+ await this.dashboardLogStream.start();
612
+ }
353
613
  // ── Per-request data piping ────────────────────────────────────
354
614
  const debugStore = this.debugStore;
355
615
  const dashStore = this.dashboardStore;
356
616
  let lastQueryId = 0;
357
617
  let lastEventId = 0;
618
+ let warnedPersistOnce = false;
358
619
  setOnRequestComplete(({ method, url, statusCode, duration, trace }) => {
359
620
  if (!dashStore.isReady())
360
621
  return;
@@ -372,14 +633,24 @@ export default class ServerStatsProvider {
372
633
  }
373
634
  // Persist asynchronously (fire-and-forget)
374
635
  dashStore
375
- .persistRequest(method, url, statusCode, duration, newQueries, trace ?? null)
636
+ .persistRequest({
637
+ method,
638
+ url,
639
+ statusCode,
640
+ duration,
641
+ queries: newQueries,
642
+ trace: trace ?? null,
643
+ })
376
644
  .then((requestId) => {
377
645
  if (requestId !== null && newEvents.length > 0) {
378
646
  return dashStore.recordEvents(requestId, newEvents);
379
647
  }
380
648
  })
381
- .catch(() => {
382
- // Silently ignore persistence errors
649
+ .catch((err) => {
650
+ if (!warnedPersistOnce) {
651
+ warnedPersistOnce = true;
652
+ log.warn('failed to persist request data — ' + (err?.message || 'unknown error'));
653
+ }
383
654
  });
384
655
  });
385
656
  // ── Transmit streaming for real-time dashboard updates ────────
@@ -391,13 +662,24 @@ export default class ServerStatsProvider {
391
662
  // Transmit not installed — skip real-time updates
392
663
  }
393
664
  if (transmit) {
665
+ this.transmitAvailable = true;
394
666
  const dashChannel = 'server-stats/dashboard';
667
+ if (!this.transmitChannels.includes(dashChannel)) {
668
+ this.transmitChannels.push(dashChannel);
669
+ }
395
670
  this.dashboardBroadcastTimer = setInterval(async () => {
396
671
  try {
397
672
  if (!dashStore.isReady())
398
673
  return;
399
674
  const overview = await dashStore.getOverviewMetrics('1h');
400
- transmit.broadcast(dashChannel, overview);
675
+ const diagnostics = {
676
+ collectors: this.engine.getCollectorHealth(),
677
+ buffers: this.debugStore.getBufferStats(),
678
+ };
679
+ transmit.broadcast(dashChannel, {
680
+ ...overview,
681
+ diagnostics,
682
+ });
401
683
  }
402
684
  catch {
403
685
  // Silently ignore
@@ -405,6 +687,80 @@ export default class ServerStatsProvider {
405
687
  }, 5_000);
406
688
  }
407
689
  }
690
+ /** Return diagnostics state for the Internals endpoint. */
691
+ getDiagnostics() {
692
+ const config = this.resolvedConfig;
693
+ const toolbarConfig = config?.devToolbar;
694
+ return {
695
+ timers: {
696
+ collectionInterval: {
697
+ active: this.intervalId !== null,
698
+ intervalMs: config?.intervalMs ?? 0,
699
+ },
700
+ dashboardBroadcast: {
701
+ active: this.dashboardBroadcastTimer !== null,
702
+ intervalMs: 5000,
703
+ },
704
+ debugBroadcast: {
705
+ active: this.debugBroadcastTimer !== null,
706
+ debounceMs: 200,
707
+ },
708
+ persistFlush: {
709
+ active: this.flushTimer !== null,
710
+ intervalMs: 30_000,
711
+ },
712
+ retentionCleanup: {
713
+ active: this.dashboardStore?.isReady() ?? false,
714
+ intervalMs: 60 * 60 * 1000,
715
+ },
716
+ },
717
+ transmit: {
718
+ available: this.transmitAvailable,
719
+ channels: this.transmitChannels,
720
+ },
721
+ integrations: {
722
+ prometheus: { active: this.prometheusActive },
723
+ pinoHook: {
724
+ active: this.pinoHookActive,
725
+ mode: this.pinoHookActive ? 'stream' : toolbarConfig?.enabled ? 'none' : 'none',
726
+ },
727
+ edgePlugin: { active: this.edgePluginActive },
728
+ cacheInspector: {
729
+ available: this.resolvedCollectors.some((c) => c.name === 'redis'),
730
+ },
731
+ queueInspector: {
732
+ available: this.resolvedCollectors.some((c) => c.name === 'queue'),
733
+ },
734
+ },
735
+ config: {
736
+ intervalMs: config?.intervalMs ?? 0,
737
+ transport: config?.transport ?? 'none',
738
+ channelName: config?.channelName ?? '',
739
+ endpoint: config?.endpoint ?? false,
740
+ skipInTest: config?.skipInTest !== false,
741
+ hasOnStatsCallback: typeof config?.onStats === 'function',
742
+ hasShouldShowCallback: typeof config?.shouldShow === 'function',
743
+ },
744
+ devToolbar: {
745
+ enabled: !!toolbarConfig?.enabled,
746
+ maxQueries: toolbarConfig?.maxQueries ?? 500,
747
+ maxEvents: toolbarConfig?.maxEvents ?? 200,
748
+ maxEmails: toolbarConfig?.maxEmails ?? 100,
749
+ maxTraces: toolbarConfig?.maxTraces ?? 200,
750
+ slowQueryThresholdMs: toolbarConfig?.slowQueryThresholdMs ?? 100,
751
+ tracing: toolbarConfig?.tracing ?? false,
752
+ dashboard: toolbarConfig?.dashboard ?? false,
753
+ dashboardPath: toolbarConfig?.dashboardPath ?? '/__stats',
754
+ debugEndpoint: toolbarConfig?.debugEndpoint ?? '/admin/api/debug',
755
+ retentionDays: toolbarConfig?.retentionDays ?? 7,
756
+ dbPath: toolbarConfig?.dbPath ?? '.adonisjs/server-stats/dashboard.sqlite3',
757
+ persistDebugData: toolbarConfig?.persistDebugData ?? false,
758
+ renderer: toolbarConfig?.renderer ?? 'preact',
759
+ excludeFromTracing: toolbarConfig?.excludeFromTracing ?? [],
760
+ customPaneCount: toolbarConfig?.panes?.length ?? 0,
761
+ },
762
+ };
763
+ }
408
764
  async shutdown() {
409
765
  if (this.intervalId) {
410
766
  clearInterval(this.intervalId);
@@ -427,8 +783,8 @@ export default class ServerStatsProvider {
427
783
  try {
428
784
  await this.debugStore.saveToDisk(this.persistPath);
429
785
  }
430
- catch {
431
- // Silently ignore save errors during shutdown
786
+ catch (err) {
787
+ log.warn('could not save debug data on shutdown — ' + err?.message);
432
788
  }
433
789
  }
434
790
  // Clean up dashboard resources