UNPKG

@dudousxd/nestjs-telescope

Version:

Laravel Telescope-style observability console for NestJS — core: watchers, recorder, correlation, SQLite store, headless API.

68 lines 2.74 kB
// packages/core/src/metrics/traces.ts import { EntryType } from '../entry/entry.js'; const DEFAULT_LIMIT = 50; /** Narrows an entry's content to the request shape (method + uri). */ function asRequestLabel(content) { if (typeof content !== 'object' || content === null) return undefined; const record = Object.fromEntries(Object.entries(content)); const uri = record.uri; const method = record.method; if (typeof uri !== 'string') return undefined; return typeof method === 'string' ? `${method} ${uri}` : uri; } /** Groups window entries by `traceId` (null trace ids skipped) into a summary * per distinct trace, sorted by `lastAt` desc and sliced to `limit`. Pure. */ export function summarizeTraces(entries, options = {}) { const limit = Math.max(0, Math.floor(options.limit ?? DEFAULT_LIMIT)); const byTrace = new Map(); for (const entry of entries) { const traceId = entry.traceId; if (traceId === null) continue; let accumulator = byTrace.get(traceId); if (accumulator === undefined) { accumulator = { traceId, entryCount: 0, types: new Set(), firstAt: entry.createdAt, lastAt: entry.createdAt, totalDurationMs: 0, }; byTrace.set(traceId, accumulator); } accumulator.entryCount += 1; accumulator.types.add(entry.type); if (entry.createdAt.getTime() < accumulator.firstAt.getTime()) { accumulator.firstAt = entry.createdAt; } if (entry.createdAt.getTime() > accumulator.lastAt.getTime()) { accumulator.lastAt = entry.createdAt; } if (entry.durationMs !== null) { accumulator.totalDurationMs += entry.durationMs; } if (accumulator.rootLabel === undefined && entry.type === EntryType.Request) { const label = asRequestLabel(entry.content); if (label !== undefined) accumulator.rootLabel = label; } } const summaries = []; for (const accumulator of byTrace.values()) { summaries.push({ traceId: accumulator.traceId, entryCount: accumulator.entryCount, types: [...accumulator.types].sort(), firstAt: accumulator.firstAt, lastAt: accumulator.lastAt, totalDurationMs: accumulator.totalDurationMs, ...(accumulator.rootLabel !== undefined ? { rootLabel: accumulator.rootLabel } : {}), }); } summaries.sort((a, b) => b.lastAt.getTime() - a.lastAt.getTime()); return summaries.slice(0, limit); } //# sourceMappingURL=traces.js.map