adonisjs-server-stats 1.9.0 → 1.10.3
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 +23 -14
- package/dist/core/config-utils.d.ts +8 -0
- package/dist/core/constants.d.ts +4 -0
- package/dist/core/dashboard-data-controller.d.ts +16 -0
- package/dist/core/dashboard-data-helpers.d.ts +12 -0
- package/dist/core/debug-data-controller.d.ts +4 -0
- package/dist/core/define-config-helpers.d.ts +25 -0
- package/dist/core/feature-detect-helpers.d.ts +36 -0
- package/dist/core/formatters-helpers.d.ts +23 -0
- package/dist/core/index.js +596 -509
- package/dist/core/log-utils-helpers.d.ts +13 -0
- package/dist/core/metrics.d.ts +3 -28
- package/dist/core/pagination.d.ts +0 -9
- package/dist/core/server-stats-controller.d.ts +6 -0
- package/dist/core/split-pane.d.ts +18 -0
- package/dist/core/trace-utils.d.ts +5 -0
- package/dist/core/transmit-helpers.d.ts +7 -0
- package/dist/core/types-dashboard.d.ts +178 -0
- package/dist/core/types-diagnostics.d.ts +85 -0
- package/dist/core/types.d.ts +11 -443
- package/dist/react/{CacheSection-xH75hwXu.js → CacheSection-baMZotSn.js} +2 -2
- package/dist/react/CacheTab-2cw_rMzj.js +117 -0
- package/dist/react/{ConfigSection-D8BO1Ry9.js → ConfigSection-DGgqjAal.js} +1 -1
- package/dist/react/{ConfigTab-CcN-tfjv.js → ConfigTab-H3OnYqmK.js} +1 -1
- package/dist/react/CustomPaneTab-B6r7ha0u.js +98 -0
- package/dist/react/{EmailsSection-BzlsTdPs.js → EmailsSection-C-UZISG-.js} +2 -2
- package/dist/react/EmailsTab-DbK4Eobn.js +139 -0
- package/dist/react/{EventsSection-CGQWiIdV.js → EventsSection-C7RQW_LY.js} +2 -2
- package/dist/react/EventsTab-CfVr7AiM.js +57 -0
- package/dist/react/{FilterBar-DQRXpWrb.js → FilterBar-CQ7bD669.js} +15 -15
- package/dist/react/{JobsSection-D7AHQmZi.js → JobsSection-CQHNK_Ls.js} +2 -2
- package/dist/react/{JobsTab-B3Lfdqed.js → JobsTab-znzf6jzk.js} +54 -42
- package/dist/react/{LogsSection-Cly1dpvS.js → LogsSection-Dmm3rE2B.js} +9 -3
- package/dist/react/LogsTab-D8unMV5P.js +108 -0
- package/dist/react/{OverviewSection-CkBGFEWq.js → OverviewSection-ABP9ueBo.js} +1 -1
- package/dist/react/{QueriesSection-CfCpnNUD.js → QueriesSection-CnmSkznA.js} +2 -2
- package/dist/react/{QueriesTab-DbBmAqzO.js → QueriesTab-BQzcxEiW.js} +37 -40
- package/dist/react/RelatedLogs-3A8RuGKH.js +52 -0
- package/dist/react/RequestsSection-kW79_M7k.js +341 -0
- package/dist/react/{RoutesSection-CRqF-cNM.js → RoutesSection-BRhxrtjZ.js} +2 -2
- package/dist/react/RoutesTab-CpYH5lUw.js +68 -0
- package/dist/react/TimelineTab-DjLR35Ce.js +214 -0
- package/dist/react/index-CsImORX6.js +1121 -0
- package/dist/react/index.js +1 -1
- package/dist/react/react/components/{Dashboard/shared → shared}/FilterBar.d.ts +4 -3
- package/dist/react/react/components/shared/RelatedLogs.d.ts +7 -0
- package/dist/react/react/hooks/useDashboardData.d.ts +4 -8
- package/dist/react/style.css +1 -1
- package/dist/src/collectors/app_collector.d.ts +0 -8
- package/dist/src/collectors/app_collector.js +45 -52
- package/dist/src/collectors/auto_detect.d.ts +0 -23
- package/dist/src/collectors/auto_detect.js +33 -55
- package/dist/src/collectors/db_pool_collector.d.ts +14 -16
- package/dist/src/collectors/db_pool_collector.js +72 -57
- package/dist/src/collectors/log_collector.d.ts +0 -47
- package/dist/src/collectors/log_collector.js +36 -65
- package/dist/src/collectors/queue_collector.d.ts +0 -20
- package/dist/src/collectors/queue_collector.js +60 -76
- package/dist/src/collectors/redis_collector.d.ts +10 -10
- package/dist/src/collectors/redis_collector.js +69 -66
- package/dist/src/config/deprecation_migration.d.ts +7 -0
- package/dist/src/config/deprecation_migration.js +201 -0
- package/dist/src/controller/debug_controller.d.ts +1 -1
- package/dist/src/controller/debug_controller.js +87 -81
- package/dist/src/dashboard/cache_handlers.d.ts +14 -0
- package/dist/src/dashboard/cache_handlers.js +52 -0
- package/dist/src/dashboard/chart_aggregator.d.ts +0 -7
- package/dist/src/dashboard/chart_aggregator.js +68 -50
- package/dist/src/dashboard/coalesce_cache.d.ts +25 -0
- package/dist/src/dashboard/coalesce_cache.js +47 -0
- package/dist/src/dashboard/dashboard_controller.d.ts +11 -37
- package/dist/src/dashboard/dashboard_controller.js +52 -532
- package/dist/src/dashboard/dashboard_page_assets.d.ts +17 -0
- package/dist/src/dashboard/dashboard_page_assets.js +51 -0
- package/dist/src/dashboard/dashboard_store.d.ts +19 -217
- package/dist/src/dashboard/dashboard_store.js +115 -1069
- package/dist/src/dashboard/dashboard_types.d.ts +83 -0
- package/dist/src/dashboard/dashboard_types.js +4 -0
- package/dist/src/dashboard/detail_queries.d.ts +19 -0
- package/dist/src/dashboard/detail_queries.js +98 -0
- package/dist/src/dashboard/email_event_builder.d.ts +8 -0
- package/dist/src/dashboard/email_event_builder.js +65 -0
- package/dist/src/dashboard/explain_query.d.ts +8 -0
- package/dist/src/dashboard/explain_query.js +22 -0
- package/dist/src/dashboard/filter_handlers.d.ts +23 -0
- package/dist/src/dashboard/filter_handlers.js +56 -0
- package/dist/src/dashboard/filtered_queries.d.ts +15 -0
- package/dist/src/dashboard/filtered_queries.js +155 -0
- package/dist/src/dashboard/flush_manager.d.ts +25 -0
- package/dist/src/dashboard/flush_manager.js +107 -0
- package/dist/src/dashboard/format_helpers.d.ts +126 -0
- package/dist/src/dashboard/format_helpers.js +140 -0
- package/dist/src/dashboard/inspector_manager.d.ts +36 -0
- package/dist/src/dashboard/inspector_manager.js +102 -0
- package/dist/src/dashboard/integrations/config_inspector.js +11 -13
- package/dist/src/dashboard/integrations/queue_inspector.d.ts +3 -3
- package/dist/src/dashboard/integrations/queue_inspector.js +13 -10
- package/dist/src/dashboard/jobs_handlers.d.ts +14 -0
- package/dist/src/dashboard/jobs_handlers.js +61 -0
- package/dist/src/dashboard/knex_factory.d.ts +18 -0
- package/dist/src/dashboard/knex_factory.js +91 -0
- package/dist/src/dashboard/migrator.js +30 -153
- package/dist/src/dashboard/migrator_tables.d.ts +19 -0
- package/dist/src/dashboard/migrator_tables.js +153 -0
- package/dist/src/dashboard/overview_queries.d.ts +66 -0
- package/dist/src/dashboard/overview_queries.js +155 -0
- package/dist/src/dashboard/overview_query_runners.d.ts +25 -0
- package/dist/src/dashboard/overview_query_runners.js +84 -0
- package/dist/src/dashboard/overview_store_queries.d.ts +40 -0
- package/dist/src/dashboard/overview_store_queries.js +69 -0
- package/dist/src/dashboard/paginate_helper.d.ts +12 -0
- package/dist/src/dashboard/paginate_helper.js +33 -0
- package/dist/src/dashboard/query_explain_handler.d.ts +10 -0
- package/dist/src/dashboard/query_explain_handler.js +80 -0
- package/dist/src/dashboard/read_queries.d.ts +32 -0
- package/dist/src/dashboard/read_queries.js +107 -0
- package/dist/src/dashboard/saved_filter_queries.d.ts +10 -0
- package/dist/src/dashboard/saved_filter_queries.js +24 -0
- package/dist/src/dashboard/storage_stats.d.ts +41 -0
- package/dist/src/dashboard/storage_stats.js +81 -0
- package/dist/src/dashboard/write_queue.d.ts +106 -0
- package/dist/src/dashboard/write_queue.js +225 -0
- package/dist/src/data/data_access.d.ts +6 -36
- package/dist/src/data/data_access.js +43 -188
- package/dist/src/data/data_access_helpers.d.ts +130 -0
- package/dist/src/data/data_access_helpers.js +212 -0
- package/dist/src/debug/debug_store.js +37 -32
- package/dist/src/debug/email_collector.d.ts +1 -10
- package/dist/src/debug/email_collector.js +78 -81
- package/dist/src/debug/event_collector.d.ts +0 -9
- package/dist/src/debug/event_collector.js +79 -62
- package/dist/src/debug/query_collector.js +23 -19
- package/dist/src/debug/route_inspector.d.ts +1 -5
- package/dist/src/debug/route_inspector.js +50 -51
- package/dist/src/debug/trace_collector.d.ts +10 -2
- package/dist/src/debug/trace_collector.js +23 -16
- package/dist/src/debug/types.d.ts +5 -1
- package/dist/src/define_config.d.ts +0 -65
- package/dist/src/define_config.js +93 -333
- package/dist/src/edge/client/dashboard.js +2 -2
- package/dist/src/edge/client/debug-panel-deferred.js +1 -1
- package/dist/src/edge/client/stats-bar.js +1 -1
- package/dist/src/edge/client-vue/dashboard.js +5 -5
- package/dist/src/edge/client-vue/debug-panel-deferred.js +3 -3
- package/dist/src/edge/client-vue/stats-bar.js +3 -3
- package/dist/src/edge/plugin.d.ts +0 -16
- package/dist/src/edge/plugin.js +57 -64
- package/dist/src/engine/request_metrics.d.ts +1 -0
- package/dist/src/engine/request_metrics.js +32 -42
- package/dist/src/middleware/request_tracking_middleware.d.ts +3 -8
- package/dist/src/middleware/request_tracking_middleware.js +65 -91
- package/dist/src/provider/auth_middleware_detector.d.ts +16 -0
- package/dist/src/provider/auth_middleware_detector.js +97 -0
- package/dist/src/provider/boot_helpers.d.ts +20 -0
- package/dist/src/provider/boot_helpers.js +91 -0
- package/dist/src/provider/boot_initializer.d.ts +28 -0
- package/dist/src/provider/boot_initializer.js +35 -0
- package/dist/src/provider/dashboard_init.d.ts +30 -0
- package/dist/src/provider/dashboard_init.js +138 -0
- package/dist/src/provider/dashboard_setup.d.ts +25 -0
- package/dist/src/provider/dashboard_setup.js +78 -0
- package/dist/src/provider/diagnostics.d.ts +134 -0
- package/dist/src/provider/diagnostics.js +127 -0
- package/dist/src/provider/email_bridge.d.ts +43 -0
- package/dist/src/provider/email_bridge.js +80 -0
- package/dist/src/provider/email_helpers.d.ts +13 -0
- package/dist/src/provider/email_helpers.js +68 -0
- package/dist/src/provider/pino_hook.d.ts +17 -0
- package/dist/src/provider/pino_hook.js +35 -0
- package/dist/src/provider/provider_helpers_extra.d.ts +47 -0
- package/dist/src/provider/provider_helpers_extra.js +177 -0
- package/dist/src/provider/server_stats_provider.d.ts +39 -85
- package/dist/src/provider/server_stats_provider.js +131 -936
- package/dist/src/provider/shutdown_helpers.d.ts +43 -0
- package/dist/src/provider/shutdown_helpers.js +70 -0
- package/dist/src/provider/toolbar_setup.d.ts +57 -0
- package/dist/src/provider/toolbar_setup.js +141 -0
- package/dist/src/routes/dashboard_routes.d.ts +14 -0
- package/dist/src/routes/dashboard_routes.js +197 -0
- package/dist/src/routes/debug_routes.d.ts +14 -0
- package/dist/src/routes/debug_routes.js +101 -0
- package/dist/src/routes/register_routes.d.ts +0 -78
- package/dist/src/routes/register_routes.js +22 -347
- package/dist/src/routes/stats_routes.d.ts +5 -0
- package/dist/src/routes/stats_routes.js +14 -0
- package/dist/src/styles/components.css +177 -0
- package/dist/src/styles/dashboard.css +8 -90
- package/dist/src/styles/debug-panel.css +10 -31
- package/dist/src/types.d.ts +306 -15
- package/dist/vue/{CacheSection-Cx-hj09X.js → CacheSection-ITqvpfH5.js} +1 -1
- package/dist/vue/{ConfigSection-CMXyryf6.js → ConfigSection-DTn3GslE.js} +1 -1
- package/dist/vue/{EmailsSection-DgKl9xGT.js → EmailsSection-DtLJ4XoS.js} +1 -1
- package/dist/vue/{EventsSection-BNMCAim1.js → EventsSection-BOYYz0Ty.js} +1 -1
- package/dist/vue/{JobsSection-CCMgMlxd.js → JobsSection-BazTxcJL.js} +1 -1
- package/dist/vue/{LogsSection-CvOnTxUu.js → LogsSection-D55PjTKX.js} +9 -3
- package/dist/vue/{LogsTab-Bg3o0Mm6.js → LogsTab-47zEK7jL.js} +4 -1
- package/dist/vue/{OverviewSection-CHgaKtUR.js → OverviewSection-1uBKo-Tu.js} +1 -1
- package/dist/vue/{QueriesSection-BnHRD98z.js → QueriesSection-rpoZ4ogd.js} +1 -1
- package/dist/vue/RelatedLogs.vue_vue_type_script_setup_true_lang-CB2_TzYW.js +84 -0
- package/dist/vue/RequestsSection-x7LvT0MC.js +401 -0
- package/dist/vue/{RoutesSection-BrceOcKQ.js → RoutesSection-CCD0zZqQ.js} +1 -1
- package/dist/vue/TimelineTab-zj5Z5OdT.js +338 -0
- package/dist/vue/components/Dashboard/sections/RequestsSection.vue.d.ts +4 -0
- package/dist/vue/components/DebugPanel/tabs/TimelineTab.vue.d.ts +4 -0
- package/dist/vue/components/{Dashboard/sections/TimelineSection.vue.d.ts → shared/RelatedLogs.vue.d.ts} +5 -6
- package/dist/vue/composables/useDashboardData.d.ts +12 -23
- package/dist/vue/index-C8MxnS7Q.js +1232 -0
- package/dist/vue/index.js +1 -1
- package/dist/vue/style.css +1 -1
- package/package.json +1 -1
- package/dist/react/CacheTab-DYmsZJJ1.js +0 -123
- package/dist/react/CustomPaneTab-D7_o3Ec6.js +0 -104
- package/dist/react/EmailsTab-Uh2CQY3o.js +0 -153
- package/dist/react/EventsTab-CC6DQzEm.js +0 -63
- package/dist/react/LogsTab-BbYK-iyh.js +0 -103
- package/dist/react/RequestsSection-Cb5a6MlT.js +0 -209
- package/dist/react/RoutesTab-Bwreij3e.js +0 -74
- package/dist/react/TimelineSection-B2y06kRE.js +0 -158
- package/dist/react/TimelineTab-6hthfdBB.js +0 -193
- package/dist/react/WaterfallChart-Cj73WdfM.js +0 -100
- package/dist/react/index-CecA4IdQ.js +0 -1075
- package/dist/react/react/components/Dashboard/sections/TimelineSection.d.ts +0 -8
- package/dist/vue/RequestsSection-B-uSlM0f.js +0 -243
- package/dist/vue/TimelineSection-CfvnA2Oo.js +0 -186
- package/dist/vue/TimelineTab-Db6lKKsD.js +0 -250
- package/dist/vue/WaterfallChart.vue_vue_type_script_setup_true_lang-tZ13cNj1.js +0 -118
- package/dist/vue/index-oLxS08vN.js +0 -1235
|
@@ -1,36 +1,67 @@
|
|
|
1
1
|
import { log, dim, bold } from '../utils/logger.js';
|
|
2
|
+
/** Default metrics returned when queue data is unavailable. */
|
|
3
|
+
const QUEUE_DEFAULTS = {
|
|
4
|
+
queueActive: 0,
|
|
5
|
+
queueWaiting: 0,
|
|
6
|
+
queueDelayed: 0,
|
|
7
|
+
queueFailed: 0,
|
|
8
|
+
queueWorkerCount: 0,
|
|
9
|
+
};
|
|
10
|
+
/** Fetch job counts from a BullMQ queue. */
|
|
11
|
+
async function fetchQueueCounts(queueName, connection) {
|
|
12
|
+
const { Queue } = await import('bullmq');
|
|
13
|
+
const queue = new Queue(queueName, { connection });
|
|
14
|
+
const [counts, workers] = await Promise.all([queue.getJobCounts(), queue.getWorkers()]);
|
|
15
|
+
await queue.close();
|
|
16
|
+
return {
|
|
17
|
+
queueActive: counts.active ?? 0,
|
|
18
|
+
queueWaiting: counts.waiting ?? 0,
|
|
19
|
+
queueDelayed: counts.delayed ?? 0,
|
|
20
|
+
queueFailed: counts.failed ?? 0,
|
|
21
|
+
queueWorkerCount: workers.length,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** Handle queue collection errors with one-time warnings. */
|
|
25
|
+
function handleQueueError(error, queueName, connection, warned) {
|
|
26
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
27
|
+
const isImportError = message.includes('Cannot find package') ||
|
|
28
|
+
message.includes('MODULE_NOT_FOUND') ||
|
|
29
|
+
message.includes('ERR_MODULE_NOT_FOUND');
|
|
30
|
+
if (isImportError) {
|
|
31
|
+
if (!warned.missingBullmq) {
|
|
32
|
+
warned.missingBullmq = true;
|
|
33
|
+
log.warn(`Queue collector ${bold(queueName)}: ${bold('bullmq')} is not installed`);
|
|
34
|
+
log.block('Install the peer dependency to enable queue metrics:', [
|
|
35
|
+
`${bold('npm install bullmq')}`,
|
|
36
|
+
dim('Queue metrics will return zeros until bullmq is available.'),
|
|
37
|
+
]);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (!warned.connectionError) {
|
|
41
|
+
warned.connectionError = true;
|
|
42
|
+
const { host, port } = connection;
|
|
43
|
+
log.warn(`Queue collector ${bold(queueName)}: cannot connect to Redis at ${bold(`${host}:${port}`)}`);
|
|
44
|
+
log.block('Connection failed:', [
|
|
45
|
+
`${dim('Error:')} ${message}`,
|
|
46
|
+
dim('Is Redis running? Check with: redis-cli ping'),
|
|
47
|
+
dim('Queue metrics will return zeros until the connection succeeds.'),
|
|
48
|
+
]);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
2
51
|
/**
|
|
3
52
|
* Monitors a BullMQ job queue for active, waiting, delayed, and failed jobs.
|
|
4
53
|
*
|
|
5
|
-
* Creates a temporary BullMQ `Queue` instance each tick to fetch counts,
|
|
6
|
-
* then immediately closes it.
|
|
7
|
-
*
|
|
8
|
-
* **Metrics produced:**
|
|
9
|
-
* - `queueActive` -- jobs being processed
|
|
10
|
-
* - `queueWaiting` -- jobs waiting for a worker
|
|
11
|
-
* - `queueDelayed` -- jobs scheduled for the future
|
|
12
|
-
* - `queueFailed` -- permanently failed jobs
|
|
13
|
-
* - `queueWorkerCount` -- connected worker processes
|
|
14
|
-
*
|
|
15
54
|
* Returns zeros if BullMQ is unavailable or the queue cannot be reached.
|
|
16
55
|
*
|
|
17
56
|
* **Peer dependencies:** `bullmq`
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* ```ts
|
|
21
|
-
* import { queueCollector } from 'adonisjs-server-stats/collectors'
|
|
22
|
-
*
|
|
23
|
-
* queueCollector({
|
|
24
|
-
* queueName: 'default',
|
|
25
|
-
* connection: { host: 'localhost', port: 6379, password: 'secret' },
|
|
26
|
-
* })
|
|
27
|
-
* ```
|
|
28
57
|
*/
|
|
29
58
|
export function queueCollector(opts) {
|
|
30
59
|
const queueName = opts.queueName ?? 'default';
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
60
|
+
const warned = {
|
|
61
|
+
missingBullmq: false,
|
|
62
|
+
connectionError: false,
|
|
63
|
+
missingConnection: false,
|
|
64
|
+
};
|
|
34
65
|
return {
|
|
35
66
|
name: 'queue',
|
|
36
67
|
label: `queue — ${queueName} @ ${opts.connection?.host ?? '?'}:${opts.connection?.port ?? '?'}`,
|
|
@@ -43,68 +74,21 @@ export function queueCollector(opts) {
|
|
|
43
74
|
},
|
|
44
75
|
async collect() {
|
|
45
76
|
if (!opts.connection) {
|
|
46
|
-
if (!
|
|
47
|
-
|
|
77
|
+
if (!warned.missingConnection) {
|
|
78
|
+
warned.missingConnection = true;
|
|
48
79
|
log.warn(`Queue collector ${bold(queueName)}: missing ${bold('connection')} option`);
|
|
49
80
|
log.block('Provide a Redis connection when creating the collector:', [
|
|
50
81
|
`${dim('queueCollector({ connection: { host: "localhost", port: 6379 } })')}`,
|
|
51
82
|
]);
|
|
52
83
|
}
|
|
53
|
-
return
|
|
54
|
-
queueActive: 0,
|
|
55
|
-
queueWaiting: 0,
|
|
56
|
-
queueDelayed: 0,
|
|
57
|
-
queueFailed: 0,
|
|
58
|
-
queueWorkerCount: 0,
|
|
59
|
-
};
|
|
84
|
+
return QUEUE_DEFAULTS;
|
|
60
85
|
}
|
|
61
86
|
try {
|
|
62
|
-
|
|
63
|
-
const queue = new Queue(queueName, { connection: opts.connection });
|
|
64
|
-
const [counts, workers] = await Promise.all([queue.getJobCounts(), queue.getWorkers()]);
|
|
65
|
-
await queue.close();
|
|
66
|
-
return {
|
|
67
|
-
queueActive: counts.active ?? 0,
|
|
68
|
-
queueWaiting: counts.waiting ?? 0,
|
|
69
|
-
queueDelayed: counts.delayed ?? 0,
|
|
70
|
-
queueFailed: counts.failed ?? 0,
|
|
71
|
-
queueWorkerCount: workers.length,
|
|
72
|
-
};
|
|
87
|
+
return await fetchQueueCounts(queueName, opts.connection);
|
|
73
88
|
}
|
|
74
89
|
catch (error) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
message.includes('MODULE_NOT_FOUND') ||
|
|
78
|
-
message.includes('ERR_MODULE_NOT_FOUND');
|
|
79
|
-
if (isImportError) {
|
|
80
|
-
if (!warnedMissingBullmq) {
|
|
81
|
-
warnedMissingBullmq = true;
|
|
82
|
-
log.warn(`Queue collector ${bold(queueName)}: ${bold('bullmq')} is not installed`);
|
|
83
|
-
log.block('Install the peer dependency to enable queue metrics:', [
|
|
84
|
-
`${bold('npm install bullmq')}`,
|
|
85
|
-
dim('Queue metrics will return zeros until bullmq is available.'),
|
|
86
|
-
]);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
if (!warnedConnectionError) {
|
|
91
|
-
warnedConnectionError = true;
|
|
92
|
-
const { host, port } = opts.connection;
|
|
93
|
-
log.warn(`Queue collector ${bold(queueName)}: cannot connect to Redis at ${bold(`${host}:${port}`)}`);
|
|
94
|
-
log.block('Connection failed:', [
|
|
95
|
-
`${dim('Error:')} ${message}`,
|
|
96
|
-
dim('Is Redis running? Check with: redis-cli ping'),
|
|
97
|
-
dim('Queue metrics will return zeros until the connection succeeds.'),
|
|
98
|
-
]);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return {
|
|
102
|
-
queueActive: 0,
|
|
103
|
-
queueWaiting: 0,
|
|
104
|
-
queueDelayed: 0,
|
|
105
|
-
queueFailed: 0,
|
|
106
|
-
queueWorkerCount: 0,
|
|
107
|
-
};
|
|
90
|
+
handleQueueError(error, queueName, opts.connection, warned);
|
|
91
|
+
return QUEUE_DEFAULTS;
|
|
108
92
|
}
|
|
109
93
|
},
|
|
110
94
|
};
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import type { MetricCollector } from './collector.js';
|
|
2
|
+
/** Parse a Redis INFO section into key-value pairs. */
|
|
3
|
+
export declare function parseRedisInfo(info: string): Record<string, string>;
|
|
4
|
+
/** Compute metrics from parsed Redis INFO sections + DBSIZE. */
|
|
5
|
+
export declare function computeRedisMetrics(memParsed: Record<string, string>, statsParsed: Record<string, string>, dbSize: unknown): {
|
|
6
|
+
redisOk: boolean;
|
|
7
|
+
redisMemoryUsedMb: number;
|
|
8
|
+
redisConnectedClients: number;
|
|
9
|
+
redisKeysCount: number;
|
|
10
|
+
redisHitRate: number;
|
|
11
|
+
};
|
|
2
12
|
/**
|
|
3
13
|
* Monitors Redis health, memory, connections, keys, and cache hit rate.
|
|
4
14
|
*
|
|
5
|
-
* Uses the AdonisJS Redis service to send `PING`, `INFO`, and `DBSIZE`
|
|
6
|
-
* commands. Returns safe defaults if Redis is unavailable.
|
|
7
|
-
*
|
|
8
|
-
* **Metrics produced:**
|
|
9
|
-
* - `redisOk` -- `true` if PING returned PONG
|
|
10
|
-
* - `redisMemoryUsedMb` -- server memory usage (MB)
|
|
11
|
-
* - `redisConnectedClients` -- connected client count
|
|
12
|
-
* - `redisKeysCount` -- total keys across all databases
|
|
13
|
-
* - `redisHitRate` -- cache hit rate (%)
|
|
14
|
-
*
|
|
15
15
|
* **Peer dependencies:** `@adonisjs/redis`
|
|
16
16
|
*/
|
|
17
17
|
export declare function redisCollector(): MetricCollector;
|
|
@@ -3,19 +3,71 @@ import { log, dim, bold } from '../utils/logger.js';
|
|
|
3
3
|
let warnedNotInstalled = false;
|
|
4
4
|
let warnedPingFailed = false;
|
|
5
5
|
let warnedConnectionError = false;
|
|
6
|
+
/** Default metrics returned when Redis is unavailable. */
|
|
7
|
+
const REDIS_DEFAULTS = {
|
|
8
|
+
redisOk: false,
|
|
9
|
+
redisMemoryUsedMb: 0,
|
|
10
|
+
redisConnectedClients: 0,
|
|
11
|
+
redisKeysCount: 0,
|
|
12
|
+
redisHitRate: 0,
|
|
13
|
+
};
|
|
14
|
+
/** Parse a Redis INFO section into key-value pairs. */
|
|
15
|
+
export function parseRedisInfo(info) {
|
|
16
|
+
const result = {};
|
|
17
|
+
for (const line of info.split('\r\n')) {
|
|
18
|
+
const idx = line.indexOf(':');
|
|
19
|
+
if (idx > 0) {
|
|
20
|
+
result[line.slice(0, idx)] = line.slice(idx + 1);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
/** Compute metrics from parsed Redis INFO sections + DBSIZE. */
|
|
26
|
+
export function computeRedisMetrics(memParsed, statsParsed, dbSize) {
|
|
27
|
+
const usedMemoryBytes = Number.parseInt(memParsed['used_memory'] ?? '0', 10);
|
|
28
|
+
const connectedClients = Number.parseInt(memParsed['connected_clients'] ?? statsParsed['connected_clients'] ?? '0', 10);
|
|
29
|
+
const hits = Number.parseInt(statsParsed['keyspace_hits'] ?? '0', 10);
|
|
30
|
+
const misses = Number.parseInt(statsParsed['keyspace_misses'] ?? '0', 10);
|
|
31
|
+
const total = hits + misses;
|
|
32
|
+
const hitRate = total > 0 ? (hits / total) * 100 : 0;
|
|
33
|
+
return {
|
|
34
|
+
redisOk: true,
|
|
35
|
+
redisMemoryUsedMb: usedMemoryBytes / (1024 * 1024),
|
|
36
|
+
redisConnectedClients: connectedClients,
|
|
37
|
+
redisKeysCount: typeof dbSize === 'number' ? dbSize : 0,
|
|
38
|
+
redisHitRate: hitRate,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/** Import Redis service, returning null if unavailable. */
|
|
42
|
+
async function importRedis() {
|
|
43
|
+
try {
|
|
44
|
+
const mod = await appImport('@adonisjs/redis/services/main');
|
|
45
|
+
return mod.default;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
if (!warnedNotInstalled) {
|
|
49
|
+
warnedNotInstalled = true;
|
|
50
|
+
log.block(`Redis collector ${bold('skipped')} — @adonisjs/redis is not installed`, [
|
|
51
|
+
dim('Redis metrics will return defaults until the package is added.'),
|
|
52
|
+
`Run ${bold('node ace add @adonisjs/redis')} to install it.`,
|
|
53
|
+
]);
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** Warn once when PING fails. */
|
|
59
|
+
function warnPingFailed(pong) {
|
|
60
|
+
if (warnedPingFailed)
|
|
61
|
+
return;
|
|
62
|
+
warnedPingFailed = true;
|
|
63
|
+
log.block(`Redis collector ${bold('unhealthy')} — PING returned ${bold(String(pong))} instead of PONG`, [
|
|
64
|
+
dim('Redis may be down or misconfigured.'),
|
|
65
|
+
`Check your connection settings in ${bold('config/redis.ts')}.`,
|
|
66
|
+
]);
|
|
67
|
+
}
|
|
6
68
|
/**
|
|
7
69
|
* Monitors Redis health, memory, connections, keys, and cache hit rate.
|
|
8
70
|
*
|
|
9
|
-
* Uses the AdonisJS Redis service to send `PING`, `INFO`, and `DBSIZE`
|
|
10
|
-
* commands. Returns safe defaults if Redis is unavailable.
|
|
11
|
-
*
|
|
12
|
-
* **Metrics produced:**
|
|
13
|
-
* - `redisOk` -- `true` if PING returned PONG
|
|
14
|
-
* - `redisMemoryUsedMb` -- server memory usage (MB)
|
|
15
|
-
* - `redisConnectedClients` -- connected client count
|
|
16
|
-
* - `redisKeysCount` -- total keys across all databases
|
|
17
|
-
* - `redisHitRate` -- cache hit rate (%)
|
|
18
|
-
*
|
|
19
71
|
* **Peer dependencies:** `@adonisjs/redis`
|
|
20
72
|
*/
|
|
21
73
|
export function redisCollector() {
|
|
@@ -26,70 +78,21 @@ export function redisCollector() {
|
|
|
26
78
|
return {};
|
|
27
79
|
},
|
|
28
80
|
async collect() {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
redisConnectedClients: 0,
|
|
33
|
-
redisKeysCount: 0,
|
|
34
|
-
redisHitRate: 0,
|
|
35
|
-
};
|
|
36
|
-
let redis;
|
|
37
|
-
try {
|
|
38
|
-
const mod = await appImport('@adonisjs/redis/services/main');
|
|
39
|
-
redis = mod.default;
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
if (!warnedNotInstalled) {
|
|
43
|
-
warnedNotInstalled = true;
|
|
44
|
-
log.block(`Redis collector ${bold('skipped')} — @adonisjs/redis is not installed`, [
|
|
45
|
-
dim('Redis metrics will return defaults until the package is added.'),
|
|
46
|
-
`Run ${bold('node ace add @adonisjs/redis')} to install it.`,
|
|
47
|
-
]);
|
|
48
|
-
}
|
|
49
|
-
return defaults;
|
|
50
|
-
}
|
|
81
|
+
const redis = await importRedis();
|
|
82
|
+
if (!redis)
|
|
83
|
+
return REDIS_DEFAULTS;
|
|
51
84
|
try {
|
|
52
85
|
const pong = await redis.ping();
|
|
53
86
|
if (pong !== 'PONG') {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
log.block(`Redis collector ${bold('unhealthy')} — PING returned ${bold(String(pong))} instead of PONG`, [
|
|
57
|
-
dim('Redis may be down or misconfigured.'),
|
|
58
|
-
`Check your connection settings in ${bold('config/redis.ts')}.`,
|
|
59
|
-
]);
|
|
60
|
-
}
|
|
61
|
-
return defaults;
|
|
87
|
+
warnPingFailed(pong);
|
|
88
|
+
return REDIS_DEFAULTS;
|
|
62
89
|
}
|
|
63
90
|
const [memoryInfo, statsInfo, dbSize] = await Promise.all([
|
|
64
91
|
redis.info('memory'),
|
|
65
92
|
redis.info('stats'),
|
|
66
93
|
redis.dbsize(),
|
|
67
94
|
]);
|
|
68
|
-
|
|
69
|
-
const result = {};
|
|
70
|
-
for (const line of info.split('\r\n')) {
|
|
71
|
-
const idx = line.indexOf(':');
|
|
72
|
-
if (idx > 0) {
|
|
73
|
-
result[line.slice(0, idx)] = line.slice(idx + 1);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return result;
|
|
77
|
-
};
|
|
78
|
-
const memParsed = parseInfo(memoryInfo);
|
|
79
|
-
const statsParsed = parseInfo(statsInfo);
|
|
80
|
-
const usedMemoryBytes = Number.parseInt(memParsed['used_memory'] ?? '0', 10);
|
|
81
|
-
const connectedClients = Number.parseInt(memParsed['connected_clients'] ?? statsParsed['connected_clients'] ?? '0', 10);
|
|
82
|
-
const hits = Number.parseInt(statsParsed['keyspace_hits'] ?? '0', 10);
|
|
83
|
-
const misses = Number.parseInt(statsParsed['keyspace_misses'] ?? '0', 10);
|
|
84
|
-
const total = hits + misses;
|
|
85
|
-
const hitRate = total > 0 ? (hits / total) * 100 : 0;
|
|
86
|
-
return {
|
|
87
|
-
redisOk: true,
|
|
88
|
-
redisMemoryUsedMb: usedMemoryBytes / (1024 * 1024),
|
|
89
|
-
redisConnectedClients: connectedClients,
|
|
90
|
-
redisKeysCount: typeof dbSize === 'number' ? dbSize : 0,
|
|
91
|
-
redisHitRate: hitRate,
|
|
92
|
-
};
|
|
95
|
+
return computeRedisMetrics(parseRedisInfo(memoryInfo), parseRedisInfo(statsInfo), dbSize);
|
|
93
96
|
}
|
|
94
97
|
catch (error) {
|
|
95
98
|
if (!warnedConnectionError) {
|
|
@@ -100,7 +103,7 @@ export function redisCollector() {
|
|
|
100
103
|
`Make sure Redis is running and accessible. Check ${bold('config/redis.ts')} for connection details.`,
|
|
101
104
|
]);
|
|
102
105
|
}
|
|
103
|
-
return
|
|
106
|
+
return REDIS_DEFAULTS;
|
|
104
107
|
}
|
|
105
108
|
},
|
|
106
109
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ServerStatsConfig } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Detect deprecated config names and log a single grouped warning block.
|
|
4
|
+
*
|
|
5
|
+
* Only warns for fields the user **actually set** (not undefined).
|
|
6
|
+
*/
|
|
7
|
+
export declare function logDeprecationWarnings(config: ServerStatsConfig): void;
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Deprecation warning logic for renamed config fields
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
//
|
|
5
|
+
// Extracted from define_config.ts to reduce complexity and file length.
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
import { bold, dim } from '../utils/logger.js';
|
|
8
|
+
const SIMPLE_DEPRECATIONS = [
|
|
9
|
+
{
|
|
10
|
+
key: 'intervalMs',
|
|
11
|
+
old: 'intervalMs',
|
|
12
|
+
newName: 'pollInterval',
|
|
13
|
+
before: (c) => [`intervalMs: ${c.intervalMs}`],
|
|
14
|
+
after: (c) => [`pollInterval: ${c.intervalMs}`],
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
key: 'transport',
|
|
18
|
+
old: 'transport',
|
|
19
|
+
newName: 'realtime',
|
|
20
|
+
before: (c) => [`transport: '${c.transport}'`],
|
|
21
|
+
after: (c) => [`realtime: ${c.transport === 'transmit'}`],
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
key: 'endpoint',
|
|
25
|
+
old: 'endpoint',
|
|
26
|
+
newName: 'statsEndpoint',
|
|
27
|
+
before: (c) => {
|
|
28
|
+
const d = c.endpoint === false ? 'false' : `'${c.endpoint}'`;
|
|
29
|
+
return [`endpoint: ${d}`];
|
|
30
|
+
},
|
|
31
|
+
after: (c) => {
|
|
32
|
+
const d = c.endpoint === false ? 'false' : `'${c.endpoint}'`;
|
|
33
|
+
return [`statsEndpoint: ${d}`];
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
key: 'shouldShow',
|
|
38
|
+
old: 'shouldShow',
|
|
39
|
+
newName: 'authorize',
|
|
40
|
+
before: () => ['shouldShow: (ctx) => ...'],
|
|
41
|
+
after: () => ['authorize: (ctx) => ...'],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
key: 'channelName',
|
|
45
|
+
old: 'channelName',
|
|
46
|
+
newName: 'advanced.channelName',
|
|
47
|
+
before: (c) => [`channelName: '${c.channelName}'`],
|
|
48
|
+
after: (c) => [`advanced: { channelName: '${c.channelName}' }`],
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
key: 'skipInTest',
|
|
52
|
+
old: 'skipInTest',
|
|
53
|
+
newName: 'advanced.skipInTest',
|
|
54
|
+
before: (c) => [`skipInTest: ${c.skipInTest}`],
|
|
55
|
+
after: (c) => [`advanced: { skipInTest: ${c.skipInTest} }`],
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
/** Fields to include in the "before" snapshot of devToolbar. */
|
|
59
|
+
const BEFORE_FIELDS = [
|
|
60
|
+
{ key: 'enabled', format: (v) => `enabled: ${v}` },
|
|
61
|
+
{ key: 'dashboard', format: (v) => `dashboard: ${v}` },
|
|
62
|
+
{ key: 'dashboardPath', format: (v) => `dashboardPath: '${v}'` },
|
|
63
|
+
{ key: 'retentionDays', format: (v) => `retentionDays: ${v}` },
|
|
64
|
+
{ key: 'slowQueryThresholdMs', format: (v) => `slowQueryThresholdMs: ${v}` },
|
|
65
|
+
{ key: 'tracing', format: (v) => `tracing: ${v}` },
|
|
66
|
+
{ key: 'persistDebugData', format: (v) => `persistDebugData: ${JSON.stringify(v)}` },
|
|
67
|
+
{ key: 'maxQueries', format: (v) => `maxQueries: ${v}` },
|
|
68
|
+
{ key: 'maxEvents', format: (v) => `maxEvents: ${v}` },
|
|
69
|
+
{ key: 'maxEmails', format: (v) => `maxEmails: ${v}` },
|
|
70
|
+
{ key: 'maxTraces', format: (v) => `maxTraces: ${v}` },
|
|
71
|
+
{ key: 'renderer', format: (v) => `renderer: '${v}'` },
|
|
72
|
+
{ key: 'panes', format: () => `panes: [...]` },
|
|
73
|
+
{ key: 'excludeFromTracing', format: () => `excludeFromTracing: [...]` },
|
|
74
|
+
{ key: 'debugEndpoint', format: (v) => `debugEndpoint: '${v}'` },
|
|
75
|
+
{ key: 'dbPath', format: (v) => `dbPath: '${v}'` },
|
|
76
|
+
];
|
|
77
|
+
function buildBeforeParts(dt) {
|
|
78
|
+
const parts = ['devToolbar: {'];
|
|
79
|
+
for (const { key, format } of BEFORE_FIELDS) {
|
|
80
|
+
if (dt[key] !== undefined) {
|
|
81
|
+
parts.push(` ${format(dt[key])},`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
parts.push('}');
|
|
85
|
+
return parts;
|
|
86
|
+
}
|
|
87
|
+
const TOOLBAR_AFTER_FIELDS = [
|
|
88
|
+
{ key: 'slowQueryThresholdMs', format: (v) => ` slowQueryThreshold: ${v},` },
|
|
89
|
+
{ key: 'tracing', format: (v) => ` tracing: ${v},` },
|
|
90
|
+
{ key: 'persistDebugData', format: (v) => ` persist: ${JSON.stringify(v)},` },
|
|
91
|
+
{ key: 'panes', format: () => ` panes: [...],` },
|
|
92
|
+
{ key: 'excludeFromTracing', format: () => ` excludeFromTracing: [...],` },
|
|
93
|
+
];
|
|
94
|
+
function buildToolbarAfter(dt) {
|
|
95
|
+
if (!dt.enabled)
|
|
96
|
+
return [];
|
|
97
|
+
const details = TOOLBAR_AFTER_FIELDS.filter(({ key }) => dt[key] !== undefined);
|
|
98
|
+
if (details.length === 0)
|
|
99
|
+
return ['toolbar: true'];
|
|
100
|
+
return ['toolbar: {', ...details.map(({ key, format }) => format(dt[key])), '}'];
|
|
101
|
+
}
|
|
102
|
+
function buildDashboardAfter(dt) {
|
|
103
|
+
if (!dt.dashboard)
|
|
104
|
+
return [];
|
|
105
|
+
const hasDetails = dt.dashboardPath !== undefined || dt.retentionDays !== undefined;
|
|
106
|
+
if (!hasDetails)
|
|
107
|
+
return ['dashboard: true'];
|
|
108
|
+
const parts = ['dashboard: {'];
|
|
109
|
+
if (dt.dashboardPath !== undefined)
|
|
110
|
+
parts.push(` path: '${dt.dashboardPath}',`);
|
|
111
|
+
if (dt.retentionDays !== undefined)
|
|
112
|
+
parts.push(` retentionDays: ${dt.retentionDays},`);
|
|
113
|
+
parts.push('}');
|
|
114
|
+
return parts;
|
|
115
|
+
}
|
|
116
|
+
function buildAdvancedAfter(dt) {
|
|
117
|
+
const parts = [];
|
|
118
|
+
if (dt.maxQueries !== undefined)
|
|
119
|
+
parts.push(` maxQueries: ${dt.maxQueries},`);
|
|
120
|
+
if (dt.maxEvents !== undefined)
|
|
121
|
+
parts.push(` maxEvents: ${dt.maxEvents},`);
|
|
122
|
+
if (dt.maxEmails !== undefined)
|
|
123
|
+
parts.push(` maxEmails: ${dt.maxEmails},`);
|
|
124
|
+
if (dt.maxTraces !== undefined)
|
|
125
|
+
parts.push(` maxTraces: ${dt.maxTraces},`);
|
|
126
|
+
if (dt.renderer !== undefined)
|
|
127
|
+
parts.push(` renderer: '${dt.renderer}',`);
|
|
128
|
+
if (dt.debugEndpoint !== undefined)
|
|
129
|
+
parts.push(` debugEndpoint: '${dt.debugEndpoint}',`);
|
|
130
|
+
if (dt.dbPath !== undefined)
|
|
131
|
+
parts.push(` dbPath: '${dt.dbPath}',`);
|
|
132
|
+
if (parts.length === 0)
|
|
133
|
+
return [];
|
|
134
|
+
return ['advanced: {', ...parts, '}'];
|
|
135
|
+
}
|
|
136
|
+
function buildDevToolbarMigration(dt) {
|
|
137
|
+
const afterParts = [
|
|
138
|
+
...buildToolbarAfter(dt),
|
|
139
|
+
...buildDashboardAfter(dt),
|
|
140
|
+
...buildAdvancedAfter(dt),
|
|
141
|
+
];
|
|
142
|
+
const advancedPresent = buildAdvancedAfter(dt).length > 0;
|
|
143
|
+
const newLabel = [
|
|
144
|
+
dt.enabled !== undefined ? 'toolbar' : '',
|
|
145
|
+
dt.dashboard ? 'dashboard' : '',
|
|
146
|
+
advancedPresent ? 'advanced' : '',
|
|
147
|
+
]
|
|
148
|
+
.filter(Boolean)
|
|
149
|
+
.join(' + ') || 'toolbar + dashboard + advanced';
|
|
150
|
+
return {
|
|
151
|
+
old: 'devToolbar',
|
|
152
|
+
new: newLabel,
|
|
153
|
+
before: buildBeforeParts(dt),
|
|
154
|
+
after: afterParts,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
// Main export
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
/**
|
|
161
|
+
* Detect deprecated config names and log a single grouped warning block.
|
|
162
|
+
*
|
|
163
|
+
* Only warns for fields the user **actually set** (not undefined).
|
|
164
|
+
*/
|
|
165
|
+
export function logDeprecationWarnings(config) {
|
|
166
|
+
const entries = [];
|
|
167
|
+
for (const dep of SIMPLE_DEPRECATIONS) {
|
|
168
|
+
if (config[dep.key] !== undefined) {
|
|
169
|
+
entries.push({
|
|
170
|
+
old: dep.old,
|
|
171
|
+
new: dep.newName,
|
|
172
|
+
before: dep.before(config),
|
|
173
|
+
after: dep.after(config),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (config.devToolbar !== undefined) {
|
|
178
|
+
entries.push(buildDevToolbarMigration(config.devToolbar));
|
|
179
|
+
}
|
|
180
|
+
if (entries.length === 0)
|
|
181
|
+
return;
|
|
182
|
+
const TAG = '\x1b[36m[ \x1b[1m\uD83D\uDD0D server-stats\x1b[0m\x1b[36m ]\x1b[0m';
|
|
183
|
+
const lines = [''];
|
|
184
|
+
lines.push(`${TAG} Some config options have been renamed — here's how to update:`);
|
|
185
|
+
lines.push('');
|
|
186
|
+
for (const entry of entries) {
|
|
187
|
+
lines.push(` ${dim(entry.old)} ${dim('\u2192')} ${bold(entry.new)}`);
|
|
188
|
+
lines.push('');
|
|
189
|
+
for (const line of entry.before) {
|
|
190
|
+
lines.push(` ${dim('before:')} ${dim(line)}`);
|
|
191
|
+
}
|
|
192
|
+
for (const line of entry.after) {
|
|
193
|
+
lines.push(` ${dim('after:')} ${line}`);
|
|
194
|
+
}
|
|
195
|
+
lines.push('');
|
|
196
|
+
}
|
|
197
|
+
lines.push(` ${dim('No rush — the old names still work. They will be removed in the next major version.')}`);
|
|
198
|
+
lines.push(` ${dim('Update')} ${bold('config/server_stats.ts')} ${dim('when you get a chance.')}`);
|
|
199
|
+
lines.push('');
|
|
200
|
+
console.log(lines.join('\n'));
|
|
201
|
+
}
|
|
@@ -19,8 +19,8 @@ export default class DebugController {
|
|
|
19
19
|
private cachedAdonisVersion;
|
|
20
20
|
constructor(store: DebugStore, serverConfig?: ResolvedServerStatsConfig | undefined, diagnosticsDeps?: DiagnosticsDeps);
|
|
21
21
|
config({ response }: HttpContext): Promise<void>;
|
|
22
|
-
/** Lazily create a ConfigInspector from the app reference. */
|
|
23
22
|
private getConfigInspector;
|
|
23
|
+
private cacheVersions;
|
|
24
24
|
diagnostics({ response }: HttpContext): Promise<void>;
|
|
25
25
|
}
|
|
26
26
|
export {};
|