index-timing.mjs
78 lines 2.5 KB
Raw
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor ⚠ breaking 2 days ago
1 /**
2 * Per-request timing instrumentation for POST /api/v1/index in hub/bridge/server.mjs.
3 *
4 * Why this exists: when a hosted re-index hits the Netlify sync-function timeout (~26–30 s
5 * before this PR; ~60 s after), the gateway logs a generic 30 s duration but neither side
6 * tells us which sub-step (canister export, embed loop, blob persist, etc.) dominated.
7 * Without that signal we cannot tell whether the bottleneck is provider latency
8 * (DeepInfra batch embed), the canister export, or the Netlify Blobs vector persist —
9 * all of which require different fixes (parallelize embed, async/background, etc.).
10 *
11 * Logs a single JSON object per step under a stable `type` so Netlify / Datadog filters
12 * can scrape reliably. No PII beyond vault_id + sanitized canister_uid (already in use).
13 *
14 * Pure module: side-effect is the injected logger only (default console.log).
15 */
16
17 /**
18 * @param {object} [opts]
19 * @param {string|null} [opts.vaultId]
20 * @param {string|null} [opts.canisterUid]
21 * @param {(line: string) => void} [opts.logger] - Defaults to console.log; injected for tests.
22 * @param {() => number} [opts.now] - Defaults to Date.now; injected for tests.
23 * @returns {{ step: (name: string, extra?: object) => number, finish: (extra?: object) => number, totalMs: () => number }}
24 */
25 export function createIndexTimer({ vaultId = null, canisterUid = null, logger = console.log, now = Date.now } = {}) {
26 const t0 = now();
27 let last = t0;
28 let stepCount = 0;
29 let finished = false;
30
31 function step(name, extra = {}) {
32 if (finished) return 0;
33 if (typeof name !== 'string' || !name) {
34 throw new Error('createIndexTimer.step requires a non-empty name');
35 }
36 const t = now();
37 const ms = t - last;
38 const totalMs = t - t0;
39 last = t;
40 stepCount++;
41 const line = {
42 type: 'knowtation_index_step',
43 ts: new Date(t).toISOString(),
44 vault_id: vaultId,
45 canister_uid: canisterUid,
46 step: name,
47 ms,
48 total_ms: totalMs,
49 ...extra,
50 };
51 logger(JSON.stringify(line));
52 return ms;
53 }
54
55 function finish(extra = {}) {
56 if (finished) return now() - t0;
57 finished = true;
58 const t = now();
59 const totalMs = t - t0;
60 const line = {
61 type: 'knowtation_index_done',
62 ts: new Date(t).toISOString(),
63 vault_id: vaultId,
64 canister_uid: canisterUid,
65 total_ms: totalMs,
66 step_count: stepCount,
67 ...extra,
68 };
69 logger(JSON.stringify(line));
70 return totalMs;
71 }
72
73 function totalMs() {
74 return now() - t0;
75 }
76
77 return { step, finish, totalMs };
78 }
File History 2 commits
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor 2 days ago
sha256:9103f98c89257ed2b01c237cea895dabb3e85ea337dccb1161c175e4422355b6 docs: accept Calendar Events v0 spec with Phase 0 security … Human 2 days ago