@lensmcp/protocol-types 1.25.6 → 1.25.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +1 -0
- package/index.js +1 -1
- package/lib/context.d.ts +1 -0
- package/lib/context.js +1 -1
- package/lib/dashboard.d.ts +300 -2
- package/lib/event.d.ts +1 -0
- package/lib/node.d.ts +1 -0
- package/lib/page-visit.d.ts +136 -0
- package/lib/page-visit.js +1 -0
- package/package.json +1 -1
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";export*from"./lib/schema-version.js";export*from"./lib/source-location.js";export*from"./lib/context.js";export*from"./lib/event.js";export*from"./lib/node.js";export*from"./lib/edge.js";export*from"./lib/attributes.js";export*from"./lib/producer-health.js";export*from"./lib/resources.js";export*from"./lib/tokens.js";export*from"./lib/capture-demand.js";export*from"./lib/bounded-clone.js";export*from"./lib/bounded-map.js";export*from"./lib/flood-guard.js";export*from"./lib/dashboard.js";export*from"./lib/log-query.js";export*from"./lib/error-dismissal.js";export*from"./lib/ai-content.js";export*from"./lib/http-exchange.js";export*from"./lib/pod-memory.js";export*from"./lib/perf-rules.js";export*from"./lib/sources.js";
|
|
1
|
+
"use strict";export*from"./lib/schema-version.js";export*from"./lib/source-location.js";export*from"./lib/context.js";export*from"./lib/event.js";export*from"./lib/node.js";export*from"./lib/edge.js";export*from"./lib/attributes.js";export*from"./lib/producer-health.js";export*from"./lib/resources.js";export*from"./lib/tokens.js";export*from"./lib/capture-demand.js";export*from"./lib/bounded-clone.js";export*from"./lib/bounded-map.js";export*from"./lib/flood-guard.js";export*from"./lib/dashboard.js";export*from"./lib/log-query.js";export*from"./lib/error-dismissal.js";export*from"./lib/ai-content.js";export*from"./lib/http-exchange.js";export*from"./lib/pod-memory.js";export*from"./lib/perf-rules.js";export*from"./lib/sources.js";export*from"./lib/page-visit.js";
|
package/lib/context.d.ts
CHANGED
|
@@ -70,6 +70,7 @@ export declare const TraceContextSchema: z.ZodObject<{
|
|
|
70
70
|
causedByNodeId: z.ZodOptional<z.ZodString>;
|
|
71
71
|
requestId: z.ZodOptional<z.ZodString>;
|
|
72
72
|
parentRequestId: z.ZodOptional<z.ZodString>;
|
|
73
|
+
runId: z.ZodOptional<z.ZodString>;
|
|
73
74
|
traceparent: z.ZodOptional<z.ZodString>;
|
|
74
75
|
projectName: z.ZodOptional<z.ZodString>;
|
|
75
76
|
userActionId: z.ZodOptional<z.ZodString>;
|
package/lib/context.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{z as e}from"zod";export const FlowOriginTypeSchema=e.enum(["user-click","user-input","keyboard","route-load","effect","memo-recompute","timer","raf","idle-callback","websocket-message","broadcast-channel","post-message","storage-event","service-worker-message","media-query-change","visibility-change","resize","intersection-observer","mutation-observer","backend-response","hmr-update","ai-turn","page-load","form-submit","input-change","request","job"]),TraceContextSchema=e.object({sessionId:e.string(),browserContextId:e.string().optional(),tabId:e.string().optional(),frameId:e.string().optional(),route:e.string().optional(),url:e.string().optional(),flowId:e.string().optional(),originType:FlowOriginTypeSchema.optional(),originNodeId:e.string().optional(),causedByNodeId:e.string().optional(),requestId:e.string().optional(),parentRequestId:e.string().optional(),traceparent:e.string().optional(),projectName:e.string().optional(),userActionId:e.string().optional(),userIdHash:e.string().optional(),tenantIdHash:e.string().optional()});
|
|
1
|
+
"use strict";import{z as e}from"zod";export const FlowOriginTypeSchema=e.enum(["user-click","user-input","keyboard","route-load","effect","memo-recompute","timer","raf","idle-callback","websocket-message","broadcast-channel","post-message","storage-event","service-worker-message","media-query-change","visibility-change","resize","intersection-observer","mutation-observer","backend-response","hmr-update","ai-turn","page-load","form-submit","input-change","request","job"]),TraceContextSchema=e.object({sessionId:e.string(),browserContextId:e.string().optional(),tabId:e.string().optional(),frameId:e.string().optional(),route:e.string().optional(),url:e.string().optional(),flowId:e.string().optional(),originType:FlowOriginTypeSchema.optional(),originNodeId:e.string().optional(),causedByNodeId:e.string().optional(),requestId:e.string().optional(),parentRequestId:e.string().optional(),runId:e.string().optional(),traceparent:e.string().optional(),projectName:e.string().optional(),userActionId:e.string().optional(),userIdHash:e.string().optional(),tenantIdHash:e.string().optional()});
|
package/lib/dashboard.d.ts
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* on-demand GETs.
|
|
12
12
|
*/
|
|
13
13
|
import type { HttpExchange } from './http-exchange.js';
|
|
14
|
+
import type { PageVisitNavType, PageVisitRaw, PageVisitReadyBy, PageVisitRequest, PageVisitVitals } from './page-visit.js';
|
|
14
15
|
/** Bumped only on a breaking change to the stream framing itself. */
|
|
15
16
|
export declare const DASHBOARD_PROTOCOL = 1;
|
|
16
17
|
/** The swimlane a flow event belongs to (mirrors `FlowArea` in `@lensmcp/core`'s flow-shape). */
|
|
@@ -521,6 +522,14 @@ export interface DashFlowDetail {
|
|
|
521
522
|
segmentStats?: DashSegmentStats;
|
|
522
523
|
/** Present when the read asked for one segment (`?segment=`): `events` then holds only that segment. */
|
|
523
524
|
focus?: DashFlowSegment;
|
|
525
|
+
/**
|
|
526
|
+
* Present when the read asked for a time window (`?from=&to=`, epoch ms — a page visit's start and ready): `events`
|
|
527
|
+
* then holds only the flow's steps inside it, while `segments`/`phases` still describe the whole flow.
|
|
528
|
+
*/
|
|
529
|
+
window?: {
|
|
530
|
+
from?: number;
|
|
531
|
+
to?: number;
|
|
532
|
+
};
|
|
524
533
|
/**
|
|
525
534
|
* Present when the flow was no longer in the live window and was read back — from the workspace's event history
|
|
526
535
|
* (30 days) or the bus files. `complete: false`: older events of it may be missing.
|
|
@@ -872,12 +881,33 @@ export interface DashSummary {
|
|
|
872
881
|
* `err:<what>` something that threw.
|
|
873
882
|
*/
|
|
874
883
|
export type DashTouches = Record<string, number>;
|
|
884
|
+
/**
|
|
885
|
+
* A run's SQL by its service's own count (node-instrumentation's `db-request-account`): every statement it ran and what
|
|
886
|
+
* they took, and how many of their events reached the lens. Each statement shape's flood bucket lets only some events
|
|
887
|
+
* through, so a run's `touches` and `sqlMs` can count a fraction of what it ran — this is the whole of it.
|
|
888
|
+
*/
|
|
889
|
+
export interface DashSqlAccount {
|
|
890
|
+
statements: number;
|
|
891
|
+
ms: number;
|
|
892
|
+
/** Statements whose event reached the lens — what `touches` counts (and session statements, BEGIN and the like). */
|
|
893
|
+
seen: number;
|
|
894
|
+
failed?: number;
|
|
895
|
+
/**
|
|
896
|
+
* Folded by time, not by the run's own id: a service on a tap from before `runId` that sent several calls under one
|
|
897
|
+
* request id at once can have had the accounts of two such calls swapped. Their sum is right.
|
|
898
|
+
*/
|
|
899
|
+
byTime?: true;
|
|
900
|
+
}
|
|
875
901
|
export interface DashRouteRun {
|
|
876
902
|
at: number;
|
|
877
903
|
flowId?: string;
|
|
878
904
|
requestId?: string;
|
|
879
905
|
status?: number;
|
|
880
906
|
durationMs?: number;
|
|
907
|
+
/** What its SQL statements took, summed (ms) — the statements its `sql:` touches count. */
|
|
908
|
+
sqlMs?: number;
|
|
909
|
+
/** Its SQL by its service's own count, when the service sent one — the whole of it, where `touches` may hold a part. */
|
|
910
|
+
sqlAccount?: DashSqlAccount;
|
|
881
911
|
/** Who called it: another service by name, else `client`. */
|
|
882
912
|
caller?: string;
|
|
883
913
|
touches: DashTouches;
|
|
@@ -1091,6 +1121,201 @@ export interface DashRoutesCatalog {
|
|
|
1091
1121
|
/** How far back the kept history reaches. */
|
|
1092
1122
|
since?: number;
|
|
1093
1123
|
}
|
|
1124
|
+
/** p50 / p95 over a page's kept samples, and how many it has. */
|
|
1125
|
+
export interface DashPageStat {
|
|
1126
|
+
p50: number;
|
|
1127
|
+
p95: number;
|
|
1128
|
+
n: number;
|
|
1129
|
+
}
|
|
1130
|
+
/** One request of a visit, as the browser saw it, joined to the backend's run of it when that was seen. */
|
|
1131
|
+
export interface DashPageRequest extends PageVisitRequest {
|
|
1132
|
+
/** The route that answered it (`<service> METHOD /route`, an id of catalog://routes). */
|
|
1133
|
+
routeId?: string;
|
|
1134
|
+
service?: string;
|
|
1135
|
+
/** The server's own status and time. */
|
|
1136
|
+
status?: number;
|
|
1137
|
+
serverMs?: number;
|
|
1138
|
+
/**
|
|
1139
|
+
* SQL statements, and what they took, over its run and the cluster calls it waited on — by the services' own count
|
|
1140
|
+
* where they sent one (`DashRouteRun.sqlAccount`), else what reached the lens.
|
|
1141
|
+
*/
|
|
1142
|
+
sql?: number;
|
|
1143
|
+
sqlMs?: number;
|
|
1144
|
+
/** Of `sql`, how many statements' events reached the lens — only where that is fewer. */
|
|
1145
|
+
sqlSeen?: number;
|
|
1146
|
+
/** Key-value commands and calls outside the cluster, over the same runs. */
|
|
1147
|
+
cache?: number;
|
|
1148
|
+
ext?: number;
|
|
1149
|
+
/** Other services' runs under its request id, inside its own run (east-west): how many, and by route (at most 10 routes). */
|
|
1150
|
+
callCount?: number;
|
|
1151
|
+
calls?: Array<{
|
|
1152
|
+
routeId: string;
|
|
1153
|
+
n: number;
|
|
1154
|
+
}>;
|
|
1155
|
+
/** Same method, path and query hash as an earlier request of the visit. */
|
|
1156
|
+
dup?: true;
|
|
1157
|
+
}
|
|
1158
|
+
/** One visit of a page, in a few hundred bytes — the requests in full only on the newest two and the slowest. */
|
|
1159
|
+
export interface DashPageVisit {
|
|
1160
|
+
visitId: string;
|
|
1161
|
+
tabId?: string;
|
|
1162
|
+
/** The pathname it opened. */
|
|
1163
|
+
path: string;
|
|
1164
|
+
nav: 'hard' | 'spa';
|
|
1165
|
+
navType?: PageVisitNavType;
|
|
1166
|
+
cause?: 'hmr';
|
|
1167
|
+
redirectedFrom?: string;
|
|
1168
|
+
/** The page the tab showed before (an SPA navigation): its pattern, or its path when it had none. */
|
|
1169
|
+
from?: string;
|
|
1170
|
+
startAt: number;
|
|
1171
|
+
readyAt?: number;
|
|
1172
|
+
readyBy?: PageVisitReadyBy;
|
|
1173
|
+
readyMs?: number;
|
|
1174
|
+
appReadyMs?: number;
|
|
1175
|
+
endAt?: number;
|
|
1176
|
+
flowIds: string[];
|
|
1177
|
+
/** Requests it made until ready, with those past the 60 the browser lists. */
|
|
1178
|
+
requests: number;
|
|
1179
|
+
/** Of the listed ones, how many were joined to their backend run. */
|
|
1180
|
+
joined: number;
|
|
1181
|
+
/** Requests whose run has not been seen yet — joined as it arrives, given up two minutes after the visit. */
|
|
1182
|
+
waiting?: number;
|
|
1183
|
+
/** The same request made again in the visit (method, path and query hash). */
|
|
1184
|
+
duplicates: number;
|
|
1185
|
+
/** Over its joined requests (`DashPageRequest.sql`). */
|
|
1186
|
+
sql: number;
|
|
1187
|
+
sqlMs: number;
|
|
1188
|
+
/** Of `sql`, how many statements' events reached the lens — only where that is fewer. */
|
|
1189
|
+
sqlSeen?: number;
|
|
1190
|
+
/** The joined requests by the service that answered them. */
|
|
1191
|
+
services?: Record<string, number>;
|
|
1192
|
+
commits: number;
|
|
1193
|
+
renders: number;
|
|
1194
|
+
renderMs: number;
|
|
1195
|
+
maxCommitMs: number;
|
|
1196
|
+
stormCommits: number;
|
|
1197
|
+
suspenseWaits: number;
|
|
1198
|
+
updates: number;
|
|
1199
|
+
errors: number;
|
|
1200
|
+
firstError?: string;
|
|
1201
|
+
/** A request answered 5xx, the page threw, or it was never ready (`timeout`). */
|
|
1202
|
+
failed?: true;
|
|
1203
|
+
afterReady?: PageVisitRaw['afterReady'];
|
|
1204
|
+
vitals?: PageVisitVitals;
|
|
1205
|
+
longTasks?: PageVisitRaw['longTasks'];
|
|
1206
|
+
heapMb?: number;
|
|
1207
|
+
chunks?: PageVisitRaw['chunks'];
|
|
1208
|
+
/** Its requests in full — kept for the newest two visits and the slowest. */
|
|
1209
|
+
requestList?: DashPageRequest[];
|
|
1210
|
+
}
|
|
1211
|
+
/** A request the page makes, over its kept visits: `METHOD /path` with ids folded. */
|
|
1212
|
+
export interface DashPageUse {
|
|
1213
|
+
template: string;
|
|
1214
|
+
method: string;
|
|
1215
|
+
path: string;
|
|
1216
|
+
host?: string;
|
|
1217
|
+
/** The backend route that answers it, once a run of it was joined. */
|
|
1218
|
+
routeId?: string;
|
|
1219
|
+
/** In how many visits, and how often per visit that made it. */
|
|
1220
|
+
inVisits: number;
|
|
1221
|
+
perVisit: number;
|
|
1222
|
+
/** The browser's time to its response headers. */
|
|
1223
|
+
p50?: number;
|
|
1224
|
+
/** Calls that answered 4xx/5xx or failed on the network. */
|
|
1225
|
+
failed: number;
|
|
1226
|
+
/** Calls that repeated an earlier one of their visit (same method, path and query hash). */
|
|
1227
|
+
duplicates: number;
|
|
1228
|
+
/** SQL statements per joined call, on average. */
|
|
1229
|
+
sqlPerCall?: number;
|
|
1230
|
+
/** Made by the latest visit. */
|
|
1231
|
+
latest: boolean;
|
|
1232
|
+
}
|
|
1233
|
+
export type DashPageChangeKind = 'new-request' | 'gone-request' | 'status' | 'failed' | 'count' | 'sql' | 'duration';
|
|
1234
|
+
export interface DashPageChange {
|
|
1235
|
+
kind: DashPageChangeKind;
|
|
1236
|
+
/** The request template it is about, when it is about one. */
|
|
1237
|
+
key?: string;
|
|
1238
|
+
/** One line: "now requests GET /api/orders/:id", "GET /api/x ×1 → ×3", "SQL 12 → 31 statements", "ready 420 ms → 1,310 ms". */
|
|
1239
|
+
text: string;
|
|
1240
|
+
}
|
|
1241
|
+
export interface DashPageSummary {
|
|
1242
|
+
/** `<app> <pattern>`. */
|
|
1243
|
+
id: string;
|
|
1244
|
+
/** Its newest finished page review — none until the `page` review exists (planning/pages S6). */
|
|
1245
|
+
review?: DashReviewMark;
|
|
1246
|
+
/** The app the Vite plugin serves (or the page's host). */
|
|
1247
|
+
app: string;
|
|
1248
|
+
/** The router's full match pattern. */
|
|
1249
|
+
pattern: string;
|
|
1250
|
+
firstSeenAt: number;
|
|
1251
|
+
lastSeenAt: number;
|
|
1252
|
+
visits: number;
|
|
1253
|
+
hard: number;
|
|
1254
|
+
spa: number;
|
|
1255
|
+
/** Hard loads the dev server's hot reload caused: listed, kept out of every sample. */
|
|
1256
|
+
hmr: number;
|
|
1257
|
+
errors: number;
|
|
1258
|
+
failedVisits: number;
|
|
1259
|
+
/** Ready per population: SPA visits from the navigation (`readyMs`), hard loads from the app's entry (`appReadyMs`). */
|
|
1260
|
+
ready: {
|
|
1261
|
+
spa?: DashPageStat;
|
|
1262
|
+
hard?: DashPageStat;
|
|
1263
|
+
};
|
|
1264
|
+
/** Per visit: requests, SQL statements and ms, renders and render ms, store updates. */
|
|
1265
|
+
perVisit: Partial<Record<'requests' | 'sql' | 'sqlMs' | 'renders' | 'renderMs' | 'updates', DashPageStat>>;
|
|
1266
|
+
/** The latest visit — not a hot reload, unless the page has nothing else — without its request list. */
|
|
1267
|
+
last?: DashPageVisit;
|
|
1268
|
+
/** Where its SPA visits came from (the tab's page before), most often first; at most 3. */
|
|
1269
|
+
from: Array<{
|
|
1270
|
+
page: string;
|
|
1271
|
+
n: number;
|
|
1272
|
+
}>;
|
|
1273
|
+
/** The latest visit against the one before — hot reloads left out. */
|
|
1274
|
+
changes: DashPageChange[];
|
|
1275
|
+
}
|
|
1276
|
+
export interface DashPageDetail extends DashPageSummary {
|
|
1277
|
+
/** Newest first, at most 20; the newest two carry `requestList`. */
|
|
1278
|
+
recent: DashPageVisit[];
|
|
1279
|
+
/** The slowest visit kept (by its population's ready), with its requests. */
|
|
1280
|
+
slowest?: DashPageVisit;
|
|
1281
|
+
/** What it requests, most visits first; at most 50. */
|
|
1282
|
+
uses: DashPageUse[];
|
|
1283
|
+
/** The most-rendered components, over the visits that reported them; at most 20. */
|
|
1284
|
+
components: Array<{
|
|
1285
|
+
name: string;
|
|
1286
|
+
n: number;
|
|
1287
|
+
ms: number;
|
|
1288
|
+
inVisits: number;
|
|
1289
|
+
}>;
|
|
1290
|
+
/** The most-updated store paths; at most 20. */
|
|
1291
|
+
store: Array<{
|
|
1292
|
+
store: string;
|
|
1293
|
+
path: string;
|
|
1294
|
+
n: number;
|
|
1295
|
+
inVisits: number;
|
|
1296
|
+
}>;
|
|
1297
|
+
/** Real paths that took this pattern, newest first; at most 10. */
|
|
1298
|
+
paths: string[];
|
|
1299
|
+
}
|
|
1300
|
+
/** Visits with no router pattern, by app and templated path: not pages (planning/hub decision 9). */
|
|
1301
|
+
export interface DashPageUnmatched {
|
|
1302
|
+
app: string;
|
|
1303
|
+
path: string;
|
|
1304
|
+
visits: number;
|
|
1305
|
+
lastSeenAt: number;
|
|
1306
|
+
}
|
|
1307
|
+
export interface DashPagesCatalog {
|
|
1308
|
+
at: number;
|
|
1309
|
+
/** Most recently seen first. */
|
|
1310
|
+
pages: DashPageSummary[];
|
|
1311
|
+
/** At most 50 paths; `visits` sums them. */
|
|
1312
|
+
unmatched: {
|
|
1313
|
+
visits: number;
|
|
1314
|
+
paths: DashPageUnmatched[];
|
|
1315
|
+
};
|
|
1316
|
+
/** How far back the kept visits reach. */
|
|
1317
|
+
since?: number;
|
|
1318
|
+
}
|
|
1094
1319
|
/** What one AI model was asked through an endpoint, and what it cost in tokens. */
|
|
1095
1320
|
export interface DashAiUse {
|
|
1096
1321
|
model: string;
|
|
@@ -1381,6 +1606,15 @@ export interface DashDbStores {
|
|
|
1381
1606
|
errors: string[];
|
|
1382
1607
|
notes: string[];
|
|
1383
1608
|
stores: DashDbStore[];
|
|
1609
|
+
/** The newest read failed, and this is the last one that did not: why the newer failed, and when. */
|
|
1610
|
+
kept?: DashDbKept;
|
|
1611
|
+
}
|
|
1612
|
+
/** A read the lens kept because a newer one failed — a busy machine's statement timeout must not blank the screen. */
|
|
1613
|
+
export interface DashDbKept {
|
|
1614
|
+
/** Why the newer read failed, in Postgres's words. */
|
|
1615
|
+
failed: string;
|
|
1616
|
+
/** When it failed (epoch ms); the kept read's own time is its `at`. */
|
|
1617
|
+
at: number;
|
|
1384
1618
|
}
|
|
1385
1619
|
export interface DashDbStore {
|
|
1386
1620
|
name: string;
|
|
@@ -1478,8 +1712,51 @@ export interface DashDbSchema {
|
|
|
1478
1712
|
rows: DashDbStatementStat[];
|
|
1479
1713
|
};
|
|
1480
1714
|
findings: DashDbFinding[];
|
|
1715
|
+
/** What the findings judged — and what a size floor left out, so «no finding» is not read as «nothing there». */
|
|
1716
|
+
checked?: DashDbChecked;
|
|
1481
1717
|
/** A read that failed, in Postgres's words. */
|
|
1482
1718
|
error?: string;
|
|
1719
|
+
/** The newest read failed, and this is the last one that did not: why the newer failed, and when. */
|
|
1720
|
+
kept?: DashDbKept;
|
|
1721
|
+
}
|
|
1722
|
+
/** One database's last read by LensMCP's own checks (`db.schema`), as `db://analysis` names it beside the analyzer's runs. */
|
|
1723
|
+
export interface DashDbChecksSeen {
|
|
1724
|
+
store: string;
|
|
1725
|
+
database: string;
|
|
1726
|
+
at: number;
|
|
1727
|
+
findings: number;
|
|
1728
|
+
byKind: Partial<Record<DashDbFinding['kind'], number>>;
|
|
1729
|
+
/** {@link DashDbChecked.note}: what the checks judged. */
|
|
1730
|
+
judged?: string;
|
|
1731
|
+
}
|
|
1732
|
+
/**
|
|
1733
|
+
* What LensMCP's own checks of a database judged (foodguard-83). The table checks (seq-scan, dead-rows,
|
|
1734
|
+
* unindexed-foreign-key) judge only tables of `floorRows` rows or more — on a development database that is often none.
|
|
1735
|
+
*/
|
|
1736
|
+
export interface DashDbChecked {
|
|
1737
|
+
tables: number;
|
|
1738
|
+
/** Tables at or over the floor: the ones the table checks judged. */
|
|
1739
|
+
judged: number;
|
|
1740
|
+
floorRows: number;
|
|
1741
|
+
/** Under the floor, the most sequentially scanned — not judged, named so the floor hides nothing. */
|
|
1742
|
+
belowFloor: Array<{
|
|
1743
|
+
table: string;
|
|
1744
|
+
rows: number;
|
|
1745
|
+
seqScans: number;
|
|
1746
|
+
}>;
|
|
1747
|
+
indexes: number;
|
|
1748
|
+
/**
|
|
1749
|
+
* Foreign keys no valid index leads with; of those, the ones the check judged (a big child, a parent with deletes),
|
|
1750
|
+
* and the ones under the floor whose referenced table has deletes — a cost once the child grows.
|
|
1751
|
+
*/
|
|
1752
|
+
foreignKeys?: {
|
|
1753
|
+
total: number;
|
|
1754
|
+
unindexed: number;
|
|
1755
|
+
judged: number;
|
|
1756
|
+
atScale: number;
|
|
1757
|
+
};
|
|
1758
|
+
/** The above in a sentence. */
|
|
1759
|
+
note: string;
|
|
1483
1760
|
}
|
|
1484
1761
|
export interface DashDbTableInfo {
|
|
1485
1762
|
schema: string;
|
|
@@ -1512,6 +1789,8 @@ export interface DashDbIndex {
|
|
|
1512
1789
|
valid: boolean;
|
|
1513
1790
|
/** Part of a partitioned table's index (or that index itself): changed on the parent, never on its own. */
|
|
1514
1791
|
partition?: boolean;
|
|
1792
|
+
/** The primary key, unique or exclusion constraint it backs — dropping it drops the constraint. */
|
|
1793
|
+
constraint?: string;
|
|
1515
1794
|
scans: number;
|
|
1516
1795
|
rowsRead: number;
|
|
1517
1796
|
bytes: number;
|
|
@@ -1747,7 +2026,7 @@ export interface DashDbStatementStat {
|
|
|
1747
2026
|
hitRatio?: number;
|
|
1748
2027
|
}
|
|
1749
2028
|
export interface DashDbFinding {
|
|
1750
|
-
kind: 'unused-index' | 'duplicate-index' | 'invalid-index' | 'seq-scan' | 'dead-rows';
|
|
2029
|
+
kind: 'unused-index' | 'duplicate-index' | 'invalid-index' | 'seq-scan' | 'dead-rows' | 'unindexed-foreign-key';
|
|
1751
2030
|
severity: 'high' | 'medium' | 'low';
|
|
1752
2031
|
table: string;
|
|
1753
2032
|
index?: string;
|
|
@@ -1755,6 +2034,25 @@ export interface DashDbFinding {
|
|
|
1755
2034
|
detail: string;
|
|
1756
2035
|
/** The statement that would fix it — shown to copy, never run by the lens. */
|
|
1757
2036
|
fix?: string;
|
|
2037
|
+
/** An index finding: the index's own scans and size. */
|
|
2038
|
+
scans?: number;
|
|
2039
|
+
bytes?: number;
|
|
2040
|
+
/** duplicate-index: the index that stays, and why it is enough (`backs <constraint>`, `unique`, `wider`, `the same`). */
|
|
2041
|
+
kept?: {
|
|
2042
|
+
index: string;
|
|
2043
|
+
why: string;
|
|
2044
|
+
scans: number;
|
|
2045
|
+
bytes: number;
|
|
2046
|
+
};
|
|
2047
|
+
/** The table's inserts + updates since Postgres began counting — each index costs a write on every one. */
|
|
2048
|
+
writes?: number;
|
|
2049
|
+
/** unindexed-foreign-key: the constraint, and the table it references. */
|
|
2050
|
+
foreignKey?: {
|
|
2051
|
+
name: string;
|
|
2052
|
+
columns: string[];
|
|
2053
|
+
references: string;
|
|
2054
|
+
onDelete: string;
|
|
2055
|
+
};
|
|
1758
2056
|
}
|
|
1759
2057
|
/** One Redis command by its shape: the command and its key with ids folded (`GET session:*`); a script by its hash. */
|
|
1760
2058
|
export interface DashKvCommandShape {
|
|
@@ -2158,7 +2456,7 @@ export interface DashAiRun {
|
|
|
2158
2456
|
* (`files`); `external`: the external APIs the services call (`external`); `log`: one log line (its `seq`).
|
|
2159
2457
|
*/
|
|
2160
2458
|
target: {
|
|
2161
|
-
kind: 'sql' | 'route' | 'error' | 'flow' | 'ui' | 'kv' | 'queue' | 'db' | 'dbtable' | 'kvstore' | 'queuestore' | 'files' | 'external' | 'log';
|
|
2459
|
+
kind: 'sql' | 'route' | 'error' | 'flow' | 'ui' | 'kv' | 'queue' | 'db' | 'dbtable' | 'kvstore' | 'queuestore' | 'files' | 'external' | 'log' | 'page';
|
|
2162
2460
|
id: string;
|
|
2163
2461
|
label: string;
|
|
2164
2462
|
name?: string;
|
package/lib/event.d.ts
CHANGED
|
@@ -151,6 +151,7 @@ export declare const BaseEventSchema: z.ZodObject<{
|
|
|
151
151
|
causedByNodeId: z.ZodOptional<z.ZodString>;
|
|
152
152
|
requestId: z.ZodOptional<z.ZodString>;
|
|
153
153
|
parentRequestId: z.ZodOptional<z.ZodString>;
|
|
154
|
+
runId: z.ZodOptional<z.ZodString>;
|
|
154
155
|
traceparent: z.ZodOptional<z.ZodString>;
|
|
155
156
|
projectName: z.ZodOptional<z.ZodString>;
|
|
156
157
|
userActionId: z.ZodOptional<z.ZodString>;
|
package/lib/node.d.ts
CHANGED
|
@@ -188,6 +188,7 @@ export declare const TraceNodeSchema: z.ZodObject<{
|
|
|
188
188
|
causedByNodeId: z.ZodOptional<z.ZodString>;
|
|
189
189
|
requestId: z.ZodOptional<z.ZodString>;
|
|
190
190
|
parentRequestId: z.ZodOptional<z.ZodString>;
|
|
191
|
+
runId: z.ZodOptional<z.ZodString>;
|
|
191
192
|
traceparent: z.ZodOptional<z.ZodString>;
|
|
192
193
|
projectName: z.ZodOptional<z.ZodString>;
|
|
193
194
|
userActionId: z.ZodOptional<z.ZodString>;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A page visit, as the browser measures it (planning/pages/00-plan.md §2): from navigation start (a hard load) or a
|
|
3
|
+
* pathname change (an SPA navigation) to "ready" — the first commit after the page's own requests settle — and on to
|
|
4
|
+
* its end (the next visit, `pagehide`, or a minute after ready). A visit is not a flow: it records the flows its work
|
|
5
|
+
* ran under. The tab sends one event when the visit is ready (`phase: 'ready'`) and one when it ends (`phase: 'end'`);
|
|
6
|
+
* the lens joins its requests to the backend's routes and SQL by request id and folds it into the page catalog.
|
|
7
|
+
*
|
|
8
|
+
* Field names stay clear of the redactor's secret words (key, code, session, token …): it would blank their values.
|
|
9
|
+
* No query string is ever sent — a request names its pathname and a hash of its query.
|
|
10
|
+
*/
|
|
11
|
+
export declare const PAGE_VISIT_KIND: "page-visit";
|
|
12
|
+
/** How the visit began. A hard load: the navigation's type; an SPA navigation: the history call. */
|
|
13
|
+
export type PageVisitNavType = 'navigate' | 'reload' | 'back_forward' | 'push' | 'replace' | 'pop';
|
|
14
|
+
/**
|
|
15
|
+
* How ready was decided: `settled` — the first commit after the page's requests settled, with none started within the
|
|
16
|
+
* quiet window; `no-requests` — it made none (the first commit that held); `no-commit` — the requests settled and
|
|
17
|
+
* nothing committed within a second after (the last commit before); `timeout` — not ready within the cap (its open
|
|
18
|
+
* requests are named); `left` — the next visit began first.
|
|
19
|
+
*/
|
|
20
|
+
export type PageVisitReadyBy = 'settled' | 'no-requests' | 'no-commit' | 'timeout' | 'left';
|
|
21
|
+
/** One request the page made during the visit (every `fetch`, with or without a flow). */
|
|
22
|
+
export interface PageVisitRequest {
|
|
23
|
+
/** The request id the lens's fetch hook stamped (`x-request-id`): what the backend's server-request carries. */
|
|
24
|
+
rid: string;
|
|
25
|
+
/** Method. */
|
|
26
|
+
m: string;
|
|
27
|
+
/** Host + pathname (no query): `api.foodguard.localhost/registry/v1/business-profile/situation-state`. */
|
|
28
|
+
p: string;
|
|
29
|
+
/** A short hash of the query string, so two calls with different queries tell apart — never the query. */
|
|
30
|
+
qh?: string;
|
|
31
|
+
/** When it started, in ms after the visit's start. */
|
|
32
|
+
s: number;
|
|
33
|
+
/** Ms until its response headers (a streamed body does not count); absent while still open. */
|
|
34
|
+
d?: number;
|
|
35
|
+
/** HTTP status; 0 for a network failure. */
|
|
36
|
+
st?: number;
|
|
37
|
+
/** The flow the request ran under, if one was open. */
|
|
38
|
+
flowId?: string;
|
|
39
|
+
/** Started after ready (polling, a lazy panel). */
|
|
40
|
+
late?: true;
|
|
41
|
+
}
|
|
42
|
+
export interface PageVisitRenders {
|
|
43
|
+
commits: number;
|
|
44
|
+
/** Components rendered, summed over the commits. */
|
|
45
|
+
renders: number;
|
|
46
|
+
/** React's own render time (actualDuration), summed. */
|
|
47
|
+
renderMs: number;
|
|
48
|
+
maxCommitMs: number;
|
|
49
|
+
/** Commits that rendered more than the storm threshold. */
|
|
50
|
+
stormCommits: number;
|
|
51
|
+
mounts: number;
|
|
52
|
+
/** Commits that showed a Suspense fallback (a lazy chunk or data still loading). */
|
|
53
|
+
suspenseWaits: number;
|
|
54
|
+
/** The most-rendered components, by renders: name, renders, ms. At most 8. */
|
|
55
|
+
top: Array<{
|
|
56
|
+
name: string;
|
|
57
|
+
n: number;
|
|
58
|
+
ms: number;
|
|
59
|
+
}>;
|
|
60
|
+
}
|
|
61
|
+
export interface PageVisitStore {
|
|
62
|
+
updates: number;
|
|
63
|
+
/** The most-updated store paths. At most 8. */
|
|
64
|
+
top: Array<{
|
|
65
|
+
store: string;
|
|
66
|
+
path: string;
|
|
67
|
+
n: number;
|
|
68
|
+
}>;
|
|
69
|
+
}
|
|
70
|
+
/** The browser's own timings of a hard load (Web Vitals and friends) — on a Vite dev server, not a production build. */
|
|
71
|
+
export interface PageVisitVitals {
|
|
72
|
+
ttfb?: number;
|
|
73
|
+
fcp?: number;
|
|
74
|
+
lcp?: number;
|
|
75
|
+
cls?: number;
|
|
76
|
+
inp?: number;
|
|
77
|
+
dcl?: number;
|
|
78
|
+
load?: number;
|
|
79
|
+
}
|
|
80
|
+
export interface PageVisitRaw {
|
|
81
|
+
kind: typeof PAGE_VISIT_KIND;
|
|
82
|
+
phase: 'ready' | 'end';
|
|
83
|
+
visitId: string;
|
|
84
|
+
/** The browser tab (the client runtime's id), so a tab's visits read in order. */
|
|
85
|
+
tabId?: string;
|
|
86
|
+
/** The app the Vite plugin serves (its project name), or the page's host. */
|
|
87
|
+
app: string;
|
|
88
|
+
/** The router's full match pattern (`/companies/:id/onboarding/chat`) — absent when no router pattern is known. */
|
|
89
|
+
pattern?: string;
|
|
90
|
+
/** The pathname the visit opened (≤ 200 characters, no query). */
|
|
91
|
+
path: string;
|
|
92
|
+
nav: 'hard' | 'spa';
|
|
93
|
+
navType?: PageVisitNavType;
|
|
94
|
+
/** A hard load the dev server's hot reload caused. */
|
|
95
|
+
cause?: 'hmr';
|
|
96
|
+
/** The pathname a `replace` before ready came from (a redirect): the visit went on. */
|
|
97
|
+
redirectedFrom?: string;
|
|
98
|
+
/** Epoch ms: navigation start (hard) or the history call (SPA). */
|
|
99
|
+
startAt: number;
|
|
100
|
+
readyAt?: number;
|
|
101
|
+
readyBy?: PageVisitReadyBy;
|
|
102
|
+
/** Ms from start to ready. */
|
|
103
|
+
readyMs?: number;
|
|
104
|
+
/** A hard load: ms from the app's entry module to ready — what the app took, without the dev server serving it. */
|
|
105
|
+
appReadyMs?: number;
|
|
106
|
+
endAt?: number;
|
|
107
|
+
/** The flows the visit's work ran under. */
|
|
108
|
+
flowIds: string[];
|
|
109
|
+
/** Up to 60 requests; the rest counted. */
|
|
110
|
+
requests: PageVisitRequest[];
|
|
111
|
+
requestsDropped?: number;
|
|
112
|
+
renders: PageVisitRenders;
|
|
113
|
+
store: PageVisitStore;
|
|
114
|
+
errors: {
|
|
115
|
+
n: number;
|
|
116
|
+
first?: string;
|
|
117
|
+
};
|
|
118
|
+
/** From ready to the end (the `end` event only). */
|
|
119
|
+
afterReady?: {
|
|
120
|
+
requests: number;
|
|
121
|
+
templates: string[];
|
|
122
|
+
renders: number;
|
|
123
|
+
updates: number;
|
|
124
|
+
};
|
|
125
|
+
vitals?: PageVisitVitals;
|
|
126
|
+
longTasks?: {
|
|
127
|
+
n: number;
|
|
128
|
+
totalMs: number;
|
|
129
|
+
maxMs: number;
|
|
130
|
+
};
|
|
131
|
+
heapMb?: number;
|
|
132
|
+
chunks?: {
|
|
133
|
+
n: number;
|
|
134
|
+
kb: number;
|
|
135
|
+
};
|
|
136
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";export const PAGE_VISIT_KIND="page-visit";
|