@dudousxd/nestjs-telescope
Version:
Laravel Telescope-style observability console for NestJS — core: watchers, recorder, correlation, SQLite store, headless API.
68 lines • 2.74 kB
JavaScript
// 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