effect-inspect 0.1.1 → 0.2.0

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.
Files changed (34) hide show
  1. package/README.md +68 -0
  2. package/app/dist/client/assets/{index-smV05cfr.js → index-T-bCzOWw.js} +2 -2
  3. package/app/dist/client/assets/routes-C2qO8k2W.js +5 -0
  4. package/app/dist/server/assets/{_tanstack-start-manifest_v-CFQ3DEVN.js → _tanstack-start-manifest_v-B2BMiICr.js} +3 -3
  5. package/app/dist/server/assets/{router-CN98Ramo.js → router-dMcw-pHq.js} +1 -1
  6. package/app/dist/server/assets/{routes-eZ4XqxE9.js → routes-BmnrEVoN.js} +203 -157
  7. package/app/dist/server/server.js +2 -2
  8. package/dist/cli/QueryCommands.d.ts +127 -0
  9. package/dist/cli/QueryCommands.js +768 -0
  10. package/dist/cli.d.ts +1 -2
  11. package/dist/cli.js +150 -8
  12. package/dist/client/Client.d.ts +42 -1
  13. package/dist/client/Client.js +88 -4
  14. package/dist/collector/QueryApi.d.ts +29 -0
  15. package/dist/collector/QueryApi.js +91 -0
  16. package/dist/collector/Server.d.ts +1 -1
  17. package/dist/collector/Server.js +15 -8
  18. package/dist/collector/Store.d.ts +56 -16
  19. package/dist/collector/Store.js +37 -11
  20. package/dist/protocol/Codec.d.ts +10 -0
  21. package/dist/protocol/Schema.d.ts +118 -1
  22. package/dist/protocol/Schema.js +53 -1
  23. package/dist/query/Client.d.ts +30 -0
  24. package/dist/query/Client.js +74 -0
  25. package/dist/query/Query.d.ts +599 -0
  26. package/dist/query/Query.js +876 -0
  27. package/dist/trace/Timing.d.ts +18 -0
  28. package/dist/trace/Timing.js +57 -0
  29. package/dist/trace/TraceFile.d.ts +54 -0
  30. package/dist/trace/TraceFile.js +86 -0
  31. package/dist/trace/TraceStore.d.ts +202 -0
  32. package/dist/trace/TraceStore.js +328 -0
  33. package/package.json +3 -1
  34. package/app/dist/client/assets/routes-TKgeFdSW.js +0 -5
