@fractaal/pi-telemetry 0.86.9 → 1.6.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.
package/dist/memory.d.ts CHANGED
@@ -1,11 +1,20 @@
1
- import type { SpanAttributes, SpanOptions, SpanStatus, TelemetryContext, TelemetrySpan } from "./index.ts";
1
+ import type { MetricQuery, SpanAttributes, SpanOptions, SpanStatus, StoredMetric, StoredTrace, TelemetryCarrier, TelemetryContext, TelemetryPropagation, TelemetrySpan, TelemetryStore, TraceQuery } from "./index.ts";
2
+ import type { HistogramOptions, InstrumentOptions, TelemetryCounter, TelemetryHistogram, TelemetryMetrics, TelemetryUpDownCounter } from "./metrics.ts";
2
3
  export interface RecordedTelemetryEvent {
3
4
  readonly name: string;
4
5
  readonly attributes: Readonly<SpanAttributes>;
5
6
  }
7
+ export interface RecordedTelemetryLink {
8
+ readonly context: Readonly<TelemetryCarrier>;
9
+ readonly attributes: Readonly<SpanAttributes>;
10
+ }
6
11
  export interface RecordedTelemetrySpan {
7
12
  readonly id: number;
13
+ /** Local parent ID, or null for roots and parents owned by another recorder. */
8
14
  readonly parentId: number | null;
15
+ readonly context: Readonly<TelemetryCarrier>;
16
+ readonly parentContext: Readonly<TelemetryCarrier> | null;
17
+ readonly links: readonly RecordedTelemetryLink[];
9
18
  readonly name: string;
10
19
  readonly attributes: Readonly<SpanAttributes>;
11
20
  readonly events: readonly RecordedTelemetryEvent[];
@@ -13,13 +22,49 @@ export interface RecordedTelemetrySpan {
13
22
  readonly settled: boolean;
14
23
  readonly endSequence?: number;
15
24
  }
25
+ export interface RecordedTelemetryMeasurement {
26
+ readonly kind: "counter" | "upDownCounter" | "histogram";
27
+ readonly name: string;
28
+ readonly description?: string;
29
+ readonly unit?: string;
30
+ readonly boundaries?: readonly number[];
31
+ readonly value: number;
32
+ readonly attributes: Readonly<SpanAttributes>;
33
+ readonly context: Readonly<TelemetryCarrier> | null;
34
+ }
35
+ /**
36
+ * Now as milliseconds since the epoch, rounded to the microsecond: `performance.now()` (monotonic, sub-millisecond)
37
+ * plus an anchor to the wall clock. While the two agree within 10 ms, times in one process keep their order and
38
+ * spacing to the microsecond; past that the clock follows `Date.now()` again, at whole milliseconds. Every adapter
39
+ * of this package and Chord's SQLite store stamp span starts with it, so their times agree.
40
+ */
41
+ export declare function telemetryNow(): number;
16
42
  /**
17
43
  * Backend-neutral reference implementation that records spans in process memory.
18
44
  * Create a fresh instance to isolate tests or independent recording scopes.
19
45
  */
20
- export declare class InMemoryTelemetryContext implements TelemetryContext {
46
+ export declare class InMemoryTelemetryContext implements TelemetryContext, TelemetryPropagation, TelemetryMetrics, TelemetryStore {
47
+ readonly metrics: TelemetryMetrics;
48
+ readonly propagation: TelemetryPropagation;
21
49
  private readonly state;
22
50
  startSpan<T>(options: SpanOptions, callback: (span: TelemetrySpan) => T | Promise<T>): Promise<T>;
51
+ /** Returns a detached carrier for a known span or extracted parent, including settled spans. */
52
+ inject(context: TelemetryContext): TelemetryCarrier | undefined;
53
+ /** Missing or non-string carrier identities fall back to this recorder's root context. */
54
+ extract(carrier: TelemetryCarrier | undefined): TelemetryContext;
55
+ counter(name: string, options?: InstrumentOptions): TelemetryCounter;
56
+ upDownCounter(name: string, options?: InstrumentOptions): TelemetryUpDownCounter;
57
+ histogram(name: string, options?: HistogramOptions): TelemetryHistogram;
58
+ private storedSpans;
59
+ getTrace(traceId: string): Promise<StoredTrace | undefined>;
60
+ findTraces(query?: TraceQuery): Promise<{
61
+ traces: readonly StoredTrace[];
62
+ cursor?: string;
63
+ }>;
64
+ /** Read raw measurements as count-one rows, without changing getMetrics() snapshots. */
65
+ findMetrics(query: MetricQuery): Promise<readonly StoredMetric[]>;
66
+ /** Returns detached measurements in recording order, without aggregation. */
67
+ getMetrics(): readonly RecordedTelemetryMeasurement[];
23
68
  /** Returns detached snapshots in span-start order. */
24
69
  getSpans(): readonly RecordedTelemetrySpan[];
25
70
  }
@@ -1 +1 @@
1
- {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEX,cAAc,EACd,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IAC9C,QAAQ,CAAC,MAAM,EAAE,SAAS,sBAAsB,EAAE,CAAC;IACnD,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AAmKD;;;GAGG;AACH,qBAAa,wBAAyB,YAAW,gBAAgB;IAChE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAIpB;IAEF,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAEhG;IAED,sDAAsD;IACtD,QAAQ,IAAI,SAAS,qBAAqB,EAAE,CAc3C;CACD"}
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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"}
package/dist/memory.js CHANGED
@@ -1,24 +1,44 @@
1
1
  import { NOOP_TELEMETRY_CONTEXT } from "./noop.js";
2
- function copyAttributeValue(value) {
3
- return Array.isArray(value) ? [...value] : value;
2
+ function carrierId(carrier) {
3
+ return `${carrier["pi-memory-scope"]}:${carrier["pi-memory-span"]}`;
4
4
  }
5
+ // The clock of span times: wall-clock milliseconds at microsecond resolution, from the monotonic high-resolution
6
+ // clock anchored to the wall clock (`telemetryNow`, also Chord's SQLite store's).
7
+ /**
8
+ * How far the anchored clock may part from `Date.now()` before it is anchored anew: more than `Date.now()`'s own
9
+ * truncation to whole milliseconds, less than any step worth following (a wall clock set, a sleep the monotonic clock
10
+ * did not count).
11
+ */
12
+ const TOLERANCE_MS = 10;
13
+ /** The wall-clock time of `performance.now()`'s zero; `performance.timeOrigin` until the first step is followed. */
14
+ let anchor = performance.timeOrigin;
15
+ /**
16
+ * Now as milliseconds since the epoch, rounded to the microsecond: `performance.now()` (monotonic, sub-millisecond)
17
+ * plus an anchor to the wall clock. While the two agree within 10 ms, times in one process keep their order and
18
+ * spacing to the microsecond; past that the clock follows `Date.now()` again, at whole milliseconds. Every adapter
19
+ * of this package and Chord's SQLite store stamp span starts with it, so their times agree.
20
+ */
21
+ export function telemetryNow() {
22
+ const clock = performance.now();
23
+ const wall = Date.now();
24
+ if (Math.abs(anchor + clock - wall) > TOLERANCE_MS)
25
+ anchor = wall - clock;
26
+ return microseconds(anchor + clock);
27
+ }
28
+ /** `ms` rounded to the microsecond, as span times are. */
29
+ function microseconds(ms) {
30
+ return Math.round(ms * 1000) / 1000;
31
+ }
32
+ // Identity survives settlement without exposing backend IDs on the generic context contract.
33
+ const contextCarriers = new WeakMap();
5
34
  function copyAttributes(attributes) {
6
- const copy = {};
7
- if (!attributes)
8
- return copy;
9
- for (const [name, value] of Object.entries(attributes)) {
10
- if (value !== undefined)
11
- copy[name] = copyAttributeValue(value);
12
- }
13
- return copy;
35
+ return Object.fromEntries(Object.entries(attributes ?? {})
36
+ .filter(([, value]) => value !== undefined)
37
+ .map(([name, value]) => [name, Array.isArray(value) ? [...value] : value]));
14
38
  }
15
- function mergeAttributes(current, attributes) {
16
- const merged = copyAttributes(current);
17
- for (const [name, value] of Object.entries(attributes)) {
18
- if (value !== undefined)
19
- merged[name] = copyAttributeValue(value);
20
- }
21
- return merged;
39
+ function copyLink(link) {
40
+ const context = contextCarriers.get(link.context);
41
+ return context ? { context: { ...context }, attributes: copyAttributes(link.attributes) } : undefined;
22
42
  }
23
43
  function copyStatus(status) {
24
44
  if (status.status === "ok")
@@ -27,31 +47,28 @@ function copyStatus(status) {
27
47
  ? { status: "error", error: { name: status.error.name, message: status.error.message } }
28
48
  : { status: "error" };
29
49
  }
30
- function automaticErrorStatus(error) {
31
- try {
32
- if (error instanceof Error) {
33
- return { status: "error", error: { name: error.name, message: error.message } };
34
- }
35
- }
36
- catch {
37
- // Error inspection is passive. Fall through to an error status without details.
38
- }
39
- return { status: "error" };
40
- }
41
- function settleSpan(state, span, failed, error) {
42
- if (span.settled)
43
- return;
44
- if (failed && !span.explicitStatus)
45
- span.status = automaticErrorStatus(error);
46
- span.settled = true;
47
- span.endSequence = state.nextEndSequence++;
48
- }
49
50
  function createSpan(state, parent, options) {
50
51
  const name = options.name;
51
52
  const attributes = copyAttributes(options.attributes);
53
+ const links = [];
54
+ for (const link of options.links ?? []) {
55
+ const copy = copyLink(link);
56
+ if (copy)
57
+ links.push(copy);
58
+ }
59
+ const id = state.nextSpanId++;
52
60
  return {
53
- id: state.nextSpanId++,
54
- parentId: parent?.id ?? null,
61
+ startedMs: telemetryNow(),
62
+ clock: performance.now(),
63
+ id,
64
+ parentId: parent?.localId ?? null,
65
+ context: {
66
+ "pi-memory-scope": state.scope,
67
+ "pi-memory-span": String(id),
68
+ "pi-memory-trace": parent?.context["pi-memory-trace"] ?? `${state.scope}:${id}`,
69
+ },
70
+ parentContext: parent ? { ...parent.context } : null,
71
+ links,
55
72
  name,
56
73
  attributes,
57
74
  events: [],
@@ -60,85 +77,243 @@ function createSpan(state, parent, options) {
60
77
  settled: false,
61
78
  };
62
79
  }
63
- function startInMemorySpan(state, parent, options, callback) {
64
- if (parent?.settled)
65
- return NOOP_TELEMETRY_CONTEXT.startSpan(options, callback);
66
- let recordedSpan;
67
- try {
68
- recordedSpan = createSpan(state, parent, options);
69
- state.spans.push(recordedSpan);
70
- }
71
- catch {
72
- return NOOP_TELEMETRY_CONTEXT.startSpan(options, callback);
73
- }
80
+ function startInertSpan(state, options, callback) {
81
+ return NOOP_TELEMETRY_CONTEXT.startSpan(options, (noop) => callback({
82
+ ...noop,
83
+ metrics: state.metrics,
84
+ propagation: state.propagation,
85
+ startSpan: (childOptions, childCallback) => startInertSpan(state, childOptions, childCallback),
86
+ }));
87
+ }
88
+ async function startInMemorySpan(state, parent, options, callback) {
89
+ if (parent?.span?.settled)
90
+ return startInertSpan(state, options, callback);
91
+ const recordedSpan = createSpan(state, parent, options);
92
+ state.spans.push(recordedSpan);
74
93
  const span = {
75
- startSpan: (childOptions, childCallback) => startInMemorySpan(state, recordedSpan, childOptions, childCallback),
94
+ metrics: state.metrics,
95
+ propagation: state.propagation,
96
+ startSpan: (childOptions, childCallback) => startInMemorySpan(state, { context: recordedSpan.context, localId: recordedSpan.id, span: recordedSpan }, childOptions, childCallback),
97
+ addLink(link) {
98
+ if (recordedSpan.settled)
99
+ return;
100
+ const copy = copyLink(link);
101
+ if (copy)
102
+ recordedSpan.links.push(copy);
103
+ },
76
104
  addEvent(name, attributes) {
77
105
  if (recordedSpan.settled)
78
106
  return;
79
- try {
80
- recordedSpan.events.push({ name, attributes: copyAttributes(attributes) });
81
- }
82
- catch {
83
- // Recording is passive. Ignore malformed or unreadable telemetry payloads.
84
- }
107
+ recordedSpan.events.push({
108
+ name,
109
+ timeMs: microseconds(performance.now() - recordedSpan.clock),
110
+ attributes: copyAttributes(attributes),
111
+ });
85
112
  },
86
113
  setAttributes(attributes) {
87
114
  if (recordedSpan.settled)
88
115
  return;
89
- try {
90
- recordedSpan.attributes = mergeAttributes(recordedSpan.attributes, attributes);
91
- }
92
- catch {
93
- // Recording is passive. Ignore malformed or unreadable telemetry payloads.
94
- }
116
+ recordedSpan.attributes = { ...recordedSpan.attributes, ...copyAttributes(attributes) };
95
117
  },
96
118
  setStatus(status) {
97
119
  if (recordedSpan.settled)
98
120
  return;
99
- try {
100
- recordedSpan.status = copyStatus(status);
101
- recordedSpan.explicitStatus = true;
102
- }
103
- catch {
104
- // Recording is passive. Ignore malformed or unreadable telemetry payloads.
105
- }
121
+ recordedSpan.status = copyStatus(status);
122
+ recordedSpan.explicitStatus = true;
106
123
  },
107
124
  };
108
- let result;
125
+ contextCarriers.set(span, recordedSpan.context);
109
126
  try {
110
- result = callback(span);
127
+ return await callback(span);
111
128
  }
112
129
  catch (error) {
113
- settleSpan(state, recordedSpan, true, error);
114
- return Promise.reject(error);
115
- }
116
- return Promise.resolve(result).then((value) => {
117
- settleSpan(state, recordedSpan, false);
118
- return value;
119
- }, (error) => {
120
- settleSpan(state, recordedSpan, true, error);
130
+ if (!recordedSpan.explicitStatus)
131
+ recordedSpan.status =
132
+ error instanceof Error
133
+ ? { status: "error", error: { name: error.name, message: error.message } }
134
+ : { status: "error" };
121
135
  throw error;
122
- });
136
+ }
137
+ finally {
138
+ recordedSpan.settled = true;
139
+ recordedSpan.endedMs = microseconds(recordedSpan.startedMs + performance.now() - recordedSpan.clock);
140
+ recordedSpan.endSequence = state.nextEndSequence++;
141
+ }
142
+ }
143
+ function createMeasurementRecorder(state, kind, name, options) {
144
+ const description = options?.description;
145
+ const unit = options?.unit;
146
+ const boundaries = kind === "histogram" && options?.boundaries !== undefined ? [...options.boundaries] : undefined;
147
+ const metadata = {
148
+ kind,
149
+ name,
150
+ ...(description === undefined ? {} : { description }),
151
+ ...(unit === undefined ? {} : { unit }),
152
+ ...(boundaries === undefined ? {} : { boundaries }),
153
+ };
154
+ return (value, attributes, context) => {
155
+ const carrier = context === undefined ? undefined : contextCarriers.get(context);
156
+ state.measurements.push({
157
+ intervalMs: Math.floor(Date.now() / 10_000) * 10_000,
158
+ measurement: {
159
+ ...metadata,
160
+ value,
161
+ attributes: copyAttributes(attributes),
162
+ context: carrier ? { ...carrier } : null,
163
+ },
164
+ });
165
+ };
123
166
  }
124
167
  /**
125
168
  * Backend-neutral reference implementation that records spans in process memory.
126
169
  * Create a fresh instance to isolate tests or independent recording scopes.
127
170
  */
128
171
  export class InMemoryTelemetryContext {
172
+ metrics = this;
173
+ propagation = this;
129
174
  state = {
175
+ metrics: this,
176
+ propagation: this,
177
+ scope: crypto.randomUUID(),
130
178
  spans: [],
179
+ measurements: [],
131
180
  nextSpanId: 1,
132
181
  nextEndSequence: 1,
133
182
  };
134
183
  startSpan(options, callback) {
135
184
  return startInMemorySpan(this.state, undefined, options, callback);
136
185
  }
186
+ /** Returns a detached carrier for a known span or extracted parent, including settled spans. */
187
+ inject(context) {
188
+ const carrier = contextCarriers.get(context);
189
+ return carrier ? { ...carrier } : undefined;
190
+ }
191
+ /** Missing or non-string carrier identities fall back to this recorder's root context. */
192
+ extract(carrier) {
193
+ const scope = carrier?.["pi-memory-scope"];
194
+ const span = carrier?.["pi-memory-span"];
195
+ const traceId = carrier?.["pi-memory-trace"];
196
+ if (typeof scope !== "string" || typeof span !== "string" || typeof traceId !== "string")
197
+ return this;
198
+ const context = { "pi-memory-scope": scope, "pi-memory-span": span, "pi-memory-trace": traceId };
199
+ const localId = scope === this.state.scope ? Number(span) : null;
200
+ const parent = {
201
+ metrics: this,
202
+ propagation: this,
203
+ startSpan: (options, callback) => startInMemorySpan(this.state, { context, localId }, options, callback),
204
+ };
205
+ contextCarriers.set(parent, context);
206
+ return parent;
207
+ }
208
+ counter(name, options) {
209
+ return { add: createMeasurementRecorder(this.state, "counter", name, options) };
210
+ }
211
+ upDownCounter(name, options) {
212
+ return { add: createMeasurementRecorder(this.state, "upDownCounter", name, options) };
213
+ }
214
+ histogram(name, options) {
215
+ return { record: createMeasurementRecorder(this.state, "histogram", name, options) };
216
+ }
217
+ storedSpans() {
218
+ return this.state.spans
219
+ .filter((span) => span.settled)
220
+ .map((span) => ({
221
+ id: carrierId(span.context),
222
+ traceId: span.context["pi-memory-trace"],
223
+ ...(span.parentContext ? { parentId: carrierId(span.parentContext) } : {}),
224
+ name: span.name,
225
+ startedMs: span.startedMs,
226
+ endedMs: span.endedMs,
227
+ attributes: copyAttributes(span.attributes),
228
+ events: span.events.map((event) => ({
229
+ name: event.name,
230
+ timeMs: event.timeMs,
231
+ attributes: copyAttributes(event.attributes),
232
+ })),
233
+ links: span.links.map((link) => ({
234
+ traceId: link.context["pi-memory-trace"],
235
+ spanId: carrierId(link.context),
236
+ attributes: copyAttributes(link.attributes),
237
+ })),
238
+ status: copyStatus(span.status),
239
+ }))
240
+ .sort((a, b) => a.startedMs - b.startedMs || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
241
+ }
242
+ async getTrace(traceId) {
243
+ const spans = this.storedSpans().filter((span) => span.traceId === traceId);
244
+ return spans.length ? { traceId, spans } : undefined;
245
+ }
246
+ async findTraces(query = {}) {
247
+ const limit = query.limit ?? 20;
248
+ const after = query.cursor === undefined ? undefined : JSON.parse(query.cursor);
249
+ const grouped = new Map();
250
+ for (const span of this.storedSpans()) {
251
+ let trace = grouped.get(span.traceId);
252
+ if (!trace) {
253
+ trace = { traceId: span.traceId, spans: [] };
254
+ grouped.set(span.traceId, trace);
255
+ }
256
+ trace.spans.push(span);
257
+ }
258
+ const matches = [...grouped.values()]
259
+ .filter((trace) => {
260
+ const first = trace.spans[0];
261
+ return ((query.name === undefined || first.name === query.name) &&
262
+ (query.startMin === undefined || first.startedMs >= query.startMin) &&
263
+ (query.startMax === undefined || first.startedMs <= query.startMax) &&
264
+ (!after || first.startedMs < after[0] || (first.startedMs === after[0] && trace.traceId > after[1])) &&
265
+ (!query.errors || trace.spans.some((span) => span.status.status === "error")) &&
266
+ (!query.attributes ||
267
+ trace.spans.some((span) => Object.entries(query.attributes).every(([key, value]) => span.attributes[key] === value))));
268
+ })
269
+ .sort((a, b) => b.spans[0].startedMs - a.spans[0].startedMs ||
270
+ (a.traceId < b.traceId ? -1 : a.traceId > b.traceId ? 1 : 0));
271
+ const traces = matches.slice(0, limit);
272
+ const last = traces.at(-1);
273
+ return {
274
+ traces,
275
+ ...(matches.length > limit ? { cursor: JSON.stringify([last.spans[0].startedMs, last.traceId]) } : {}),
276
+ };
277
+ }
278
+ /** Read raw measurements as count-one rows, without changing getMetrics() snapshots. */
279
+ async findMetrics(query) {
280
+ return this.state.measurements
281
+ .filter(({ intervalMs, measurement }) => measurement.name === query.name &&
282
+ (query.startMin === undefined || intervalMs >= query.startMin) &&
283
+ (query.startMax === undefined || intervalMs <= query.startMax) &&
284
+ Object.entries(query.attributes ?? {}).every(([key, value]) => measurement.attributes[key] === value))
285
+ .map(({ intervalMs, measurement }) => ({
286
+ intervalMs,
287
+ name: measurement.name,
288
+ kind: measurement.kind,
289
+ ...(measurement.unit === undefined ? {} : { unit: measurement.unit }),
290
+ attributes: copyAttributes(measurement.attributes),
291
+ count: 1,
292
+ sum: measurement.value,
293
+ min: measurement.value,
294
+ max: measurement.value,
295
+ }));
296
+ }
297
+ /** Returns detached measurements in recording order, without aggregation. */
298
+ getMetrics() {
299
+ return this.state.measurements.map(({ measurement }) => ({
300
+ ...measurement,
301
+ ...(measurement.boundaries === undefined ? {} : { boundaries: [...measurement.boundaries] }),
302
+ attributes: copyAttributes(measurement.attributes),
303
+ context: measurement.context ? { ...measurement.context } : null,
304
+ }));
305
+ }
137
306
  /** Returns detached snapshots in span-start order. */
138
307
  getSpans() {
139
308
  return this.state.spans.map((span) => ({
140
309
  id: span.id,
141
310
  parentId: span.parentId,
311
+ context: { ...span.context },
312
+ parentContext: span.parentContext ? { ...span.parentContext } : null,
313
+ links: span.links.map((link) => ({
314
+ context: { ...link.context },
315
+ attributes: copyAttributes(link.attributes),
316
+ })),
142
317
  name: span.name,
143
318
  attributes: copyAttributes(span.attributes),
144
319
  events: span.events.map((event) => ({
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tAttributeValue,\n\tSpanAttributes,\n\tSpanOptions,\n\tSpanStatus,\n\tTelemetryContext,\n\tTelemetrySpan,\n} from \"./index.ts\";\nimport { NOOP_TELEMETRY_CONTEXT } from \"./noop.ts\";\n\nexport interface RecordedTelemetryEvent {\n\treadonly name: string;\n\treadonly attributes: Readonly<SpanAttributes>;\n}\n\nexport interface RecordedTelemetrySpan {\n\treadonly id: number;\n\treadonly parentId: number | null;\n\treadonly name: string;\n\treadonly attributes: Readonly<SpanAttributes>;\n\treadonly events: readonly RecordedTelemetryEvent[];\n\treadonly status: SpanStatus;\n\treadonly settled: boolean;\n\treadonly endSequence?: number;\n}\n\ninterface MutableRecordedTelemetryEvent {\n\tname: string;\n\tattributes: SpanAttributes;\n}\n\ninterface MutableRecordedTelemetrySpan {\n\tid: number;\n\tparentId: number | null;\n\tname: string;\n\tattributes: SpanAttributes;\n\tevents: MutableRecordedTelemetryEvent[];\n\tstatus: SpanStatus;\n\texplicitStatus: boolean;\n\tsettled: boolean;\n\tendSequence?: number;\n}\n\ninterface InMemoryTelemetryState {\n\tspans: MutableRecordedTelemetrySpan[];\n\tnextSpanId: number;\n\tnextEndSequence: number;\n}\n\nfunction copyAttributeValue(value: AttributeValue): AttributeValue {\n\treturn Array.isArray(value) ? ([...value] as AttributeValue) : value;\n}\n\nfunction copyAttributes(attributes?: SpanAttributes): SpanAttributes {\n\tconst copy: SpanAttributes = {};\n\tif (!attributes) return copy;\n\tfor (const [name, value] of Object.entries(attributes)) {\n\t\tif (value !== undefined) copy[name] = copyAttributeValue(value);\n\t}\n\treturn copy;\n}\n\nfunction mergeAttributes(current: SpanAttributes, attributes: SpanAttributes): SpanAttributes {\n\tconst merged = copyAttributes(current);\n\tfor (const [name, value] of Object.entries(attributes)) {\n\t\tif (value !== undefined) merged[name] = copyAttributeValue(value);\n\t}\n\treturn merged;\n}\n\nfunction copyStatus(status: SpanStatus): SpanStatus {\n\tif (status.status === \"ok\") return { status: \"ok\" };\n\treturn status.error\n\t\t? { status: \"error\", error: { name: status.error.name, message: status.error.message } }\n\t\t: { status: \"error\" };\n}\n\nfunction automaticErrorStatus(error: unknown): SpanStatus {\n\ttry {\n\t\tif (error instanceof Error) {\n\t\t\treturn { status: \"error\", error: { name: error.name, message: error.message } };\n\t\t}\n\t} catch {\n\t\t// Error inspection is passive. Fall through to an error status without details.\n\t}\n\treturn { status: \"error\" };\n}\n\nfunction settleSpan(\n\tstate: InMemoryTelemetryState,\n\tspan: MutableRecordedTelemetrySpan,\n\tfailed: boolean,\n\terror?: unknown,\n): void {\n\tif (span.settled) return;\n\tif (failed && !span.explicitStatus) span.status = automaticErrorStatus(error);\n\tspan.settled = true;\n\tspan.endSequence = state.nextEndSequence++;\n}\n\nfunction createSpan(\n\tstate: InMemoryTelemetryState,\n\tparent: MutableRecordedTelemetrySpan | undefined,\n\toptions: SpanOptions,\n): MutableRecordedTelemetrySpan {\n\tconst name = options.name;\n\tconst attributes = copyAttributes(options.attributes);\n\treturn {\n\t\tid: state.nextSpanId++,\n\t\tparentId: parent?.id ?? null,\n\t\tname,\n\t\tattributes,\n\t\tevents: [],\n\t\tstatus: { status: \"ok\" },\n\t\texplicitStatus: false,\n\t\tsettled: false,\n\t};\n}\n\nfunction startInMemorySpan<T>(\n\tstate: InMemoryTelemetryState,\n\tparent: MutableRecordedTelemetrySpan | undefined,\n\toptions: SpanOptions,\n\tcallback: (span: TelemetrySpan) => T | Promise<T>,\n): Promise<T> {\n\tif (parent?.settled) return NOOP_TELEMETRY_CONTEXT.startSpan(options, callback);\n\n\tlet recordedSpan: MutableRecordedTelemetrySpan;\n\ttry {\n\t\trecordedSpan = createSpan(state, parent, options);\n\t\tstate.spans.push(recordedSpan);\n\t} catch {\n\t\treturn NOOP_TELEMETRY_CONTEXT.startSpan(options, callback);\n\t}\n\n\tconst span: TelemetrySpan = {\n\t\tstartSpan: <Result>(\n\t\t\tchildOptions: SpanOptions,\n\t\t\tchildCallback: (child: TelemetrySpan) => Result | Promise<Result>,\n\t\t) => startInMemorySpan(state, recordedSpan, childOptions, childCallback),\n\t\taddEvent(name, attributes) {\n\t\t\tif (recordedSpan.settled) return;\n\t\t\ttry {\n\t\t\t\trecordedSpan.events.push({ name, attributes: copyAttributes(attributes) });\n\t\t\t} catch {\n\t\t\t\t// Recording is passive. Ignore malformed or unreadable telemetry payloads.\n\t\t\t}\n\t\t},\n\t\tsetAttributes(attributes) {\n\t\t\tif (recordedSpan.settled) return;\n\t\t\ttry {\n\t\t\t\trecordedSpan.attributes = mergeAttributes(recordedSpan.attributes, attributes);\n\t\t\t} catch {\n\t\t\t\t// Recording is passive. Ignore malformed or unreadable telemetry payloads.\n\t\t\t}\n\t\t},\n\t\tsetStatus(status) {\n\t\t\tif (recordedSpan.settled) return;\n\t\t\ttry {\n\t\t\t\trecordedSpan.status = copyStatus(status);\n\t\t\t\trecordedSpan.explicitStatus = true;\n\t\t\t} catch {\n\t\t\t\t// Recording is passive. Ignore malformed or unreadable telemetry payloads.\n\t\t\t}\n\t\t},\n\t};\n\n\tlet result: T | Promise<T>;\n\ttry {\n\t\tresult = callback(span);\n\t} catch (error) {\n\t\tsettleSpan(state, recordedSpan, true, error);\n\t\treturn Promise.reject(error);\n\t}\n\n\treturn Promise.resolve(result).then(\n\t\t(value) => {\n\t\t\tsettleSpan(state, recordedSpan, false);\n\t\t\treturn value;\n\t\t},\n\t\t(error: unknown) => {\n\t\t\tsettleSpan(state, recordedSpan, true, error);\n\t\t\tthrow error;\n\t\t},\n\t);\n}\n\n/**\n * Backend-neutral reference implementation that records spans in process memory.\n * Create a fresh instance to isolate tests or independent recording scopes.\n */\nexport class InMemoryTelemetryContext implements TelemetryContext {\n\tprivate readonly state: InMemoryTelemetryState = {\n\t\tspans: [],\n\t\tnextSpanId: 1,\n\t\tnextEndSequence: 1,\n\t};\n\n\tstartSpan<T>(options: SpanOptions, callback: (span: TelemetrySpan) => T | Promise<T>): Promise<T> {\n\t\treturn startInMemorySpan(this.state, undefined, options, callback);\n\t}\n\n\t/** Returns detached snapshots in span-start order. */\n\tgetSpans(): readonly RecordedTelemetrySpan[] {\n\t\treturn this.state.spans.map((span) => ({\n\t\t\tid: span.id,\n\t\t\tparentId: span.parentId,\n\t\t\tname: span.name,\n\t\t\tattributes: copyAttributes(span.attributes),\n\t\t\tevents: span.events.map((event) => ({\n\t\t\t\tname: event.name,\n\t\t\t\tattributes: copyAttributes(event.attributes),\n\t\t\t})),\n\t\t\tstatus: copyStatus(span.status),\n\t\t\tsettled: span.settled,\n\t\t\t...(span.endSequence === undefined ? {} : { endSequence: span.endSequence }),\n\t\t}));\n\t}\n}\n"]}
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tMetricQuery,\n\tSpanAttributes,\n\tSpanLink,\n\tSpanOptions,\n\tSpanStatus,\n\tStoredMetric,\n\tStoredSpan,\n\tStoredTrace,\n\tTelemetryCarrier,\n\tTelemetryContext,\n\tTelemetryPropagation,\n\tTelemetrySpan,\n\tTelemetryStore,\n\tTraceQuery,\n} from \"./index.ts\";\nimport type {\n\tHistogramOptions,\n\tInstrumentOptions,\n\tTelemetryCounter,\n\tTelemetryHistogram,\n\tTelemetryMetrics,\n\tTelemetryUpDownCounter,\n} from \"./metrics.ts\";\nimport { NOOP_TELEMETRY_CONTEXT } from \"./noop.ts\";\n\nexport interface RecordedTelemetryEvent {\n\treadonly name: string;\n\treadonly attributes: Readonly<SpanAttributes>;\n}\n\nexport interface RecordedTelemetryLink {\n\treadonly context: Readonly<TelemetryCarrier>;\n\treadonly attributes: Readonly<SpanAttributes>;\n}\n\nexport interface RecordedTelemetrySpan {\n\treadonly id: number;\n\t/** Local parent ID, or null for roots and parents owned by another recorder. */\n\treadonly parentId: number | null;\n\treadonly context: Readonly<TelemetryCarrier>;\n\treadonly parentContext: Readonly<TelemetryCarrier> | null;\n\treadonly links: readonly RecordedTelemetryLink[];\n\treadonly name: string;\n\treadonly attributes: Readonly<SpanAttributes>;\n\treadonly events: readonly RecordedTelemetryEvent[];\n\treadonly status: SpanStatus;\n\treadonly settled: boolean;\n\treadonly endSequence?: number;\n}\n\nexport interface RecordedTelemetryMeasurement {\n\treadonly kind: \"counter\" | \"upDownCounter\" | \"histogram\";\n\treadonly name: string;\n\treadonly description?: string;\n\treadonly unit?: string;\n\treadonly boundaries?: readonly number[];\n\treadonly value: number;\n\treadonly attributes: Readonly<SpanAttributes>;\n\treadonly context: Readonly<TelemetryCarrier> | null;\n}\n\ninterface MutableRecordedTelemetryEvent {\n\ttimeMs: number;\n\tname: string;\n\tattributes: SpanAttributes;\n}\n\ninterface MutableRecordedTelemetrySpan {\n\tstartedMs: number;\n\tclock: number;\n\tendedMs?: number;\n\tid: number;\n\tparentId: number | null;\n\tcontext: TelemetryCarrier;\n\tparentContext: TelemetryCarrier | null;\n\tlinks: RecordedTelemetryLink[];\n\tname: string;\n\tattributes: SpanAttributes;\n\tevents: MutableRecordedTelemetryEvent[];\n\tstatus: SpanStatus;\n\texplicitStatus: boolean;\n\tsettled: boolean;\n\tendSequence?: number;\n}\n\ninterface InMemoryParent {\n\tcontext: TelemetryCarrier;\n\tlocalId: number | null;\n\tspan?: MutableRecordedTelemetrySpan;\n}\n\nfunction carrierId(carrier: Readonly<TelemetryCarrier>): string {\n\treturn `${carrier[\"pi-memory-scope\"]}:${carrier[\"pi-memory-span\"]}`;\n}\n\n// The clock of span times: wall-clock milliseconds at microsecond resolution, from the monotonic high-resolution\n// clock anchored to the wall clock (`telemetryNow`, also Chord's SQLite store's).\n\n/**\n * How far the anchored clock may part from `Date.now()` before it is anchored anew: more than `Date.now()`'s own\n * truncation to whole milliseconds, less than any step worth following (a wall clock set, a sleep the monotonic clock\n * did not count).\n */\nconst TOLERANCE_MS = 10;\n\n/** The wall-clock time of `performance.now()`'s zero; `performance.timeOrigin` until the first step is followed. */\nlet anchor = performance.timeOrigin;\n\n/**\n * Now as milliseconds since the epoch, rounded to the microsecond: `performance.now()` (monotonic, sub-millisecond)\n * plus an anchor to the wall clock. While the two agree within 10 ms, times in one process keep their order and\n * spacing to the microsecond; past that the clock follows `Date.now()` again, at whole milliseconds. Every adapter\n * of this package and Chord's SQLite store stamp span starts with it, so their times agree.\n */\nexport function telemetryNow(): number {\n\tconst clock = performance.now();\n\tconst wall = Date.now();\n\tif (Math.abs(anchor + clock - wall) > TOLERANCE_MS) anchor = wall - clock;\n\treturn microseconds(anchor + clock);\n}\n\n/** `ms` rounded to the microsecond, as span times are. */\nfunction microseconds(ms: number): number {\n\treturn Math.round(ms * 1000) / 1000;\n}\n\n// Identity survives settlement without exposing backend IDs on the generic context contract.\nconst contextCarriers = new WeakMap<TelemetryContext, TelemetryCarrier>();\n\ninterface InMemoryTelemetryState {\n\tmetrics: TelemetryMetrics;\n\tpropagation: TelemetryPropagation;\n\tscope: string;\n\tspans: MutableRecordedTelemetrySpan[];\n\tmeasurements: { intervalMs: number; measurement: RecordedTelemetryMeasurement }[];\n\tnextSpanId: number;\n\tnextEndSequence: number;\n}\n\nfunction copyAttributes(attributes?: SpanAttributes): SpanAttributes {\n\treturn Object.fromEntries(\n\t\tObject.entries(attributes ?? {})\n\t\t\t.filter(([, value]) => value !== undefined)\n\t\t\t.map(([name, value]) => [name, Array.isArray(value) ? [...value] : value]),\n\t);\n}\n\nfunction copyLink(link: SpanLink): RecordedTelemetryLink | undefined {\n\tconst context = contextCarriers.get(link.context);\n\treturn context ? { context: { ...context }, attributes: copyAttributes(link.attributes) } : undefined;\n}\n\nfunction copyStatus(status: SpanStatus): SpanStatus {\n\tif (status.status === \"ok\") return { status: \"ok\" };\n\treturn status.error\n\t\t? { status: \"error\", error: { name: status.error.name, message: status.error.message } }\n\t\t: { status: \"error\" };\n}\n\nfunction createSpan(\n\tstate: InMemoryTelemetryState,\n\tparent: InMemoryParent | undefined,\n\toptions: SpanOptions,\n): MutableRecordedTelemetrySpan {\n\tconst name = options.name;\n\tconst attributes = copyAttributes(options.attributes);\n\tconst links: RecordedTelemetryLink[] = [];\n\tfor (const link of options.links ?? []) {\n\t\tconst copy = copyLink(link);\n\t\tif (copy) links.push(copy);\n\t}\n\tconst id = state.nextSpanId++;\n\treturn {\n\t\tstartedMs: telemetryNow(),\n\t\tclock: performance.now(),\n\t\tid,\n\t\tparentId: parent?.localId ?? null,\n\t\tcontext: {\n\t\t\t\"pi-memory-scope\": state.scope,\n\t\t\t\"pi-memory-span\": String(id),\n\t\t\t\"pi-memory-trace\": parent?.context[\"pi-memory-trace\"] ?? `${state.scope}:${id}`,\n\t\t},\n\t\tparentContext: parent ? { ...parent.context } : null,\n\t\tlinks,\n\t\tname,\n\t\tattributes,\n\t\tevents: [],\n\t\tstatus: { status: \"ok\" },\n\t\texplicitStatus: false,\n\t\tsettled: false,\n\t};\n}\n\nfunction startInertSpan<T>(\n\tstate: InMemoryTelemetryState,\n\toptions: SpanOptions,\n\tcallback: (span: TelemetrySpan) => T | Promise<T>,\n): Promise<T> {\n\treturn NOOP_TELEMETRY_CONTEXT.startSpan(options, (noop) =>\n\t\tcallback({\n\t\t\t...noop,\n\t\t\tmetrics: state.metrics,\n\t\t\tpropagation: state.propagation,\n\t\t\tstartSpan: <Result>(\n\t\t\t\tchildOptions: SpanOptions,\n\t\t\t\tchildCallback: (span: TelemetrySpan) => Result | Promise<Result>,\n\t\t\t) => startInertSpan(state, childOptions, childCallback),\n\t\t}),\n\t);\n}\n\nasync function startInMemorySpan<T>(\n\tstate: InMemoryTelemetryState,\n\tparent: InMemoryParent | undefined,\n\toptions: SpanOptions,\n\tcallback: (span: TelemetrySpan) => T | Promise<T>,\n): Promise<T> {\n\tif (parent?.span?.settled) return startInertSpan(state, options, callback);\n\n\tconst recordedSpan = createSpan(state, parent, options);\n\tstate.spans.push(recordedSpan);\n\n\tconst span: TelemetrySpan = {\n\t\tmetrics: state.metrics,\n\t\tpropagation: state.propagation,\n\t\tstartSpan: <Result>(\n\t\t\tchildOptions: SpanOptions,\n\t\t\tchildCallback: (child: TelemetrySpan) => Result | Promise<Result>,\n\t\t) =>\n\t\t\tstartInMemorySpan(\n\t\t\t\tstate,\n\t\t\t\t{ context: recordedSpan.context, localId: recordedSpan.id, span: recordedSpan },\n\t\t\t\tchildOptions,\n\t\t\t\tchildCallback,\n\t\t\t),\n\t\taddLink(link) {\n\t\t\tif (recordedSpan.settled) return;\n\t\t\tconst copy = copyLink(link);\n\t\t\tif (copy) recordedSpan.links.push(copy);\n\t\t},\n\t\taddEvent(name, attributes) {\n\t\t\tif (recordedSpan.settled) return;\n\t\t\trecordedSpan.events.push({\n\t\t\t\tname,\n\t\t\t\ttimeMs: microseconds(performance.now() - recordedSpan.clock),\n\t\t\t\tattributes: copyAttributes(attributes),\n\t\t\t});\n\t\t},\n\t\tsetAttributes(attributes) {\n\t\t\tif (recordedSpan.settled) return;\n\t\t\trecordedSpan.attributes = { ...recordedSpan.attributes, ...copyAttributes(attributes) };\n\t\t},\n\t\tsetStatus(status) {\n\t\t\tif (recordedSpan.settled) return;\n\t\t\trecordedSpan.status = copyStatus(status);\n\t\t\trecordedSpan.explicitStatus = true;\n\t\t},\n\t};\n\n\tcontextCarriers.set(span, recordedSpan.context);\n\n\ttry {\n\t\treturn await callback(span);\n\t} catch (error) {\n\t\tif (!recordedSpan.explicitStatus)\n\t\t\trecordedSpan.status =\n\t\t\t\terror instanceof Error\n\t\t\t\t\t? { status: \"error\", error: { name: error.name, message: error.message } }\n\t\t\t\t\t: { status: \"error\" };\n\t\tthrow error;\n\t} finally {\n\t\trecordedSpan.settled = true;\n\t\trecordedSpan.endedMs = microseconds(recordedSpan.startedMs + performance.now() - recordedSpan.clock);\n\t\trecordedSpan.endSequence = state.nextEndSequence++;\n\t}\n}\n\nfunction createMeasurementRecorder(\n\tstate: InMemoryTelemetryState,\n\tkind: RecordedTelemetryMeasurement[\"kind\"],\n\tname: string,\n\toptions?: HistogramOptions,\n): (value: number, attributes?: SpanAttributes, context?: TelemetryContext) => void {\n\tconst description = options?.description;\n\tconst unit = options?.unit;\n\tconst boundaries = kind === \"histogram\" && options?.boundaries !== undefined ? [...options.boundaries] : undefined;\n\tconst metadata = {\n\t\tkind,\n\t\tname,\n\t\t...(description === undefined ? {} : { description }),\n\t\t...(unit === undefined ? {} : { unit }),\n\t\t...(boundaries === undefined ? {} : { boundaries }),\n\t};\n\treturn (value, attributes, context) => {\n\t\tconst carrier = context === undefined ? undefined : contextCarriers.get(context);\n\t\tstate.measurements.push({\n\t\t\tintervalMs: Math.floor(Date.now() / 10_000) * 10_000,\n\t\t\tmeasurement: {\n\t\t\t\t...metadata,\n\t\t\t\tvalue,\n\t\t\t\tattributes: copyAttributes(attributes),\n\t\t\t\tcontext: carrier ? { ...carrier } : null,\n\t\t\t},\n\t\t});\n\t};\n}\n\n/**\n * Backend-neutral reference implementation that records spans in process memory.\n * Create a fresh instance to isolate tests or independent recording scopes.\n */\nexport class InMemoryTelemetryContext\n\timplements TelemetryContext, TelemetryPropagation, TelemetryMetrics, TelemetryStore\n{\n\treadonly metrics: TelemetryMetrics = this;\n\treadonly propagation: TelemetryPropagation = this;\n\tprivate readonly state: InMemoryTelemetryState = {\n\t\tmetrics: this,\n\t\tpropagation: this,\n\t\tscope: crypto.randomUUID(),\n\t\tspans: [],\n\t\tmeasurements: [],\n\t\tnextSpanId: 1,\n\t\tnextEndSequence: 1,\n\t};\n\n\tstartSpan<T>(options: SpanOptions, callback: (span: TelemetrySpan) => T | Promise<T>): Promise<T> {\n\t\treturn startInMemorySpan(this.state, undefined, options, callback);\n\t}\n\n\t/** Returns a detached carrier for a known span or extracted parent, including settled spans. */\n\tinject(context: TelemetryContext): TelemetryCarrier | undefined {\n\t\tconst carrier = contextCarriers.get(context);\n\t\treturn carrier ? { ...carrier } : undefined;\n\t}\n\n\t/** Missing or non-string carrier identities fall back to this recorder's root context. */\n\textract(carrier: TelemetryCarrier | undefined): TelemetryContext {\n\t\tconst scope = carrier?.[\"pi-memory-scope\"];\n\t\tconst span = carrier?.[\"pi-memory-span\"];\n\t\tconst traceId = carrier?.[\"pi-memory-trace\"];\n\t\tif (typeof scope !== \"string\" || typeof span !== \"string\" || typeof traceId !== \"string\") return this;\n\t\tconst context = { \"pi-memory-scope\": scope, \"pi-memory-span\": span, \"pi-memory-trace\": traceId };\n\t\tconst localId = scope === this.state.scope ? Number(span) : null;\n\t\tconst parent: TelemetryContext = {\n\t\t\tmetrics: this,\n\t\t\tpropagation: this,\n\t\t\tstartSpan: <T>(options: SpanOptions, callback: (span: TelemetrySpan) => T | Promise<T>) =>\n\t\t\t\tstartInMemorySpan(this.state, { context, localId }, options, callback),\n\t\t};\n\t\tcontextCarriers.set(parent, context);\n\t\treturn parent;\n\t}\n\n\tcounter(name: string, options?: InstrumentOptions): TelemetryCounter {\n\t\treturn { add: createMeasurementRecorder(this.state, \"counter\", name, options) };\n\t}\n\n\tupDownCounter(name: string, options?: InstrumentOptions): TelemetryUpDownCounter {\n\t\treturn { add: createMeasurementRecorder(this.state, \"upDownCounter\", name, options) };\n\t}\n\n\thistogram(name: string, options?: HistogramOptions): TelemetryHistogram {\n\t\treturn { record: createMeasurementRecorder(this.state, \"histogram\", name, options) };\n\t}\n\n\tprivate storedSpans(): StoredSpan[] {\n\t\treturn this.state.spans\n\t\t\t.filter((span) => span.settled)\n\t\t\t.map((span) => ({\n\t\t\t\tid: carrierId(span.context),\n\t\t\t\ttraceId: span.context[\"pi-memory-trace\"]!,\n\t\t\t\t...(span.parentContext ? { parentId: carrierId(span.parentContext) } : {}),\n\t\t\t\tname: span.name,\n\t\t\t\tstartedMs: span.startedMs,\n\t\t\t\tendedMs: span.endedMs!,\n\t\t\t\tattributes: copyAttributes(span.attributes),\n\t\t\t\tevents: span.events.map((event) => ({\n\t\t\t\t\tname: event.name,\n\t\t\t\t\ttimeMs: event.timeMs,\n\t\t\t\t\tattributes: copyAttributes(event.attributes),\n\t\t\t\t})),\n\t\t\t\tlinks: span.links.map((link) => ({\n\t\t\t\t\ttraceId: link.context[\"pi-memory-trace\"]!,\n\t\t\t\t\tspanId: carrierId(link.context),\n\t\t\t\t\tattributes: copyAttributes(link.attributes),\n\t\t\t\t})),\n\t\t\t\tstatus: copyStatus(span.status),\n\t\t\t}))\n\t\t\t.sort((a, b) => a.startedMs - b.startedMs || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));\n\t}\n\n\tasync getTrace(traceId: string): Promise<StoredTrace | undefined> {\n\t\tconst spans = this.storedSpans().filter((span) => span.traceId === traceId);\n\t\treturn spans.length ? { traceId, spans } : undefined;\n\t}\n\n\tasync findTraces(query: TraceQuery = {}): Promise<{ traces: readonly StoredTrace[]; cursor?: string }> {\n\t\tconst limit = query.limit ?? 20;\n\t\tconst after = query.cursor === undefined ? undefined : (JSON.parse(query.cursor) as [number, string]);\n\t\tconst grouped = new Map<string, { traceId: string; spans: StoredSpan[] }>();\n\t\tfor (const span of this.storedSpans()) {\n\t\t\tlet trace = grouped.get(span.traceId);\n\t\t\tif (!trace) {\n\t\t\t\ttrace = { traceId: span.traceId, spans: [] };\n\t\t\t\tgrouped.set(span.traceId, trace);\n\t\t\t}\n\t\t\ttrace.spans.push(span);\n\t\t}\n\t\tconst matches = [...grouped.values()]\n\t\t\t.filter((trace) => {\n\t\t\t\tconst first = trace.spans[0]!;\n\t\t\t\treturn (\n\t\t\t\t\t(query.name === undefined || first.name === query.name) &&\n\t\t\t\t\t(query.startMin === undefined || first.startedMs >= query.startMin) &&\n\t\t\t\t\t(query.startMax === undefined || first.startedMs <= query.startMax) &&\n\t\t\t\t\t(!after || first.startedMs < after[0] || (first.startedMs === after[0] && trace.traceId > after[1])) &&\n\t\t\t\t\t(!query.errors || trace.spans.some((span) => span.status.status === \"error\")) &&\n\t\t\t\t\t(!query.attributes ||\n\t\t\t\t\t\ttrace.spans.some((span) =>\n\t\t\t\t\t\t\tObject.entries(query.attributes!).every(([key, value]) => span.attributes[key] === value),\n\t\t\t\t\t\t))\n\t\t\t\t);\n\t\t\t})\n\t\t\t.sort(\n\t\t\t\t(a, b) =>\n\t\t\t\t\tb.spans[0]!.startedMs - a.spans[0]!.startedMs ||\n\t\t\t\t\t(a.traceId < b.traceId ? -1 : a.traceId > b.traceId ? 1 : 0),\n\t\t\t);\n\t\tconst traces = matches.slice(0, limit);\n\t\tconst last = traces.at(-1)!;\n\t\treturn {\n\t\t\ttraces,\n\t\t\t...(matches.length > limit ? { cursor: JSON.stringify([last.spans[0]!.startedMs, last.traceId]) } : {}),\n\t\t};\n\t}\n\n\t/** Read raw measurements as count-one rows, without changing getMetrics() snapshots. */\n\tasync findMetrics(query: MetricQuery): Promise<readonly StoredMetric[]> {\n\t\treturn this.state.measurements\n\t\t\t.filter(\n\t\t\t\t({ intervalMs, measurement }) =>\n\t\t\t\t\tmeasurement.name === query.name &&\n\t\t\t\t\t(query.startMin === undefined || intervalMs >= query.startMin) &&\n\t\t\t\t\t(query.startMax === undefined || intervalMs <= query.startMax) &&\n\t\t\t\t\tObject.entries(query.attributes ?? {}).every(([key, value]) => measurement.attributes[key] === value),\n\t\t\t)\n\t\t\t.map(({ intervalMs, measurement }) => ({\n\t\t\t\tintervalMs,\n\t\t\t\tname: measurement.name,\n\t\t\t\tkind: measurement.kind,\n\t\t\t\t...(measurement.unit === undefined ? {} : { unit: measurement.unit }),\n\t\t\t\tattributes: copyAttributes(measurement.attributes),\n\t\t\t\tcount: 1,\n\t\t\t\tsum: measurement.value,\n\t\t\t\tmin: measurement.value,\n\t\t\t\tmax: measurement.value,\n\t\t\t}));\n\t}\n\n\t/** Returns detached measurements in recording order, without aggregation. */\n\tgetMetrics(): readonly RecordedTelemetryMeasurement[] {\n\t\treturn this.state.measurements.map(({ measurement }) => ({\n\t\t\t...measurement,\n\t\t\t...(measurement.boundaries === undefined ? {} : { boundaries: [...measurement.boundaries] }),\n\t\t\tattributes: copyAttributes(measurement.attributes),\n\t\t\tcontext: measurement.context ? { ...measurement.context } : null,\n\t\t}));\n\t}\n\n\t/** Returns detached snapshots in span-start order. */\n\tgetSpans(): readonly RecordedTelemetrySpan[] {\n\t\treturn this.state.spans.map((span) => ({\n\t\t\tid: span.id,\n\t\t\tparentId: span.parentId,\n\t\t\tcontext: { ...span.context },\n\t\t\tparentContext: span.parentContext ? { ...span.parentContext } : null,\n\t\t\tlinks: span.links.map((link) => ({\n\t\t\t\tcontext: { ...link.context },\n\t\t\t\tattributes: copyAttributes(link.attributes),\n\t\t\t})),\n\t\t\tname: span.name,\n\t\t\tattributes: copyAttributes(span.attributes),\n\t\t\tevents: span.events.map((event) => ({\n\t\t\t\tname: event.name,\n\t\t\t\tattributes: copyAttributes(event.attributes),\n\t\t\t})),\n\t\t\tstatus: copyStatus(span.status),\n\t\t\tsettled: span.settled,\n\t\t\t...(span.endSequence === undefined ? {} : { endSequence: span.endSequence }),\n\t\t}));\n\t}\n}\n"]}