Setting the file. One moment.
Route Errors · Vercel Optimize · vercel-labs/agent-skills · Skills Docs
ContentsBack to the top of the page lib/gates/route-errors.mjs
lib/gates/ route-errors.mjs
JavaScript · 80 lines · 3 KB
10 scope: 'route' ,
11 sourceCitation: 'vercel-optimize gate threshold' ,
12 description:
13 'Routes producing > 250 5xx errors over the window, or with > 1% error rate on at least 1,000 total requests. Errored function invocations still bill at full duration; high error rates also poison user experience.' ,
14 };
15
16 export function gate ( signals ) {
17 const errors = extractErrors (signals);
18 return errors
19 . filter (( e ) => e.count > 250 || (e.total >= MIN_VOLUME_FOR_RATE_EMISSION && (e.errorRate ?? 0 ) > 0.01 ))
20 . map (( e ) => withRouteShapeWarnings ({
21 kind: metadata.id,
22 scope: 'route' ,
23 route: e.route,
24 files: [],
25 priority: e.count,
26 confidence: 0.93 ,
27 o11ySignal: e.errorRate != null
28 ? `errs=${ e . count },rate=${ ( e . errorRate * 100 ). toFixed ( 1 ) }%`
29 : `errs=${ e . count }` ,
30 reason: 'concentrated 5xx errors' ,
31 question: `Why does ${ e . route } produce ${ e . count } 5xx errors over the window, and what code path is failing?` ,
32 evidence: { metric: e.metric, route: e.route, count: e.count, totalRequests: e.total, errorRate: e.errorRate },
33 }, signals));
34 }
35
36 function extractErrors ( signals ) {
37 const fnStatus = signals.metrics?.fnStatusByRoute;
38 if (Array. isArray (fnStatus?.rows)) return extractFromStatusRows (fnStatus.rows, 'fnStatusByRoute' );
39
40 const m = signals.metrics?.requestsByRouteStatus;
41 const cache = signals.metrics?.requestsByRouteCache;
42 if ( ! m?.ok && ! Array. isArray (m?.rows)) return [];
43
44 const errors = extractFromStatusRows (m?.rows ?? [], 'requestsByRouteStatus' );
45
46 // cache rollup is summed across cache_result, giving per-route total request count.
47 const totalByRoute = new Map ();
48 for ( const row of (cache?.rows ?? [])) {
49 if ( ! row.route) continue ;
50 totalByRoute. set (row.route, (totalByRoute. get (row.route) ?? 0 ) + (row.value ?? 0 ));
51 }
52
53 return errors. map (( e ) => {
54 const total = totalByRoute. get (e.route) ?? 0 ;
55 return {
56 ... e,
57 total,
58 errorRate: total > 0 ? e.count / total : null ,
59 };
60 });
61 }
62
63 function extractFromStatusRows ( rows , metric ) {
64 const errByRoute = new Map ();
65 const totalByRoute = new Map ();
66 for ( const row of rows) {
67 const route = row.route;
68 if ( ! route) continue ;
69 const v = row.value ?? 0 ;
70 const status = String (row.http_status ?? '' );
71 if ( / ^ 5 \d\d $ / . test (status)) errByRoute. set (route, (errByRoute. get (route) ?? 0 ) + v);
72 totalByRoute. set (route, (totalByRoute. get (route) ?? 0 ) + v);
73 }
74
75 return [ ... errByRoute. entries ()]. map (([ route , count ]) => {
76 const total = totalByRoute. get (route) ?? 0 ;
77 const errorRate = total > 0 ? count / total : null ;
78 return { route, count, total, errorRate, metric };
79 });
80 }