All files / src/lib db-slow-log.ts

100% Statements 14/14
100% Branches 10/10
100% Functions 2/2
100% Lines 9/9

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39                      147x           24x 20x 16x 12x 8x 4x             6x       6x          
import type { DbErrorContext } from "@/lib/db-error-log";
 
// Production DB LATENCY sink — the success-path mirror of logDbError. Where
// logDbError observes a failed transaction, logDbSlow observes a slow one: a
// transaction that committed fine but took too long. It only OBSERVES through a
// structured Vercel log; it never handles, slows, or breaks the request. Emitted
// from the withTransaction seam every hot-path tx flows through (recompute +
// results materialization).
 
// Slow if a transaction takes longer than this. A generous floor so normal
// recomputes (tens of ms) never trip it — only pathological latency surfaces.
export const SLOW_OP_THRESHOLD_MS = 1000;
 
// Coarse buckets are retained for callers/tests that need stable latency bands.
// Each bucket is the lower bound of its range: [1s,2s)→"1s", [2s,5s)→"2s",
// … , [30s,∞)→"30s+".
export function bucketMs(ms: number): string {
  if (ms < 2000) return "1s";
  if (ms < 5000) return "2s";
  if (ms < 10000) return "5s";
  if (ms < 20000) return "10s";
  if (ms < 30000) return "20s";
  return "30s+";
}
 
export function logDbSlow(op: string, ms: number, ctx: DbErrorContext): void {
  // MUST NEVER THROW: telemetry can't be allowed to break or slow the request.
  // Everything below is wrapped so logDbSlow only ever observes — the caller's
  // result/error is unaffected.
  try {
    // Greppable prefix + a single JSON payload, searchable in Vercel runtime
    // logs by "[db_slow]" like "[db_error]". IDS ONLY (ctx is DbErrorContext) —
    // never PII, never SQL, never params.
    console.error("[db_slow]", JSON.stringify({ op, ms, ...ctx }));
  } catch {
    // Swallow: the telemetry path is best-effort observation.
  }
}