launchlayer-apm-agent 0.1.0

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/config.yaml ADDED
@@ -0,0 +1,31 @@
1
+ agent:
2
+ collector_url: "${AGENT_COLLECTOR_URL:-http://localhost:4318}"
3
+ api_key: "${AGENT_API_KEY:-dev-api-key}"
4
+ instance_id: "${INSTANCE_ID:-local-dev}"
5
+ hostname: "${HOSTNAME:-localhost}"
6
+
7
+ host:
8
+ enabled: true
9
+ interval_seconds: 30
10
+ proc_path: "/proc"
11
+
12
+ docker:
13
+ enabled: true
14
+ interval_seconds: 30
15
+ socket: "/var/run/docker.sock"
16
+
17
+ databases:
18
+ - name: "local-pg"
19
+ host: "${DB_HOST:-localhost}"
20
+ port: ${DB_PORT:-5433}
21
+ database: "${DB_NAME:-app_db}"
22
+ username: "${DB_USER:-bi_monitor}"
23
+ password: "${DB_PASSWORD:-monitor_password}"
24
+ ssl: false
25
+ interval_seconds: 60
26
+ explain_enabled: true
27
+
28
+ receiver:
29
+ enabled: true
30
+ port: 9999
31
+ bind: "127.0.0.1"
@@ -0,0 +1,19 @@
1
+ import { DatabaseConfig } from '../config';
2
+ export interface DatabaseSnapshot {
3
+ dbName: string;
4
+ slowQueries: any[];
5
+ tableStats: any[];
6
+ indexes: any[];
7
+ connections: any;
8
+ tableSizes: any[];
9
+ bloat: any[];
10
+ replicationLag: any[];
11
+ vacuumStats: any[];
12
+ explainPlans: any[];
13
+ }
14
+ /**
15
+ * Collect all database metrics from a monitored PostgreSQL instance.
16
+ * Runs 8 SQL queries against pg_stat_* views.
17
+ */
18
+ export declare function collectDatabaseMetrics(dbConfig: DatabaseConfig): Promise<DatabaseSnapshot>;
19
+ //# sourceMappingURL=database.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/collectors/database.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,GAAG,EAAE,CAAC;IACnB,UAAU,EAAE,GAAG,EAAE,CAAC;IAClB,OAAO,EAAE,GAAG,EAAE,CAAC;IACf,WAAW,EAAE,GAAG,CAAC;IACjB,UAAU,EAAE,GAAG,EAAE,CAAC;IAClB,KAAK,EAAE,GAAG,EAAE,CAAC;IACb,cAAc,EAAE,GAAG,EAAE,CAAC;IACtB,WAAW,EAAE,GAAG,EAAE,CAAC;IACnB,YAAY,EAAE,GAAG,EAAE,CAAC;CACrB;AAMD;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC,gBAAgB,CAAC,CAgD3B"}
@@ -0,0 +1,500 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.collectDatabaseMetrics = collectDatabaseMetrics;
37
+ const pg_1 = require("pg");
38
+ const crypto = __importStar(require("crypto"));
39
+ // Track which queryids have been explained recently (1 per hour)
40
+ const explainCache = new Map();
41
+ const EXPLAIN_COOLDOWN_MS = 60 * 60 * 1000; // 1 hour
42
+ /**
43
+ * Collect all database metrics from a monitored PostgreSQL instance.
44
+ * Runs 8 SQL queries against pg_stat_* views.
45
+ */
46
+ async function collectDatabaseMetrics(dbConfig) {
47
+ const client = new pg_1.Client({
48
+ host: dbConfig.host,
49
+ port: dbConfig.port,
50
+ database: dbConfig.database,
51
+ user: dbConfig.username,
52
+ password: dbConfig.password,
53
+ ssl: dbConfig.ssl ? { rejectUnauthorized: false } : false,
54
+ connectionTimeoutMillis: 10000,
55
+ statement_timeout: 15000,
56
+ });
57
+ await client.connect();
58
+ try {
59
+ const [slowQueries, tableStats, indexes, connections, tableSizes, bloat, replicationLag, vacuumStats] = await Promise.all([
60
+ getSlowQueries(client),
61
+ getTableStats(client),
62
+ getIndexStats(client),
63
+ getConnections(client),
64
+ getTableSizes(client),
65
+ getBloatEstimates(client),
66
+ getReplicationLag(client),
67
+ getVacuumStats(client),
68
+ ]);
69
+ // EXPLAIN plans are collected separately (sequential, sampled)
70
+ let explainPlans = [];
71
+ if (dbConfig.explain_enabled && slowQueries.length > 0) {
72
+ explainPlans = await getExplainPlans(client, dbConfig.name, slowQueries);
73
+ }
74
+ return {
75
+ dbName: dbConfig.name,
76
+ slowQueries,
77
+ tableStats,
78
+ indexes,
79
+ connections,
80
+ tableSizes,
81
+ bloat,
82
+ replicationLag,
83
+ vacuumStats,
84
+ explainPlans,
85
+ };
86
+ }
87
+ finally {
88
+ await client.end().catch(() => { });
89
+ }
90
+ }
91
+ // ================================================================
92
+ // Query 1: Slow queries from pg_stat_statements
93
+ // ================================================================
94
+ async function getSlowQueries(client) {
95
+ try {
96
+ const result = await client.query(`
97
+ SELECT
98
+ queryid,
99
+ LEFT(query, 300) AS query_sample,
100
+ calls,
101
+ total_exec_time AS total_time_ms,
102
+ mean_exec_time AS mean_time_ms,
103
+ stddev_exec_time AS stddev_time_ms,
104
+ min_exec_time AS min_time_ms,
105
+ max_exec_time AS max_time_ms,
106
+ CASE WHEN calls > 0 THEN rows / calls ELSE 0 END AS rows_per_call,
107
+ CASE WHEN shared_blks_hit + shared_blks_read > 0
108
+ THEN ROUND(shared_blks_hit::NUMERIC / (shared_blks_hit + shared_blks_read) * 100, 1)
109
+ ELSE 0
110
+ END AS cache_hit_pct
111
+ FROM pg_stat_statements
112
+ WHERE calls > 5
113
+ AND mean_exec_time > 100
114
+ AND query NOT LIKE '%pg_stat%'
115
+ ORDER BY mean_exec_time DESC
116
+ LIMIT 50
117
+ `);
118
+ return result.rows.map((r) => ({
119
+ queryid: r.queryid,
120
+ querySample: r.query_sample,
121
+ calls: parseInt(r.calls),
122
+ totalTimeMs: parseFloat(r.total_time_ms),
123
+ meanTimeMs: parseFloat(r.mean_time_ms),
124
+ stddevTimeMs: parseFloat(r.stddev_time_ms || '0'),
125
+ minTimeMs: parseFloat(r.min_time_ms || '0'),
126
+ maxTimeMs: parseFloat(r.max_time_ms || '0'),
127
+ rowsPerCall: parseFloat(r.rows_per_call || '0'),
128
+ cacheHitPct: parseFloat(r.cache_hit_pct || '0'),
129
+ }));
130
+ }
131
+ catch (err) {
132
+ if (err.message?.includes('pg_stat_statements')) {
133
+ console.warn('[database] pg_stat_statements not available — enable it in postgresql.conf');
134
+ }
135
+ else {
136
+ console.error('[database] Failed to get slow queries:', err.message);
137
+ }
138
+ return [];
139
+ }
140
+ }
141
+ // ================================================================
142
+ // Query 2: Table stats from pg_stat_user_tables
143
+ // ================================================================
144
+ async function getTableStats(client) {
145
+ const result = await client.query(`
146
+ SELECT
147
+ schemaname AS schema_name,
148
+ relname AS table_name,
149
+ COALESCE(seq_scan, 0) AS seq_scan,
150
+ COALESCE(idx_scan, 0) AS idx_scan,
151
+ CASE WHEN COALESCE(seq_scan, 0) + COALESCE(idx_scan, 0) > 0
152
+ THEN ROUND(seq_scan::NUMERIC / (seq_scan + idx_scan) * 100, 1)
153
+ ELSE 0
154
+ END AS seq_scan_pct,
155
+ COALESCE(n_live_tup, 0) AS n_live_tup,
156
+ COALESCE(n_dead_tup, 0) AS n_dead_tup,
157
+ CASE WHEN COALESCE(n_live_tup, 0) + COALESCE(n_dead_tup, 0) > 0
158
+ THEN ROUND(n_dead_tup::NUMERIC / (n_live_tup + n_dead_tup) * 100, 1)
159
+ ELSE 0
160
+ END AS dead_tup_pct,
161
+ last_vacuum,
162
+ last_autovacuum,
163
+ last_analyze,
164
+ last_autoanalyze
165
+ FROM pg_stat_user_tables
166
+ WHERE seq_scan + idx_scan > 10
167
+ ORDER BY seq_scan_pct DESC
168
+ LIMIT 50
169
+ `);
170
+ return result.rows.map((r) => ({
171
+ schemaName: r.schema_name,
172
+ tableName: r.table_name,
173
+ seqScan: parseInt(r.seq_scan),
174
+ idxScan: parseInt(r.idx_scan),
175
+ seqScanPct: parseFloat(r.seq_scan_pct),
176
+ nLiveTup: parseInt(r.n_live_tup),
177
+ nDeadTup: parseInt(r.n_dead_tup),
178
+ deadTupPct: parseFloat(r.dead_tup_pct),
179
+ lastVacuum: r.last_vacuum,
180
+ lastAutovacuum: r.last_autovacuum,
181
+ lastAnalyze: r.last_analyze,
182
+ lastAutoanalyze: r.last_autoanalyze,
183
+ }));
184
+ }
185
+ // ================================================================
186
+ // Query 3: Index stats
187
+ // ================================================================
188
+ async function getIndexStats(client) {
189
+ const result = await client.query(`
190
+ SELECT
191
+ s.schemaname AS schema_name,
192
+ s.indexrelname AS index_name,
193
+ s.relname AS table_name,
194
+ COALESCE(s.idx_scan, 0) AS idx_scan,
195
+ COALESCE(s.idx_tup_read, 0) AS idx_tup_read,
196
+ COALESCE(s.idx_tup_fetch, 0) AS idx_tup_fetch,
197
+ pg_relation_size(s.indexrelid) AS index_size_bytes,
198
+ i.indisprimary AS is_primary,
199
+ i.indisunique AS is_unique
200
+ FROM pg_stat_user_indexes s
201
+ JOIN pg_index i ON s.indexrelid = i.indexrelid
202
+ ORDER BY s.idx_scan ASC
203
+ LIMIT 100
204
+ `);
205
+ return result.rows.map((r) => ({
206
+ schemaName: r.schema_name,
207
+ indexName: r.index_name,
208
+ tableName: r.table_name,
209
+ idxScan: parseInt(r.idx_scan),
210
+ idxTupRead: parseInt(r.idx_tup_read),
211
+ idxTupFetch: parseInt(r.idx_tup_fetch),
212
+ indexSizeBytes: parseInt(r.index_size_bytes),
213
+ isPrimary: r.is_primary,
214
+ isUnique: r.is_unique,
215
+ }));
216
+ }
217
+ // ================================================================
218
+ // Query 4: Connection activity + blocking chains
219
+ // ================================================================
220
+ async function getConnections(client) {
221
+ const connResult = await client.query(`
222
+ SELECT
223
+ (SELECT setting::INTEGER FROM pg_settings WHERE name = 'max_connections') AS max_connections,
224
+ COUNT(*) FILTER (WHERE state = 'active') AS active_count,
225
+ COUNT(*) FILTER (WHERE state = 'idle') AS idle_count,
226
+ COUNT(*) FILTER (WHERE state = 'idle in transaction') AS idle_in_txn,
227
+ COUNT(*) FILTER (WHERE wait_event_type = 'Lock') AS waiting_count,
228
+ COUNT(*) AS total_count
229
+ FROM pg_stat_activity
230
+ WHERE backend_type = 'client backend'
231
+ `);
232
+ const c = connResult.rows[0];
233
+ const maxConn = parseInt(c.max_connections);
234
+ const totalCount = parseInt(c.total_count);
235
+ // Blocking chains
236
+ let blockingChains = [];
237
+ try {
238
+ const blockResult = await client.query(`
239
+ SELECT
240
+ blocked.pid AS blocked_pid,
241
+ LEFT(blocked.query, 200) AS blocked_query,
242
+ EXTRACT(EPOCH FROM (NOW() - blocked.query_start))::NUMERIC AS blocked_for_sec,
243
+ blocking.pid AS blocking_pid,
244
+ LEFT(blocking.query, 200) AS blocking_query
245
+ FROM pg_stat_activity blocked
246
+ JOIN LATERAL unnest(pg_blocking_pids(blocked.pid)) AS blocking_pid ON true
247
+ JOIN pg_stat_activity blocking ON blocking.pid = blocking_pid
248
+ WHERE blocked.wait_event_type = 'Lock'
249
+ LIMIT 20
250
+ `);
251
+ blockingChains = blockResult.rows.map((r) => ({
252
+ blockedPid: r.blocked_pid,
253
+ blockedQuery: r.blocked_query,
254
+ blockedForSec: parseFloat(r.blocked_for_sec || '0'),
255
+ blockingPid: r.blocking_pid,
256
+ blockingQuery: r.blocking_query,
257
+ }));
258
+ }
259
+ catch {
260
+ // pg_blocking_pids may not be available on all versions
261
+ }
262
+ return {
263
+ maxConnections: maxConn,
264
+ activeCount: parseInt(c.active_count),
265
+ idleCount: parseInt(c.idle_count),
266
+ idleInTxn: parseInt(c.idle_in_txn),
267
+ waitingCount: parseInt(c.waiting_count),
268
+ totalCount,
269
+ utilizationPct: maxConn > 0 ? Math.round((totalCount / maxConn) * 1000) / 10 : 0,
270
+ blockingChains,
271
+ };
272
+ }
273
+ // ================================================================
274
+ // Query 5: Replication lag
275
+ // ================================================================
276
+ async function getReplicationLag(client) {
277
+ try {
278
+ const result = await client.query(`
279
+ SELECT
280
+ application_name AS replica_name,
281
+ client_addr::TEXT,
282
+ state,
283
+ sent_lsn::TEXT,
284
+ write_lsn::TEXT,
285
+ flush_lsn::TEXT,
286
+ replay_lsn::TEXT,
287
+ EXTRACT(MILLISECONDS FROM write_lag)::NUMERIC AS write_lag_ms,
288
+ EXTRACT(MILLISECONDS FROM flush_lag)::NUMERIC AS flush_lag_ms,
289
+ EXTRACT(MILLISECONDS FROM replay_lag)::NUMERIC AS replay_lag_ms,
290
+ pg_wal_lsn_diff(sent_lsn, replay_lsn) AS bytes_behind
291
+ FROM pg_stat_replication
292
+ `);
293
+ return result.rows.map((r) => ({
294
+ replicaName: r.replica_name,
295
+ clientAddr: r.client_addr,
296
+ state: r.state,
297
+ sentLsn: r.sent_lsn,
298
+ writeLsn: r.write_lsn,
299
+ flushLsn: r.flush_lsn,
300
+ replayLsn: r.replay_lsn,
301
+ writeLagMs: r.write_lag_ms ? parseFloat(r.write_lag_ms) : null,
302
+ flushLagMs: r.flush_lag_ms ? parseFloat(r.flush_lag_ms) : null,
303
+ replayLagMs: r.replay_lag_ms ? parseFloat(r.replay_lag_ms) : null,
304
+ bytesBehind: r.bytes_behind ? parseInt(r.bytes_behind) : null,
305
+ }));
306
+ }
307
+ catch {
308
+ // Not a primary or insufficient permissions
309
+ return [];
310
+ }
311
+ }
312
+ // ================================================================
313
+ // Query 6: Table sizes
314
+ // ================================================================
315
+ async function getTableSizes(client) {
316
+ const result = await client.query(`
317
+ SELECT
318
+ schemaname AS schema_name,
319
+ relname AS table_name,
320
+ pg_total_relation_size(relid) AS total_bytes,
321
+ pg_table_size(relid) AS table_bytes,
322
+ pg_indexes_size(relid) AS index_bytes,
323
+ COALESCE(pg_total_relation_size(reltoastrelid), 0) AS toast_bytes,
324
+ n_live_tup AS row_estimate
325
+ FROM pg_stat_user_tables
326
+ ORDER BY pg_total_relation_size(relid) DESC
327
+ LIMIT 100
328
+ `);
329
+ return result.rows.map((r) => ({
330
+ schemaName: r.schema_name,
331
+ tableName: r.table_name,
332
+ totalBytes: parseInt(r.total_bytes),
333
+ tableBytes: parseInt(r.table_bytes),
334
+ indexBytes: parseInt(r.index_bytes),
335
+ toastBytes: parseInt(r.toast_bytes),
336
+ rowEstimate: parseInt(r.row_estimate),
337
+ }));
338
+ }
339
+ // ================================================================
340
+ // Query 7: Bloat estimation (statistical, no pgstattuple needed)
341
+ // ================================================================
342
+ async function getBloatEstimates(client) {
343
+ try {
344
+ const result = await client.query(`
345
+ WITH table_bloat AS (
346
+ SELECT
347
+ schemaname AS schema_name,
348
+ tablename AS table_name,
349
+ pg_total_relation_size(schemaname || '.' || quote_ident(tablename)) AS real_bytes,
350
+ CASE WHEN c.reltuples > 0 THEN
351
+ GREATEST(
352
+ pg_total_relation_size(schemaname || '.' || quote_ident(tablename)) -
353
+ (c.reltuples * (
354
+ (SELECT SUM(avg_width) FROM pg_stats WHERE tablename = c.relname AND schemaname = s.schemaname) + 24
355
+ ))::BIGINT,
356
+ 0
357
+ )
358
+ ELSE 0
359
+ END AS bloat_bytes
360
+ FROM pg_stats s
361
+ JOIN pg_class c ON c.relname = s.tablename
362
+ JOIN pg_namespace n ON n.oid = c.relnamespace AND n.nspname = s.schemaname
363
+ WHERE s.schemaname NOT IN ('pg_catalog', 'information_schema')
364
+ GROUP BY schemaname, tablename, c.reltuples, c.relname
365
+ HAVING pg_total_relation_size(schemaname || '.' || quote_ident(tablename)) > 1048576
366
+ )
367
+ SELECT
368
+ schema_name,
369
+ table_name,
370
+ real_bytes,
371
+ bloat_bytes,
372
+ CASE WHEN real_bytes > 0
373
+ THEN ROUND(bloat_bytes::NUMERIC / real_bytes * 100, 1)
374
+ ELSE 0
375
+ END AS bloat_pct
376
+ FROM table_bloat
377
+ WHERE bloat_bytes > 0
378
+ ORDER BY bloat_pct DESC
379
+ LIMIT 50
380
+ `);
381
+ return result.rows.map((r) => ({
382
+ schemaName: r.schema_name,
383
+ tableName: r.table_name,
384
+ realBytes: parseInt(r.real_bytes),
385
+ bloatBytes: parseInt(r.bloat_bytes),
386
+ bloatPct: parseFloat(r.bloat_pct),
387
+ }));
388
+ }
389
+ catch (err) {
390
+ console.error('[database] Failed to estimate bloat:', err.message);
391
+ return [];
392
+ }
393
+ }
394
+ // ================================================================
395
+ // Query 8: Vacuum stats
396
+ // ================================================================
397
+ async function getVacuumStats(client) {
398
+ const result = await client.query(`
399
+ SELECT
400
+ schemaname AS schema_name,
401
+ relname AS table_name,
402
+ COALESCE(n_dead_tup, 0) AS n_dead_tup,
403
+ COALESCE(n_live_tup, 0) AS n_live_tup,
404
+ CASE WHEN COALESCE(n_live_tup, 0) + COALESCE(n_dead_tup, 0) > 0
405
+ THEN ROUND(n_dead_tup::NUMERIC / (n_live_tup + n_dead_tup) * 100, 1)
406
+ ELSE 0
407
+ END AS dead_tup_pct,
408
+ last_vacuum,
409
+ last_autovacuum,
410
+ last_analyze,
411
+ last_autoanalyze,
412
+ autovacuum_count,
413
+ vacuum_count
414
+ FROM pg_stat_user_tables
415
+ ORDER BY n_dead_tup DESC
416
+ LIMIT 50
417
+ `);
418
+ return result.rows.map((r) => ({
419
+ schemaName: r.schema_name,
420
+ tableName: r.table_name,
421
+ nDeadTup: parseInt(r.n_dead_tup),
422
+ nLiveTup: parseInt(r.n_live_tup),
423
+ deadTupPct: parseFloat(r.dead_tup_pct),
424
+ lastVacuum: r.last_vacuum,
425
+ lastAutovacuum: r.last_autovacuum,
426
+ lastAnalyze: r.last_analyze,
427
+ lastAutoanalyze: r.last_autoanalyze,
428
+ autovacuumCount: parseInt(r.autovacuum_count || '0'),
429
+ vacuumCount: parseInt(r.vacuum_count || '0'),
430
+ }));
431
+ }
432
+ // ================================================================
433
+ // EXPLAIN plan capture (sampled, safe)
434
+ // ================================================================
435
+ async function getExplainPlans(client, dbName, slowQueries) {
436
+ const plans = [];
437
+ const now = Date.now();
438
+ // Only explain top 5 slowest queries, 1 per queryid per hour
439
+ const candidates = slowQueries.slice(0, 5);
440
+ for (const sq of candidates) {
441
+ const cacheKey = `${dbName}:${sq.queryid}`;
442
+ const lastExplained = explainCache.get(cacheKey) || 0;
443
+ if (now - lastExplained < EXPLAIN_COOLDOWN_MS)
444
+ continue;
445
+ try {
446
+ // Set a tight timeout for EXPLAIN
447
+ await client.query('SET LOCAL statement_timeout = 5000');
448
+ // Use EXPLAIN (not ANALYZE) — safe, doesn't execute the query
449
+ const result = await client.query(`EXPLAIN (FORMAT JSON) ${sq.querySample}`);
450
+ if (result.rows.length > 0) {
451
+ const planJson = result.rows[0]['QUERY PLAN'];
452
+ const planStr = JSON.stringify(planJson);
453
+ const planHash = crypto.createHash('md5').update(planStr).digest('hex');
454
+ // Count plan node types
455
+ let seqScans = 0;
456
+ let indexScans = 0;
457
+ let sortOps = 0;
458
+ let totalCost = 0;
459
+ const countNodes = (node) => {
460
+ if (!node)
461
+ return;
462
+ const nodeType = node['Node Type'] || '';
463
+ if (nodeType === 'Seq Scan')
464
+ seqScans++;
465
+ if (nodeType.includes('Index'))
466
+ indexScans++;
467
+ if (nodeType === 'Sort')
468
+ sortOps++;
469
+ totalCost = Math.max(totalCost, node['Total Cost'] || 0);
470
+ if (node.Plans) {
471
+ for (const child of node.Plans) {
472
+ countNodes(child);
473
+ }
474
+ }
475
+ };
476
+ if (Array.isArray(planJson) && planJson[0]?.Plan) {
477
+ countNodes(planJson[0].Plan);
478
+ }
479
+ plans.push({
480
+ queryid: sq.queryid,
481
+ querySample: sq.querySample,
482
+ planJson,
483
+ planHash,
484
+ totalCost,
485
+ planningTime: planJson[0]?.['Planning Time'] || null,
486
+ seqScansInPlan: seqScans,
487
+ indexScansInPlan: indexScans,
488
+ sortOpsInPlan: sortOps,
489
+ });
490
+ explainCache.set(cacheKey, now);
491
+ }
492
+ }
493
+ catch {
494
+ // EXPLAIN may fail for some queries (e.g., utility statements)
495
+ // Silently skip
496
+ }
497
+ }
498
+ return plans;
499
+ }
500
+ //# sourceMappingURL=database.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/collectors/database.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,wDAkDC;AA3ED,2BAA4B;AAC5B,+CAAiC;AAgBjC,iEAAiE;AACjE,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;AAC/C,MAAM,mBAAmB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,SAAS;AAErD;;;GAGG;AACI,KAAK,UAAU,sBAAsB,CAC1C,QAAwB;IAExB,MAAM,MAAM,GAAG,IAAI,WAAM,CAAC;QACxB,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,IAAI,EAAE,QAAQ,CAAC,QAAQ;QACvB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK;QACzD,uBAAuB,EAAE,KAAK;QAC9B,iBAAiB,EAAE,KAAK;KACzB,CAAC,CAAC;IAEH,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IAEvB,IAAI,CAAC;QACH,MAAM,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,WAAW,CAAC,GACnG,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,cAAc,CAAC,MAAM,CAAC;YACtB,aAAa,CAAC,MAAM,CAAC;YACrB,aAAa,CAAC,MAAM,CAAC;YACrB,cAAc,CAAC,MAAM,CAAC;YACtB,aAAa,CAAC,MAAM,CAAC;YACrB,iBAAiB,CAAC,MAAM,CAAC;YACzB,iBAAiB,CAAC,MAAM,CAAC;YACzB,cAAc,CAAC,MAAM,CAAC;SACvB,CAAC,CAAC;QAEL,+DAA+D;QAC/D,IAAI,YAAY,GAAU,EAAE,CAAC;QAC7B,IAAI,QAAQ,CAAC,eAAe,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvD,YAAY,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAC3E,CAAC;QAED,OAAO;YACL,MAAM,EAAE,QAAQ,CAAC,IAAI;YACrB,WAAW;YACX,UAAU;YACV,OAAO;YACP,WAAW;YACX,UAAU;YACV,KAAK;YACL,cAAc;YACd,WAAW;YACX,YAAY;SACb,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACrC,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,gDAAgD;AAChD,mEAAmE;AACnE,KAAK,UAAU,cAAc,CAAC,MAAc;IAC1C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;KAqBjC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC7B,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,WAAW,EAAE,CAAC,CAAC,YAAY;YAC3B,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;YACxB,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC;YACxC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC;YACtC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC,cAAc,IAAI,GAAG,CAAC;YACjD,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,WAAW,IAAI,GAAG,CAAC;YAC3C,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,WAAW,IAAI,GAAG,CAAC;YAC3C,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,aAAa,IAAI,GAAG,CAAC;YAC/C,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,aAAa,IAAI,GAAG,CAAC;SAChD,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,IAAI,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;YAChD,OAAO,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;QAC7F,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,gDAAgD;AAChD,mEAAmE;AACnE,KAAK,UAAU,aAAa,CAAC,MAAc;IACzC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;GAwBjC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7B,UAAU,EAAE,CAAC,CAAC,WAAW;QACzB,SAAS,EAAE,CAAC,CAAC,UAAU;QACvB,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC7B,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC7B,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC;QACtC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;QAChC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;QAChC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC;QACtC,UAAU,EAAE,CAAC,CAAC,WAAW;QACzB,cAAc,EAAE,CAAC,CAAC,eAAe;QACjC,WAAW,EAAE,CAAC,CAAC,YAAY;QAC3B,eAAe,EAAE,CAAC,CAAC,gBAAgB;KACpC,CAAC,CAAC,CAAC;AACN,CAAC;AAED,mEAAmE;AACnE,uBAAuB;AACvB,mEAAmE;AACnE,KAAK,UAAU,aAAa,CAAC,MAAc;IACzC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;GAejC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7B,UAAU,EAAE,CAAC,CAAC,WAAW;QACzB,SAAS,EAAE,CAAC,CAAC,UAAU;QACvB,SAAS,EAAE,CAAC,CAAC,UAAU;QACvB,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC7B,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC;QACpC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC;QACtC,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC;QAC5C,SAAS,EAAE,CAAC,CAAC,UAAU;QACvB,QAAQ,EAAE,CAAC,CAAC,SAAS;KACtB,CAAC,CAAC,CAAC;AACN,CAAC;AAED,mEAAmE;AACnE,iDAAiD;AACjD,mEAAmE;AACnE,KAAK,UAAU,cAAc,CAAC,MAAc;IAC1C,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;;;;;;;;;;GAUrC,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7B,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAE3C,kBAAkB;IAClB,IAAI,cAAc,GAAU,EAAE,CAAC;IAC/B,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;;;;;;;;;;;;KAYtC,CAAC,CAAC;QAEH,cAAc,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC5C,UAAU,EAAE,CAAC,CAAC,WAAW;YACzB,YAAY,EAAE,CAAC,CAAC,aAAa;YAC7B,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC,eAAe,IAAI,GAAG,CAAC;YACnD,WAAW,EAAE,CAAC,CAAC,YAAY;YAC3B,aAAa,EAAE,CAAC,CAAC,cAAc;SAChC,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,MAAM,CAAC;QACP,wDAAwD;IAC1D,CAAC;IAED,OAAO;QACL,cAAc,EAAE,OAAO;QACvB,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC;QACrC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;QACjC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;QAClC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC;QACvC,UAAU;QACV,cAAc,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QAChF,cAAc;KACf,CAAC;AACJ,CAAC;AAED,mEAAmE;AACnE,2BAA2B;AAC3B,mEAAmE;AACnE,KAAK,UAAU,iBAAiB,CAAC,MAAc;IAC7C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;;;;;;;;;;;;;;KAcjC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC7B,WAAW,EAAE,CAAC,CAAC,YAAY;YAC3B,UAAU,EAAE,CAAC,CAAC,WAAW;YACzB,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,OAAO,EAAE,CAAC,CAAC,QAAQ;YACnB,QAAQ,EAAE,CAAC,CAAC,SAAS;YACrB,QAAQ,EAAE,CAAC,CAAC,SAAS;YACrB,SAAS,EAAE,CAAC,CAAC,UAAU;YACvB,UAAU,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI;YAC9D,UAAU,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI;YAC9D,WAAW,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI;YACjE,WAAW,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI;SAC9D,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,MAAM,CAAC;QACP,4CAA4C;QAC5C,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,uBAAuB;AACvB,mEAAmE;AACnE,KAAK,UAAU,aAAa,CAAC,MAAc;IACzC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;;;;;;;;;;;;GAYjC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7B,UAAU,EAAE,CAAC,CAAC,WAAW;QACzB,SAAS,EAAE,CAAC,CAAC,UAAU;QACvB,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;QACnC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;QACnC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;QACnC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;QACnC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC;KACtC,CAAC,CAAC,CAAC;AACN,CAAC;AAED,mEAAmE;AACnE,iEAAiE;AACjE,mEAAmE;AACnE,KAAK,UAAU,iBAAiB,CAAC,MAAc;IAC7C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAoCjC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC7B,UAAU,EAAE,CAAC,CAAC,WAAW;YACzB,SAAS,EAAE,CAAC,CAAC,UAAU;YACvB,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;YACjC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;YACnC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;SAClC,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QACnE,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,wBAAwB;AACxB,mEAAmE;AACnE,KAAK,UAAU,cAAc,CAAC,MAAc;IAC1C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;GAmBjC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7B,UAAU,EAAE,CAAC,CAAC,WAAW;QACzB,SAAS,EAAE,CAAC,CAAC,UAAU;QACvB,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;QAChC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;QAChC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC;QACtC,UAAU,EAAE,CAAC,CAAC,WAAW;QACzB,cAAc,EAAE,CAAC,CAAC,eAAe;QACjC,WAAW,EAAE,CAAC,CAAC,YAAY;QAC3B,eAAe,EAAE,CAAC,CAAC,gBAAgB;QACnC,eAAe,EAAE,QAAQ,CAAC,CAAC,CAAC,gBAAgB,IAAI,GAAG,CAAC;QACpD,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,IAAI,GAAG,CAAC;KAC7C,CAAC,CAAC,CAAC;AACN,CAAC;AAED,mEAAmE;AACnE,uCAAuC;AACvC,mEAAmE;AACnE,KAAK,UAAU,eAAe,CAC5B,MAAc,EACd,MAAc,EACd,WAAkB;IAElB,MAAM,KAAK,GAAU,EAAE,CAAC;IACxB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEvB,6DAA6D;IAC7D,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE3C,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,GAAG,MAAM,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;QAC3C,MAAM,aAAa,GAAG,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEtD,IAAI,GAAG,GAAG,aAAa,GAAG,mBAAmB;YAAE,SAAS;QAExD,IAAI,CAAC;YACH,kCAAkC;YAClC,MAAM,MAAM,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;YAEzD,8DAA8D;YAC9D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;YAE7E,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;gBAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;gBACzC,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAExE,wBAAwB;gBACxB,IAAI,QAAQ,GAAG,CAAC,CAAC;gBACjB,IAAI,UAAU,GAAG,CAAC,CAAC;gBACnB,IAAI,OAAO,GAAG,CAAC,CAAC;gBAChB,IAAI,SAAS,GAAG,CAAC,CAAC;gBAElB,MAAM,UAAU,GAAG,CAAC,IAAS,EAAE,EAAE;oBAC/B,IAAI,CAAC,IAAI;wBAAE,OAAO;oBAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;oBACzC,IAAI,QAAQ,KAAK,UAAU;wBAAE,QAAQ,EAAE,CAAC;oBACxC,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;wBAAE,UAAU,EAAE,CAAC;oBAC7C,IAAI,QAAQ,KAAK,MAAM;wBAAE,OAAO,EAAE,CAAC;oBACnC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;oBAEzD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;wBACf,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;4BAC/B,UAAU,CAAC,KAAK,CAAC,CAAC;wBACpB,CAAC;oBACH,CAAC;gBACH,CAAC,CAAC;gBAEF,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;oBACjD,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC/B,CAAC;gBAED,KAAK,CAAC,IAAI,CAAC;oBACT,OAAO,EAAE,EAAE,CAAC,OAAO;oBACnB,WAAW,EAAE,EAAE,CAAC,WAAW;oBAC3B,QAAQ;oBACR,QAAQ;oBACR,SAAS;oBACT,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,IAAI;oBACpD,cAAc,EAAE,QAAQ;oBACxB,gBAAgB,EAAE,UAAU;oBAC5B,aAAa,EAAE,OAAO;iBACvB,CAAC,CAAC;gBAEH,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,+DAA+D;YAC/D,gBAAgB;QAClB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,17 @@
1
+ export interface ContainerMetric {
2
+ containerId: string;
3
+ containerName: string;
4
+ image: string;
5
+ cpuPct: number;
6
+ memUsedMb: number;
7
+ memLimitMb: number;
8
+ netInKbps: number;
9
+ netOutKbps: number;
10
+ restartCount: number;
11
+ status: string;
12
+ }
13
+ /**
14
+ * Collect Docker container metrics via the Docker Engine API over unix socket.
15
+ */
16
+ export declare function collectDockerMetrics(socketPath: string): Promise<ContainerMetric[]>;
17
+ //# sourceMappingURL=docker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../src/collectors/docker.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAgDzF"}