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.
- package/README.md +351 -171
- package/dist/configure.d.ts.map +1 -1
- package/dist/core/api-client.d.ts +73 -0
- package/dist/core/api-client.d.ts.map +1 -0
- package/dist/core/config-utils.d.ts +109 -0
- package/dist/core/config-utils.d.ts.map +1 -0
- package/dist/core/constants.d.ts +11 -0
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/dashboard-api.d.ts +65 -0
- package/dist/core/dashboard-api.d.ts.map +1 -0
- package/dist/core/dashboard-data-controller.d.ts +157 -0
- package/dist/core/dashboard-data-controller.d.ts.map +1 -0
- package/dist/core/debug-data-controller.d.ts +89 -0
- package/dist/core/debug-data-controller.d.ts.map +1 -0
- package/dist/core/feature-detect.d.ts +67 -0
- package/dist/core/feature-detect.d.ts.map +1 -0
- package/dist/core/formatters.d.ts +189 -0
- package/dist/core/formatters.d.ts.map +1 -0
- package/dist/core/history-buffer.d.ts +23 -0
- package/dist/core/history-buffer.d.ts.map +1 -0
- package/dist/core/icons.d.ts +36 -0
- package/dist/core/icons.d.ts.map +1 -0
- package/dist/core/index.d.ts +39 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +1961 -0
- package/dist/core/internals-utils.d.ts +71 -0
- package/dist/core/internals-utils.d.ts.map +1 -0
- package/dist/core/job-utils.d.ts +45 -0
- package/dist/core/job-utils.d.ts.map +1 -0
- package/dist/core/log-utils.d.ts +34 -0
- package/dist/core/log-utils.d.ts.map +1 -0
- package/dist/core/metrics.d.ts +41 -0
- package/dist/core/metrics.d.ts.map +1 -0
- package/dist/core/pagination.d.ts +128 -0
- package/dist/core/pagination.d.ts.map +1 -0
- package/dist/core/query-utils.d.ts +35 -0
- package/dist/core/query-utils.d.ts.map +1 -0
- package/dist/core/resizable-columns.d.ts +18 -0
- package/dist/core/resizable-columns.d.ts.map +1 -0
- package/dist/core/routes.d.ts +12 -0
- package/dist/core/routes.d.ts.map +1 -0
- package/dist/core/server-stats-controller.d.ts +106 -0
- package/dist/core/server-stats-controller.d.ts.map +1 -0
- package/dist/core/sparkline.d.ts +80 -0
- package/dist/core/sparkline.d.ts.map +1 -0
- package/dist/core/theme.d.ts +42 -0
- package/dist/core/theme.d.ts.map +1 -0
- package/dist/core/trace-utils.d.ts +62 -0
- package/dist/core/trace-utils.d.ts.map +1 -0
- package/dist/core/transmit-adapter.d.ts +59 -0
- package/dist/core/transmit-adapter.d.ts.map +1 -0
- package/dist/core/types.d.ts +619 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/react/CacheSection-DGxMDlWK.js +146 -0
- package/dist/react/CacheTab-CnVW5PLs.js +123 -0
- package/dist/react/ConfigContent-CnsEI4j3.js +397 -0
- package/dist/react/ConfigSection-DPcrfqXY.js +11 -0
- package/dist/react/ConfigTab-BSWq_o2p.js +15 -0
- package/dist/react/CustomPaneTab-xjkYwTvH.js +104 -0
- package/dist/react/DataTable-YyShr5B-.js +55 -0
- package/dist/react/EmailsSection-CSyTg1aX.js +262 -0
- package/dist/react/EmailsTab-Dh2YSa_f.js +131 -0
- package/dist/react/EventsSection-C1pbJDfW.js +86 -0
- package/dist/react/EventsTab-eCh02cdd.js +63 -0
- package/dist/react/FilterBar-DQRXpWrb.js +50 -0
- package/dist/react/InternalsContent-DBzsI0CG.js +346 -0
- package/dist/react/InternalsSection-t7ihcWO-.js +32 -0
- package/dist/react/InternalsTab-Oij0A2fN.js +30 -0
- package/dist/react/JobsSection-CLAin5vU.js +187 -0
- package/dist/react/JobsTab-Dl5nrj2z.js +141 -0
- package/dist/react/LogsSection-C1p81fXO.js +212 -0
- package/dist/react/LogsTab-D-kR7PjX.js +88 -0
- package/dist/react/OverviewSection-nm3xdACz.js +539 -0
- package/dist/react/Pagination-BkmzUDY8.js +64 -0
- package/dist/react/QueriesSection-DB12HMfQ.js +461 -0
- package/dist/react/QueriesTab-fyBB1u_Y.js +90 -0
- package/dist/react/RequestsSection-DTqB81ac.js +209 -0
- package/dist/react/RoutesSection-DJWa4NPV.js +74 -0
- package/dist/react/RoutesTab-D3l8TOpu.js +74 -0
- package/dist/react/TimelineSection-C4d-jRX1.js +158 -0
- package/dist/react/TimelineTab-C5TFaSmQ.js +193 -0
- package/dist/react/WaterfallChart-Cj73WdfM.js +100 -0
- package/dist/react/core/api-client.d.ts +73 -0
- package/dist/react/core/api-client.d.ts.map +1 -0
- package/dist/react/core/config-utils.d.ts +109 -0
- package/dist/react/core/config-utils.d.ts.map +1 -0
- package/dist/react/core/constants.d.ts +11 -0
- package/dist/react/core/constants.d.ts.map +1 -0
- package/dist/react/core/dashboard-api.d.ts +65 -0
- package/dist/react/core/dashboard-api.d.ts.map +1 -0
- package/dist/react/core/dashboard-data-controller.d.ts +157 -0
- package/dist/react/core/dashboard-data-controller.d.ts.map +1 -0
- package/dist/react/core/debug-data-controller.d.ts +89 -0
- package/dist/react/core/debug-data-controller.d.ts.map +1 -0
- package/dist/react/core/feature-detect.d.ts +67 -0
- package/dist/react/core/feature-detect.d.ts.map +1 -0
- package/dist/react/core/formatters.d.ts +189 -0
- package/dist/react/core/formatters.d.ts.map +1 -0
- package/dist/react/core/history-buffer.d.ts +23 -0
- package/dist/react/core/history-buffer.d.ts.map +1 -0
- package/dist/react/core/icons.d.ts +36 -0
- package/dist/react/core/icons.d.ts.map +1 -0
- package/dist/react/core/index.d.ts +39 -0
- package/dist/react/core/index.d.ts.map +1 -0
- package/dist/react/core/internals-utils.d.ts +71 -0
- package/dist/react/core/internals-utils.d.ts.map +1 -0
- package/dist/react/core/job-utils.d.ts +45 -0
- package/dist/react/core/job-utils.d.ts.map +1 -0
- package/dist/react/core/log-utils.d.ts +34 -0
- package/dist/react/core/log-utils.d.ts.map +1 -0
- package/dist/react/core/metrics.d.ts +41 -0
- package/dist/react/core/metrics.d.ts.map +1 -0
- package/dist/react/core/pagination.d.ts +128 -0
- package/dist/react/core/pagination.d.ts.map +1 -0
- package/dist/react/core/query-utils.d.ts +35 -0
- package/dist/react/core/query-utils.d.ts.map +1 -0
- package/dist/react/core/resizable-columns.d.ts +18 -0
- package/dist/react/core/resizable-columns.d.ts.map +1 -0
- package/dist/react/core/routes.d.ts +12 -0
- package/dist/react/core/routes.d.ts.map +1 -0
- package/dist/react/core/server-stats-controller.d.ts +106 -0
- package/dist/react/core/server-stats-controller.d.ts.map +1 -0
- package/dist/react/core/sparkline.d.ts +80 -0
- package/dist/react/core/sparkline.d.ts.map +1 -0
- package/dist/react/core/theme.d.ts +42 -0
- package/dist/react/core/theme.d.ts.map +1 -0
- package/dist/react/core/trace-utils.d.ts +62 -0
- package/dist/react/core/trace-utils.d.ts.map +1 -0
- package/dist/react/core/transmit-adapter.d.ts +59 -0
- package/dist/react/core/transmit-adapter.d.ts.map +1 -0
- package/dist/react/core/types.d.ts +619 -0
- package/dist/react/core/types.d.ts.map +1 -0
- package/dist/react/index-UdTfSvtO.js +1074 -0
- package/dist/react/index.js +18 -0
- package/dist/react/react/components/Dashboard/DashboardPage.d.ts +17 -0
- package/dist/react/react/components/Dashboard/DashboardPage.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/sections/CacheSection.d.ts +7 -0
- package/dist/react/react/components/Dashboard/sections/CacheSection.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/sections/ConfigSection.d.ts +7 -0
- package/dist/react/react/components/Dashboard/sections/ConfigSection.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/sections/EmailsSection.d.ts +7 -0
- package/dist/react/react/components/Dashboard/sections/EmailsSection.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/sections/EventsSection.d.ts +7 -0
- package/dist/react/react/components/Dashboard/sections/EventsSection.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/sections/InternalsSection.d.ts +14 -0
- package/dist/react/react/components/Dashboard/sections/InternalsSection.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/sections/JobsSection.d.ts +7 -0
- package/dist/react/react/components/Dashboard/sections/JobsSection.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/sections/LogsSection.d.ts +7 -0
- package/dist/react/react/components/Dashboard/sections/LogsSection.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/sections/OverviewSection.d.ts +7 -0
- package/dist/react/react/components/Dashboard/sections/OverviewSection.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/sections/QueriesSection.d.ts +7 -0
- package/dist/react/react/components/Dashboard/sections/QueriesSection.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/sections/RequestsSection.d.ts +7 -0
- package/dist/react/react/components/Dashboard/sections/RequestsSection.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/sections/RoutesSection.d.ts +7 -0
- package/dist/react/react/components/Dashboard/sections/RoutesSection.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/sections/TimelineSection.d.ts +9 -0
- package/dist/react/react/components/Dashboard/sections/TimelineSection.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/shared/DataTable.d.ts +27 -0
- package/dist/react/react/components/Dashboard/shared/DataTable.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/shared/FilterBar.d.ts +17 -0
- package/dist/react/react/components/Dashboard/shared/FilterBar.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/shared/Pagination.d.ts +13 -0
- package/dist/react/react/components/Dashboard/shared/Pagination.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/shared/TimeRangeSelector.d.ts +12 -0
- package/dist/react/react/components/Dashboard/shared/TimeRangeSelector.d.ts.map +1 -0
- package/dist/react/react/components/Dashboard/shared/WaterfallChart.d.ts +16 -0
- package/dist/react/react/components/Dashboard/shared/WaterfallChart.d.ts.map +1 -0
- package/dist/react/react/components/DebugPanel/DebugPanel.d.ts +16 -0
- package/dist/react/react/components/DebugPanel/DebugPanel.d.ts.map +1 -0
- package/dist/react/react/components/DebugPanel/tabs/CacheTab.d.ts +8 -0
- package/dist/react/react/components/DebugPanel/tabs/CacheTab.d.ts.map +1 -0
- package/dist/react/react/components/DebugPanel/tabs/ConfigTab.d.ts +8 -0
- package/dist/react/react/components/DebugPanel/tabs/ConfigTab.d.ts.map +1 -0
- package/dist/react/react/components/DebugPanel/tabs/CustomPaneTab.d.ts +14 -0
- package/dist/react/react/components/DebugPanel/tabs/CustomPaneTab.d.ts.map +1 -0
- package/dist/react/react/components/DebugPanel/tabs/EmailsTab.d.ts +7 -0
- package/dist/react/react/components/DebugPanel/tabs/EmailsTab.d.ts.map +1 -0
- package/dist/react/react/components/DebugPanel/tabs/EventsTab.d.ts +7 -0
- package/dist/react/react/components/DebugPanel/tabs/EventsTab.d.ts.map +1 -0
- package/dist/react/react/components/DebugPanel/tabs/InternalsTab.d.ts +12 -0
- package/dist/react/react/components/DebugPanel/tabs/InternalsTab.d.ts.map +1 -0
- package/dist/react/react/components/DebugPanel/tabs/JobsTab.d.ts +9 -0
- package/dist/react/react/components/DebugPanel/tabs/JobsTab.d.ts.map +1 -0
- package/dist/react/react/components/DebugPanel/tabs/LogsTab.d.ts +7 -0
- package/dist/react/react/components/DebugPanel/tabs/LogsTab.d.ts.map +1 -0
- package/dist/react/react/components/DebugPanel/tabs/QueriesTab.d.ts +7 -0
- package/dist/react/react/components/DebugPanel/tabs/QueriesTab.d.ts.map +1 -0
- package/dist/react/react/components/DebugPanel/tabs/RoutesTab.d.ts +8 -0
- package/dist/react/react/components/DebugPanel/tabs/RoutesTab.d.ts.map +1 -0
- package/dist/react/react/components/DebugPanel/tabs/TimelineTab.d.ts +7 -0
- package/dist/react/react/components/DebugPanel/tabs/TimelineTab.d.ts.map +1 -0
- package/dist/react/react/components/StatsBar/MetricCard.d.ts +21 -0
- package/dist/react/react/components/StatsBar/MetricCard.d.ts.map +1 -0
- package/dist/react/react/components/StatsBar/Sparkline.d.ts +15 -0
- package/dist/react/react/components/StatsBar/Sparkline.d.ts.map +1 -0
- package/dist/react/react/components/StatsBar/StatsBar.d.ts +22 -0
- package/dist/react/react/components/StatsBar/StatsBar.d.ts.map +1 -0
- package/dist/react/react/components/shared/Badge.d.ts +32 -0
- package/dist/react/react/components/shared/Badge.d.ts.map +1 -0
- package/dist/react/react/components/shared/ConfigContent.d.ts +13 -0
- package/dist/react/react/components/shared/ConfigContent.d.ts.map +1 -0
- package/dist/react/react/components/shared/InternalsContent.d.ts +10 -0
- package/dist/react/react/components/shared/InternalsContent.d.ts.map +1 -0
- package/dist/react/react/components/shared/JsonViewer.d.ts +12 -0
- package/dist/react/react/components/shared/JsonViewer.d.ts.map +1 -0
- package/dist/react/react/components/shared/ThemeToggle.d.ts +13 -0
- package/dist/react/react/components/shared/ThemeToggle.d.ts.map +1 -0
- package/dist/react/react/components/shared/Tooltip.d.ts +16 -0
- package/dist/react/react/components/shared/Tooltip.d.ts.map +1 -0
- package/dist/react/react/hooks/useApiClient.d.ts +10 -0
- package/dist/react/react/hooks/useApiClient.d.ts.map +1 -0
- package/dist/react/react/hooks/useDashboardApiBase.d.ts +19 -0
- package/dist/react/react/hooks/useDashboardApiBase.d.ts.map +1 -0
- package/dist/react/react/hooks/useDashboardData.d.ts +27 -0
- package/dist/react/react/hooks/useDashboardData.d.ts.map +1 -0
- package/dist/react/react/hooks/useDebugData.d.ts +17 -0
- package/dist/react/react/hooks/useDebugData.d.ts.map +1 -0
- package/dist/react/react/hooks/useFeatures.d.ts +13 -0
- package/dist/react/react/hooks/useFeatures.d.ts.map +1 -0
- package/dist/react/react/hooks/useResizableTable.d.ts +13 -0
- package/dist/react/react/hooks/useResizableTable.d.ts.map +1 -0
- package/dist/react/react/hooks/useServerStats.d.ts +21 -0
- package/dist/react/react/hooks/useServerStats.d.ts.map +1 -0
- package/dist/react/react/hooks/useTheme.d.ts +12 -0
- package/dist/react/react/hooks/useTheme.d.ts.map +1 -0
- package/dist/react/react/index.d.ts +14 -0
- package/dist/react/react/index.d.ts.map +1 -0
- package/dist/react/style.css +1 -0
- package/dist/react/useApiClient-BVtNCmnL.js +9 -0
- package/dist/react/useDashboardApiBase-Bi36pJ2L.js +14 -0
- package/dist/react/useResizableTable-CNJmACdt.js +13 -0
- package/dist/src/collectors/app_collector.d.ts.map +1 -1
- package/dist/src/collectors/app_collector.js +30 -2
- package/dist/src/collectors/auto_detect.d.ts +31 -0
- package/dist/src/collectors/auto_detect.d.ts.map +1 -0
- package/dist/src/collectors/auto_detect.js +120 -0
- package/dist/src/collectors/collector.d.ts +17 -0
- package/dist/src/collectors/collector.d.ts.map +1 -1
- package/dist/src/collectors/db_pool_collector.d.ts.map +1 -1
- package/dist/src/collectors/db_pool_collector.js +35 -1
- package/dist/src/collectors/http_collector.d.ts +4 -3
- package/dist/src/collectors/http_collector.d.ts.map +1 -1
- package/dist/src/collectors/http_collector.js +28 -11
- package/dist/src/collectors/index.d.ts +2 -0
- package/dist/src/collectors/index.d.ts.map +1 -1
- package/dist/src/collectors/index.js +1 -0
- package/dist/src/collectors/log_collector.d.ts +11 -4
- package/dist/src/collectors/log_collector.d.ts.map +1 -1
- package/dist/src/collectors/log_collector.js +51 -5
- package/dist/src/collectors/process_collector.d.ts.map +1 -1
- package/dist/src/collectors/process_collector.js +4 -0
- package/dist/src/collectors/queue_collector.d.ts.map +1 -1
- package/dist/src/collectors/queue_collector.js +55 -1
- package/dist/src/collectors/redis_collector.d.ts.map +1 -1
- package/dist/src/collectors/redis_collector.js +42 -3
- package/dist/src/collectors/system_collector.d.ts.map +1 -1
- package/dist/src/collectors/system_collector.js +4 -0
- package/dist/src/controller/api_controller.d.ts +101 -0
- package/dist/src/controller/api_controller.d.ts.map +1 -0
- package/dist/src/controller/api_controller.js +131 -0
- package/dist/src/controller/debug_controller.d.ts +19 -10
- package/dist/src/controller/debug_controller.d.ts.map +1 -1
- package/dist/src/controller/debug_controller.js +118 -101
- package/dist/src/core/theme.d.ts +42 -0
- package/dist/src/core/theme.d.ts.map +1 -0
- package/dist/src/core/theme.js +115 -0
- package/dist/src/dashboard/chart_aggregator.d.ts.map +1 -1
- package/dist/src/dashboard/chart_aggregator.js +3 -2
- package/dist/src/dashboard/dashboard_controller.d.ts +10 -14
- package/dist/src/dashboard/dashboard_controller.d.ts.map +1 -1
- package/dist/src/dashboard/dashboard_controller.js +132 -250
- package/dist/src/dashboard/dashboard_store.d.ts +62 -19
- package/dist/src/dashboard/dashboard_store.d.ts.map +1 -1
- package/dist/src/dashboard/dashboard_store.js +242 -53
- package/dist/src/dashboard/integrations/cache_inspector.d.ts +19 -1
- package/dist/src/dashboard/integrations/cache_inspector.d.ts.map +1 -1
- package/dist/src/dashboard/integrations/config_inspector.d.ts +1 -1
- package/dist/src/dashboard/integrations/config_inspector.d.ts.map +1 -1
- package/dist/src/dashboard/integrations/config_inspector.js +3 -2
- package/dist/src/dashboard/integrations/queue_inspector.d.ts +55 -10
- package/dist/src/dashboard/integrations/queue_inspector.d.ts.map +1 -1
- package/dist/src/dashboard/integrations/queue_inspector.js +70 -24
- package/dist/src/dashboard/migrator.d.ts +5 -0
- package/dist/src/dashboard/migrator.d.ts.map +1 -1
- package/dist/src/dashboard/migrator.js +44 -9
- package/dist/src/dashboard/models/stats_event.d.ts +1 -1
- package/dist/src/dashboard/models/stats_event.d.ts.map +1 -1
- package/dist/src/dashboard/models/stats_log.d.ts +1 -1
- package/dist/src/dashboard/models/stats_log.d.ts.map +1 -1
- package/dist/src/dashboard/models/stats_query.d.ts +1 -1
- package/dist/src/dashboard/models/stats_query.d.ts.map +1 -1
- package/dist/src/dashboard/models/stats_saved_filter.d.ts +1 -1
- package/dist/src/dashboard/models/stats_saved_filter.d.ts.map +1 -1
- package/dist/src/dashboard/models/stats_trace.d.ts +2 -1
- package/dist/src/dashboard/models/stats_trace.d.ts.map +1 -1
- package/dist/src/data/data_access.d.ts +105 -0
- package/dist/src/data/data_access.d.ts.map +1 -0
- package/dist/src/data/data_access.js +310 -0
- package/dist/src/data/index.d.ts +3 -0
- package/dist/src/data/index.d.ts.map +1 -0
- package/dist/src/data/index.js +1 -0
- package/dist/src/debug/debug_store.d.ts +20 -1
- package/dist/src/debug/debug_store.d.ts.map +1 -1
- package/dist/src/debug/debug_store.js +43 -15
- package/dist/src/debug/email_collector.d.ts +6 -2
- package/dist/src/debug/email_collector.d.ts.map +1 -1
- package/dist/src/debug/email_collector.js +3 -0
- package/dist/src/debug/event_collector.d.ts +6 -2
- package/dist/src/debug/event_collector.d.ts.map +1 -1
- package/dist/src/debug/event_collector.js +12 -8
- package/dist/src/debug/query_collector.d.ts +6 -2
- package/dist/src/debug/query_collector.d.ts.map +1 -1
- package/dist/src/debug/query_collector.js +3 -0
- package/dist/src/debug/ring_buffer.d.ts +1 -0
- package/dist/src/debug/ring_buffer.d.ts.map +1 -1
- package/dist/src/debug/ring_buffer.js +5 -2
- package/dist/src/debug/route_inspector.d.ts +2 -2
- package/dist/src/debug/route_inspector.d.ts.map +1 -1
- package/dist/src/debug/route_inspector.js +4 -3
- package/dist/src/debug/trace_collector.d.ts +7 -3
- package/dist/src/debug/trace_collector.d.ts.map +1 -1
- package/dist/src/debug/trace_collector.js +7 -5
- package/dist/src/debug/types.d.ts +107 -2
- package/dist/src/debug/types.d.ts.map +1 -1
- package/dist/src/debug/types.js +1 -1
- package/dist/src/define_config.d.ts +49 -5
- package/dist/src/define_config.d.ts.map +1 -1
- package/dist/src/define_config.js +361 -4
- package/dist/src/edge/bootstrap.d.ts +17 -0
- package/dist/src/edge/bootstrap.d.ts.map +1 -0
- package/dist/src/edge/bootstrap.js +29 -0
- package/dist/src/edge/client/dashboard.js +2 -3619
- package/dist/src/edge/client/debug-panel-deferred.js +1 -0
- package/dist/src/edge/client/debug-panel.js +1 -2140
- package/dist/src/edge/client/stats-bar.js +1 -801
- package/dist/src/edge/client-vue/dashboard.js +5 -0
- package/dist/src/edge/client-vue/debug-panel-deferred.js +4 -0
- package/dist/src/edge/client-vue/debug-panel.js +4 -0
- package/dist/src/edge/client-vue/stats-bar.js +4 -0
- package/dist/src/edge/plugin.d.ts +35 -2
- package/dist/src/edge/plugin.d.ts.map +1 -1
- package/dist/src/edge/plugin.js +30 -66
- package/dist/src/edge/types.d.ts +46 -0
- package/dist/src/edge/types.d.ts.map +1 -0
- package/dist/src/edge/types.js +4 -0
- package/dist/src/edge/views/dashboard.edge +1 -358
- package/dist/src/edge/views/debug-panel.edge +2 -154
- package/dist/src/edge/views/stats-bar.edge +15 -48
- package/dist/src/engine/stats_engine.d.ts +18 -0
- package/dist/src/engine/stats_engine.d.ts.map +1 -1
- package/dist/src/engine/stats_engine.js +45 -2
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/log_stream/log_stream_provider.d.ts.map +1 -1
- package/dist/src/log_stream/log_stream_provider.js +21 -4
- package/dist/src/log_stream/log_stream_service.d.ts +8 -1
- package/dist/src/log_stream/log_stream_service.d.ts.map +1 -1
- package/dist/src/log_stream/log_stream_service.js +27 -3
- package/dist/src/middleware/request_tracking_middleware.d.ts +1 -1
- package/dist/src/middleware/request_tracking_middleware.d.ts.map +1 -1
- package/dist/src/middleware/request_tracking_middleware.js +21 -6
- package/dist/src/prometheus/prometheus_collector.d.ts +2 -1
- package/dist/src/prometheus/prometheus_collector.d.ts.map +1 -1
- package/dist/src/provider/server_stats_provider.d.ts +100 -0
- package/dist/src/provider/server_stats_provider.d.ts.map +1 -1
- package/dist/src/provider/server_stats_provider.js +460 -104
- package/dist/src/routes/access_middleware.d.ts +2 -1
- package/dist/src/routes/access_middleware.d.ts.map +1 -1
- package/dist/src/routes/access_middleware.js +7 -1
- package/dist/src/routes/index.d.ts +4 -0
- package/dist/src/routes/index.d.ts.map +1 -0
- package/dist/src/routes/index.js +1 -0
- package/dist/src/routes/register_routes.d.ts +103 -0
- package/dist/src/routes/register_routes.d.ts.map +1 -0
- package/dist/src/routes/register_routes.js +356 -0
- package/dist/src/routes/router_types.d.ts +29 -0
- package/dist/src/routes/router_types.d.ts.map +1 -0
- package/dist/src/routes/router_types.js +1 -0
- package/dist/src/stubs/config.stub +12 -32
- package/dist/src/styles/components.css +1048 -0
- package/dist/src/{edge/client → styles}/dashboard.css +299 -736
- package/dist/src/{edge/client → styles}/debug-panel.css +117 -633
- package/dist/src/{edge/client → styles}/stats-bar.css +28 -10
- package/dist/src/styles/tokens.css +153 -0
- package/dist/src/styles/utilities.css +75 -0
- package/dist/src/types.d.ts +119 -16
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/app_import.d.ts +23 -0
- package/dist/src/utils/app_import.d.ts.map +1 -0
- package/dist/src/utils/app_import.js +44 -0
- package/dist/src/utils/json_helpers.d.ts +2 -2
- package/dist/src/utils/json_helpers.d.ts.map +1 -1
- package/dist/src/utils/logger.d.ts +17 -0
- package/dist/src/utils/logger.d.ts.map +1 -0
- package/dist/src/utils/logger.js +27 -0
- package/dist/src/utils/mail_helpers.d.ts +1 -1
- package/dist/src/utils/mail_helpers.d.ts.map +1 -1
- package/dist/src/utils/mail_helpers.js +1 -1
- package/dist/vue/CacheSection-C788Yfai.js +149 -0
- package/dist/vue/CacheTab-BPisYYiQ.js +104 -0
- package/dist/vue/ConfigSection-CRzYxqW2.js +576 -0
- package/dist/vue/ConfigTab-C8cafGUj.js +361 -0
- package/dist/vue/CustomPaneTab-BJxT5Dp7.js +172 -0
- package/dist/vue/EmailsSection-C8JFMtW7.js +206 -0
- package/dist/vue/EmailsTab-DhFhoNmU.js +157 -0
- package/dist/vue/EventsSection-C4wXUgxG.js +107 -0
- package/dist/vue/EventsTab-DQ4Nd6AK.js +97 -0
- package/dist/vue/FilterBar.vue_vue_type_script_setup_true_lang-ClJ37hhT.js +62 -0
- package/dist/vue/InternalsSection-BJUXE-5F.js +468 -0
- package/dist/vue/InternalsTab-DEMjqtlw.js +471 -0
- package/dist/vue/JobsSection-CsKWTjgN.js +187 -0
- package/dist/vue/JobsTab-BCvhOARO.js +117 -0
- package/dist/vue/JsonViewer.vue_vue_type_script_setup_true_lang-Vsqar1zx.js +67 -0
- package/dist/vue/LogsSection-BFVjSZ24.js +227 -0
- package/dist/vue/LogsTab-DpEQ7euu.js +122 -0
- package/dist/vue/OverviewSection-CbMdAido.js +849 -0
- package/dist/vue/PaginationControls.vue_vue_type_script_setup_true_lang-CuN7g_8Z.js +50 -0
- package/dist/vue/QueriesSection-BPiv7u3r.js +429 -0
- package/dist/vue/QueriesTab-C8_7oprC.js +107 -0
- package/dist/vue/RequestsSection-LtImH4rD.js +243 -0
- package/dist/vue/RoutesSection-CrxOxmzx.js +106 -0
- package/dist/vue/RoutesTab-Dz0MkZuF.js +80 -0
- package/dist/vue/TimelineSection-DLxMW2J_.js +186 -0
- package/dist/vue/TimelineTab-Db6lKKsD.js +250 -0
- package/dist/vue/WaterfallChart.vue_vue_type_script_setup_true_lang-tZ13cNj1.js +118 -0
- package/dist/vue/components/Dashboard/DashboardPage.vue.d.ts +18 -0
- package/dist/vue/components/Dashboard/DashboardPage.vue.d.ts.map +1 -0
- package/dist/vue/components/Dashboard/sections/CacheSection.vue.d.ts +5 -0
- package/dist/vue/components/Dashboard/sections/CacheSection.vue.d.ts.map +1 -0
- package/dist/vue/components/Dashboard/sections/ConfigSection.vue.d.ts +3 -0
- package/dist/vue/components/Dashboard/sections/ConfigSection.vue.d.ts.map +1 -0
- package/dist/vue/components/Dashboard/sections/EmailsSection.vue.d.ts +5 -0
- package/dist/vue/components/Dashboard/sections/EmailsSection.vue.d.ts.map +1 -0
- package/dist/vue/components/Dashboard/sections/EventsSection.vue.d.ts +5 -0
- package/dist/vue/components/Dashboard/sections/EventsSection.vue.d.ts.map +1 -0
- package/dist/vue/components/Dashboard/sections/InternalsSection.vue.d.ts +3 -0
- package/dist/vue/components/Dashboard/sections/InternalsSection.vue.d.ts.map +1 -0
- package/dist/vue/components/Dashboard/sections/JobsSection.vue.d.ts +5 -0
- package/dist/vue/components/Dashboard/sections/JobsSection.vue.d.ts.map +1 -0
- package/dist/vue/components/Dashboard/sections/LogsSection.vue.d.ts +3 -0
- package/dist/vue/components/Dashboard/sections/LogsSection.vue.d.ts.map +1 -0
- package/dist/vue/components/Dashboard/sections/OverviewSection.vue.d.ts +5 -0
- package/dist/vue/components/Dashboard/sections/OverviewSection.vue.d.ts.map +1 -0
- package/dist/vue/components/Dashboard/sections/QueriesSection.vue.d.ts +45 -0
- package/dist/vue/components/Dashboard/sections/QueriesSection.vue.d.ts.map +1 -0
- package/dist/vue/components/Dashboard/sections/RequestsSection.vue.d.ts +5 -0
- package/dist/vue/components/Dashboard/sections/RequestsSection.vue.d.ts.map +1 -0
- package/dist/vue/components/Dashboard/sections/RoutesSection.vue.d.ts +5 -0
- package/dist/vue/components/Dashboard/sections/RoutesSection.vue.d.ts.map +1 -0
- package/dist/vue/components/Dashboard/sections/TimelineSection.vue.d.ts +11 -0
- package/dist/vue/components/Dashboard/sections/TimelineSection.vue.d.ts.map +1 -0
- package/dist/vue/components/Dashboard/shared/FilterBar.vue.d.ts +29 -0
- package/dist/vue/components/Dashboard/shared/FilterBar.vue.d.ts.map +1 -0
- package/dist/vue/components/Dashboard/shared/PaginationControls.vue.d.ts +12 -0
- package/dist/vue/components/Dashboard/shared/PaginationControls.vue.d.ts.map +1 -0
- package/dist/vue/components/Dashboard/shared/TimeRangeSelector.vue.d.ts +11 -0
- package/dist/vue/components/Dashboard/shared/TimeRangeSelector.vue.d.ts.map +1 -0
- package/dist/vue/components/Dashboard/shared/WaterfallChart.vue.d.ts +10 -0
- package/dist/vue/components/Dashboard/shared/WaterfallChart.vue.d.ts.map +1 -0
- package/dist/vue/components/DebugPanel/DebugPanel.vue.d.ts +21 -0
- package/dist/vue/components/DebugPanel/DebugPanel.vue.d.ts.map +1 -0
- package/dist/vue/components/DebugPanel/tabs/CacheTab.vue.d.ts +12 -0
- package/dist/vue/components/DebugPanel/tabs/CacheTab.vue.d.ts.map +1 -0
- package/dist/vue/components/DebugPanel/tabs/ConfigTab.vue.d.ts +11 -0
- package/dist/vue/components/DebugPanel/tabs/ConfigTab.vue.d.ts.map +1 -0
- package/dist/vue/components/DebugPanel/tabs/CustomPaneTab.vue.d.ts +11 -0
- package/dist/vue/components/DebugPanel/tabs/CustomPaneTab.vue.d.ts.map +1 -0
- package/dist/vue/components/DebugPanel/tabs/EmailsTab.vue.d.ts +12 -0
- package/dist/vue/components/DebugPanel/tabs/EmailsTab.vue.d.ts.map +1 -0
- package/dist/vue/components/DebugPanel/tabs/EventsTab.vue.d.ts +12 -0
- package/dist/vue/components/DebugPanel/tabs/EventsTab.vue.d.ts.map +1 -0
- package/dist/vue/components/DebugPanel/tabs/InternalsTab.vue.d.ts +11 -0
- package/dist/vue/components/DebugPanel/tabs/InternalsTab.vue.d.ts.map +1 -0
- package/dist/vue/components/DebugPanel/tabs/JobsTab.vue.d.ts +13 -0
- package/dist/vue/components/DebugPanel/tabs/JobsTab.vue.d.ts.map +1 -0
- package/dist/vue/components/DebugPanel/tabs/LogsTab.vue.d.ts +15 -0
- package/dist/vue/components/DebugPanel/tabs/LogsTab.vue.d.ts.map +1 -0
- package/dist/vue/components/DebugPanel/tabs/QueriesTab.vue.d.ts +12 -0
- package/dist/vue/components/DebugPanel/tabs/QueriesTab.vue.d.ts.map +1 -0
- package/dist/vue/components/DebugPanel/tabs/RoutesTab.vue.d.ts +12 -0
- package/dist/vue/components/DebugPanel/tabs/RoutesTab.vue.d.ts.map +1 -0
- package/dist/vue/components/DebugPanel/tabs/TimelineTab.vue.d.ts +15 -0
- package/dist/vue/components/DebugPanel/tabs/TimelineTab.vue.d.ts.map +1 -0
- package/dist/vue/components/StatsBar/MetricCard.vue.d.ts +19 -0
- package/dist/vue/components/StatsBar/MetricCard.vue.d.ts.map +1 -0
- package/dist/vue/components/StatsBar/Sparkline.vue.d.ts +17 -0
- package/dist/vue/components/StatsBar/Sparkline.vue.d.ts.map +1 -0
- package/dist/vue/components/StatsBar/StatsBar.vue.d.ts +22 -0
- package/dist/vue/components/StatsBar/StatsBar.vue.d.ts.map +1 -0
- package/dist/vue/components/shared/JsonViewer.vue.d.ts +13 -0
- package/dist/vue/components/shared/JsonViewer.vue.d.ts.map +1 -0
- package/dist/vue/components/shared/ThemeToggle.vue.d.ts +8 -0
- package/dist/vue/components/shared/ThemeToggle.vue.d.ts.map +1 -0
- package/dist/vue/composables/useApiClient.d.ts +9 -0
- package/dist/vue/composables/useApiClient.d.ts.map +1 -0
- package/dist/vue/composables/useDashboardData.d.ts +53 -0
- package/dist/vue/composables/useDashboardData.d.ts.map +1 -0
- package/dist/vue/composables/useDebugData.d.ts +25 -0
- package/dist/vue/composables/useDebugData.d.ts.map +1 -0
- package/dist/vue/composables/useFeatures.d.ts +80 -0
- package/dist/vue/composables/useFeatures.d.ts.map +1 -0
- package/dist/vue/composables/useResizableTable.d.ts +16 -0
- package/dist/vue/composables/useResizableTable.d.ts.map +1 -0
- package/dist/vue/composables/useServerStats.d.ts +104 -0
- package/dist/vue/composables/useServerStats.d.ts.map +1 -0
- package/dist/vue/composables/useTheme.d.ts +6 -0
- package/dist/vue/composables/useTheme.d.ts.map +1 -0
- package/dist/vue/index-qCQpBftQ.js +1233 -0
- package/dist/vue/index.d.ts +10 -0
- package/dist/vue/index.d.ts.map +1 -0
- package/dist/vue/index.js +11 -0
- package/dist/vue/style.css +1 -0
- package/dist/vue/useApiClient-BQQ9CF-q.js +10 -0
- package/dist/vue/useResizableTable-BoivAevK.js +17 -0
- package/package.json +72 -10
- package/dist/src/dashboard/dashboard_routes.d.ts +0 -16
- package/dist/src/dashboard/dashboard_routes.d.ts.map +0 -1
- package/dist/src/dashboard/dashboard_routes.js +0 -77
- package/dist/src/routes/debug_routes.d.ts +0 -14
- package/dist/src/routes/debug_routes.d.ts.map +0 -1
- package/dist/src/routes/debug_routes.js +0 -42
- package/dist/src/routes/stats_routes.d.ts +0 -14
- package/dist/src/routes/stats_routes.d.ts.map +0 -1
- package/dist/src/routes/stats_routes.js +0 -27
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
|
-
import {
|
|
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 {
|
|
9
|
-
import {
|
|
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
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
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
|
-
|
|
76
|
-
authMiddleware.map((m) =>
|
|
77
|
-
'
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
'
|
|
81
|
-
|
|
82
|
-
'
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
'
|
|
86
|
-
|
|
87
|
-
'
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
'
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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
|
-
|
|
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
|
-
|
|
389
|
+
const mod = await import('../prometheus/prometheus_collector.js');
|
|
390
|
+
prometheusCollector = mod.ServerStatsCollector.instance;
|
|
204
391
|
}
|
|
205
392
|
catch {
|
|
206
|
-
//
|
|
393
|
+
// Prometheus not installed — skip (optional dependency)
|
|
207
394
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
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
|
-
|
|
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
|
|
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,
|
|
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
|
|
310
|
-
|
|
311
|
-
|
|
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
|
-
|
|
323
|
-
|
|
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
|
-
|
|
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
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
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
|
-
|
|
581
|
+
this.dashboardStore = null;
|
|
582
|
+
return;
|
|
338
583
|
}
|
|
339
|
-
|
|
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.
|
|
591
|
+
this.dashboardController = new DashboardControllerClass(this.dashboardStore, this.app);
|
|
347
592
|
// ── Log piping ────────────────────────────────────────────────
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|