adonisjs-server-stats 1.5.2 → 1.5.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 CHANGED
@@ -159,170 +159,15 @@ export default defineConfig({
159
159
  })
160
160
  ```
161
161
 
162
- ### 4. Add routes
162
+ ### 4. Render the stats bar
163
163
 
164
- The package has three layers of functionality, each with its own routes:
164
+ That's it for setup -- **all API routes are auto-registered by the package**. No controllers or route definitions needed. On startup you'll see:
165
165
 
166
- #### Stats bar API route (required)
167
-
168
- The stats bar polls this endpoint for live metrics. Create a controller and route:
169
-
170
- ```ts
171
- // app/controllers/admin/server_stats_controller.ts
172
- import app from '@adonisjs/core/services/app'
173
- import type { HttpContext } from '@adonisjs/core/http'
174
- import type { StatsEngine } from 'adonisjs-server-stats'
175
-
176
- export default class ServerStatsController {
177
- async index({ response }: HttpContext) {
178
- const engine = (await app.container.make('server_stats.engine')) as StatsEngine
179
- return response.json(engine.getLatestStats())
180
- }
181
- }
182
- ```
183
-
184
- ```ts
185
- // start/routes.ts
186
- router
187
- .get('/admin/api/server-stats', '#controllers/admin/server_stats_controller.index')
188
- .use(middleware.superadmin())
189
- ```
190
-
191
- > The route path must match `endpoint` in your config (default: `/admin/api/server-stats`).
192
-
193
- #### Debug toolbar routes (optional -- when `devToolbar.enabled: true`)
194
-
195
- The debug toolbar panels fetch data from these API endpoints. Create a controller and routes:
196
-
197
- ```ts
198
- // app/controllers/admin/debug_controller.ts
199
- import app from '@adonisjs/core/services/app'
200
- import type { HttpContext } from '@adonisjs/core/http'
201
- import type { DebugStore } from 'adonisjs-server-stats/debug'
202
-
203
- export default class DebugController {
204
- private async getStore(): Promise<DebugStore | null> {
205
- try {
206
- return (await app.container.make('debug.store')) as DebugStore
207
- } catch {
208
- return null
209
- }
210
- }
211
-
212
- async queries({ response }: HttpContext) {
213
- const store = await this.getStore()
214
- if (!store) return response.notFound({ error: 'Debug toolbar not enabled' })
215
- return response.json({ queries: store.queries.getLatest(500), summary: store.queries.getSummary() })
216
- }
217
-
218
- async events({ response }: HttpContext) {
219
- const store = await this.getStore()
220
- if (!store) return response.notFound({ error: 'Debug toolbar not enabled' })
221
- return response.json({ events: store.events.getLatest(200), total: store.events.getTotalCount() })
222
- }
223
-
224
- async routes({ response }: HttpContext) {
225
- const store = await this.getStore()
226
- if (!store) return response.notFound({ error: 'Debug toolbar not enabled' })
227
- return response.json({ routes: store.routes.getRoutes(), total: store.routes.getRouteCount() })
228
- }
229
-
230
- async logs({ response }: HttpContext) {
231
- const store = await this.getStore()
232
- if (!store) return response.notFound({ error: 'Debug toolbar not enabled' })
233
- return response.json({ logs: store.logs.getLatest(500), total: store.logs.getTotalCount() })
234
- }
235
-
236
- async emails({ response }: HttpContext) {
237
- const store = await this.getStore()
238
- if (!store) return response.notFound({ error: 'Debug toolbar not enabled' })
239
- const emails = store.emails.getLatest(100)
240
- const stripped = emails.map(({ html, text, ...rest }) => rest)
241
- return response.json({ emails: stripped, total: store.emails.getTotalCount() })
242
- }
243
-
244
- async emailPreview({ params, response }: HttpContext) {
245
- const store = await this.getStore()
246
- if (!store) return response.notFound({ error: 'Debug toolbar not enabled' })
247
- const html = store.emails.getEmailHtml(Number(params.id))
248
- if (!html) return response.notFound({ error: 'Email not found' })
249
- return response.header('Content-Type', 'text/html; charset=utf-8').send(html)
250
- }
251
-
252
- async traces({ response }: HttpContext) {
253
- const store = await this.getStore()
254
- if (!store) return response.notFound({ error: 'Debug toolbar not enabled' })
255
- if (!store.traces) return response.json({ traces: [], total: 0 })
256
- const traces = store.traces.getLatest(100)
257
- const list = traces.map(({ spans, warnings, ...rest }: any) => ({
258
- ...rest,
259
- warningCount: warnings.length,
260
- }))
261
- return response.json({ traces: list, total: store.traces.getTotalCount() })
262
- }
263
-
264
- async traceDetail({ params, response }: HttpContext) {
265
- const store = await this.getStore()
266
- if (!store) return response.notFound({ error: 'Debug toolbar not enabled' })
267
- if (!store.traces) return response.notFound({ error: 'Tracing not enabled' })
268
- const trace = store.traces.getTrace(Number(params.id))
269
- if (!trace) return response.notFound({ error: 'Trace not found' })
270
- return response.json(trace)
271
- }
272
- }
273
166
  ```
274
-
275
- ```ts
276
- // start/routes.ts
277
- router
278
- .group(() => {
279
- router.get('queries', '#controllers/admin/debug_controller.queries')
280
- router.get('events', '#controllers/admin/debug_controller.events')
281
- router.get('routes', '#controllers/admin/debug_controller.routes')
282
- router.get('logs', '#controllers/admin/debug_controller.logs')
283
- router.get('emails', '#controllers/admin/debug_controller.emails')
284
- router.get('emails/:id/preview', '#controllers/admin/debug_controller.emailPreview')
285
- router.get('traces', '#controllers/admin/debug_controller.traces')
286
- router.get('traces/:id', '#controllers/admin/debug_controller.traceDetail')
287
- })
288
- .prefix('/admin/api/debug')
289
- .use(middleware.superadmin())
167
+ [server-stats] auto-registered routes: /admin/api/server-stats, /admin/api/debug/*, /__stats/*
290
168
  ```
291
169
 
292
- #### Dashboard routes (automatic -- when `devToolbar.dashboard: true`)
293
-
294
- The full-page dashboard at `/__stats` **registers its own routes automatically** -- no manual route setup needed. The following routes are created under the configured `dashboardPath` (default: `/__stats`):
295
-
296
- | Method | Path | Description |
297
- |--------|------|-------------|
298
- | GET | `/` | Dashboard page (HTML) |
299
- | GET | `/api/overview` | Overview metrics |
300
- | GET | `/api/overview/chart` | Time-series chart data |
301
- | GET | `/api/requests` | Paginated request history |
302
- | GET | `/api/requests/:id` | Request detail with queries/trace |
303
- | GET | `/api/queries` | Paginated query list |
304
- | GET | `/api/queries/grouped` | Queries grouped by normalized SQL |
305
- | GET | `/api/queries/:id/explain` | EXPLAIN plan for a query |
306
- | GET | `/api/events` | Paginated event list |
307
- | GET | `/api/routes` | Route table |
308
- | GET | `/api/logs` | Paginated log entries |
309
- | GET | `/api/emails` | Paginated email list |
310
- | GET | `/api/emails/:id/preview` | Email HTML preview |
311
- | GET | `/api/traces` | Paginated trace list |
312
- | GET | `/api/traces/:id` | Trace detail with spans |
313
- | GET | `/api/cache` | Cache stats and key listing |
314
- | GET | `/api/cache/:key` | Cache key detail |
315
- | GET | `/api/jobs` | Job queue overview |
316
- | GET | `/api/jobs/:id` | Job detail |
317
- | POST | `/api/jobs/:id/retry` | Retry a failed job |
318
- | GET | `/api/config` | App config (secrets redacted) |
319
- | GET | `/api/filters` | Saved filters |
320
- | POST | `/api/filters` | Create saved filter |
321
- | DELETE | `/api/filters/:id` | Delete saved filter |
322
-
323
- All dashboard routes are gated by the `shouldShow` callback if configured.
324
-
325
- ### 5. Render the stats bar
170
+ All routes are gated by the `shouldShow` callback if configured (see [Visibility Control](#visibility-control-shouldshow)).
326
171
 
327
172
  **Edge** (add before `</body>`):
328
173
 
@@ -364,6 +209,7 @@ All dashboard routes are gated by the `shouldShow` callback if configured.
364
209
  | `dashboardPath` | `string` | `'/__stats'` | URL path for the dashboard page |
365
210
  | `retentionDays` | `number` | `7` | Days to keep historical data in SQLite |
366
211
  | `dbPath` | `string` | `'.adonisjs/server-stats/dashboard.sqlite3'` | Path to the SQLite database file (relative to app root) |
212
+ | `debugEndpoint` | `string` | `'/admin/api/debug'` | Base path for the debug toolbar API endpoints |
367
213
  | `excludeFromTracing` | `string[]` | `['/admin/api/debug', '/admin/api/server-stats']` | URL prefixes to exclude from tracing and dashboard persistence. Requests still count toward HTTP metrics but won't appear in the timeline or be stored. The stats endpoint is always excluded automatically. |
368
214
  | `panes` | `DebugPane[]` | -- | Custom debug panel tabs |
369
215
 
@@ -457,7 +303,7 @@ interface MetricCollector {
457
303
 
458
304
  ## Visibility Control (`shouldShow`)
459
305
 
460
- By default the stats bar renders for every request. Use `shouldShow` to restrict it. The callback receives the AdonisJS `HttpContext` and should return `true` to show the bar, `false` to hide it.
306
+ Use `shouldShow` to control who can see the stats bar and access all auto-registered API routes (stats, debug, dashboard). The callback receives the AdonisJS `HttpContext` and should return `true` to allow access, `false` to deny (403).
461
307
 
462
308
  Because `shouldShow` runs **after** middleware (including auth), you have full access to `ctx.auth`.
463
309
 
@@ -485,7 +331,71 @@ export default defineConfig({
485
331
  })
486
332
  ```
487
333
 
488
- > **Tip:** When `shouldShow` is not set, the bar renders for everyone. In production you almost always want to set this.
334
+ > **Tip:** When `shouldShow` is not set, the bar and all routes are accessible to everyone. In production you almost always want to set this.
335
+
336
+ ---
337
+
338
+ ## Auto-Registered Routes
339
+
340
+ All API routes are registered automatically by the package during `boot()` -- no manual controllers or route definitions needed. Each route group is gated by the `shouldShow` callback if configured.
341
+
342
+ ### Stats bar endpoint
343
+
344
+ Registered when `endpoint` is a string (default: `/admin/api/server-stats`). Returns the latest stats snapshot as JSON.
345
+
346
+ ### Debug toolbar routes
347
+
348
+ Registered when `devToolbar.enabled: true`. Base path configurable via `devToolbar.debugEndpoint` (default: `/admin/api/debug`).
349
+
350
+ | Method | Path | Description |
351
+ |--------|------|-------------|
352
+ | GET | `/queries` | SQL queries with summary stats |
353
+ | GET | `/events` | Application events |
354
+ | GET | `/routes` | Registered route table |
355
+ | GET | `/logs` | Log file entries (last 256KB) |
356
+ | GET | `/emails` | Captured emails (stripped HTML) |
357
+ | GET | `/emails/:id/preview` | Email HTML preview |
358
+ | GET | `/traces` | Request traces |
359
+ | GET | `/traces/:id` | Trace detail with spans |
360
+
361
+ ### Dashboard routes
362
+
363
+ Registered when `devToolbar.dashboard: true`. Base path configurable via `devToolbar.dashboardPath` (default: `/__stats`).
364
+
365
+ | Method | Path | Description |
366
+ |--------|------|-------------|
367
+ | GET | `/` | Dashboard page (HTML) |
368
+ | GET | `/api/overview` | Overview metrics |
369
+ | GET | `/api/overview/chart` | Time-series chart data |
370
+ | GET | `/api/requests` | Paginated request history |
371
+ | GET | `/api/requests/:id` | Request detail with queries/trace |
372
+ | GET | `/api/queries` | Paginated query list |
373
+ | GET | `/api/queries/grouped` | Queries grouped by normalized SQL |
374
+ | GET | `/api/queries/:id/explain` | EXPLAIN plan for a query |
375
+ | GET | `/api/events` | Paginated event list |
376
+ | GET | `/api/routes` | Route table |
377
+ | GET | `/api/logs` | Paginated log entries |
378
+ | GET | `/api/emails` | Paginated email list |
379
+ | GET | `/api/emails/:id/preview` | Email HTML preview |
380
+ | GET | `/api/traces` | Paginated trace list |
381
+ | GET | `/api/traces/:id` | Trace detail with spans |
382
+ | GET | `/api/cache` | Cache stats and key listing |
383
+ | GET | `/api/cache/:key` | Cache key detail |
384
+ | GET | `/api/jobs` | Job queue overview |
385
+ | GET | `/api/jobs/:id` | Job detail |
386
+ | POST | `/api/jobs/:id/retry` | Retry a failed job |
387
+ | GET | `/api/config` | App config (secrets redacted) |
388
+ | GET | `/api/filters` | Saved filters |
389
+ | POST | `/api/filters` | Create saved filter |
390
+ | DELETE | `/api/filters/:id` | Delete saved filter |
391
+
392
+ ### Global middleware note
393
+
394
+ Auto-registered routes bypass route-level middleware but are still subject to global/server middleware. If you have auth middleware (like `silentAuth`) registered globally, each polling request will trigger a DB query every few seconds.
395
+
396
+ To avoid this, either:
397
+ - Move auth middleware to a named route group instead of global middleware
398
+ - Use the `shouldShow` callback for access control (recommended)
489
399
 
490
400
  ---
491
401
 
@@ -531,7 +441,7 @@ export default defineConfig({
531
441
  })
532
442
  ```
533
443
 
534
- Register the debug API routes (see [step 4](#4-add-routes) for the full controller and route setup).
444
+ Debug routes are auto-registered by the package at `/admin/api/debug/*` (configurable via `debugEndpoint`).
535
445
 
536
446
  ### Built-in Emails Tab
537
447
 
@@ -2,7 +2,8 @@ import type { DebugStore } from '../debug/debug_store.js';
2
2
  import type { HttpContext } from '@adonisjs/core/http';
3
3
  export default class DebugController {
4
4
  private store;
5
- constructor(store: DebugStore);
5
+ private logPath;
6
+ constructor(store: DebugStore, logPath: string);
6
7
  queries({ response }: HttpContext): Promise<void>;
7
8
  events({ response }: HttpContext): Promise<void>;
8
9
  routes({ response }: HttpContext): Promise<void>;
@@ -10,5 +11,6 @@ export default class DebugController {
10
11
  emailPreview({ params, response }: HttpContext): Promise<void>;
11
12
  traces({ response }: HttpContext): Promise<void>;
12
13
  traceDetail({ params, response }: HttpContext): Promise<void>;
14
+ logs({ response }: HttpContext): Promise<void>;
13
15
  }
14
16
  //# sourceMappingURL=debug_controller.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"debug_controller.d.ts","sourceRoot":"","sources":["../../../src/controller/debug_controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAEtD,MAAM,CAAC,OAAO,OAAO,eAAe;IACtB,OAAO,CAAC,KAAK;gBAAL,KAAK,EAAE,UAAU;IAE/B,OAAO,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW;IAMjC,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW;IAKhC,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW;IAKhC,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW;IAOhC,YAAY,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,WAAW;IAS9C,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW;IAahC,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,WAAW;CAWpD"}
1
+ {"version":3,"file":"debug_controller.d.ts","sourceRoot":"","sources":["../../../src/controller/debug_controller.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAWtD,MAAM,CAAC,OAAO,OAAO,eAAe;IAIhC,OAAO,CAAC,KAAK;IAHf,OAAO,CAAC,OAAO,CAAQ;gBAGb,KAAK,EAAE,UAAU,EACzB,OAAO,EAAE,MAAM;IAKX,OAAO,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW;IAMjC,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW;IAKhC,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW;IAKhC,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW;IAOhC,YAAY,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,WAAW;IAS9C,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW;IAahC,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,WAAW;IAY7C,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW;CAgDrC"}
@@ -1,7 +1,18 @@
1
+ import { readFile, stat } from 'node:fs/promises';
2
+ const LEVEL_NAMES = {
3
+ 10: 'trace',
4
+ 20: 'debug',
5
+ 30: 'info',
6
+ 40: 'warn',
7
+ 50: 'error',
8
+ 60: 'fatal',
9
+ };
1
10
  export default class DebugController {
2
11
  store;
3
- constructor(store) {
12
+ logPath;
13
+ constructor(store, logPath) {
4
14
  this.store = store;
15
+ this.logPath = logPath;
5
16
  }
6
17
  async queries({ response }) {
7
18
  const queries = this.store.queries.getLatest(500);
@@ -53,4 +64,53 @@ export default class DebugController {
53
64
  }
54
65
  return response.json(trace);
55
66
  }
67
+ async logs({ response }) {
68
+ try {
69
+ const stats = await stat(this.logPath);
70
+ // Only read last 256KB to keep response fast
71
+ const maxBytes = 256 * 1024;
72
+ let content;
73
+ if (stats.size > maxBytes) {
74
+ const { createReadStream } = await import('node:fs');
75
+ const stream = createReadStream(this.logPath, {
76
+ start: stats.size - maxBytes,
77
+ encoding: 'utf-8',
78
+ });
79
+ const chunks = [];
80
+ for await (const chunk of stream) {
81
+ chunks.push(chunk);
82
+ }
83
+ content = chunks.join('');
84
+ // Skip first potentially incomplete line
85
+ const firstNewline = content.indexOf('\n');
86
+ if (firstNewline !== -1)
87
+ content = content.slice(firstNewline + 1);
88
+ }
89
+ else {
90
+ content = await readFile(this.logPath, 'utf-8');
91
+ }
92
+ const entries = content
93
+ .trim()
94
+ .split('\n')
95
+ .filter(Boolean)
96
+ .map((line) => {
97
+ try {
98
+ const entry = JSON.parse(line);
99
+ return {
100
+ ...entry,
101
+ levelName: LEVEL_NAMES[entry.level] || 'unknown',
102
+ timestamp: new Date(entry.time).toISOString(),
103
+ };
104
+ }
105
+ catch {
106
+ return null;
107
+ }
108
+ })
109
+ .filter(Boolean);
110
+ return response.json(entries);
111
+ }
112
+ catch {
113
+ return response.json([]);
114
+ }
115
+ }
56
116
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard_routes.d.ts","sourceRoot":"","sources":["../../../src/dashboard/dashboard_routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,mBAAmB,MAAM,2BAA2B,CAAA;AAEhE;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,GAAG,EACX,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,mBAAmB,GAAG,IAAI,EAC/C,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,QA8EnC"}
1
+ {"version":3,"file":"dashboard_routes.d.ts","sourceRoot":"","sources":["../../../src/dashboard/dashboard_routes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,mBAAmB,MAAM,2BAA2B,CAAA;AAEhE;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,GAAG,EACX,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,mBAAmB,GAAG,IAAI,EAC/C,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,QA8EnC"}
@@ -1,3 +1,4 @@
1
+ import { createAccessMiddleware } from '../routes/access_middleware.js';
1
2
  /**
2
3
  * Register all dashboard routes under the configured path.
3
4
  *
@@ -74,20 +75,3 @@ export function registerDashboardRoutes(router, dashboardPath, getController, sh
74
75
  .prefix(base)
75
76
  .use(middleware);
76
77
  }
77
- /**
78
- * Create a middleware function that gates access using the shouldShow callback.
79
- * Returns 403 if the callback returns false.
80
- */
81
- function createAccessMiddleware(shouldShow) {
82
- return async (ctx, next) => {
83
- try {
84
- if (!shouldShow(ctx)) {
85
- return ctx.response.forbidden({ error: 'Access denied' });
86
- }
87
- }
88
- catch {
89
- return ctx.response.forbidden({ error: 'Access denied' });
90
- }
91
- await next();
92
- };
93
- }
@@ -175,6 +175,8 @@ export interface DevToolbarConfig {
175
175
  retentionDays: number;
176
176
  /** Path to the SQLite database file for historical persistence. */
177
177
  dbPath: string;
178
+ /** Base path for the debug toolbar API endpoints. */
179
+ debugEndpoint: string;
178
180
  }
