UNPKG

@dudousxd/nestjs-telescope

Version:

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

64 lines 3.19 kB
import { type Entry } from '../entry/entry.js'; /** * A detected N+1 LOOP pattern within a single batch: one driving "parent" query * (the SELECT that produced the rows being iterated) followed by N similarly- * shaped "child" queries (the per-row lookups). Richer than the flat * {@link detectNPlusOne} family-count: it attributes a likely parent and weights * by the total time WASTED in the loop, so the worst offenders rank first. */ export interface NPlusOnePattern { /** The repeated child query's family hash. */ childFamilyHash: string; /** A representative child SQL (template/text). */ childSql: string; /** How many times the child query ran in the batch (>= threshold). */ count: number; /** Sum of the child queries' durations (ms) — the "wasted" time, the rank key. */ totalDurationMs: number; /** * The family hash of the query that most likely drove the loop — the distinct * query immediately preceding the loop in record order — or `null` when the * loop is the first thing in the batch (no identifiable parent). */ parentFamilyHash: string | null; /** The likely-parent SQL, or `null` when there is no identifiable parent. */ parentSql: string | null; /** A representative child entry id (deep-link / hydration seam). */ representativeId: string; /** The batch the pattern was found in. */ batchId: string; } export interface NPlusOnePatternOptions { /** Minimum repetitions of one child template to flag a loop. */ threshold: number; } /** * Detect N+1 loop patterns in a batch's query entries. For each query family that * repeats `>= threshold` times, we emit a pattern weighted by the loop's total * duration and attribute the likely driving parent (the distinct query that ran * just before the loop began). Pure; ordered by total wasted duration desc. * * DESIGN: the flat {@link detectNPlusOne} only answers "did family X repeat N * times". This adds the two things that make an N+1 actionable — *which* query * caused it, and *how much time* it cost — modelled on how Sentry/Laravel * surface N+1: the loop body plus the originating parent span, ranked by cost. */ export declare function detectNPlusOnePatterns(entries: Entry[], options: NPlusOnePatternOptions): NPlusOnePattern[]; /** The content shape of a synthetic N+1 insight entry (see {@link toSyntheticInsightEntry}). */ export interface NPlusOneInsightContent { kind: 'n-plus-one'; childSql: string; parentSql: string | null; count: number; totalDurationMs: number; message: string; } /** * Convert a detected pattern into a SYNTHETIC insight entry so the loop surfaces * in the same entry stream as everything else (deep-linked to its batch). It is * NOT a captured event — `id` is derived deterministically from the batch + * child family so re-running detection over the same batch yields a stable id * (idempotent ingestion). Carries the `n-plus-one` + `insight` tags for filtering. */ export declare function toSyntheticInsightEntry(pattern: NPlusOnePattern, at?: Date): Entry<NPlusOneInsightContent>; //# sourceMappingURL=n-plus-one-pattern.d.ts.map