@@ -0,0 +1,599 @@
1
+ /**
2
+ * Headless, read-only trace queries with one contract for every source.
3
+ *
4
+ * A {@link TraceSource} is a frozen session: a collector snapshot or a saved
5
+ * `.eitrace`. Both are the same protocol message stream, so both are analysed
6
+ * by the same code — the browser's {@link TraceStore} reconstruction and
7
+ * {@link timings} math — and a snapshot queried live answers exactly as its
8
+ * exported file does.
9
+ *
10
+ * Every answer is JSON, bounded in size, names its source and time reference,
11
+ * and says what it cannot vouch for: a response never presents partial or
12
+ * conflicting evidence as a complete, unambiguous run. Requests and responses
13
+ * are plain data so the CLI can print them and the collector can serve them.
14
+ *
15
+ * Timing is observation, not diagnosis. `durationMs` is elapsed time between a
16
+ * span's recorded start and end; `outsideChildrenMs` is the part of it not
17
+ * covered by any recorded direct child. Neither is CPU time, and neither says
18
+ * an operation is slow, stuck or under-instrumented on its own.
19
+ */
20
+ import { Result, Schema } from 'effect';
21
+ import type * as Protocol from '../protocol/Schema.ts';
22
+ /** Version of this request/response contract. Bumped on a breaking change. */
23
+ export declare const apiVersion = 1;
24
+ /** Defaults and caps for every bounded part of a response. */
25
+ export declare const limits: {
26
+ /** `sessions` page size. */
27
+ readonly sessions: {
28
+ readonly default: 50;
29
+ readonly max: 500;
30
+ };
31
+ /** `spans` page size. */
32
+ readonly spans: {
33
+ readonly default: 20;
34
+ readonly max: 200;
35
+ };
36
+ /** `logs` page size. */
37
+ readonly logs: {
38
+ readonly default: 50;
39
+ readonly max: 500;
40
+ };
41
+ /** Items per ranked list in `summary`. */
42
+ readonly top: {
43
+ readonly default: 5;
44
+ readonly max: 50;
45
+ };
46
+ /** Children listed by `span`. */
47
+ readonly children: {
48
+ readonly default: 20;
49
+ readonly max: 200;
50
+ };
51
+ /** Span events listed by `span`. */
52
+ readonly events: {
53
+ readonly default: 20;
54
+ readonly max: 200;
55
+ };
56
+ /** Nearest ancestors listed by `span`. */
57
+ readonly ancestry: 32;
58
+ /** Attribute/annotation keys kept per object; the rest are counted, not sent. */
59
+ readonly attributeKeys: 32;
60
+ /** Characters of one JSON-encoded attribute value before it is cut. */
61
+ readonly valueChars: 500;
62
+ /** Characters of a failure message. */
63
+ readonly errorChars: 500;
64
+ /** Characters of a failure stack. */
65
+ readonly stackChars: 4000;
66
+ /** Characters of a log message. */
67
+ readonly logMessageChars: 2000;
68
+ /** Characters of a span, event or group name, a log's span name, or a program/runtime. */
69
+ readonly nameChars: 200;
70
+ /** Characters of one attribute or annotation key. */
71
+ readonly keyChars: 100;
72
+ /** Characters of an error `message`. */
73
+ readonly errorMessageChars: 1000;
74
+ /** Longest `sessionId`, `spanId` or `name` a request may carry. */
75
+ readonly requestTextChars: 1024;
76
+ /**
77
+ * UTF-8 bytes of a whole serialized JSON response, envelope included. A
78
+ * response that would be larger is replaced by `ResponseTooLarge`.
79
+ * Identifiers are never shortened to fit. `.eitrace` export is a lossless
80
+ * artifact transfer, not a query response, and is not held to this.
81
+ */
82
+ readonly responseBytes: 1048576;
83
+ };
84
+ /**
85
+ * Loss counters the collector keeps for a session. Mirrors
86
+ * {@link Protocol.TraceCapture}; `undefined` on a source means unknown.
87
+ */
88
+ export type Capture = Protocol.TraceCapture;
89
+ /** One frozen session, from the collector or from a file. */
90
+ export interface TraceSource {
91
+ readonly kind: 'live' | 'file';
92
+ /** Path (or label) of the file, for `kind: 'file'`. */
93
+ readonly file?: string | undefined;
94
+ readonly session: Protocol.Session;
95
+ /** Retained protocol messages in arrival order. */
96
+ readonly messages: ReadonlyArray<Protocol.ClientMessage>;
97
+ /** Collector loss counters, or `undefined` when the source never recorded them. */
98
+ readonly capture: Capture | undefined;
99
+ /** Undecodable trailing file lines; 0 for live sources. */
100
+ readonly truncatedLines: number;
101
+ /** When the snapshot was taken (live) or the file saved, epoch millis. */
102
+ readonly snapshotAtEpochMillis: number;
103
+ }
104
+ /** A live source from a collector `Store` snapshot taken at `now`. */
105
+ export declare const fromSnapshot: (snapshot: {
106
+ readonly session: Protocol.Session;
107
+ readonly messages: ReadonlyArray<Protocol.ClientMessage>;
108
+ readonly droppedMessages: number;
109
+ readonly skippedLines: number;
110
+ readonly conflictDetection: boolean;
111
+ }, now: number) => TraceSource;
112
+ /**
113
+ * Trace-file text for a source, with its loss counters in the header so a
114
+ * query against the file reports the same completeness as the snapshot.
115
+ */
116
+ export declare const toTraceFile: (source: TraceSource) => string;
117
+ /** Parses trace-file text into a file source, or the `TraceFileError` response. */
118
+ export declare const fromTraceFile: (text: string, file: string) => Result.Result<TraceSource, QueryFailure>;
119
+ /** Span status values a span can have. */
120
+ export declare const spanStatuses: readonly ['ok', 'error', 'defect', 'interrupted', 'open'];
121
+ export type SpanStatus = (typeof spanStatuses)[number];
122
+ /** `spans` status filter: a {@link SpanStatus}, `failed` (any failure) or `any`. */
123
+ export declare const StatusFilter: Schema.Literals<readonly ["any", "failed", "ok", "error", "defect", "interrupted", "open"]>;
124
+ export type StatusFilter = Schema.Schema.Type<typeof StatusFilter>;
125
+ export declare const SpanSort: Schema.Literals<readonly ["start", "duration", "outsideChildren"]>;
126
+ export type SpanSort = Schema.Schema.Type<typeof SpanSort>;
127
+ /** Log levels a `minLevel` filter accepts, least severe first. */
128
+ export declare const logLevels: readonly ['Trace', 'Debug', 'Info', 'Warn', 'Error', 'Fatal'];
129
+ export declare const MinLevel: Schema.Literals<readonly ["Trace", "Debug", "Info", "Warn", "Error", "Fatal"]>;
130
+ export declare const LogScope: Schema.Literals<readonly ["span", "subtree"]>;
131
+ /** Lists sessions. Live: every session the collector holds. File: the file's one session. */
132
+ export declare const SessionsRequest: Schema.Struct<{
133
+ readonly op: Schema.Literal<"sessions">;
134
+ readonly limit: Schema.optional<Schema.Int>;
135
+ readonly offset: Schema.optional<Schema.Natural>;
136
+ }>;
137
+ /** Counts, failures and ranked timings for one session. */
138
+ export declare const SummaryRequest: Schema.Struct<{
139
+ readonly op: Schema.Literal<"summary">;
140
+ readonly sessionId: Schema.optional<Schema.String>;
141
+ readonly top: Schema.optional<Schema.Int>;
142
+ }>;
143
+ /** A filtered, sorted page of spans. */
144
+ export declare const SpansRequest: Schema.Struct<{
145
+ readonly op: Schema.Literal<"spans">;
146
+ readonly sessionId: Schema.optional<Schema.String>;
147
+ readonly status: Schema.optional<Schema.Literals<readonly ["any", "failed", "ok", "error", "defect", "interrupted", "open"]>>;
148
+ /** Case-insensitive substring of the span name. */
149
+ readonly name: Schema.optional<Schema.String>;
150
+ /** Only spans whose duration (or, while open, elapsed lower bound) is at least this. */
151
+ readonly minDurationMs: Schema.optional<Schema.Finite>;
152
+ /** Only spans overlapping `[fromMs, toMs]`. Timings are not clipped to it. */
153
+ readonly fromMs: Schema.optional<Schema.Finite>;
154
+ readonly toMs: Schema.optional<Schema.Finite>;
155
+ readonly sort: Schema.optional<Schema.Literals<readonly ["start", "duration", "outsideChildren"]>>;
156
+ readonly limit: Schema.optional<Schema.Int>;
157
+ readonly offset: Schema.optional<Schema.Natural>;
158
+ }>;
159
+ /** One span with bounded ancestry, children, events and attributes. */
160
+ export declare const SpanRequest: Schema.Struct<{
161
+ readonly op: Schema.Literal<"span">;
162
+ readonly sessionId: Schema.optional<Schema.String>;
163
+ readonly spanId: Schema.String;
164
+ readonly children: Schema.optional<Schema.Int>;
165
+ readonly events: Schema.optional<Schema.Int>;
166
+ }>;
167
+ /** A page of logs, optionally correlated with a span. */
168
+ export declare const LogsRequest: Schema.Struct<{
169
+ readonly op: Schema.Literal<"logs">;
170
+ readonly sessionId: Schema.optional<Schema.String>;
171
+ readonly spanId: Schema.optional<Schema.String>;
172
+ /** Requires `spanId`: that span's own logs, or its whole subtree's (default). */
173
+ readonly scope: Schema.optional<Schema.Literals<readonly ["span", "subtree"]>>;
174
+ readonly minLevel: Schema.optional<Schema.Literals<readonly ["Trace", "Debug", "Info", "Warn", "Error", "Fatal"]>>;
175
+ readonly fromMs: Schema.optional<Schema.Finite>;
176
+ readonly toMs: Schema.optional<Schema.Finite>;
177
+ readonly limit: Schema.optional<Schema.Int>;
178
+ readonly offset: Schema.optional<Schema.Natural>;
179
+ }>;
180
+ export declare const QueryRequest: Schema.Union<readonly [Schema.Struct<{
181
+ readonly op: Schema.Literal<"sessions">;
182
+ readonly limit: Schema.optional<Schema.Int>;
183
+ readonly offset: Schema.optional<Schema.Natural>;
184
+ }>, Schema.Struct<{
185
+ readonly op: Schema.Literal<"summary">;
186
+ readonly sessionId: Schema.optional<Schema.String>;
187
+ readonly top: Schema.optional<Schema.Int>;
188
+ }>, Schema.Struct<{
189
+ readonly op: Schema.Literal<"spans">;
190
+ readonly sessionId: Schema.optional<Schema.String>;
191
+ readonly status: Schema.optional<Schema.Literals<readonly ["any", "failed", "ok", "error", "defect", "interrupted", "open"]>>;
192
+ /** Case-insensitive substring of the span name. */
193
+ readonly name: Schema.optional<Schema.String>;
194
+ /** Only spans whose duration (or, while open, elapsed lower bound) is at least this. */
195
+ readonly minDurationMs: Schema.optional<Schema.Finite>;
196
+ /** Only spans overlapping `[fromMs, toMs]`. Timings are not clipped to it. */
197
+ readonly fromMs: Schema.optional<Schema.Finite>;
198
+ readonly toMs: Schema.optional<Schema.Finite>;
199
+ readonly sort: Schema.optional<Schema.Literals<readonly ["start", "duration", "outsideChildren"]>>;
200
+ readonly limit: Schema.optional<Schema.Int>;
201
+ readonly offset: Schema.optional<Schema.Natural>;
202
+ }>, Schema.Struct<{
203
+ readonly op: Schema.Literal<"span">;
204
+ readonly sessionId: Schema.optional<Schema.String>;
205
+ readonly spanId: Schema.String;
206
+ readonly children: Schema.optional<Schema.Int>;
207
+ readonly events: Schema.optional<Schema.Int>;
208
+ }>, Schema.Struct<{
209
+ readonly op: Schema.Literal<"logs">;
210
+ readonly sessionId: Schema.optional<Schema.String>;
211
+ readonly spanId: Schema.optional<Schema.String>;
212
+ /** Requires `spanId`: that span's own logs, or its whole subtree's (default). */
213
+ readonly scope: Schema.optional<Schema.Literals<readonly ["span", "subtree"]>>;
214
+ readonly minLevel: Schema.optional<Schema.Literals<readonly ["Trace", "Debug", "Info", "Warn", "Error", "Fatal"]>>;
215
+ readonly fromMs: Schema.optional<Schema.Finite>;
216
+ readonly toMs: Schema.optional<Schema.Finite>;
217
+ readonly limit: Schema.optional<Schema.Int>;
218
+ readonly offset: Schema.optional<Schema.Natural>;
219
+ }>]>;
220
+ export type QueryRequest = Schema.Schema.Type<typeof QueryRequest>;
221
+ export type SessionQuery = Exclude<QueryRequest, {
222
+ readonly op: 'sessions';
223
+ }>;
224
+ /**
225
+ * Validates an untrusted request. Unknown keys are rejected rather than
226
+ * ignored, so a misspelt filter can never silently widen a result.
227
+ */
228
+ export declare const decodeRequest: (input: unknown) => Result.Result<QueryRequest, QueryFailure>;
229
+ export type ErrorTag = 'InvalidRequest' | 'SessionNotFound' | 'SessionConflict' | 'SpanNotFound' | 'TraceFileError' | 'CollectorUnavailable' | 'CollectorError' | 'ResponseTooLarge'
230
+ /** CLI only: `export` could not write its output file. */
231
+ | 'OutputError';
232
+ /** Every failed query, whatever the source or transport. */
233
+ export interface QueryFailure {
234
+ readonly ok: false;
235
+ readonly apiVersion: typeof apiVersion;
236
+ readonly op: string | null;
237
+ readonly error: {
238
+ readonly _tag: ErrorTag;
239
+ readonly message: string;
240
+ /** What to try next. */
241
+ readonly hint: string;
242
+ readonly [detail: string]: unknown;
243
+ };
244
+ }
245
+ /**
246
+ * A failure response. `op` is echoed only when it is a known operation and
247
+ * `message` is cut to `errorMessageChars`, so untrusted input cannot inflate it.
248
+ */
249
+ export declare const failure: (op: string | null, tag: ErrorTag, message: string, hint: string, details?: Record<string, unknown>) => QueryFailure;
250
+ /**
251
+ * Enforces {@link limits.responseBytes} on a complete response. An oversized
252
+ * response, success or failure, becomes a small fixed-shape
253
+ * `ResponseTooLarge` failure that echoes no caller text.
254
+ */
255
+ export declare const limitResponse: <R extends QueryResponse>(response: R) => R | QueryFailure;
256
+ /** Which session answered, and from where. */
257
+ export interface SourceInfo {
258
+ readonly kind: 'live' | 'file';
259
+ readonly file: string | null;
260
+ readonly sessionId: string;
261
+ /** Cut to `nameChars`. */
262
+ readonly program: string;
263
+ readonly programTruncated: boolean;
264
+ readonly pid: number;
265
+ /** Cut to `nameChars`. */
266
+ readonly runtime: string;
267
+ readonly runtimeTruncated: boolean;
268
+ /** Live: the client was still connected at snapshot time, so more may arrive. */
269
+ readonly active: boolean;
270
+ /** Wall clock of the session's time origin (`startMs` 0). */
271
+ readonly startedAtEpochMillis: number;
272
+ readonly endedAtEpochMillis: number | null;
273
+ /** Live: snapshot time. File: save time. */
274
+ readonly snapshotAtEpochMillis: number;
275
+ }
276
+ /** How to read every `...Ms` field in a response. */
277
+ export interface TimeInfo {
278
+ readonly unit: 'ms';
279
+ /**
280
+ * `sessionStart`: milliseconds since the session's clock origin, taken when
281
+ * its inspect client started. Wall clock = `startedAtEpochMillis + ms`.
282
+ * Monotonic, so comparable within a session only. Values can be negative:
283
+ * work that started before the inspect client did.
284
+ */
285
+ readonly reference: 'sessionStart';
286
+ /** Earliest retained timestamp (span start/end, event, log, memory), or `null` with no timed data. */
287
+ readonly observedFromMs: number | null;
288
+ /** Latest retained timestamp, or `null` with no timed data. Open spans are measured up to here. */
289
+ readonly observedUntilMs: number | null;
290
+ }
291
+ /**
292
+ * What the evidence may be missing. `status`:
293
+ * - `lossRecorded`: at least one loss or gap counter below
294
+ * (`collectorDroppedMessages` … `spansMissingParent`) is non-zero.
295
+ * - `noLossRecorded`: collector counters are known and every loss or gap
296
+ * counter is 0.
297
+ * Not proof of completeness — only what was measured.
298
+ * - `unknown`: nothing was recorded as lost, but the source never kept the
299
+ * collector counters (a browser save or older file).
300
+ */
301
+ export interface Completeness {
302
+ readonly status: 'lossRecorded' | 'noLossRecorded' | 'unknown';
303
+ /** Evicted by the collector's per-session capacity; `null` = unknown. */
304
+ readonly collectorDroppedMessages: number | null;
305
+ /** Undecodable lines the collector skipped; `null` = unknown. */
306
+ readonly collectorSkippedLines: number | null;
307
+ /** Drops the client reported (its `effect_inspect.dropped` Warn logs) in retained logs. */
308
+ readonly clientDroppedMessages: number;
309
+ /** Undecodable trailing lines of a file (a cut-short save). */
310
+ readonly fileTruncatedLines: number;
311
+ /** Distinct span ids with a retained end or event but no retained start anywhere. */
312
+ readonly spansMissingStart: number;
313
+ /**
314
+ * Distinct span ids whose end or event arrived before their retained start.
315
+ * That end or event is not applied, so the span can read as open or lack
316
+ * events. A single client does not send this order.
317
+ */
318
+ readonly spansOutOfOrder: number;
319
+ /** Spans whose local parent span is not retained. */
320
+ readonly spansMissingParent: number;
321
+ /** Spans with no recorded end: still running, or their end was never received. */
322
+ readonly openSpans: number;
323
+ readonly retainedMessages: number;
324
+ /**
325
+ * Messages the collector accepted for the session (retained + evicted);
326
+ * `null` = unknown. Unchanged between two responses means same data.
327
+ */
328
+ readonly messagesObserved: number | null;
329
+ }
330
+ /**
331
+ * Collision state. A query never succeeds against a session with
332
+ * `count > 0` (see `SessionConflict`). `detection`:
333
+ * - `enforced`: the collector would have refused and counted a reused ID.
334
+ * - `unavailable`: the owning client predates instance IDs; a reused ID
335
+ * would have merged silently, so `count: 0` proves nothing.
336
+ * - `unknown`: a file without collector metadata.
337
+ */
338
+ export interface ConflictInfo {
339
+ readonly count: number | null;
340
+ readonly detection: 'enforced' | 'unavailable' | 'unknown';
341
+ }
342
+ /** Shared context of every successful per-session response. */
343
+ export interface Context {
344
+ readonly source: SourceInfo;
345
+ readonly time: TimeInfo;
346
+ readonly completeness: Completeness;
347
+ readonly conflict: ConflictInfo;
348
+ }
349
+ export interface ErrorInfo {
350
+ readonly kind: 'Fail' | 'Die' | 'Interrupt';
351
+ readonly message: string;
352
+ readonly messageTruncated: boolean;
353
+ }
354
+ /**
355
+ * One span, compactly. For a completed span `durationMs = childCoveredMs +
356
+ * outsideChildrenMs`; for an open span those three are `null` and
357
+ * `elapsedLowerBoundMs` says how long it had been open by `observedUntilMs`.
358
+ */
359
+ export interface SpanItem {
360
+ /** Exact, never shortened. */
361
+ readonly spanId: string;
362
+ /** Exact, never shortened. */
363
+ readonly traceId: string;
364
+ /** Cut to `nameChars`. */
365
+ readonly name: string;
366
+ readonly nameTruncated: boolean;
367
+ readonly kind: Protocol.SpanKind;
368
+ /** Local parent id, or `null` for a root or externally-parented span. */
369
+ readonly parentSpanId: string | null;
370
+ readonly status: SpanStatus;
371
+ readonly startMs: number;
372
+ readonly endMs: number | null;
373
+ readonly durationMs: number | null;
374
+ /** Union of recorded direct-child intervals, clipped to this span. */
375
+ readonly childCoveredMs: number | null;
376
+ /** `durationMs - childCoveredMs`: not covered by a recorded child. Not CPU time. */
377
+ readonly outsideChildrenMs: number | null;
378
+ readonly elapsedLowerBoundMs: number | null;
379
+ readonly childCount: number;
380
+ /** Children without an end; counted as covering until this span's end. */
381
+ readonly openChildCount: number;
382
+ readonly eventCount: number;
383
+ readonly logCount: number;
384
+ readonly error: ErrorInfo | null;
385
+ }
386
+ /**
387
+ * A JSON object cut down to a bounded size, as entries in the source's key
388
+ * order. Entries (not an object) so two keys cut to the same prefix stay apart.
389
+ */
390
+ export interface BoundedAttributes {
391
+ readonly entries: ReadonlyArray<{
392
+ /** Cut to `keyChars`. */
393
+ readonly key: string;
394
+ readonly keyTruncated: boolean;
395
+ /**
396
+ * The value; if its JSON encoding exceeds `valueChars`, the first
397
+ * `valueChars` characters of that encoding, as a string.
398
+ */
399
+ readonly value: Protocol.Json;
400
+ readonly valueTruncated: boolean;
401
+ }>;
402
+ /** Keys dropped beyond the first `attributeKeys`. */
403
+ readonly omittedKeys: number;
404
+ }
405
+ export interface SpanRef {
406
+ readonly spanId: string;
407
+ readonly name: string;
408
+ readonly nameTruncated: boolean;
409
+ readonly status: SpanStatus;
410
+ readonly startMs: number;
411
+ readonly durationMs: number | null;
412
+ }
413
+ export interface SpanDetail extends SpanItem {
414
+ readonly attributes: BoundedAttributes;
415
+ readonly stack: string | null;
416
+ readonly stackTruncated: boolean;
417
+ readonly parent: {
418
+ readonly kind: 'none';
419
+ } | {
420
+ readonly kind: 'local';
421
+ readonly spanId: string;
422
+ readonly retained: boolean;
423
+ } | {
424
+ readonly kind: 'external';
425
+ readonly spanId: string;
426
+ readonly traceId: string;
427
+ };
428
+ /** Root-most first, ending at the direct parent. */
429
+ readonly ancestry: {
430
+ readonly items: ReadonlyArray<SpanRef>;
431
+ /** More ancestors exist above the first item. */
432
+ readonly truncated: boolean;
433
+ };
434
+ /** First children by start time. */
435
+ readonly children: {
436
+ readonly total: number;
437
+ readonly items: ReadonlyArray<SpanItem>;
438
+ };
439
+ /** First span events by time. */
440
+ readonly events: {
441
+ readonly total: number;
442
+ readonly items: ReadonlyArray<{
443
+ /** Cut to `nameChars`. */
444
+ readonly name: string;
445
+ readonly nameTruncated: boolean;
446
+ readonly timeMs: number;
447
+ readonly attributes: BoundedAttributes;
448
+ }>;
449
+ };
450
+ }
451
+ export interface LogItem {
452
+ readonly timeMs: number;
453
+ readonly level: Protocol.LogLevel;
454
+ /** The message; a non-string message is JSON-encoded. */
455
+ readonly message: string;
456
+ readonly messageTruncated: boolean;
457
+ readonly spanId: string | null;
458
+ /** The span's name cut to `nameChars`, or `null` when unknown or not retained. */
459
+ readonly spanName: string | null;
460
+ readonly spanNameTruncated: boolean;
461
+ readonly fiberId: number | null;
462
+ readonly annotations: BoundedAttributes;
463
+ }
464
+ export interface Page<A> {
465
+ readonly total: number;
466
+ readonly offset: number;
467
+ readonly limit: number;
468
+ /** Offset of the next page, or `null` on the last. */
469
+ readonly nextOffset: number | null;
470
+ readonly items: ReadonlyArray<A>;
471
+ }
472
+ export interface NameGroup {
473
+ /** Cut to `nameChars`; groups are formed on the full name. */
474
+ readonly name: string;
475
+ readonly nameTruncated: boolean;
476
+ readonly count: number;
477
+ readonly completed: number;
478
+ readonly open: number;
479
+ /** Spans with any failure outcome, interruptions included. */
480
+ readonly failed: number;
481
+ /** Sum over completed spans. Nested and concurrent spans overlap. */
482
+ readonly totalDurationMs: number;
483
+ readonly maxDurationMs: number | null;
484
+ readonly totalOutsideChildrenMs: number;
485
+ }
486
+ export interface Summary {
487
+ readonly spans: {
488
+ readonly total: number;
489
+ readonly ok: number;
490
+ readonly error: number;
491
+ readonly defect: number;
492
+ readonly interrupted: number;
493
+ readonly open: number;
494
+ };
495
+ readonly spanEvents: number;
496
+ readonly logs: {
497
+ readonly total: number;
498
+ readonly byLevel: Partial<Record<Protocol.LogLevel, number>>;
499
+ };
500
+ readonly memory: {
501
+ readonly samples: number;
502
+ readonly peakHeapUsedBytes: number;
503
+ readonly peakRssBytes: number;
504
+ readonly lastHeapUsedBytes: number;
505
+ } | null;
506
+ /** `error`/`defect` spans (not interruptions), earliest start first. */
507
+ readonly failures: {
508
+ readonly total: number;
509
+ readonly items: ReadonlyArray<SpanItem>;
510
+ };
511
+ /** Completed spans, largest `durationMs` first. */
512
+ readonly longest: ReadonlyArray<SpanItem>;
513
+ /** Completed spans, largest `outsideChildrenMs` first. */
514
+ readonly largestOutsideChildren: ReadonlyArray<SpanItem>;
515
+ /** Open spans, largest `elapsedLowerBoundMs` first. */
516
+ readonly longestOpen: ReadonlyArray<SpanItem>;
517
+ /** Span names, largest `totalDurationMs` first. */
518
+ readonly names: {
519
+ readonly total: number;
520
+ readonly items: ReadonlyArray<NameGroup>;
521
+ };
522
+ }
523
+ export type SessionsResult = Page<{
524
+ readonly sessionId: string;
525
+ readonly program: string;
526
+ readonly programTruncated: boolean;
527
+ readonly pid: number;
528
+ readonly runtime: string;
529
+ readonly runtimeTruncated: boolean;
530
+ readonly active: boolean;
531
+ readonly startedAtEpochMillis: number;
532
+ readonly endedAtEpochMillis: number | null;
533
+ /** Refused reuses of this ID; `null` when none were recorded (see `conflict`). */
534
+ readonly conflicts: number | null;
535
+ }>;
536
+ interface Success<Op extends string, R> {
537
+ readonly ok: true;
538
+ readonly apiVersion: typeof apiVersion;
539
+ readonly op: Op;
540
+ /** The request as applied, defaults filled in. */
541
+ readonly query: Record<string, unknown>;
542
+ readonly result: R;
543
+ }
544
+ export type SessionsResponse = Success<'sessions', SessionsResult> & {
545
+ readonly source: {
546
+ readonly kind: 'live' | 'file';
547
+ readonly file: string | null;
548
+ };
549
+ };
550
+ export type SummaryResponse = Success<'summary', Summary> & Context;
551
+ /**
552
+ * How `fromMs`/`toMs` were applied to `spans`, or `null` without either:
553
+ * spans whose `[startMs, endMs]` (open: `[startMs, observedUntilMs]`)
554
+ * overlaps `[fromMs, toMs]`, bounds inclusive, are selected, and their
555
+ * timings are for the whole span, not clipped to the window.
556
+ */
557
+ export interface SpanWindow {
558
+ readonly fromMs: number | null;
559
+ readonly toMs: number | null;
560
+ readonly match: 'overlap';
561
+ readonly inclusive: true;
562
+ readonly timings: 'fullSpan';
563
+ }
564
+ /** How `fromMs`/`toMs` were applied to `logs`: log times within the range, inclusive. */
565
+ export interface LogWindow {
566
+ readonly fromMs: number | null;
567
+ readonly toMs: number | null;
568
+ readonly match: 'within';
569
+ readonly inclusive: true;
570
+ }
571
+ export type SpansResponse = Success<'spans', Page<SpanItem>> & Context & {
572
+ readonly window: SpanWindow | null;
573
+ };
574
+ export type SpanResponse = Success<'span', SpanDetail> & Context;
575
+ export type LogsResponse = Success<'logs', Page<LogItem>> & Context & {
576
+ readonly window: LogWindow | null;
577
+ };
578
+ export type QueryResponse = SessionsResponse | SummaryResponse | SpansResponse | SpanResponse | LogsResponse | QueryFailure;
579
+ /**
580
+ * Lists `sessions`, newest start first (ties by id). Discovery only: a caller
581
+ * that chose its session ID should query it directly instead.
582
+ */
583
+ export declare const listSessions: (source: SessionsResponse['source'], sessions: ReadonlyArray<Protocol.Session>, request: Extract<QueryRequest, {
584
+ readonly op: 'sessions';
585
+ }>) => SessionsResponse | QueryFailure;
586
+ /**
587
+ * Answers a per-session query against one frozen source. The caller has
588
+ * already matched `request.sessionId` to `source` exactly; this refuses a
589
+ * session with a recorded ID conflict instead of answering for it. The
590
+ * response is held to {@link limits.responseBytes}.
591
+ */
592
+ export declare const run: (source: TraceSource, request: SessionQuery) => QueryResponse;
593
+ /** Answers a request against trace-file text: the offline equivalent of a collector query. */
594
+ export declare const queryFile: (text: string, file: string, input: unknown) => QueryResponse;
595
+ /** The live `SessionNotFound` failure, shared by the collector's handlers. */
596
+ export declare const liveSessionNotFound: (op: string, sessionId: string) => QueryFailure;
597
+ /** The live failure for a per-session request without a `sessionId`. */
598
+ export declare const sessionRequired: (op: string) => QueryFailure;
599
+ export {};