179
181
  /**
180
182
  * Color names available for the `badge` column format.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/debug/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/debug/types.ts"],"names":[],"mappings":"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"}
@@ -8,10 +8,10 @@
8
8
  * data-logs-endpoint — logs API URL
9
9
  */
10
10
  ;(function () {
11
- const BASE = '/admin/api/debug'
12
11
  const REFRESH_INTERVAL = 3000
13
12
  const panel = document.getElementById('ss-dbg-panel')
14
13
  const wrench = document.getElementById('ss-dbg-wrench')
14
+ const BASE = (panel && panel.dataset.debugEndpoint) || '/admin/api/debug'
15
15
  const closeBtn = document.getElementById('ss-dbg-close')
16
16
 
17
17
  if (!panel || !wrench) return
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/edge/plugin.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAKpD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,IACrD,MAAM,GAAG,UAmHlB"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/edge/plugin.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAKpD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,IACrD,MAAM,GAAG,UAqHlB"}
@@ -93,9 +93,11 @@ export function edgePluginServerStats(config) {
93
93
  groups,
94
94
  };
95
95
  if (showDebug) {
96
+ const debugEndpoint = config.devToolbar?.debugEndpoint || '/admin/api/debug';
96
97
  state.debugCss = read('client/debug-panel.css');
97
98
  state.debugJs = read('client/debug-panel.js');
98
- state.logsEndpoint = '/admin/api/debug/logs';
99
+ state.debugEndpoint = debugEndpoint;
100
+ state.logsEndpoint = debugEndpoint + '/logs';
99
101
  state.customPanes = config.devToolbar?.panes || [];
100
102
  state.showTracing = !!config.devToolbar?.tracing;
101
103
  state.dashboardPath = config.devToolbar?.dashboard
@@ -1,4 +1,4 @@
1
- <div id="ss-dbg-panel" class="ss-dbg-panel" data-logs-endpoint="{{ logsEndpoint }}" data-tracing="{{ showTracing ? '1' : '0' }}"@if(dashboardPath) data-dashboard-path="{{ dashboardPath }}"@end>
1
+ <div id="ss-dbg-panel" class="ss-dbg-panel" data-logs-endpoint="{{ logsEndpoint }}" data-tracing="{{ showTracing ? '1' : '0' }}" data-debug-endpoint="{{ debugEndpoint }}"@if(dashboardPath) data-dashboard-path="{{ dashboardPath }}"@end>
2
2
  <div class="ss-dbg-tabs">
3
3
  <div class="ss-dbg-tabs-scroll">
4
4
  @if(showTracing)
@@ -11,6 +11,8 @@ export default class ServerStatsProvider {
11
11
  private debugBroadcastTimer;
12
12
  private persistPath;
13
13
  private flushTimer;
14
+ private statsController;
15
+ private debugController;
14
16
  constructor(app: ApplicationService);
15
17
  boot(): Promise<void>;
16
18
  ready(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"server_stats_provider.d.ts","sourceRoot":"","sources":["../../../src/provider/server_stats_provider.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAE9D,MAAM,CAAC,OAAO,OAAO,mBAAmB;IAY1B,SAAS,CAAC,GAAG,EAAE,kBAAkB;IAX7C,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,cAAc,CAA8B;IACpD,OAAO,CAAC,mBAAmB,CAAmC;IAC9D,OAAO,CAAC,kBAAkB,CAAgC;IAC1D,OAAO,CAAC,uBAAuB,CAA8C;IAC7E,OAAO,CAAC,mBAAmB,CAA6C;IACxE,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,UAAU,CAA8C;gBAE1C,GAAG,EAAE,kBAAkB;IAEvC,IAAI;IAkCJ,KAAK;YA+EG,eAAe;IAmF7B;;;;;;OAMG;YACW,cAAc;IAoGtB,QAAQ;CAwCf"}
1
+ {"version":3,"file":"server_stats_provider.d.ts","sourceRoot":"","sources":["../../../src/provider/server_stats_provider.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAE9D,MAAM,CAAC,OAAO,OAAO,mBAAmB;IAc1B,SAAS,CAAC,GAAG,EAAE,kBAAkB;IAb7C,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,cAAc,CAA8B;IACpD,OAAO,CAAC,mBAAmB,CAAmC;IAC9D,OAAO,CAAC,kBAAkB,CAAgC;IAC1D,OAAO,CAAC,uBAAuB,CAA8C;IAC7E,OAAO,CAAC,mBAAmB,CAA6C;IACxE,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,eAAe,CAAqC;IAC5D,OAAO,CAAC,eAAe,CAA+B;gBAEhC,GAAG,EAAE,kBAAkB;IAEvC,IAAI;IAqFJ,KAAK;YAuFG,eAAe;IAwF7B;;;;;;OAMG;YACW,cAAc;IAoGtB,QAAQ;CAwCf"}
@@ -4,6 +4,8 @@ import { DebugStore } from '../debug/debug_store.js';
4
4
  import { StatsEngine } from '../engine/stats_engine.js';
5
5
  import { LogStreamService } from '../log_stream/log_stream_service.js';
6
6
  import { setShouldShow, setTraceCollector, setDashboardPath, setExcludedPrefixes, setOnRequestComplete, } from '../middleware/request_tracking_middleware.js';
7
+ import { registerDebugRoutes } from '../routes/debug_routes.js';
8
+ import { registerStatsRoutes } from '../routes/stats_routes.js';
7
9
  export default class ServerStatsProvider {
8
10
  app;
9
11
  intervalId = null;
@@ -16,6 +18,8 @@ export default class ServerStatsProvider {
16
18
  debugBroadcastTimer = null;
17
19
  persistPath = null;
18
20
  flushTimer = null;
21
+ statsController = null;
22
+ debugController = null;
19
23
  constructor(app) {
20
24
  this.app = app;
21
25
  }
@@ -27,17 +31,46 @@ export default class ServerStatsProvider {
27
31
  if (config.shouldShow) {
28
32
  setShouldShow(config.shouldShow);
29
33
  }
30
- // Register dashboard routes early (before router commits).
31
- // The controller is created later in ready() — routes use a lazy getter.
32
- const toolbarConfig = config.devToolbar;
33
- if (toolbarConfig?.enabled && toolbarConfig.dashboard && !this.app.inProduction) {
34
- try {
35
- const router = await this.app.container.make('router');
36
- const dashPath = toolbarConfig.dashboardPath ?? '/__stats';
37
- registerDashboardRoutes(router, dashPath, () => this.dashboardController, config.shouldShow);
34
+ let router = null;
35
+ try {
36
+ router = await this.app.container.make('router');
37
+ }
38
+ catch {
39
+ // Router not available — skip all route registration
40
+ }
41
+ if (router && !this.app.inProduction) {
42
+ const registeredPaths = [];
43
+ // ── Auto-register stats bar endpoint ───────────────────────
44
+ if (typeof config.endpoint === 'string') {
45
+ registerStatsRoutes(router, config.endpoint, () => this.statsController, config.shouldShow);
46
+ registeredPaths.push(config.endpoint);
38
47
  }
39
- catch {
40
- // Router not available — skip route registration
48
+ // ── Auto-register debug toolbar routes ─────────────────────
49
+ const toolbarConfig = config.devToolbar;
50
+ if (toolbarConfig?.enabled) {
51
+ const debugEndpoint = toolbarConfig.debugEndpoint ?? '/admin/api/debug';
52
+ registerDebugRoutes(router, debugEndpoint, () => this.debugController, config.shouldShow);
53
+ registeredPaths.push(debugEndpoint + '/*');
54
+ // ── Auto-register dashboard routes ─────────────────────────
55
+ if (toolbarConfig.dashboard) {
56
+ const dashPath = toolbarConfig.dashboardPath ?? '/__stats';
57
+ registerDashboardRoutes(router, dashPath, () => this.dashboardController, config.shouldShow);
58
+ registeredPaths.push(dashPath + '/*');
59
+ }
60
+ }
61
+ // Log registered routes
62
+ if (registeredPaths.length > 0) {
63
+ const tag = '\x1b[36m[ \x1b[1m🔍 server-stats\x1b[0m\x1b[36m ]\x1b[0m';
64
+ const dim = (s) => `\x1b[2m${s}\x1b[0m`;
65
+ const bold = (s) => `\x1b[1m${s}\x1b[0m`;
66
+ console.log(`\n${tag} routes registered:\n` +
67
+ registeredPaths.map((p) => ` ${dim('→')} ${bold(p)}`).join('\n') +
68
+ '\n\n' +
69
+ `${tag} ${dim('heads up — these routes get polled every ~3s.')}\n` +
70
+ ` ${dim('global middleware (like silentAuth) runs on every poll,')}\n` +
71
+ ` ${dim('which means extra DB queries. two ways to fix this:')}\n` +
72
+ ` ${dim('1. move auth middleware to a route group (not server.use)')}\n` +
73
+ ` ${dim('2. use the shouldShow callback in config for access control')}\n`);
41
74
  }
42
75
  }
43
76
  if (!this.app.usingEdgeJS)
@@ -60,6 +93,9 @@ export default class ServerStatsProvider {
60
93
  this.engine = new StatsEngine(config.collectors);
61
94
  this.app.container.singleton('server_stats.engine', () => this.engine);
62
95
  await this.engine.start();
96
+ // Create the stats controller (makes the stats route functional)
97
+ const StatsControllerClass = (await import('../controller/server_stats_controller.js')).default;
98
+ this.statsController = new StatsControllerClass(this.engine);
63
99
  // Dev toolbar setup
64
100
  const toolbarConfig = config.devToolbar;
65
101
  if (toolbarConfig?.enabled && !this.app.inProduction) {
@@ -76,12 +112,14 @@ export default class ServerStatsProvider {
76
112
  dashboardPath: toolbarConfig.dashboardPath ?? '/__stats',
77
113
  retentionDays: toolbarConfig.retentionDays ?? 7,
78
114
  dbPath: toolbarConfig.dbPath ?? '.adonisjs/server-stats/dashboard.sqlite3',
115
+ debugEndpoint: toolbarConfig.debugEndpoint ?? '/admin/api/debug',
79
116
  });
80
117
  // Exclude the stats endpoint and user-specified prefixes from tracing
81
118
  // so the debug panel's own polling doesn't flood the timeline
82
- const defaultExcludes = ['/admin/api/debug', '/admin/api/server-stats'];
119
+ const debugEndpoint = toolbarConfig.debugEndpoint ?? '/admin/api/debug';
120
+ const defaultExcludes = [debugEndpoint, config.endpoint].filter((p) => typeof p === 'string');
83
121
  const prefixes = [...(toolbarConfig.excludeFromTracing ?? defaultExcludes)];
84
- if (typeof config.endpoint === 'string') {
122
+ if (typeof config.endpoint === 'string' && !prefixes.includes(config.endpoint)) {
85
123
  prefixes.push(config.endpoint);
86
124
  }
87
125
  if (prefixes.length > 0) {
@@ -149,6 +187,10 @@ export default class ServerStatsProvider {
149
187
  // Router not available
150
188
  }
151
189
  await this.debugStore.start(emitter, router);
190
+ // Create the debug controller (makes the debug routes functional)
191
+ const logPath = this.app.makePath('logs', 'adonisjs.log');
192
+ const DebugControllerClass = (await import('../controller/debug_controller.js')).default;
193
+ this.debugController = new DebugControllerClass(this.debugStore, logPath);
152
194
  // Wire trace collector into the request tracking middleware
153
195
  if (this.debugStore.traces) {
154
196
  setTraceCollector(this.debugStore.traces);
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Create a middleware function that gates access using the shouldShow callback.
3
+ * Returns 403 if the callback returns false.
4
+ *
5
+ * Shared by stats, debug, and dashboard route registrars.
6
+ */
7
+ export declare function createAccessMiddleware(shouldShow: (ctx: any) => boolean): (ctx: any, next: () => Promise<void>) => Promise<any>;
8
+ //# sourceMappingURL=access_middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access_middleware.d.ts","sourceRoot":"","sources":["../../../src/routes/access_middleware.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,IACxD,KAAK,GAAG,EAAE,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,kBAUlD"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Create a middleware function that gates access using the shouldShow callback.
3
+ * Returns 403 if the callback returns false.
4
+ *
5
+ * Shared by stats, debug, and dashboard route registrars.
6
+ */
7
+ export function createAccessMiddleware(shouldShow) {
8
+ return async (ctx, next) => {
9
+ try {
10
+ if (!shouldShow(ctx)) {
11
+ return ctx.response.forbidden({ error: 'Access denied' });
12
+ }
13
+ }
14
+ catch {
15
+ return ctx.response.forbidden({ error: 'Access denied' });
16
+ }
17
+ await next();
18
+ };
19
+ }
@@ -0,0 +1,14 @@
1
+ import type DebugController from '../controller/debug_controller.js';
2
+ /**
3
+ * Register all debug toolbar API routes under the given base path.
4
+ *
5
+ * Uses a lazy controller getter so routes can be registered during
6
+ * `boot()` while the DebugStore/controller is created during `ready()`.
7
+ *
8
+ * @param router The AdonisJS router instance.
9
+ * @param basePath The base path (e.g. `/admin/api/debug`).
10
+ * @param getController Lazy getter for the debug controller.
11
+ * @param shouldShow Optional access-control callback.
12
+ */
13
+ export declare function registerDebugRoutes(router: any, basePath: string, getController: () => DebugController | null, shouldShow?: (ctx: any) => boolean): void;
14
+ //# sourceMappingURL=debug_routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug_routes.d.ts","sourceRoot":"","sources":["../../../src/routes/debug_routes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,eAAe,MAAM,mCAAmC,CAAA;AAEpE;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,GAAG,EACX,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,eAAe,GAAG,IAAI,EAC3C,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,QAgCnC"}
@@ -0,0 +1,42 @@
1
+ import { createAccessMiddleware } from './access_middleware.js';
2
+ /**
3
+ * Register all debug toolbar API routes under the given base path.
4
+ *
5
+ * Uses a lazy controller getter so routes can be registered during
6
+ * `boot()` while the DebugStore/controller is created during `ready()`.
7
+ *
8
+ * @param router The AdonisJS router instance.
9
+ * @param basePath The base path (e.g. `/admin/api/debug`).
10
+ * @param getController Lazy getter for the debug controller.
11
+ * @param shouldShow Optional access-control callback.
12
+ */
13
+ export function registerDebugRoutes(router, basePath, getController, shouldShow) {
14
+ const base = basePath.replace(/\/+$/, '');
15
+ const middleware = shouldShow ? [createAccessMiddleware(shouldShow)] : [];
16
+ const bind = (method) => {
17
+ return async (ctx) => {
18
+ const controller = getController();
19
+ if (!controller) {
20
+ return ctx.response.serviceUnavailable({
21
+ error: 'Debug toolbar is starting up, please retry',
22
+ });
23
+ }
24
+ return controller[method].call(controller, ctx);
25
+ };
26
+ };
27
+ router
28
+ .group(() => {
29
+ router.get('/queries', bind('queries')).as('server-stats.debug.queries');
30
+ router.get('/events', bind('events')).as('server-stats.debug.events');
31
+ router.get('/routes', bind('routes')).as('server-stats.debug.routes');
32
+ router.get('/logs', bind('logs')).as('server-stats.debug.logs');
33
+ router.get('/emails', bind('emails')).as('server-stats.debug.emails');
34
+ router
35
+ .get('/emails/:id/preview', bind('emailPreview'))
36
+ .as('server-stats.debug.emailPreview');
37
+ router.get('/traces', bind('traces')).as('server-stats.debug.traces');
38
+ router.get('/traces/:id', bind('traceDetail')).as('server-stats.debug.traceDetail');
39
+ })
40
+ .prefix(base)
41
+ .use(middleware);
42
+ }
@@ -0,0 +1,14 @@
1
+ import type ServerStatsController from '../controller/server_stats_controller.js';
2
+ /**
3
+ * Register the stats bar API endpoint.
4
+ *
5
+ * Uses a lazy controller getter so the route can be registered during
6
+ * `boot()` while the engine/controller is created during `ready()`.
7
+ *
8
+ * @param router The AdonisJS router instance.
9
+ * @param endpoint The endpoint path (e.g. `/admin/api/server-stats`).
10
+ * @param getController Lazy getter for the stats controller.
11
+ * @param shouldShow Optional access-control callback.
12
+ */
13
+ export declare function registerStatsRoutes(router: any, endpoint: string, getController: () => ServerStatsController | null, shouldShow?: (ctx: any) => boolean): void;
14
+ //# sourceMappingURL=stats_routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats_routes.d.ts","sourceRoot":"","sources":["../../../src/routes/stats_routes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,qBAAqB,MAAM,0CAA0C,CAAA;AAEjF;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,GAAG,EACX,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,qBAAqB,GAAG,IAAI,EACjD,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,QAgBnC"}
@@ -0,0 +1,27 @@
1
+ import { createAccessMiddleware } from './access_middleware.js';
2
+ /**
3
+ * Register the stats bar API endpoint.
4
+ *
5
+ * Uses a lazy controller getter so the route can be registered during
6
+ * `boot()` while the engine/controller is created during `ready()`.
7
+ *
8
+ * @param router The AdonisJS router instance.
9
+ * @param endpoint The endpoint path (e.g. `/admin/api/server-stats`).
10
+ * @param getController Lazy getter for the stats controller.
11
+ * @param shouldShow Optional access-control callback.
12
+ */
13
+ export function registerStatsRoutes(router, endpoint, getController, shouldShow) {
14
+ const middleware = shouldShow ? [createAccessMiddleware(shouldShow)] : [];
15
+ router
16
+ .get(endpoint, async (ctx) => {
17
+ const controller = getController();
18
+ if (!controller) {
19
+ return ctx.response.serviceUnavailable({
20
+ error: 'Stats engine is starting up, please retry',
21
+ });
22
+ }
23
+ return controller.index(ctx);
24
+ })
25
+ .as('server-stats.api')
26
+ .use(middleware);
27
+ }
@@ -287,6 +287,17 @@ export interface DevToolbarOptions {
287
287
  * @default ['/admin/api/debug', '/admin/api/server-stats']
288
288
  */
289
289
  excludeFromTracing?: string[];
290
+ /**
291
+ * Base path for the debug toolbar API endpoints.
292
+ *
293
+ * The debug panel fetches data from endpoints under this path
294
+ * (e.g. `{debugEndpoint}/queries`, `{debugEndpoint}/events`).
295
+ *
296
+ * Must start with `/`.
297
+ *
298
+ * @default '/admin/api/debug'
299
+ */
300
+ debugEndpoint?: string;
290
301
  }
291
302
  /**
292
303
  * Top-level configuration for `adonisjs-server-stats`.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adonisjs-server-stats",
3
- "version": "1.5.2",
3
+ "version": "1.5.3",
4
4
  "description": "Real-time server monitoring for AdonisJS v6 applications",
5
5
  "keywords": [
6
6
  "adonisjs",