adonisjs-server-stats 1.4.0 → 1.5.1
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 +114 -116
- package/dist/configure.d.ts.map +1 -1
- package/dist/src/controller/debug_controller.d.ts +2 -2
- package/dist/src/controller/debug_controller.d.ts.map +1 -1
- package/dist/src/controller/server_stats_controller.d.ts +1 -1
- package/dist/src/controller/server_stats_controller.d.ts.map +1 -1
- package/dist/src/dashboard/chart_aggregator.d.ts.map +1 -1
- package/dist/src/dashboard/chart_aggregator.js +8 -8
- package/dist/src/dashboard/dashboard_controller.d.ts +12 -97
- package/dist/src/dashboard/dashboard_controller.d.ts.map +1 -1
- package/dist/src/dashboard/dashboard_controller.js +244 -522
- package/dist/src/dashboard/dashboard_routes.d.ts.map +1 -1
- package/dist/src/dashboard/dashboard_routes.js +7 -2
- package/dist/src/dashboard/dashboard_store.d.ts +6 -3
- package/dist/src/dashboard/dashboard_store.d.ts.map +1 -1
- package/dist/src/dashboard/dashboard_store.js +54 -78
- package/dist/src/dashboard/integrations/cache_inspector.d.ts.map +1 -1
- package/dist/src/dashboard/integrations/queue_inspector.d.ts.map +1 -1
- package/dist/src/dashboard/migrator.d.ts.map +1 -1
- package/dist/src/dashboard/migrator.js +3 -1
- 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_query.d.ts +1 -1
- package/dist/src/dashboard/models/stats_query.d.ts.map +1 -1
- package/dist/src/dashboard/models/stats_request.d.ts +2 -2
- package/dist/src/dashboard/models/stats_request.d.ts.map +1 -1
- package/dist/src/dashboard/models/stats_request.js +1 -1
- package/dist/src/dashboard/models/stats_trace.d.ts +1 -1
- package/dist/src/dashboard/models/stats_trace.d.ts.map +1 -1
- package/dist/src/debug/debug_store.d.ts +6 -6
- package/dist/src/debug/debug_store.d.ts.map +1 -1
- package/dist/src/debug/debug_store.js +10 -10
- package/dist/src/debug/email_collector.d.ts +0 -9
- package/dist/src/debug/email_collector.d.ts.map +1 -1
- package/dist/src/debug/email_collector.js +6 -28
- package/dist/src/debug/event_collector.d.ts +1 -1
- package/dist/src/debug/event_collector.d.ts.map +1 -1
- package/dist/src/debug/event_collector.js +17 -17
- package/dist/src/debug/query_collector.d.ts +1 -1
- package/dist/src/debug/query_collector.d.ts.map +1 -1
- package/dist/src/debug/query_collector.js +13 -14
- package/dist/src/debug/ring_buffer.d.ts.map +1 -1
- package/dist/src/debug/route_inspector.d.ts +1 -1
- package/dist/src/debug/route_inspector.d.ts.map +1 -1
- package/dist/src/debug/route_inspector.js +12 -12
- package/dist/src/debug/trace_collector.d.ts.map +1 -1
- package/dist/src/debug/trace_collector.js +6 -5
- package/dist/src/edge/client/dashboard.css +516 -171
- package/dist/src/edge/client/dashboard.js +2756 -1662
- package/dist/src/edge/client/debug-panel.css +476 -133
- package/dist/src/edge/client/debug-panel.js +1496 -1043
- package/dist/src/edge/client/stats-bar.css +64 -30
- package/dist/src/edge/client/stats-bar.js +598 -319
- package/dist/src/edge/plugin.d.ts +1 -1
- package/dist/src/edge/plugin.d.ts.map +1 -1
- package/dist/src/edge/plugin.js +41 -59
- package/dist/src/edge/views/stats-bar.edge +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/middleware/request_tracking_middleware.d.ts +4 -4
- package/dist/src/middleware/request_tracking_middleware.d.ts.map +1 -1
- package/dist/src/middleware/request_tracking_middleware.js +7 -6
- package/dist/src/prometheus/prometheus_collector.d.ts +1 -1
- package/dist/src/prometheus/prometheus_collector.d.ts.map +1 -1
- package/dist/src/provider/server_stats_provider.d.ts +1 -1
- package/dist/src/provider/server_stats_provider.d.ts.map +1 -1
- package/dist/src/provider/server_stats_provider.js +31 -31
- package/dist/src/utils/json_helpers.d.ts +8 -0
- package/dist/src/utils/json_helpers.d.ts.map +1 -0
- package/dist/src/utils/json_helpers.js +21 -0
- package/dist/src/utils/mail_helpers.d.ts +13 -0
- package/dist/src/utils/mail_helpers.d.ts.map +1 -0
- package/dist/src/utils/mail_helpers.js +26 -0
- package/dist/src/utils/math_helpers.d.ts +8 -0
- package/dist/src/utils/math_helpers.d.ts.map +1 -0
- package/dist/src/utils/math_helpers.js +11 -0
- package/dist/src/utils/time_helpers.d.ts +12 -0
- package/dist/src/utils/time_helpers.d.ts.map +1 -0
- package/dist/src/utils/time_helpers.js +32 -0
- package/dist/src/utils/transmit_client.d.ts +9 -0
- package/dist/src/utils/transmit_client.d.ts.map +1 -0
- package/dist/src/utils/transmit_client.js +20 -0
- package/package.json +35 -29
|
@@ -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,
|
|
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"}
|
|
@@ -39,7 +39,9 @@ export function registerDashboardRoutes(router, dashboardPath, getController, sh
|
|
|
39
39
|
// Queries
|
|
40
40
|
router.get('/api/queries', bind('queries')).as('server-stats.queries');
|
|
41
41
|
router.get('/api/queries/grouped', bind('queriesGrouped')).as('server-stats.queries.grouped');
|
|
42
|
-
router
|
|
42
|
+
router
|
|
43
|
+
.get('/api/queries/:id/explain', bind('queryExplain'))
|
|
44
|
+
.as('server-stats.queries.explain');
|
|
43
45
|
// Events
|
|
44
46
|
router.get('/api/events', bind('events')).as('server-stats.events');
|
|
45
47
|
// Routes
|
|
@@ -54,7 +56,10 @@ export function registerDashboardRoutes(router, dashboardPath, getController, sh
|
|
|
54
56
|
router.get('/api/traces/:id', bind('traceDetail')).as('server-stats.traces.show');
|
|
55
57
|
// Cache
|
|
56
58
|
router.get('/api/cache', bind('cacheStats')).as('server-stats.cache');
|
|
57
|
-
router
|
|
59
|
+
router
|
|
60
|
+
.get('/api/cache/:key', bind('cacheKey'))
|
|
61
|
+
.as('server-stats.cache.show')
|
|
62
|
+
.where('key', /.*/);
|
|
58
63
|
// Jobs / Queue
|
|
59
64
|
router.get('/api/jobs', bind('jobs')).as('server-stats.jobs');
|
|
60
65
|
router.get('/api/jobs/:id', bind('jobDetail')).as('server-stats.jobs.show');
|
|
@@ -3,6 +3,7 @@ import type { QueryRecord, EventRecord, EmailRecord, TraceRecord } from '../debu
|
|
|
3
3
|
export interface RequestFilters {
|
|
4
4
|
method?: string;
|
|
5
5
|
url?: string;
|
|
6
|
+
status?: number;
|
|
6
7
|
statusMin?: number;
|
|
7
8
|
statusMax?: number;
|
|
8
9
|
durationMin?: number;
|
|
@@ -105,12 +106,12 @@ export declare class DashboardStore {
|
|
|
105
106
|
* Grouped query patterns: aggregated by sql_normalized
|
|
106
107
|
* with count, avg/min/max/total duration.
|
|
107
108
|
*/
|
|
108
|
-
getQueriesGrouped(): Promise<any[]>;
|
|
109
|
+
getQueriesGrouped(limit?: number, sort?: string): Promise<any[]>;
|
|
109
110
|
/** Paginated event history with optional filters. */
|
|
110
111
|
getEvents(page?: number, perPage?: number, filters?: EventFilters): Promise<PaginatedResult<any>>;
|
|
111
112
|
/** Paginated email history with optional filters. */
|
|
112
|
-
getEmails(page?: number, perPage?: number, filters?: EmailFilters): Promise<PaginatedResult<any>>;
|
|
113
|
-
/** Get email HTML body for preview. */
|
|
113
|
+
getEmails(page?: number, perPage?: number, filters?: EmailFilters, excludeBody?: boolean): Promise<PaginatedResult<any>>;
|
|
114
|
+
/** Get email HTML body for preview (falls back to text_body). */
|
|
114
115
|
getEmailHtml(id: number): Promise<string | null>;
|
|
115
116
|
/**
|
|
116
117
|
* Paginated log history with structured search support.
|
|
@@ -170,6 +171,8 @@ export declare class DashboardStore {
|
|
|
170
171
|
count: number;
|
|
171
172
|
}[];
|
|
172
173
|
}>;
|
|
174
|
+
/** Get sparkline data points from pre-aggregated metrics. */
|
|
175
|
+
getSparklineData(range: string): Promise<any[]>;
|
|
173
176
|
getSavedFilters(section?: string): Promise<any[]>;
|
|
174
177
|
createSavedFilter(name: string, section: string, filterConfig: Record<string, any>): Promise<any>;
|
|
175
178
|
deleteSavedFilter(id: number): Promise<boolean>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard_store.d.ts","sourceRoot":"","sources":["../../../src/dashboard/dashboard_store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dashboard_store.d.ts","sourceRoot":"","sources":["../../../src/dashboard/dashboard_store.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { mkdir } from 'node:fs/promises';
|
|
2
2
|
import { dirname } from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { safeParseJson, safeParseJsonArray } from '../utils/json_helpers.js';
|
|
4
|
+
import { extractAddresses } from '../utils/mail_helpers.js';
|
|
5
|
+
import { round } from '../utils/math_helpers.js';
|
|
6
|
+
import { rangeToCutoff, rangeToMinutes, roundBucket } from '../utils/time_helpers.js';
|
|
4
7
|
import { ChartAggregator } from './chart_aggregator.js';
|
|
8
|
+
import { autoMigrate, runRetentionCleanup } from './migrator.js';
|
|
5
9
|
// ---------------------------------------------------------------------------
|
|
6
10
|
// DashboardStore
|
|
7
11
|
// ---------------------------------------------------------------------------
|
|
@@ -113,7 +117,7 @@ export class DashboardStore {
|
|
|
113
117
|
method,
|
|
114
118
|
url,
|
|
115
119
|
status_code: statusCode,
|
|
116
|
-
duration:
|
|
120
|
+
duration: round(duration),
|
|
117
121
|
span_count: spanCount,
|
|
118
122
|
warning_count: warningCount,
|
|
119
123
|
});
|
|
@@ -136,7 +140,7 @@ export class DashboardStore {
|
|
|
136
140
|
sql_text: q.sql,
|
|
137
141
|
sql_normalized: normalizeSql(q.sql),
|
|
138
142
|
bindings: q.bindings ? JSON.stringify(q.bindings) : null,
|
|
139
|
-
duration:
|
|
143
|
+
duration: round(q.duration),
|
|
140
144
|
method: q.method,
|
|
141
145
|
model: q.model,
|
|
142
146
|
connection: q.connection,
|
|
@@ -197,9 +201,7 @@ export class DashboardStore {
|
|
|
197
201
|
if (!this.db)
|
|
198
202
|
return;
|
|
199
203
|
try {
|
|
200
|
-
const levelName = typeof entry.levelName === 'string'
|
|
201
|
-
? entry.levelName
|
|
202
|
-
: String(entry.level || 'unknown');
|
|
204
|
+
const levelName = typeof entry.levelName === 'string' ? entry.levelName : String(entry.level || 'unknown');
|
|
203
205
|
await this.db('server_stats_logs').insert({
|
|
204
206
|
level: levelName,
|
|
205
207
|
message: String(entry.msg || entry.message || ''),
|
|
@@ -221,7 +223,7 @@ export class DashboardStore {
|
|
|
221
223
|
method: trace.method,
|
|
222
224
|
url: trace.url,
|
|
223
225
|
status_code: trace.statusCode,
|
|
224
|
-
total_duration:
|
|
226
|
+
total_duration: round(trace.totalDuration),
|
|
225
227
|
span_count: trace.spanCount,
|
|
226
228
|
spans: JSON.stringify(trace.spans),
|
|
227
229
|
warnings: trace.warnings.length > 0 ? JSON.stringify(trace.warnings) : null,
|
|
@@ -255,6 +257,8 @@ export class DashboardStore {
|
|
|
255
257
|
query.where('method', filters.method);
|
|
256
258
|
if (filters?.url)
|
|
257
259
|
query.where('url', 'like', `%${filters.url}%`);
|
|
260
|
+
if (filters?.status)
|
|
261
|
+
query.where('status_code', filters.status);
|
|
258
262
|
if (filters?.statusMin)
|
|
259
263
|
query.where('status_code', '>=', filters.statusMin);
|
|
260
264
|
if (filters?.statusMax)
|
|
@@ -286,14 +290,20 @@ export class DashboardStore {
|
|
|
286
290
|
* Grouped query patterns: aggregated by sql_normalized
|
|
287
291
|
* with count, avg/min/max/total duration.
|
|
288
292
|
*/
|
|
289
|
-
async getQueriesGrouped() {
|
|
293
|
+
async getQueriesGrouped(limit = 200, sort = 'total_duration') {
|
|
290
294
|
if (!this.db)
|
|
291
295
|
return [];
|
|
296
|
+
const validSorts = {
|
|
297
|
+
count: 'count',
|
|
298
|
+
avg_duration: 'avg_duration',
|
|
299
|
+
total_duration: 'total_duration',
|
|
300
|
+
};
|
|
301
|
+
const orderCol = validSorts[sort] || 'total_duration';
|
|
292
302
|
return this.db('server_stats_queries')
|
|
293
303
|
.select('sql_normalized', this.db.raw('COUNT(*) as count'), this.db.raw('ROUND(AVG(duration), 2) as avg_duration'), this.db.raw('ROUND(MIN(duration), 2) as min_duration'), this.db.raw('ROUND(MAX(duration), 2) as max_duration'), this.db.raw('ROUND(SUM(duration), 2) as total_duration'))
|
|
294
304
|
.groupBy('sql_normalized')
|
|
295
|
-
.orderBy(
|
|
296
|
-
.limit(
|
|
305
|
+
.orderBy(orderCol, 'desc')
|
|
306
|
+
.limit(limit);
|
|
297
307
|
}
|
|
298
308
|
/** Paginated event history with optional filters. */
|
|
299
309
|
async getEvents(page = 1, perPage = 50, filters) {
|
|
@@ -303,7 +313,7 @@ export class DashboardStore {
|
|
|
303
313
|
});
|
|
304
314
|
}
|
|
305
315
|
/** Paginated email history with optional filters. */
|
|
306
|
-
async getEmails(page = 1, perPage = 50, filters) {
|
|
316
|
+
async getEmails(page = 1, perPage = 50, filters, excludeBody = false) {
|
|
307
317
|
return this.paginate('server_stats_emails', page, perPage, (query) => {
|
|
308
318
|
if (filters?.from)
|
|
309
319
|
query.where('from_addr', 'like', `%${filters.from}%`);
|
|
@@ -315,14 +325,22 @@ export class DashboardStore {
|
|
|
315
325
|
query.where('mailer', filters.mailer);
|
|
316
326
|
if (filters?.status)
|
|
317
327
|
query.where('status', filters.status);
|
|
328
|
+
if (excludeBody) {
|
|
329
|
+
query.select('id', 'from_addr', 'to_addr', 'cc', 'bcc', 'subject', 'mailer', 'status', 'message_id', 'attachment_count', 'created_at');
|
|
330
|
+
}
|
|
318
331
|
});
|
|
319
332
|
}
|
|
320
|
-
/** Get email HTML body for preview. */
|
|
333
|
+
/** Get email HTML body for preview (falls back to text_body). */
|
|
321
334
|
async getEmailHtml(id) {
|
|
322
335
|
if (!this.db)
|
|
323
336
|
return null;
|
|
324
|
-
const row = await this.db('server_stats_emails')
|
|
325
|
-
|
|
337
|
+
const row = await this.db('server_stats_emails')
|
|
338
|
+
.where('id', id)
|
|
339
|
+
.select('html', 'text_body')
|
|
340
|
+
.first();
|
|
341
|
+
if (!row)
|
|
342
|
+
return null;
|
|
343
|
+
return row.html || row.text_body || null;
|
|
326
344
|
}
|
|
327
345
|
/**
|
|
328
346
|
* Paginated log history with structured search support.
|
|
@@ -379,12 +397,8 @@ export class DashboardStore {
|
|
|
379
397
|
return null;
|
|
380
398
|
return {
|
|
381
399
|
...row,
|
|
382
|
-
spans:
|
|
383
|
-
warnings: row.warnings
|
|
384
|
-
? typeof row.warnings === 'string'
|
|
385
|
-
? JSON.parse(row.warnings)
|
|
386
|
-
: row.warnings
|
|
387
|
-
: [],
|
|
400
|
+
spans: safeParseJson(row.spans) ?? [],
|
|
401
|
+
warnings: safeParseJsonArray(row.warnings),
|
|
388
402
|
};
|
|
389
403
|
}
|
|
390
404
|
/** Single request with associated queries, events, and trace. */
|
|
@@ -406,12 +420,8 @@ export class DashboardStore {
|
|
|
406
420
|
trace: trace
|
|
407
421
|
? {
|
|
408
422
|
...trace,
|
|
409
|
-
spans:
|
|
410
|
-
warnings: trace.warnings
|
|
411
|
-
? typeof trace.warnings === 'string'
|
|
412
|
-
? JSON.parse(trace.warnings)
|
|
413
|
-
: trace.warnings
|
|
414
|
-
: [],
|
|
423
|
+
spans: safeParseJson(trace.spans) ?? [],
|
|
424
|
+
warnings: safeParseJsonArray(trace.warnings),
|
|
415
425
|
}
|
|
416
426
|
: null,
|
|
417
427
|
};
|
|
@@ -471,10 +481,10 @@ export class DashboardStore {
|
|
|
471
481
|
.orderBy('created_at', 'desc')
|
|
472
482
|
.limit(5);
|
|
473
483
|
return {
|
|
474
|
-
avgResponseTime:
|
|
475
|
-
p95ResponseTime:
|
|
476
|
-
requestsPerMinute:
|
|
477
|
-
errorRate:
|
|
484
|
+
avgResponseTime: round(avgResponseTime),
|
|
485
|
+
p95ResponseTime: round(p95ResponseTime),
|
|
486
|
+
requestsPerMinute: round(requestsPerMin),
|
|
487
|
+
errorRate: round((errorCount / total) * 100),
|
|
478
488
|
totalRequests: total,
|
|
479
489
|
slowestEndpoints: slowestEndpoints.map((s) => ({
|
|
480
490
|
url: s.url,
|
|
@@ -484,7 +494,7 @@ export class DashboardStore {
|
|
|
484
494
|
queryStats: {
|
|
485
495
|
total: queryStats?.total ?? 0,
|
|
486
496
|
avgDuration: queryStats?.avg_duration ?? 0,
|
|
487
|
-
perRequest: total > 0 ?
|
|
497
|
+
perRequest: total > 0 ? round((queryStats?.total ?? 0) / total) : 0,
|
|
488
498
|
},
|
|
489
499
|
recentErrors: recentErrors.map((e) => ({
|
|
490
500
|
id: e.id,
|
|
@@ -539,11 +549,11 @@ export class DashboardStore {
|
|
|
539
549
|
return Array.from(grouped.values()).map((g) => ({
|
|
540
550
|
bucket: g.bucket,
|
|
541
551
|
request_count: g.request_count,
|
|
542
|
-
avg_duration: g._count > 0 ?
|
|
543
|
-
p95_duration:
|
|
552
|
+
avg_duration: g._count > 0 ? round(g.avg_duration / g._count) : 0,
|
|
553
|
+
p95_duration: round(g.p95_duration),
|
|
544
554
|
error_count: g.error_count,
|
|
545
555
|
query_count: g.query_count,
|
|
546
|
-
avg_query_duration: g._count > 0 ?
|
|
556
|
+
avg_query_duration: g._count > 0 ? round(g.avg_query_duration / g._count) : 0,
|
|
547
557
|
}));
|
|
548
558
|
}
|
|
549
559
|
/**
|
|
@@ -637,6 +647,16 @@ export class DashboardStore {
|
|
|
637
647
|
return empty;
|
|
638
648
|
}
|
|
639
649
|
}
|
|
650
|
+
/** Get sparkline data points from pre-aggregated metrics. */
|
|
651
|
+
async getSparklineData(range) {
|
|
652
|
+
if (!this.db)
|
|
653
|
+
return [];
|
|
654
|
+
const cutoff = rangeToCutoff(range);
|
|
655
|
+
const metrics = await this.db('server_stats_metrics')
|
|
656
|
+
.where('created_at', '>=', cutoff)
|
|
657
|
+
.orderBy('bucket', 'asc');
|
|
658
|
+
return metrics.slice(-15);
|
|
659
|
+
}
|
|
640
660
|
// =========================================================================
|
|
641
661
|
// Saved filters CRUD
|
|
642
662
|
// =========================================================================
|
|
@@ -768,47 +788,3 @@ function normalizeSql(sql) {
|
|
|
768
788
|
.replace(/\s+/g, ' ')
|
|
769
789
|
.trim();
|
|
770
790
|
}
|
|
771
|
-
/** Extract email addresses from various AdonisJS mail address formats. */
|
|
772
|
-
function extractAddresses(value) {
|
|
773
|
-
if (!value)
|
|
774
|
-
return '';
|
|
775
|
-
if (typeof value === 'string')
|
|
776
|
-
return value;
|
|
777
|
-
if (Array.isArray(value)) {
|
|
778
|
-
return value
|
|
779
|
-
.map((v) => (typeof v === 'string' ? v : v?.address || ''))
|
|
780
|
-
.filter(Boolean)
|
|
781
|
-
.join(', ');
|
|
782
|
-
}
|
|
783
|
-
if (typeof value === 'object' && value.address)
|
|
784
|
-
return value.address;
|
|
785
|
-
return '';
|
|
786
|
-
}
|
|
787
|
-
/** Convert a range string to a SQLite-compatible datetime cutoff. */
|
|
788
|
-
function rangeToCutoff(range) {
|
|
789
|
-
const minutes = rangeToMinutes(range);
|
|
790
|
-
const cutoff = new Date(Date.now() - minutes * 60_000);
|
|
791
|
-
return cutoff.toISOString().replace('T', ' ').slice(0, 19);
|
|
792
|
-
}
|
|
793
|
-
/** Convert a range string to total minutes. */
|
|
794
|
-
function rangeToMinutes(range) {
|
|
795
|
-
switch (range) {
|
|
796
|
-
case '1h':
|
|
797
|
-
return 60;
|
|
798
|
-
case '6h':
|
|
799
|
-
return 360;
|
|
800
|
-
case '24h':
|
|
801
|
-
return 1440;
|
|
802
|
-
case '7d':
|
|
803
|
-
return 10080;
|
|
804
|
-
default:
|
|
805
|
-
return 60;
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
/** Round a bucket timestamp string down to the nearest N minutes. */
|
|
809
|
-
function roundBucket(bucket, minutes) {
|
|
810
|
-
const date = new Date(bucket.replace(' ', 'T') + 'Z');
|
|
811
|
-
const ms = minutes * 60_000;
|
|
812
|
-
const rounded = new Date(Math.floor(date.getTime() / ms) * ms);
|
|
813
|
-
return rounded.toISOString().replace('T', ' ').slice(0, 19);
|
|
814
|
-
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache_inspector.d.ts","sourceRoot":"","sources":["../../../../src/dashboard/integrations/cache_inspector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAM9D,MAAM,WAAW,UAAU;IACzB,6CAA6C;IAC7C,SAAS,EAAE,OAAO,CAAA;IAElB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAA;IAEZ,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAA;IAEd,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAA;IAEf,mCAAmC;IACnC,eAAe,EAAE,MAAM,CAAA;IAEvB,qDAAqD;IACrD,eAAe,EAAE,MAAM,CAAA;IAEvB,mCAAmC;IACnC,gBAAgB,EAAE,MAAM,CAAA;IAExB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAA;IAEX,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAA;IAEZ,uEAAuE;IACvE,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,kBAAkB;IACjC,sCAAsC;IACtC,IAAI,EAAE,aAAa,EAAE,CAAA;IAErB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAA;IAEX,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAA;IAEb,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAA;IAEZ,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAA;IAEX,mEAAmE;IACnE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAMD;;;;;;GAMG;AACH,qBAAa,cAAc;IACb,OAAO,CAAC,KAAK;gBAAL,KAAK,EAAE,GAAG;IAE9B;;;OAGG;WACU,WAAW,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IASnE;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC;IAoDrC;;;;;;OAMG;IACG,QAAQ,CAAC,OAAO,SAAM,EAAE,MAAM,SAAM,EAAE,KAAK,SAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"cache_inspector.d.ts","sourceRoot":"","sources":["../../../../src/dashboard/integrations/cache_inspector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAM9D,MAAM,WAAW,UAAU;IACzB,6CAA6C;IAC7C,SAAS,EAAE,OAAO,CAAA;IAElB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAA;IAEZ,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAA;IAEd,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAA;IAEf,mCAAmC;IACnC,eAAe,EAAE,MAAM,CAAA;IAEvB,qDAAqD;IACrD,eAAe,EAAE,MAAM,CAAA;IAEvB,mCAAmC;IACnC,gBAAgB,EAAE,MAAM,CAAA;IAExB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAA;IAEX,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAA;IAEZ,uEAAuE;IACvE,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,kBAAkB;IACjC,sCAAsC;IACtC,IAAI,EAAE,aAAa,EAAE,CAAA;IAErB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAA;IAEX,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAA;IAEb,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAA;IAEZ,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAA;IAEX,mEAAmE;IACnE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAMD;;;;;;GAMG;AACH,qBAAa,cAAc;IACb,OAAO,CAAC,KAAK;gBAAL,KAAK,EAAE,GAAG;IAE9B;;;OAGG;WACU,WAAW,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IASnE;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC;IAoDrC;;;;;;OAMG;IACG,QAAQ,CAAC,OAAO,SAAM,EAAE,MAAM,SAAM,EAAE,KAAK,SAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAoBrF;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAqBzD;;;;OAIG;IACG,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAa9C;;OAEG;YACW,cAAc;CAkC7B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue_inspector.d.ts","sourceRoot":"","sources":["../../../../src/dashboard/integrations/queue_inspector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAM9D,MAAM,WAAW,aAAa;IAC5B,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAA;IAEd,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAA;IAEf,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAA;IAEf,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAA;IAEjB,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAA;IAEd,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,mBAAmB;IACnB,EAAE,EAAE,MAAM,CAAA;IAEV,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAA;IAEZ,0BAA0B;IAC1B,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAA;IAE5E,0BAA0B;IAC1B,IAAI,EAAE,GAAG,CAAA;IAET,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAA;IAEhB,gCAAgC;IAChC,WAAW,EAAE,MAAM,CAAA;IAEnB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IAEzB,gDAAgD;IAChD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAE3B,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAA;IAEjB,4DAA4D;IAC5D,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAE1B,0DAA0D;IAC1D,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAEzB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB;AAED,MAAM,WAAW,cAAe,SAAQ,eAAe;IACrD,0CAA0C;IAC1C,UAAU,EAAE,MAAM,EAAE,CAAA;IAEpB,iDAAiD;IACjD,WAAW,EAAE,GAAG,CAAA;IAEhB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,mCAAmC;IACnC,IAAI,EAAE,eAAe,EAAE,CAAA;IAEvB,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAA;CACd;AAMD,KAAK,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAErF;;;;;;GAMG;AACH,qBAAa,cAAc;IACb,OAAO,CAAC,YAAY;gBAAZ,YAAY,EAAE,GAAG;IAErC;;OAEG;WACU,WAAW,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IASnE;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,aAAa,CAAC;IAoC3C;;;;;;OAMG;IACG,QAAQ,CACZ,MAAM,GAAE,SAAoB,EAC5B,IAAI,SAAI,EACR,OAAO,SAAK,GACX,OAAO,CAAC,kBAAkB,CAAC;IA0B9B;;OAEG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAqBxD;;;;OAIG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAsB5C;;;;;OAKG;IACH,OAAO,CAAC,QAAQ;IAuBhB;;OAEG;IACH,OAAO,CAAC,gBAAgB;
|
|
1
|
+
{"version":3,"file":"queue_inspector.d.ts","sourceRoot":"","sources":["../../../../src/dashboard/integrations/queue_inspector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAM9D,MAAM,WAAW,aAAa;IAC5B,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAA;IAEd,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAA;IAEf,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAA;IAEf,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAA;IAEjB,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAA;IAEd,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,mBAAmB;IACnB,EAAE,EAAE,MAAM,CAAA;IAEV,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAA;IAEZ,0BAA0B;IAC1B,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAA;IAE5E,0BAA0B;IAC1B,IAAI,EAAE,GAAG,CAAA;IAET,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAA;IAEhB,gCAAgC;IAChC,WAAW,EAAE,MAAM,CAAA;IAEnB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IAEzB,gDAAgD;IAChD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAE3B,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAA;IAEjB,4DAA4D;IAC5D,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAE1B,0DAA0D;IAC1D,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAEzB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB;AAED,MAAM,WAAW,cAAe,SAAQ,eAAe;IACrD,0CAA0C;IAC1C,UAAU,EAAE,MAAM,EAAE,CAAA;IAEpB,iDAAiD;IACjD,WAAW,EAAE,GAAG,CAAA;IAEhB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,mCAAmC;IACnC,IAAI,EAAE,eAAe,EAAE,CAAA;IAEvB,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAA;CACd;AAMD,KAAK,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAErF;;;;;;GAMG;AACH,qBAAa,cAAc;IACb,OAAO,CAAC,YAAY;gBAAZ,YAAY,EAAE,GAAG;IAErC;;OAEG;WACU,WAAW,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IASnE;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,aAAa,CAAC;IAoC3C;;;;;;OAMG;IACG,QAAQ,CACZ,MAAM,GAAE,SAAoB,EAC5B,IAAI,SAAI,EACR,OAAO,SAAK,GACX,OAAO,CAAC,kBAAkB,CAAC;IA0B9B;;OAEG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAqBxD;;;;OAIG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAsB5C;;;;;OAKG;IACH,OAAO,CAAC,QAAQ;IAuBhB;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAoBzB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrator.d.ts","sourceRoot":"","sources":["../../../src/dashboard/migrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAEhC;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,EAAE,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"migrator.d.ts","sourceRoot":"","sources":["../../../src/dashboard/migrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAEhC;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,EAAE,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CA6IzD;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYxF"}
|
|
@@ -136,7 +136,9 @@ export async function autoMigrate(db) {
|
|
|
136
136
|
export async function runRetentionCleanup(db, retentionDays) {
|
|
137
137
|
const modifier = `-${retentionDays} days`;
|
|
138
138
|
// Cascade deletes queries, events, traces via FK ON DELETE CASCADE
|
|
139
|
-
await db.raw(`DELETE FROM server_stats_requests WHERE created_at < datetime('now', ?)`, [
|
|
139
|
+
await db.raw(`DELETE FROM server_stats_requests WHERE created_at < datetime('now', ?)`, [
|
|
140
|
+
modifier,
|
|
141
|
+
]);
|
|
140
142
|
// Standalone tables
|
|
141
143
|
await db.raw(`DELETE FROM server_stats_logs WHERE created_at < datetime('now', ?)`, [modifier]);
|
|
142
144
|
await db.raw(`DELETE FROM server_stats_emails WHERE created_at < datetime('now', ?)`, [modifier]);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BaseModel } from '@adonisjs/lucid/orm';
|
|
2
|
-
import type { BelongsTo } from '@adonisjs/lucid/types/relations';
|
|
3
2
|
import StatsRequest from './stats_request.js';
|
|
3
|
+
import type { BelongsTo } from '@adonisjs/lucid/types/relations';
|
|
4
4
|
export default class StatsEvent extends BaseModel {
|
|
5
5
|
static connection: string;
|
|
6
6
|
static table: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats_event.d.ts","sourceRoot":"","sources":["../../../../src/dashboard/models/stats_event.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAqB,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"stats_event.d.ts","sourceRoot":"","sources":["../../../../src/dashboard/models/stats_event.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAqB,MAAM,qBAAqB,CAAA;AAElE,OAAO,YAAY,MAAM,oBAAoB,CAAA;AAE7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAA;AAEhE,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,SAAS;IAC/C,MAAM,CAAC,UAAU,SAAiB;IAClC,MAAM,CAAC,KAAK,SAAwB;IAG5B,EAAE,EAAE,MAAM,CAAA;IAGV,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IAGxB,SAAS,EAAE,MAAM,CAAA;IAOjB,IAAI,EAAE,GAAG,GAAG,IAAI,CAAA;IAGhB,SAAS,EAAE,MAAM,CAAA;IAGjB,OAAO,EAAE,SAAS,CAAC,OAAO,YAAY,CAAC,CAAA;CAChD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BaseModel } from '@adonisjs/lucid/orm';
|
|
2
|
-
import type { BelongsTo } from '@adonisjs/lucid/types/relations';
|
|
3
2
|
import StatsRequest from './stats_request.js';
|
|
3
|
+
import type { BelongsTo } from '@adonisjs/lucid/types/relations';
|
|
4
4
|
export default class StatsQuery extends BaseModel {
|
|
5
5
|
static connection: string;
|
|
6
6
|
static table: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats_query.d.ts","sourceRoot":"","sources":["../../../../src/dashboard/models/stats_query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAqB,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"stats_query.d.ts","sourceRoot":"","sources":["../../../../src/dashboard/models/stats_query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAqB,MAAM,qBAAqB,CAAA;AAElE,OAAO,YAAY,MAAM,oBAAoB,CAAA;AAE7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAA;AAEhE,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,SAAS;IAC/C,MAAM,CAAC,UAAU,SAAiB;IAClC,MAAM,CAAC,KAAK,SAAyB;IAG7B,EAAE,EAAE,MAAM,CAAA;IAGV,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IAGxB,OAAO,EAAE,MAAM,CAAA;IAGf,aAAa,EAAE,MAAM,CAAA;IAOrB,QAAQ,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;IAGtB,QAAQ,EAAE,MAAM,CAAA;IAGhB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IAGrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IAGpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAGzB,aAAa,EAAE,MAAM,CAAA;IAGrB,SAAS,EAAE,MAAM,CAAA;IAGjB,OAAO,EAAE,SAAS,CAAC,OAAO,YAAY,CAAC,CAAA;CAChD"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { BaseModel } from '@adonisjs/lucid/orm';
|
|
2
|
-
import type { HasMany } from '@adonisjs/lucid/types/relations';
|
|
3
|
-
import StatsQuery from './stats_query.js';
|
|
4
2
|
import StatsEvent from './stats_event.js';
|
|
3
|
+
import StatsQuery from './stats_query.js';
|
|
5
4
|
import StatsTrace from './stats_trace.js';
|
|
5
|
+
import type { HasMany } from '@adonisjs/lucid/types/relations';
|
|
6
6
|
export default class StatsRequest extends BaseModel {
|
|
7
7
|
static connection: string;
|
|
8
8
|
static table: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats_request.d.ts","sourceRoot":"","sources":["../../../../src/dashboard/models/stats_request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAmB,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"stats_request.d.ts","sourceRoot":"","sources":["../../../../src/dashboard/models/stats_request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAmB,MAAM,qBAAqB,CAAA;AAEhE,OAAO,UAAU,MAAM,kBAAkB,CAAA;AACzC,OAAO,UAAU,MAAM,kBAAkB,CAAA;AACzC,OAAO,UAAU,MAAM,kBAAkB,CAAA;AAEzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAA;AAE9D,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,SAAS;IACjD,MAAM,CAAC,UAAU,SAAiB;IAClC,MAAM,CAAC,KAAK,SAA0B;IAG9B,EAAE,EAAE,MAAM,CAAA;IAGV,MAAM,EAAE,MAAM,CAAA;IAGd,GAAG,EAAE,MAAM,CAAA;IAGX,UAAU,EAAE,MAAM,CAAA;IAGlB,QAAQ,EAAE,MAAM,CAAA;IAGhB,SAAS,EAAE,MAAM,CAAA;IAGjB,YAAY,EAAE,MAAM,CAAA;IAGpB,SAAS,EAAE,MAAM,CAAA;IAGjB,OAAO,EAAE,OAAO,CAAC,OAAO,UAAU,CAAC,CAAA;IAGnC,MAAM,EAAE,OAAO,CAAC,OAAO,UAAU,CAAC,CAAA;IAGlC,MAAM,EAAE,OAAO,CAAC,OAAO,UAAU,CAAC,CAAA;CAC3C"}
|
|
@@ -8,8 +8,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
9
|
};
|
|
10
10
|
import { BaseModel, column, hasMany } from '@adonisjs/lucid/orm';
|
|
11
|
-
import StatsQuery from './stats_query.js';
|
|
12
11
|
import StatsEvent from './stats_event.js';
|
|
12
|
+
import StatsQuery from './stats_query.js';
|
|
13
13
|
import StatsTrace from './stats_trace.js';
|
|
14
14
|
export default class StatsRequest extends BaseModel {
|
|
15
15
|
static connection = 'server_stats';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BaseModel } from '@adonisjs/lucid/orm';
|
|
2
|
-
import type { BelongsTo } from '@adonisjs/lucid/types/relations';
|
|
3
2
|
import StatsRequest from './stats_request.js';
|
|
3
|
+
import type { BelongsTo } from '@adonisjs/lucid/types/relations';
|
|
4
4
|
export default class StatsTrace extends BaseModel {
|
|
5
5
|
static connection: string;
|
|
6
6
|
static table: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats_trace.d.ts","sourceRoot":"","sources":["../../../../src/dashboard/models/stats_trace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAqB,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"stats_trace.d.ts","sourceRoot":"","sources":["../../../../src/dashboard/models/stats_trace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAqB,MAAM,qBAAqB,CAAA;AAElE,OAAO,YAAY,MAAM,oBAAoB,CAAA;AAE7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAA;AAEhE,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,SAAS;IAC/C,MAAM,CAAC,UAAU,SAAiB;IAClC,MAAM,CAAC,KAAK,SAAwB;IAG5B,EAAE,EAAE,MAAM,CAAA;IAGV,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IAGxB,MAAM,EAAE,MAAM,CAAA;IAGd,GAAG,EAAE,MAAM,CAAA;IAGX,UAAU,EAAE,MAAM,CAAA;IAGlB,aAAa,EAAE,MAAM,CAAA;IAGrB,SAAS,EAAE,MAAM,CAAA;IAOjB,KAAK,EAAE,GAAG,EAAE,CAAA;IAOZ,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;IAGzB,SAAS,EAAE,MAAM,CAAA;IAGjB,OAAO,EAAE,SAAS,CAAC,OAAO,YAAY,CAAC,CAAA;CAChD"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { EventCollector } from
|
|
3
|
-
import {
|
|
4
|
-
import { RouteInspector } from
|
|
5
|
-
import { TraceCollector } from
|
|
6
|
-
import type { DevToolbarConfig } from
|
|
1
|
+
import { EmailCollector } from './email_collector.js';
|
|
2
|
+
import { EventCollector } from './event_collector.js';
|
|
3
|
+
import { QueryCollector } from './query_collector.js';
|
|
4
|
+
import { RouteInspector } from './route_inspector.js';
|
|
5
|
+
import { TraceCollector } from './trace_collector.js';
|
|
6
|
+
import type { DevToolbarConfig } from './types.js';
|
|
7
7
|
/**
|
|
8
8
|
* Singleton store holding all debug data collectors.
|
|
9
9
|
* Bound to the AdonisJS container as `debug.store`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debug_store.d.ts","sourceRoot":"","sources":["../../../src/debug/debug_store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"debug_store.d.ts","sourceRoot":"","sources":["../../../src/debug/debug_store.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD;;;GAGG;AACH,qBAAa,UAAU;IACrB,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAA;IAChC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAA;gBAE1B,MAAM,EAAE,gBAAgB;IAQpC;;;OAGG;IACH,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IAO9C,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrD,IAAI,IAAI,IAAI;IAOZ,kEAAkE;IAC5D,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBjD,uDAAuD;IACjD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAuBpD"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { writeFile, readFile, rename, mkdir } from
|
|
2
|
-
import { dirname } from
|
|
3
|
-
import {
|
|
4
|
-
import { EventCollector } from
|
|
5
|
-
import {
|
|
6
|
-
import { RouteInspector } from
|
|
7
|
-
import { TraceCollector } from
|
|
1
|
+
import { writeFile, readFile, rename, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import { EmailCollector } from './email_collector.js';
|
|
4
|
+
import { EventCollector } from './event_collector.js';
|
|
5
|
+
import { QueryCollector } from './query_collector.js';
|
|
6
|
+
import { RouteInspector } from './route_inspector.js';
|
|
7
|
+
import { TraceCollector } from './trace_collector.js';
|
|
8
8
|
/**
|
|
9
9
|
* Singleton store holding all debug data collectors.
|
|
10
10
|
* Bound to the AdonisJS container as `debug.store`.
|
|
@@ -56,16 +56,16 @@ export class DebugStore {
|
|
|
56
56
|
data.traces = this.traces.getTraces();
|
|
57
57
|
}
|
|
58
58
|
const json = JSON.stringify(data);
|
|
59
|
-
const tmpPath = filePath +
|
|
59
|
+
const tmpPath = filePath + '.tmp';
|
|
60
60
|
await mkdir(dirname(filePath), { recursive: true });
|
|
61
|
-
await writeFile(tmpPath, json,
|
|
61
|
+
await writeFile(tmpPath, json, 'utf-8');
|
|
62
62
|
await rename(tmpPath, filePath);
|
|
63
63
|
}
|
|
64
64
|
/** Restore collector data from a JSON file on disk. */
|
|
65
65
|
async loadFromDisk(filePath) {
|
|
66
66
|
let raw;
|
|
67
67
|
try {
|
|
68
|
-
raw = await readFile(filePath,
|
|
68
|
+
raw = await readFile(filePath, 'utf-8');
|
|
69
69
|
}
|
|
70
70
|
catch {
|
|
71
71
|
return; // file doesn't exist yet
|
|
@@ -21,18 +21,9 @@ export declare class EmailCollector {
|
|
|
21
21
|
getTotalCount(): number;
|
|
22
22
|
clear(): void;
|
|
23
23
|
private buildRecord;
|
|
24
|
-
/**
|
|
25
|
-
* Normalize various address formats to a comma-separated string.
|
|
26
|
-
*
|
|
27
|
-
* AdonisJS mail addresses can be:
|
|
28
|
-
* - A string: `"user@example.com"`
|
|
29
|
-
* - An object: `{ address: "user@example.com", name: "User" }`
|
|
30
|
-
* - An array of strings or objects
|
|
31
|
-
*/
|
|
32
24
|
/** Register a callback that fires whenever a new email is recorded. */
|
|
33
25
|
onNewItem(cb: ((item: EmailRecord) => void) | null): void;
|
|
34
26
|
/** Restore persisted records into the buffer and reset the ID counter. */
|
|
35
27
|
loadRecords(records: EmailRecord[]): void;
|
|
36
|
-
private extractAddresses;
|
|
37
28
|
}
|
|
38
29
|
//# sourceMappingURL=email_collector.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email_collector.d.ts","sourceRoot":"","sources":["../../../src/debug/email_collector.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"email_collector.d.ts","sourceRoot":"","sources":["../../../src/debug/email_collector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C;;;;;;;;GAQG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,QAAQ,CAAmD;gBAEvD,SAAS,GAAE,MAAY;IAI7B,KAAK,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAwDxC,IAAI,IAAI,IAAI;IAUZ,SAAS,IAAI,WAAW,EAAE;IAI1B,SAAS,CAAC,CAAC,GAAE,MAAY,GAAG,WAAW,EAAE;IAIzC,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAMvC,aAAa,IAAI,MAAM;IAIvB,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,WAAW;IAkBnB,uEAAuE;IACvE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IAIzD,0EAA0E;IAC1E,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI;CAK1C"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { extractAddresses } from '../utils/mail_helpers.js';
|
|
1
2
|
import { RingBuffer } from './ring_buffer.js';
|
|
2
3
|
/**
|
|
3
4
|
* Listens to AdonisJS mail events and stores captured emails in a ring buffer.
|
|
@@ -26,7 +27,7 @@ export class EmailCollector {
|
|
|
26
27
|
};
|
|
27
28
|
const onSent = (data) => {
|
|
28
29
|
const msg = data?.message || data;
|
|
29
|
-
const to =
|
|
30
|
+
const to = extractAddresses(msg?.to);
|
|
30
31
|
const subject = msg?.subject || '';
|
|
31
32
|
// Try to find the matching 'sending' record and update it
|
|
32
33
|
const all = this.buffer.toArray();
|
|
@@ -92,10 +93,10 @@ export class EmailCollector {
|
|
|
92
93
|
buildRecord(msg, status, data) {
|
|
93
94
|
return {
|
|
94
95
|
id: this.buffer.getNextId(),
|
|
95
|
-
from:
|
|
96
|
-
to:
|
|
97
|
-
cc:
|
|
98
|
-
bcc:
|
|
96
|
+
from: extractAddresses(msg?.from) || 'unknown',
|
|
97
|
+
to: extractAddresses(msg?.to) || 'unknown',
|
|
98
|
+
cc: extractAddresses(msg?.cc) || null,
|
|
99
|
+
bcc: extractAddresses(msg?.bcc) || null,
|
|
99
100
|
subject: msg?.subject || '(no subject)',
|
|
100
101
|
html: msg?.html || null,
|
|
101
102
|
text: msg?.text || null,
|
|
@@ -106,14 +107,6 @@ export class EmailCollector {
|
|
|
106
107
|
timestamp: Date.now(),
|
|
107
108
|
};
|
|
108
109
|
}
|
|
109
|
-
/**
|
|
110
|
-
* Normalize various address formats to a comma-separated string.
|
|
111
|
-
*
|
|
112
|
-
* AdonisJS mail addresses can be:
|
|
113
|
-
* - A string: `"user@example.com"`
|
|
114
|
-
* - An object: `{ address: "user@example.com", name: "User" }`
|
|
115
|
-
* - An array of strings or objects
|
|
116
|
-
*/
|
|
117
110
|
/** Register a callback that fires whenever a new email is recorded. */
|
|
118
111
|
onNewItem(cb) {
|
|
119
112
|
this.buffer.onPush(cb);
|
|
@@ -124,19 +117,4 @@ export class EmailCollector {
|
|
|
124
117
|
const maxId = records.reduce((m, r) => Math.max(m, r.id), 0);
|
|
125
118
|
this.buffer.setNextId(maxId + 1);
|
|
126
119
|
}
|
|
127
|
-
extractAddresses(value) {
|
|
128
|
-
if (!value)
|
|
129
|
-
return '';
|
|
130
|
-
if (typeof value === 'string')
|
|
131
|
-
return value;
|
|
132
|
-
if (Array.isArray(value)) {
|
|
133
|
-
return value
|
|
134
|
-
.map((v) => (typeof v === 'string' ? v : v?.address || ''))
|
|
135
|
-
.filter(Boolean)
|
|
136
|
-
.join(', ');
|
|
137
|
-
}
|
|
138
|
-
if (typeof value === 'object' && value.address)
|
|
139
|
-
return value.address;
|
|
140
|
-
return '';
|
|
141
|
-
}
|
|
142
120
|
}
|