@proj-airi/trace-kit 0.0.0-stage → 0.15.3
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/LICENSE +21 -0
- package/README.md +102 -2
- package/dist/clock-CewQJzn8.d.mts +545 -0
- package/dist/clock-hjTPEs21.mjs +212 -0
- package/dist/collector/index.d.mts +207 -0
- package/dist/collector/index.mjs +601 -0
- package/dist/conventions-DLiC8rkL.mjs +285 -0
- package/dist/index-DV04qeax.d.mts +49 -0
- package/dist/index.d.mts +782 -0
- package/dist/index.mjs +6 -0
- package/dist/keys-DD_VE8Fk.mjs +34 -0
- package/dist/profiles/agent.d.mts +70 -0
- package/dist/profiles/agent.mjs +295 -0
- package/dist/profiles/voice.d.mts +128 -0
- package/dist/profiles/voice.mjs +669 -0
- package/dist/projections/index.d.mts +3 -0
- package/dist/projections/index.mjs +1 -0
- package/dist/semconv-BOVWnou1.d.mts +832 -0
- package/dist/semconv.d.mts +2 -0
- package/dist/semconv.mjs +832 -0
- package/dist/series-ring-CaKfvyWQ.mjs +118 -0
- package/dist/series-ring-DCb7czkl.d.mts +49 -0
- package/dist/sink-BoftsA-W.mjs +501 -0
- package/dist/testing/index.d.mts +79 -0
- package/dist/testing/index.mjs +880 -0
- package/dist/timeline-B4Vc6qQf.mjs +766 -0
- package/dist/types-Fp54Yi6b.d.mts +319 -0
- package/dist/views/index.d.mts +97 -0
- package/dist/views/index.mjs +219 -0
- package/package.json +71 -3
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { n as SeriesRetention, r as SeriesRing } from "./series-ring-DCb7czkl.mjs";
|
|
2
|
+
import { A as TraceAttributes, D as TraceAnnotation, F as TraceIds, L as TraceLink, U as TraceRef, g as TraceMetricDefinition, n as ClockGraph, o as TraceFeedMessage, tt as TraceStatus, u as TraceAggregate, w as TraceTrackDefinition, z as TraceRecord } from "./clock-CewQJzn8.mjs";
|
|
3
|
+
//#region src/projections/reader.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Records by source, epoch, and seq.
|
|
6
|
+
*
|
|
7
|
+
* A map from `source/epoch` to a map from `seq` keeps one number per record. A map with `source/epoch/seq` strings as
|
|
8
|
+
* keys keeps one string per record, and costs about five times the memory for the same lookups.
|
|
9
|
+
*/
|
|
10
|
+
declare class RecordIndex {
|
|
11
|
+
private readonly epochs;
|
|
12
|
+
private count;
|
|
13
|
+
get size(): number;
|
|
14
|
+
get(ref: TraceRef): TraceRecord | undefined;
|
|
15
|
+
has(ref: TraceRef): boolean;
|
|
16
|
+
/** Adds a record. A record with the same source, epoch, and seq stays, and the call returns false. */
|
|
17
|
+
add(record: TraceRecord): boolean;
|
|
18
|
+
clear(): void;
|
|
19
|
+
}
|
|
20
|
+
/** The index key of a link target. */
|
|
21
|
+
declare function linkTargetKey(to: TraceRef | {
|
|
22
|
+
spanId: string;
|
|
23
|
+
} | {
|
|
24
|
+
key: string;
|
|
25
|
+
id: string | number;
|
|
26
|
+
}): string;
|
|
27
|
+
/**
|
|
28
|
+
* Feeds collector messages to projections in apply order.
|
|
29
|
+
*
|
|
30
|
+
* Apply order is the arrival order of the feed. For one epoch, it is the `seq` order, as the transports deliver it.
|
|
31
|
+
* Display order is the converted time, which each projection reads from the context.
|
|
32
|
+
*
|
|
33
|
+
* The reader keeps its own clock graph from the snapshot records in the feed, so a replay of a file converts times in
|
|
34
|
+
* the same way as the live view. `version` changes on each handled message. A view reads through selectors keyed on it.
|
|
35
|
+
*/
|
|
36
|
+
declare class TraceReader {
|
|
37
|
+
private readonly projections;
|
|
38
|
+
readonly clocks: ClockGraph;
|
|
39
|
+
readonly indexes: TraceIndexes;
|
|
40
|
+
version: number;
|
|
41
|
+
caughtUp: boolean;
|
|
42
|
+
private readonly states;
|
|
43
|
+
constructor(projections: AnyTraceProjection[], traceClock?: string);
|
|
44
|
+
handle(message: TraceFeedMessage): void;
|
|
45
|
+
/** Feeds records without a collector, for example the lines of a file or the records of a test. */
|
|
46
|
+
handleRecords(records: Iterable<TraceRecord>): void;
|
|
47
|
+
/** The view of a projection of this reader. */
|
|
48
|
+
view<State, View>(projection: TraceProjection<State, View>): View;
|
|
49
|
+
/** The state of a projection, typed for the call. Each state was created by the same projection. */
|
|
50
|
+
private stateOf;
|
|
51
|
+
reset(): void;
|
|
52
|
+
/** The event time of a record on the trace clock. */
|
|
53
|
+
timeOf(record: TraceRecord): {
|
|
54
|
+
time: number;
|
|
55
|
+
estimated: boolean;
|
|
56
|
+
};
|
|
57
|
+
private apply;
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/projections/types.d.ts
|
|
61
|
+
/** Indexes that every projection of one reader shares. The reader fills them before the projections run. */
|
|
62
|
+
interface TraceIndexes {
|
|
63
|
+
/** Records by source, epoch, and seq. */
|
|
64
|
+
byKey: RecordIndex;
|
|
65
|
+
/** The `span.begin` or `span.complete` record of each span ID. */
|
|
66
|
+
bySpanId: Map<string, TraceRecord>;
|
|
67
|
+
/** Records that link to a target, by target key: a record key, `span:<id>`, or `id:<key>=<value>`. */
|
|
68
|
+
linksTo: Map<string, TraceRecord[]>;
|
|
69
|
+
/** Records by `<id key>=<value>`. */
|
|
70
|
+
byId: Map<string, TraceRecord[]>;
|
|
71
|
+
}
|
|
72
|
+
interface TraceApplyContext {
|
|
73
|
+
/** The record came from the pinned set. */
|
|
74
|
+
pinned: boolean;
|
|
75
|
+
/** The record arrived after the watermark of its source. */
|
|
76
|
+
late: boolean;
|
|
77
|
+
/** The event time on the trace clock. Without a clock path, the observed time. */
|
|
78
|
+
time: number;
|
|
79
|
+
/** The time is estimated: a clock on the path has no measured latency, or no clock path exists. */
|
|
80
|
+
estimated: boolean;
|
|
81
|
+
indexes: TraceIndexes;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Turns records into view state.
|
|
85
|
+
*
|
|
86
|
+
* `handleRecord` is pure: no I/O, no clock, and no Vue refs. It tolerates orphans and duplicates. The state is plain
|
|
87
|
+
* objects and typed arrays, and `handleRecord` can mutate it in place for speed. A reader owns the state.
|
|
88
|
+
*/
|
|
89
|
+
interface TraceProjection<State, View = State> {
|
|
90
|
+
/** A stable key, for example `timeline`, `event-log`, or `voice.floor-transfer`. */
|
|
91
|
+
key: string;
|
|
92
|
+
reset: () => State;
|
|
93
|
+
handleRecord: (state: State, record: TraceRecord, context: TraceApplyContext) => State;
|
|
94
|
+
/** Points of a series from the collector backlog, on the trace clock. */
|
|
95
|
+
handleSeries?: (state: State, series: Extract<TraceFeedMessage, {
|
|
96
|
+
kind: 'series';
|
|
97
|
+
}>) => State;
|
|
98
|
+
/** The collector evicted records in this range of the trace clock. */
|
|
99
|
+
evict?: (state: State, range: {
|
|
100
|
+
from: number;
|
|
101
|
+
to: number;
|
|
102
|
+
}) => State;
|
|
103
|
+
finalize?: (state: State) => State;
|
|
104
|
+
select: (state: State) => View;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* A projection whose state the reader treats as opaque, so one reader holds projections of different states.
|
|
108
|
+
*
|
|
109
|
+
* The state parameters are `never`: under `strictFunctionTypes`, a function of any state can stand in for them. The
|
|
110
|
+
* reader only passes a state back to the projection that created it.
|
|
111
|
+
*/
|
|
112
|
+
interface AnyTraceProjection {
|
|
113
|
+
key: string;
|
|
114
|
+
reset: () => unknown;
|
|
115
|
+
handleRecord: (state: never, record: TraceRecord, context: TraceApplyContext) => unknown;
|
|
116
|
+
handleSeries?: (state: never, series: Extract<TraceFeedMessage, {
|
|
117
|
+
kind: 'series';
|
|
118
|
+
}>) => unknown;
|
|
119
|
+
evict?: (state: never, range: {
|
|
120
|
+
from: number;
|
|
121
|
+
to: number;
|
|
122
|
+
}) => unknown;
|
|
123
|
+
finalize?: (state: never) => unknown;
|
|
124
|
+
select: (state: never) => unknown;
|
|
125
|
+
}
|
|
126
|
+
interface TimelineInstant {
|
|
127
|
+
/** `source/epoch/seq` of the record. */
|
|
128
|
+
key: string;
|
|
129
|
+
name: string;
|
|
130
|
+
track: string;
|
|
131
|
+
time: number;
|
|
132
|
+
spanKey?: string;
|
|
133
|
+
ids?: TraceIds;
|
|
134
|
+
attrs?: TraceAttributes;
|
|
135
|
+
links?: TraceLink[];
|
|
136
|
+
/** The time was moved after its cause in the view. The stored record keeps its value. */
|
|
137
|
+
reordered?: boolean;
|
|
138
|
+
estimated?: boolean;
|
|
139
|
+
late?: boolean;
|
|
140
|
+
level?: 'debug' | 'info' | 'warn' | 'error';
|
|
141
|
+
}
|
|
142
|
+
interface TimelineSpan {
|
|
143
|
+
/** `source/epoch/spanId`. */
|
|
144
|
+
key: string;
|
|
145
|
+
spanId: string;
|
|
146
|
+
source: string;
|
|
147
|
+
epoch: string;
|
|
148
|
+
track: string;
|
|
149
|
+
name: string;
|
|
150
|
+
parentKey?: string;
|
|
151
|
+
/** Nesting depth among spans of the same track. */
|
|
152
|
+
depth: number;
|
|
153
|
+
/** Sub-lane at this depth. Assigned once, at begin. */
|
|
154
|
+
lane: number;
|
|
155
|
+
ids?: TraceIds;
|
|
156
|
+
/** Merged attributes of begin, updates, and end. Spans without attributes share one frozen empty object. */
|
|
157
|
+
attrs: TraceAttributes;
|
|
158
|
+
/** Spans without links share one frozen empty list. The projection replaces a list when it adds to it. */
|
|
159
|
+
links: readonly TraceLink[];
|
|
160
|
+
start: number;
|
|
161
|
+
end?: number;
|
|
162
|
+
status?: TraceStatus;
|
|
163
|
+
reason?: string;
|
|
164
|
+
message?: string;
|
|
165
|
+
deadlineMs?: number;
|
|
166
|
+
/** The source of the span stopped, was lost, or started a new epoch before the span ended. */
|
|
167
|
+
abandoned?: boolean;
|
|
168
|
+
/** The begin is missing. The span starts at the left edge of the reader window. */
|
|
169
|
+
startMissing?: boolean;
|
|
170
|
+
estimated?: boolean;
|
|
171
|
+
reordered?: boolean;
|
|
172
|
+
late?: boolean;
|
|
173
|
+
instants: readonly TimelineInstant[];
|
|
174
|
+
annotations: readonly TraceAnnotation[];
|
|
175
|
+
}
|
|
176
|
+
interface TimelineStateChange {
|
|
177
|
+
key: string;
|
|
178
|
+
track: string;
|
|
179
|
+
time: number;
|
|
180
|
+
value: string;
|
|
181
|
+
from?: string;
|
|
182
|
+
/** The `rule` attribute: the rule that decided the change. */
|
|
183
|
+
rule?: string;
|
|
184
|
+
links?: TraceLink[];
|
|
185
|
+
source: string;
|
|
186
|
+
/** A record from a source that does not own the state of the track. */
|
|
187
|
+
foreignOwner?: boolean;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* The points of one series. `times` and `values` are views of its ring. Read them again after the reader handles more
|
|
191
|
+
* records, because an append or a compaction replaces them.
|
|
192
|
+
*/
|
|
193
|
+
interface TimelineSeries {
|
|
194
|
+
readonly times: Float64Array;
|
|
195
|
+
readonly values: Float32Array;
|
|
196
|
+
/**
|
|
197
|
+
* Changes when points that a reader saw before change: a compaction, an expiry, or a late point. A cache that
|
|
198
|
+
* appends only new points starts again after a change.
|
|
199
|
+
*/
|
|
200
|
+
readonly revision: number;
|
|
201
|
+
}
|
|
202
|
+
/** Options of the timeline projection. */
|
|
203
|
+
interface TimelineProjectionOptions {
|
|
204
|
+
/**
|
|
205
|
+
* The retention of the series. A live viewer keeps the default, so a long session stays bounded. A file replay
|
|
206
|
+
* passes `false` and keeps every point.
|
|
207
|
+
* @default DEFAULT_SERIES_RETENTION
|
|
208
|
+
*/
|
|
209
|
+
seriesRetention?: SeriesRetention | false;
|
|
210
|
+
}
|
|
211
|
+
interface TimelineTrack {
|
|
212
|
+
path: string;
|
|
213
|
+
/** The track definition whose path pattern matches, if any. */
|
|
214
|
+
definition?: TraceTrackDefinition;
|
|
215
|
+
/** The `{key}` values of the matched pattern. */
|
|
216
|
+
params: Record<string, string>;
|
|
217
|
+
spans: TimelineSpan[];
|
|
218
|
+
instants: TimelineInstant[];
|
|
219
|
+
states: TimelineStateChange[];
|
|
220
|
+
/** Series points by value key, on the trace clock, in time order. */
|
|
221
|
+
series: Record<string, TimelineSeries>;
|
|
222
|
+
/** The busy end of each sub-lane at each depth. An open span keeps its lane busy until `Infinity`. */
|
|
223
|
+
lanes: number[][];
|
|
224
|
+
/** A span of the track ended with an error. The viewer keeps the track visible. */
|
|
225
|
+
hasError: boolean;
|
|
226
|
+
/** The source that owns the state of the track: the first source that wrote a state. */
|
|
227
|
+
stateOwner?: string;
|
|
228
|
+
}
|
|
229
|
+
/** A global marker: a lost source or a clock discontinuity. */
|
|
230
|
+
interface TimelineMarker {
|
|
231
|
+
kind: 'source-lost' | 'clock-discontinuity';
|
|
232
|
+
time: number;
|
|
233
|
+
label: string;
|
|
234
|
+
/** The end of a shaded band. A discontinuity without a later snapshot has none. */
|
|
235
|
+
until?: number;
|
|
236
|
+
}
|
|
237
|
+
interface TimelineSource {
|
|
238
|
+
source: string;
|
|
239
|
+
epoch: string;
|
|
240
|
+
runtime?: string;
|
|
241
|
+
live: boolean;
|
|
242
|
+
/** The newest event time. The watermark of the source trails it by the allowed lateness. */
|
|
243
|
+
newestTime: number;
|
|
244
|
+
}
|
|
245
|
+
interface TimelineState {
|
|
246
|
+
tracks: Map<string, TimelineTrack>;
|
|
247
|
+
spans: Map<string, TimelineSpan>;
|
|
248
|
+
definitions: Map<string, unknown>;
|
|
249
|
+
trackDefinitions: TraceTrackDefinition[];
|
|
250
|
+
markers: TimelineMarker[];
|
|
251
|
+
gaps: {
|
|
252
|
+
from: number;
|
|
253
|
+
to: number;
|
|
254
|
+
}[];
|
|
255
|
+
sources: Map<string, TimelineSource>;
|
|
256
|
+
/** Annotations whose target is a set of IDs, such as a conversation or a topic. */
|
|
257
|
+
annotations: TraceAnnotation[];
|
|
258
|
+
start: number;
|
|
259
|
+
end: number;
|
|
260
|
+
counters: {
|
|
261
|
+
records: number;
|
|
262
|
+
late: number;
|
|
263
|
+
orphanUpdates: number;
|
|
264
|
+
reordered: number;
|
|
265
|
+
};
|
|
266
|
+
/**
|
|
267
|
+
* Updates without their begin, by span key, with the time of the newest update. They wait for the begin for the
|
|
268
|
+
* allowed lateness, then they go. `counters.orphanUpdates` counts them.
|
|
269
|
+
*/
|
|
270
|
+
pendingUpdates: Map<string, {
|
|
271
|
+
attrs: TraceAttributes;
|
|
272
|
+
time: number;
|
|
273
|
+
}>;
|
|
274
|
+
/** The ring of each series, by track path and value key. `TimelineTrack.series` reads them. */
|
|
275
|
+
seriesRings: Map<string, SeriesRing>;
|
|
276
|
+
seriesRetention: SeriesRetention | false;
|
|
277
|
+
/** The `end` of the last series compaction. */
|
|
278
|
+
seriesCompactedAt: number;
|
|
279
|
+
}
|
|
280
|
+
interface EventLogEntry {
|
|
281
|
+
key: string;
|
|
282
|
+
time: number;
|
|
283
|
+
record: TraceRecord;
|
|
284
|
+
late?: boolean;
|
|
285
|
+
pinned?: boolean;
|
|
286
|
+
estimated?: boolean;
|
|
287
|
+
}
|
|
288
|
+
interface EventLogState {
|
|
289
|
+
entries: EventLogEntry[];
|
|
290
|
+
/** Keys of the entries, so a pinned copy and its buffered copy show once. */
|
|
291
|
+
keys: Set<string>;
|
|
292
|
+
/** Entries that the limit dropped. */
|
|
293
|
+
dropped: number;
|
|
294
|
+
}
|
|
295
|
+
/** One measurement. Censored, warm-up, and failed measurements are counted, but percentiles leave them out. */
|
|
296
|
+
interface MetricSample {
|
|
297
|
+
time: number;
|
|
298
|
+
value: number;
|
|
299
|
+
/** Dimension values, for example `{ from: 'user', to: 'airi' }`. */
|
|
300
|
+
dimensions?: Record<string, string>;
|
|
301
|
+
excluded?: 'censored' | 'warmup' | 'failed';
|
|
302
|
+
}
|
|
303
|
+
/** The samples of each metric key. A derived projection selects this shape too. */
|
|
304
|
+
type MetricSamples = Record<string, MetricSample[]>;
|
|
305
|
+
interface MetricSummary {
|
|
306
|
+
key: string;
|
|
307
|
+
definition?: TraceMetricDefinition;
|
|
308
|
+
values: Partial<Record<TraceAggregate, number>>;
|
|
309
|
+
count: number;
|
|
310
|
+
excluded: {
|
|
311
|
+
censored: number;
|
|
312
|
+
warmup: number;
|
|
313
|
+
failed: number;
|
|
314
|
+
};
|
|
315
|
+
/** The summary of each dimension combination, keyed by `value|value`. */
|
|
316
|
+
byDimension?: Record<string, Partial<Record<TraceAggregate, number>>>;
|
|
317
|
+
}
|
|
318
|
+
//#endregion
|
|
319
|
+
export { TraceIndexes as _, MetricSamples as a, TraceReader as b, TimelineMarker as c, TimelineSource as d, TimelineSpan as f, TraceApplyContext as g, TimelineTrack as h, MetricSample as i, TimelineProjectionOptions as l, TimelineStateChange as m, EventLogEntry as n, MetricSummary as o, TimelineState as p, EventLogState as r, TimelineInstant as s, AnyTraceProjection as t, TimelineSeries as u, TraceProjection as v, linkTargetKey as x, RecordIndex as y };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { L as TraceLink, b as TracePresetDefinition, v as TracePipelineDefinition, z as TraceRecord } from "../clock-CewQJzn8.mjs";
|
|
2
|
+
import { _ as TraceIndexes, a as MetricSamples, b as TraceReader, f as TimelineSpan, h as TimelineTrack, l as TimelineProjectionOptions, m as TimelineStateChange, p as TimelineState, r as EventLogState, s as TimelineInstant } from "../types-Fp54Yi6b.mjs";
|
|
3
|
+
//#region src/views/types.d.ts
|
|
4
|
+
/** What a click, a hover, or a selection points to: a span, an instant, or a state change, by its key. */
|
|
5
|
+
interface TraceItemRef {
|
|
6
|
+
kind: 'span' | 'instant' | 'state';
|
|
7
|
+
key: string;
|
|
8
|
+
}
|
|
9
|
+
/** The state of a pipeline stage instance at a time. */
|
|
10
|
+
type StageStatus = 'idle' | 'busy' | 'error' | string;
|
|
11
|
+
interface PipelineNode {
|
|
12
|
+
key: string;
|
|
13
|
+
stage: string;
|
|
14
|
+
/** The stage label of the profile in the requested locale, or the stage key. */
|
|
15
|
+
label: string;
|
|
16
|
+
instance?: string;
|
|
17
|
+
status: StageStatus;
|
|
18
|
+
/** Open spans of the stage at the time. */
|
|
19
|
+
open: TimelineSpan[];
|
|
20
|
+
/** The trace has a track of the stage. Without one, the status says nothing. */
|
|
21
|
+
observed: boolean;
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/views/lookup.d.ts
|
|
25
|
+
/** The span that a span ID names. The ID index gives its source and epoch. */
|
|
26
|
+
declare function spanOfId(state: TimelineState, indexes: TraceIndexes, spanId: string): TimelineSpan | undefined;
|
|
27
|
+
/** The spans of records, once each, in record order. A record without a span ID adds nothing. */
|
|
28
|
+
declare function spansOfRecords(state: TimelineState, records: readonly TraceRecord[]): TimelineSpan[];
|
|
29
|
+
/** The spans that a link points to: the span of a span ID, or every span with a domain ID value. */
|
|
30
|
+
declare function spansOfLink(link: TraceLink, state: TimelineState, indexes: TraceIndexes): TimelineSpan[];
|
|
31
|
+
/** The selection key of the item that a record belongs to: its span, or the record itself for an instant or a state. */
|
|
32
|
+
declare function itemOfRecord(record: TraceRecord): TraceItemRef | undefined;
|
|
33
|
+
/** The item of a reference and its track. Instants and states need a scan of the tracks. */
|
|
34
|
+
declare function findItem(state: TimelineState, ref: TraceItemRef): {
|
|
35
|
+
track?: TimelineTrack;
|
|
36
|
+
span?: TimelineSpan;
|
|
37
|
+
instant?: TimelineInstant;
|
|
38
|
+
change?: TimelineStateChange;
|
|
39
|
+
};
|
|
40
|
+
/** The spans that a span encloses, in start order. Only direct children. */
|
|
41
|
+
declare function childSpans(state: TimelineState, span: TimelineSpan): TimelineSpan[];
|
|
42
|
+
/** The input and output tokens of a model span. 0 for any other span. */
|
|
43
|
+
declare function spanTokens(span: TimelineSpan): number;
|
|
44
|
+
/**
|
|
45
|
+
* Keys of the records that relate to a span: spans that it links to, spans that link to it, and spans that share one
|
|
46
|
+
* of its narrow ID values, such as a turn or an input. The view dims every other item.
|
|
47
|
+
*/
|
|
48
|
+
declare function relatedSpanKeys(state: TimelineState, selected: TimelineSpan): Set<string>;
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region src/views/pipeline.d.ts
|
|
51
|
+
/**
|
|
52
|
+
* The nodes of a pipeline at time `at`: one node for each stage instance.
|
|
53
|
+
*
|
|
54
|
+
* A stage with a state track takes its latest state at or before `at`. Otherwise it is `busy` while a span is open,
|
|
55
|
+
* `error` when its latest span before `at` ended with an error, and `idle` otherwise.
|
|
56
|
+
*/
|
|
57
|
+
declare function pipelineNodes(state: TimelineState, pipeline: TracePipelineDefinition, at: number, locale: string): PipelineNode[];
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/views/reader.d.ts
|
|
60
|
+
/**
|
|
61
|
+
* A reader with the projections that the trace views read: the timeline, the event log, and the metrics. The IO tracer
|
|
62
|
+
* store and the stories read traces the same way.
|
|
63
|
+
*
|
|
64
|
+
* A live view keeps the default series retention. A file replay passes `{ seriesRetention: false }`.
|
|
65
|
+
*/
|
|
66
|
+
declare function createTraceViewReader(traceClock: string, options?: TimelineProjectionOptions): {
|
|
67
|
+
reader: TraceReader;
|
|
68
|
+
timelineView: () => TimelineState;
|
|
69
|
+
eventLogView: () => EventLogState;
|
|
70
|
+
metricSamples: () => MetricSamples;
|
|
71
|
+
};
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/views/tracks.d.ts
|
|
74
|
+
/**
|
|
75
|
+
* A stable color for a track path without a defined color.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* hashColor('plugin:minecraft/bots/b_2/planner')
|
|
79
|
+
* // => 'hsl(295 60% 55%)'
|
|
80
|
+
*/
|
|
81
|
+
declare function hashColor(text: string): string;
|
|
82
|
+
/** Whether a track matches a preset. A preset without tracks shows every track. */
|
|
83
|
+
declare function presetMatches(preset: TracePresetDefinition | undefined, path: string): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* What a track holds, for its label: the count of its items, and how many of its spans failed. An item is a span, or
|
|
86
|
+
* an instant or a state change on a track without spans.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* trackSummary(asrTrack)
|
|
90
|
+
* // => { items: 2, failed: 1 }
|
|
91
|
+
*/
|
|
92
|
+
declare function trackSummary(track: TimelineTrack): {
|
|
93
|
+
items: number;
|
|
94
|
+
failed: number;
|
|
95
|
+
};
|
|
96
|
+
//#endregion
|
|
97
|
+
export { PipelineNode, StageStatus, TraceItemRef, childSpans, createTraceViewReader, findItem, hashColor, itemOfRecord, pipelineNodes, presetMatches, relatedSpanKeys, spanOfId, spanTokens, spansOfLink, spansOfRecords, trackSummary };
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { K as localize, q as matchTrackPath } from "../conventions-DLiC8rkL.mjs";
|
|
2
|
+
import "../semconv.mjs";
|
|
3
|
+
import { n as recordKey, r as spanKeyOf } from "../keys-DD_VE8Fk.mjs";
|
|
4
|
+
import { a as TraceReader, l as createEventLogProjection, s as createAttributeMetricsProjection, t as createTimelineProjection } from "../timeline-B4Vc6qQf.mjs";
|
|
5
|
+
import { createFloorTransferProjection } from "../profiles/voice.mjs";
|
|
6
|
+
//#region src/views/lookup.ts
|
|
7
|
+
/** The span that a span ID names. The ID index gives its source and epoch. */
|
|
8
|
+
function spanOfId(state, indexes, spanId) {
|
|
9
|
+
const begin = indexes.bySpanId.get(spanId);
|
|
10
|
+
return begin ? state.spans.get(spanKeyOf(begin.source, begin.epoch, spanId)) : void 0;
|
|
11
|
+
}
|
|
12
|
+
/** The spans of records, once each, in record order. A record without a span ID adds nothing. */
|
|
13
|
+
function spansOfRecords(state, records) {
|
|
14
|
+
const spans = /* @__PURE__ */ new Map();
|
|
15
|
+
for (const record of records) {
|
|
16
|
+
if (!("spanId" in record) || !record.spanId) continue;
|
|
17
|
+
const span = state.spans.get(spanKeyOf(record.source, record.epoch, record.spanId));
|
|
18
|
+
if (span) spans.set(span.key, span);
|
|
19
|
+
}
|
|
20
|
+
return [...spans.values()];
|
|
21
|
+
}
|
|
22
|
+
/** The spans that a link points to: the span of a span ID, or every span with a domain ID value. */
|
|
23
|
+
function spansOfLink(link, state, indexes) {
|
|
24
|
+
if ("spanId" in link.to) {
|
|
25
|
+
const span = spanOfId(state, indexes, link.to.spanId);
|
|
26
|
+
return span ? [span] : [];
|
|
27
|
+
}
|
|
28
|
+
if ("key" in link.to) return spansOfRecords(state, indexes.byId.get(`${link.to.key}=${link.to.id}`) ?? []);
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
/** The selection key of the item that a record belongs to: its span, or the record itself for an instant or a state. */
|
|
32
|
+
function itemOfRecord(record) {
|
|
33
|
+
if (record.type === "span.begin" || record.type === "span.end" || record.type === "span.update" || record.type === "span.complete") return {
|
|
34
|
+
kind: "span",
|
|
35
|
+
key: spanKeyOf(record.source, record.epoch, record.spanId)
|
|
36
|
+
};
|
|
37
|
+
if (record.type === "instant" || record.type === "log") return {
|
|
38
|
+
kind: "instant",
|
|
39
|
+
key: recordKey(record)
|
|
40
|
+
};
|
|
41
|
+
if (record.type === "state") return {
|
|
42
|
+
kind: "state",
|
|
43
|
+
key: recordKey(record)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** The item of a reference and its track. Instants and states need a scan of the tracks. */
|
|
47
|
+
function findItem(state, ref) {
|
|
48
|
+
if (ref.kind === "span") {
|
|
49
|
+
const span = state.spans.get(ref.key);
|
|
50
|
+
return {
|
|
51
|
+
span,
|
|
52
|
+
track: span ? state.tracks.get(span.track) : void 0
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
for (const track of state.tracks.values()) if (ref.kind === "instant") {
|
|
56
|
+
const instant = track.instants.find((candidate) => candidate.key === ref.key);
|
|
57
|
+
if (instant) return {
|
|
58
|
+
track,
|
|
59
|
+
instant
|
|
60
|
+
};
|
|
61
|
+
} else {
|
|
62
|
+
const change = track.states.find((candidate) => candidate.key === ref.key);
|
|
63
|
+
if (change) return {
|
|
64
|
+
track,
|
|
65
|
+
change
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return {};
|
|
69
|
+
}
|
|
70
|
+
/** The spans that a span encloses, in start order. Only direct children. */
|
|
71
|
+
function childSpans(state, span) {
|
|
72
|
+
const children = [];
|
|
73
|
+
for (const candidate of state.spans.values()) if (candidate.parentKey === span.key) children.push(candidate);
|
|
74
|
+
return children.sort((a, b) => a.start - b.start);
|
|
75
|
+
}
|
|
76
|
+
/** The input and output tokens of a model span. 0 for any other span. */
|
|
77
|
+
function spanTokens(span) {
|
|
78
|
+
return Number(span.attrs["gen_ai.usage.input_tokens"] ?? 0) + Number(span.attrs["gen_ai.usage.output_tokens"] ?? 0);
|
|
79
|
+
}
|
|
80
|
+
/** ID keys that many unrelated spans share. They do not make two spans related. */
|
|
81
|
+
const BROAD_ID_KEYS = /* @__PURE__ */ new Set([
|
|
82
|
+
"actor",
|
|
83
|
+
"conversation",
|
|
84
|
+
"agent",
|
|
85
|
+
"topic"
|
|
86
|
+
]);
|
|
87
|
+
/**
|
|
88
|
+
* Keys of the records that relate to a span: spans that it links to, spans that link to it, and spans that share one
|
|
89
|
+
* of its narrow ID values, such as a turn or an input. The view dims every other item.
|
|
90
|
+
*/
|
|
91
|
+
function relatedSpanKeys(state, selected) {
|
|
92
|
+
const related = /* @__PURE__ */ new Set([selected.key]);
|
|
93
|
+
const targetIds = /* @__PURE__ */ new Set();
|
|
94
|
+
for (const [key, value] of Object.entries(selected.ids ?? {})) if (!BROAD_ID_KEYS.has(key)) targetIds.add(`${key}=${value}`);
|
|
95
|
+
for (const link of selected.links) if ("key" in link.to) targetIds.add(`${link.to.key}=${link.to.id}`);
|
|
96
|
+
for (const span of state.spans.values()) {
|
|
97
|
+
if (span.key === selected.key) continue;
|
|
98
|
+
const linksToSelected = span.links.some((link) => "spanId" in link.to && link.to.spanId === selected.spanId);
|
|
99
|
+
const selectedLinksTo = selected.links.some((link) => "spanId" in link.to && link.to.spanId === span.spanId);
|
|
100
|
+
const sharesId = Object.entries(span.ids ?? {}).some(([key, value]) => !BROAD_ID_KEYS.has(key) && targetIds.has(`${key}=${value}`));
|
|
101
|
+
if (linksToSelected || selectedLinksTo || sharesId || span.parentKey === selected.key || selected.parentKey === span.key) related.add(span.key);
|
|
102
|
+
}
|
|
103
|
+
return related;
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
//#region src/views/pipeline.ts
|
|
107
|
+
/**
|
|
108
|
+
* The nodes of a pipeline at time `at`: one node for each stage instance.
|
|
109
|
+
*
|
|
110
|
+
* A stage with a state track takes its latest state at or before `at`. Otherwise it is `busy` while a span is open,
|
|
111
|
+
* `error` when its latest span before `at` ended with an error, and `idle` otherwise.
|
|
112
|
+
*/
|
|
113
|
+
function pipelineNodes(state, pipeline, at, locale) {
|
|
114
|
+
const nodes = [];
|
|
115
|
+
for (const stage of pipeline.stages) {
|
|
116
|
+
const instances = /* @__PURE__ */ new Map();
|
|
117
|
+
for (const track of state.tracks.values()) for (const pattern of stage.tracks) {
|
|
118
|
+
const params = matchTrackPath(pattern, track.path);
|
|
119
|
+
if (!params) continue;
|
|
120
|
+
const instance = Object.values(params)[0] ?? "";
|
|
121
|
+
const list = instances.get(instance) ?? [];
|
|
122
|
+
list.push(track);
|
|
123
|
+
instances.set(instance, list);
|
|
124
|
+
}
|
|
125
|
+
if (instances.size === 0) instances.set("", []);
|
|
126
|
+
for (const [instance, tracks] of instances) {
|
|
127
|
+
let status = "idle";
|
|
128
|
+
const open = [];
|
|
129
|
+
let latestEnded;
|
|
130
|
+
let latestState;
|
|
131
|
+
for (const track of tracks) {
|
|
132
|
+
for (const change of track.states) if (change.time <= at && (!latestState || change.time >= latestState.time)) latestState = change;
|
|
133
|
+
for (const span of track.spans) {
|
|
134
|
+
if (span.start > at) continue;
|
|
135
|
+
if (span.end === void 0 || span.end > at) {
|
|
136
|
+
if (!span.abandoned) open.push(span);
|
|
137
|
+
} else if (!latestEnded || span.end > (latestEnded.end ?? 0)) latestEnded = span;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (latestState) status = latestState.value;
|
|
141
|
+
else if (open.length > 0) status = "busy";
|
|
142
|
+
else if (latestEnded?.status === "error") status = "error";
|
|
143
|
+
nodes.push({
|
|
144
|
+
key: `${stage.key}:${instance}`,
|
|
145
|
+
stage: stage.key,
|
|
146
|
+
label: localize(stage.label, locale) ?? stage.key,
|
|
147
|
+
instance: instance || void 0,
|
|
148
|
+
status,
|
|
149
|
+
open,
|
|
150
|
+
observed: tracks.length > 0
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return nodes;
|
|
155
|
+
}
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region src/views/reader.ts
|
|
158
|
+
/**
|
|
159
|
+
* A reader with the projections that the trace views read: the timeline, the event log, and the metrics. The IO tracer
|
|
160
|
+
* store and the stories read traces the same way.
|
|
161
|
+
*
|
|
162
|
+
* A live view keeps the default series retention. A file replay passes `{ seriesRetention: false }`.
|
|
163
|
+
*/
|
|
164
|
+
function createTraceViewReader(traceClock, options = {}) {
|
|
165
|
+
const timeline = createTimelineProjection(options);
|
|
166
|
+
const eventLog = createEventLogProjection();
|
|
167
|
+
const attributeMetrics = createAttributeMetricsProjection();
|
|
168
|
+
const floorTransfer = createFloorTransferProjection();
|
|
169
|
+
const reader = new TraceReader([
|
|
170
|
+
timeline,
|
|
171
|
+
eventLog,
|
|
172
|
+
attributeMetrics,
|
|
173
|
+
floorTransfer
|
|
174
|
+
], traceClock);
|
|
175
|
+
return {
|
|
176
|
+
reader,
|
|
177
|
+
timelineView: () => reader.view(timeline),
|
|
178
|
+
eventLogView: () => reader.view(eventLog),
|
|
179
|
+
metricSamples: () => ({
|
|
180
|
+
...reader.view(attributeMetrics),
|
|
181
|
+
...reader.view(floorTransfer)
|
|
182
|
+
})
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region src/views/tracks.ts
|
|
187
|
+
/**
|
|
188
|
+
* A stable color for a track path without a defined color.
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* hashColor('plugin:minecraft/bots/b_2/planner')
|
|
192
|
+
* // => 'hsl(295 60% 55%)'
|
|
193
|
+
*/
|
|
194
|
+
function hashColor(text) {
|
|
195
|
+
let hash = 0;
|
|
196
|
+
for (const char of text) hash = hash * 31 + char.charCodeAt(0) | 0;
|
|
197
|
+
return `hsl(${25 + Math.abs(hash) % 300} 60% 55%)`;
|
|
198
|
+
}
|
|
199
|
+
/** Whether a track matches a preset. A preset without tracks shows every track. */
|
|
200
|
+
function presetMatches(preset, path) {
|
|
201
|
+
if (!preset || preset.tracks.length === 0) return true;
|
|
202
|
+
return preset.tracks.some((pattern) => matchTrackPath(pattern, path) !== void 0);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* What a track holds, for its label: the count of its items, and how many of its spans failed. An item is a span, or
|
|
206
|
+
* an instant or a state change on a track without spans.
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* trackSummary(asrTrack)
|
|
210
|
+
* // => { items: 2, failed: 1 }
|
|
211
|
+
*/
|
|
212
|
+
function trackSummary(track) {
|
|
213
|
+
return {
|
|
214
|
+
items: track.spans.length || track.instants.length || track.states.length,
|
|
215
|
+
failed: track.spans.reduce((count, span) => count + (span.status === "error" ? 1 : 0), 0)
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
//#endregion
|
|
219
|
+
export { childSpans, createTraceViewReader, findItem, hashColor, itemOfRecord, pipelineNodes, presetMatches, relatedSpanKeys, spanOfId, spanTokens, spansOfLink, spansOfRecords, trackSummary };
|