traceOf
uses tcmts.cli.main.versionsOf, which uses tcmts.share.NameTrees, which uses tcmts.store.unpacked, which uses node:zlib
The spans of one row of traceTotals (byNameNow) since since: of kind, a definition's as named now, each
version of it alike (label its name now), or, for a page, a view or a statement (no hash), those of that name.
Their numbers; each version side by side, newest first, with the entry that made it, and what changed from the
one before (and how it runs for it, if that's news); where its calls came from in the browser, as pages waited for
them (a server function's); its slowest traces and its latest. Undefined if nothing's recorded.
import type { Codebase } from "#codebase/tcmts/cli/codebase"; import { changesBetween, versionsOf, versionVerdict } from "#codebase/tcmts/cli/main"; import { percentileOf, spanOf, statsOf } from "#codebase/tcmts/cli/traced"; import type { Of, Version } from "#codebase/tcmts/cli/traced"; import type { DatabaseSync } from "node:sqlite"; export function traceOf( db: DatabaseSync, cb: Codebase, label: string, kind: string, since: number, ): | { definition: boolean; n: number; errors: number; p50: number; p95: number; max: number; versions: { hash: string; now: boolean; n: number; errors: number; p50: number; p95: number; since?: Version; }[]; change?: { changed: string[]; verdict?: { worse: boolean; said: string } }; callers: { caller?: Of; n: number; errors: number; p95: number }[]; slowest: { trace: string; start: number; dur: number; error: string | null; hash: string | null; }[]; latest: { trace: string; start: number; dur: number; error: string | null; hash: string | null; }[]; } | undefined { const hashes = ( db .prepare("SELECT DISTINCT hash FROM spans WHERE hash IS NOT NULL AND kind = ? AND start >= ?") .all(kind, since) as { hash: string }[] ) .map((r) => r.hash) .filter((h) => { const o = spanOf(cb, { hash: h, name: "" }); return o.label === label && (!o.gone || o.earlier); }); const [where, args]: [string, (string | number)[]] = hashes.length ? [ `hash IN (${hashes.map(() => "?").join(", ")}) AND kind = ? AND start >= ?`, [...hashes, kind, since], ] : ["hash IS NULL AND name = ? AND kind = ? AND start >= ?", [label, kind, since]]; const all = db .prepare( `SELECT count(*) AS n, sum(error IS NOT NULL) AS errors, max(dur) AS max FROM spans WHERE ${where}`, ) .get(...args) as { n: number; errors: number | null; max: number | null }; if (!all.n) return undefined; // (newest first, as history has them; one it doesn't, after) const history = hashes.length ? versionsOf(cb, label) : []; const order = (h: string) => { const i = history.findIndex((v) => v.hash === h); return i < 0 ? history.length : i; }; const now = hashes.find((h) => cb.store.pathsOf(h).includes(label)); const versions = [...hashes] .sort((a, b) => order(a) - order(b)) .map((h) => { const w = "hash = ? AND kind = ? AND start >= ?"; const a = [h, kind, since]; const s = statsOf(db, w, a); const v = history.find((x) => x.hash === h); return { hash: h, now: h === now, n: s.n, errors: s.errors, p50: percentileOf(db, w, a, s.n, 0.5), p95: s.p95, ...(v ? { since: v } : {}), }; }); const [newer, older] = versions; const verdict = newer && older ? versionVerdict(older, newer) : undefined; const change = newer && older ? { changed: changesBetween(cb, older.hash, newer.hash), ...(verdict ? { verdict } : {}) } : undefined; const callers: { caller?: Of; n: number; errors: number; p95: number }[] = []; if (hashes.length && kind === "call") { const browser = `hash IN (${hashes.map(() => "?").join(", ")}) AND kind = 'client' AND start >= ?`; const fromOf = `json_extract(attrs, '$."tcm.from"')`; for (const c of db .prepare( `SELECT ${fromOf} AS caller, count(*) AS n, sum(error IS NOT NULL) AS errors FROM spans WHERE ${browser} GROUP BY caller ORDER BY n DESC LIMIT 10`, ) .all(...hashes, since) as { caller: string | null; n: number; errors: number }[]) { const w = `${browser} AND ${c.caller === null ? `${fromOf} IS NULL` : `${fromOf} = ?`}`; const a = [...hashes, since, ...(c.caller === null ? [] : [c.caller])]; callers.push({ ...(c.caller ? { caller: spanOf(cb, { hash: c.caller, name: `#${c.caller.slice(0, 8)}` }) } : {}), n: c.n, errors: c.errors, p95: percentileOf(db, w, a, c.n, 0.95), }); } } const spans = (order_: string, limit: number) => db .prepare( `SELECT trace, start, dur, error, hash FROM spans WHERE ${where} ORDER BY ${order_} LIMIT ?`, ) .all(...args, limit) as { trace: string; start: number; dur: number; error: string | null; hash: string | null; }[]; return { definition: hashes.length > 0, n: all.n, errors: all.errors ?? 0, p50: percentileOf(db, where, args, all.n, 0.5), p95: percentileOf(db, where, args, all.n, 0.95), max: all.max ?? 0, versions, ...(change ? { change } : {}), callers, slowest: spans("dur DESC", 5), latest: spans("start DESC", 30), }; }
uses
- tcmts.cli.codebase.Codebase
- tcmts.cli.main.changesBetween
- tcmts.cli.main.versionVerdict
- tcmts.cli.main.versionsOf
- tcmts.cli.traced.Of
- tcmts.cli.traced.Version
- tcmts.cli.traced.percentileOf
- tcmts.cli.traced.spanOf
- tcmts.cli.traced.statsOf