@fractaal/pi-telemetry 0.86.8 → 1.4.1

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,42 @@ 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
+ }
16
35
  /**
17
36
  * Backend-neutral reference implementation that records spans in process memory.
18
37
  * Create a fresh instance to isolate tests or independent recording scopes.
19
38
  */
20
- export declare class InMemoryTelemetryContext implements TelemetryContext {
39
+ export declare class InMemoryTelemetryContext implements TelemetryContext, TelemetryPropagation, TelemetryMetrics, TelemetryStore {
40
+ readonly metrics: TelemetryMetrics;
41
+ readonly propagation: TelemetryPropagation;
21
42
  private readonly state;
22
43
  startSpan<T>(options: SpanOptions, callback: (span: TelemetrySpan) => T | Promise<T>): Promise<T>;
44
+ /** Returns a detached carrier for a known span or extracted parent, including settled spans. */
45
+ inject(context: TelemetryContext): TelemetryCarrier | undefined;
46
+ /** Missing or non-string carrier identities fall back to this recorder's root context. */
47
+ extract(carrier: TelemetryCarrier | undefined): TelemetryContext;
48
+ counter(name: string, options?: InstrumentOptions): TelemetryCounter;
49
+ upDownCounter(name: string, options?: InstrumentOptions): TelemetryUpDownCounter;
50
+ histogram(name: string, options?: HistogramOptions): TelemetryHistogram;
51
+ private storedSpans;
52
+ getTrace(traceId: string): Promise<StoredTrace | undefined>;
53
+ findTraces(query?: TraceQuery): Promise<{
54
+ traces: readonly StoredTrace[];
55
+ cursor?: string;
56
+ }>;
57
+ /** Read raw measurements as count-one rows, without changing getMetrics() snapshots. */
58
+ findMetrics(query: MetricQuery): Promise<readonly StoredMetric[]>;
59
+ /** Returns detached measurements in recording order, without aggregation. */
60
+ getMetrics(): readonly RecordedTelemetryMeasurement[];
23
61
  /** Returns detached snapshots in span-start order. */
24
62
  getSpans(): readonly RecordedTelemetrySpan[];
25
63
  }
@@ -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,17 @@
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
+ // Identity survives settlement without exposing backend IDs on the generic context contract.
6
+ const contextCarriers = new WeakMap();
5
7
  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;
8
+ return Object.fromEntries(Object.entries(attributes ?? {})
9
+ .filter(([, value]) => value !== undefined)
10
+ .map(([name, value]) => [name, Array.isArray(value) ? [...value] : value]));
14
11
  }
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;
12
+ function copyLink(link) {
13
+ const context = contextCarriers.get(link.context);
14
+ return context ? { context: { ...context }, attributes: copyAttributes(link.attributes) } : undefined;
22
15
  }
23
16
  function copyStatus(status) {
24
17
  if (status.status === "ok")
@@ -27,31 +20,28 @@ function copyStatus(status) {
27
20
  ? { status: "error", error: { name: status.error.name, message: status.error.message } }
28
21
  : { status: "error" };
29
22
  }
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
23
  function createSpan(state, parent, options) {
50
24
  const name = options.name;
51
25
  const attributes = copyAttributes(options.attributes);
26
+ const links = [];
27
+ for (const link of options.links ?? []) {
28
+ const copy = copyLink(link);
29
+ if (copy)
30
+ links.push(copy);
31
+ }
32
+ const id = state.nextSpanId++;
52
33
  return {
53
- id: state.nextSpanId++,
54
- parentId: parent?.id ?? null,
34
+ startedMs: Date.now(),
35
+ clock: performance.now(),
36
+ id,
37
+ parentId: parent?.localId ?? null,
38
+ context: {
39
+ "pi-memory-scope": state.scope,
40
+ "pi-memory-span": String(id),
41
+ "pi-memory-trace": parent?.context["pi-memory-trace"] ?? `${state.scope}:${id}`,
42
+ },
43
+ parentContext: parent ? { ...parent.context } : null,
44
+ links,
55
45
  name,
56
46
  attributes,
57
47
  events: [],
@@ -60,85 +50,243 @@ function createSpan(state, parent, options) {
60
50
  settled: false,
61
51
  };
62
52
  }
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
- }
53
+ function startInertSpan(state, options, callback) {
54
+ return NOOP_TELEMETRY_CONTEXT.startSpan(options, (noop) => callback({
55
+ ...noop,
56
+ metrics: state.metrics,
57
+ propagation: state.propagation,
58
+ startSpan: (childOptions, childCallback) => startInertSpan(state, childOptions, childCallback),
59
+ }));
60
+ }
61
+ async function startInMemorySpan(state, parent, options, callback) {
62
+ if (parent?.span?.settled)
63
+ return startInertSpan(state, options, callback);
64
+ const recordedSpan = createSpan(state, parent, options);
65
+ state.spans.push(recordedSpan);
74
66
  const span = {
75
- startSpan: (childOptions, childCallback) => startInMemorySpan(state, recordedSpan, childOptions, childCallback),
67
+ metrics: state.metrics,
68
+ propagation: state.propagation,
69
+ startSpan: (childOptions, childCallback) => startInMemorySpan(state, { context: recordedSpan.context, localId: recordedSpan.id, span: recordedSpan }, childOptions, childCallback),
70
+ addLink(link) {
71
+ if (recordedSpan.settled)
72
+ return;
73
+ const copy = copyLink(link);
74
+ if (copy)
75
+ recordedSpan.links.push(copy);
76
+ },
76
77
  addEvent(name, attributes) {
77
78
  if (recordedSpan.settled)
78
79
  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
- }
80
+ recordedSpan.events.push({
81
+ name,
82
+ timeMs: performance.now() - recordedSpan.clock,
83
+ attributes: copyAttributes(attributes),
84
+ });
85
85
  },
86
86
  setAttributes(attributes) {
87
87
  if (recordedSpan.settled)
88
88
  return;
89
- try {
90
- recordedSpan.attributes = mergeAttributes(recordedSpan.attributes, attributes);
91
- }
92
- catch {
93
- // Recording is passive. Ignore malformed or unreadable telemetry payloads.
94
- }
89
+ recordedSpan.attributes = { ...recordedSpan.attributes, ...copyAttributes(attributes) };
95
90
  },
96
91
  setStatus(status) {
97
92
  if (recordedSpan.settled)
98
93
  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
- }
94
+ recordedSpan.status = copyStatus(status);
95
+ recordedSpan.explicitStatus = true;
106
96
  },
107
97
  };
108
- let result;
98
+ contextCarriers.set(span, recordedSpan.context);
109
99
  try {
110
- result = callback(span);
100
+ return await callback(span);
111
101
  }
112
102
  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);
103
+ if (!recordedSpan.explicitStatus)
104
+ recordedSpan.status =
105
+ error instanceof Error
106
+ ? { status: "error", error: { name: error.name, message: error.message } }
107
+ : { status: "error" };
121
108
  throw error;
122
- });
109
+ }
110
+ finally {
111
+ recordedSpan.settled = true;
112
+ recordedSpan.endedMs = recordedSpan.startedMs + performance.now() - recordedSpan.clock;
113
+ recordedSpan.endSequence = state.nextEndSequence++;
114
+ }
115
+ }
116
+ function createMeasurementRecorder(state, kind, name, options) {
117
+ const description = options?.description;
118
+ const unit = options?.unit;
119
+ const boundaries = kind === "histogram" && options?.boundaries !== undefined ? [...options.boundaries] : undefined;
120
+ const metadata = {
121
+ kind,
122
+ name,
123
+ ...(description === undefined ? {} : { description }),
124
+ ...(unit === undefined ? {} : { unit }),
125
+ ...(boundaries === undefined ? {} : { boundaries }),
126
+ };
127
+ return (value, attributes, context) => {
128
+ const carrier = context === undefined ? undefined : contextCarriers.get(context);
129
+ state.measurements.push({
130
+ intervalMs: Math.floor(Date.now() / 10_000) * 10_000,
131
+ measurement: {
132
+ ...metadata,
133
+ value,
134
+ attributes: copyAttributes(attributes),
135
+ context: carrier ? { ...carrier } : null,
136
+ },
137
+ });
138
+ };
123
139
  }
124
140
  /**
125
141
  * Backend-neutral reference implementation that records spans in process memory.
126
142
  * Create a fresh instance to isolate tests or independent recording scopes.
127
143
  */
128
144
  export class InMemoryTelemetryContext {
145
+ metrics = this;
146
+ propagation = this;
129
147
  state = {
148
+ metrics: this,
149
+ propagation: this,
150
+ scope: crypto.randomUUID(),
130
151
  spans: [],
152
+ measurements: [],
131
153
  nextSpanId: 1,
132
154
  nextEndSequence: 1,
133
155
  };
134
156
  startSpan(options, callback) {
135
157
  return startInMemorySpan(this.state, undefined, options, callback);
136
158
  }
159
+ /** Returns a detached carrier for a known span or extracted parent, including settled spans. */
160
+ inject(context) {
161
+ const carrier = contextCarriers.get(context);
162
+ return carrier ? { ...carrier } : undefined;
163
+ }
164
+ /** Missing or non-string carrier identities fall back to this recorder's root context. */
165
+ extract(carrier) {
166
+ const scope = carrier?.["pi-memory-scope"];
167
+ const span = carrier?.["pi-memory-span"];
168
+ const traceId = carrier?.["pi-memory-trace"];
169
+ if (typeof scope !== "string" || typeof span !== "string" || typeof traceId !== "string")
170
+ return this;
171
+ const context = { "pi-memory-scope": scope, "pi-memory-span": span, "pi-memory-trace": traceId };
172
+ const localId = scope === this.state.scope ? Number(span) : null;
173
+ const parent = {
174
+ metrics: this,
175
+ propagation: this,
176
+ startSpan: (options, callback) => startInMemorySpan(this.state, { context, localId }, options, callback),
177
+ };
178
+ contextCarriers.set(parent, context);
179
+ return parent;
180
+ }
181
+ counter(name, options) {
182
+ return { add: createMeasurementRecorder(this.state, "counter", name, options) };
183
+ }
184
+ upDownCounter(name, options) {
185
+ return { add: createMeasurementRecorder(this.state, "upDownCounter", name, options) };
186
+ }
187
+ histogram(name, options) {
188
+ return { record: createMeasurementRecorder(this.state, "histogram", name, options) };
189
+ }
190
+ storedSpans() {
191
+ return this.state.spans
192
+ .filter((span) => span.settled)
193
+ .map((span) => ({
194
+ id: carrierId(span.context),
195
+ traceId: span.context["pi-memory-trace"],
196
+ ...(span.parentContext ? { parentId: carrierId(span.parentContext) } : {}),
197
+ name: span.name,
198
+ startedMs: span.startedMs,
199
+ endedMs: span.endedMs,
200
+ attributes: copyAttributes(span.attributes),
201
+ events: span.events.map((event) => ({
202
+ name: event.name,
203
+ timeMs: event.timeMs,
204
+ attributes: copyAttributes(event.attributes),
205
+ })),
206
+ links: span.links.map((link) => ({
207
+ traceId: link.context["pi-memory-trace"],
208
+ spanId: carrierId(link.context),
209
+ attributes: copyAttributes(link.attributes),
210
+ })),
211
+ status: copyStatus(span.status),
212
+ }))
213
+ .sort((a, b) => a.startedMs - b.startedMs || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
214
+ }
215
+ async getTrace(traceId) {
216
+ const spans = this.storedSpans().filter((span) => span.traceId === traceId);
217
+ return spans.length ? { traceId, spans } : undefined;
218
+ }
219
+ async findTraces(query = {}) {
220
+ const limit = query.limit ?? 20;
221
+ const after = query.cursor === undefined ? undefined : JSON.parse(query.cursor);
222
+ const grouped = new Map();
223
+ for (const span of this.storedSpans()) {
224
+ let trace = grouped.get(span.traceId);
225
+ if (!trace) {
226
+ trace = { traceId: span.traceId, spans: [] };
227
+ grouped.set(span.traceId, trace);
228
+ }
229
+ trace.spans.push(span);
230
+ }
231
+ const matches = [...grouped.values()]
232
+ .filter((trace) => {
233
+ const first = trace.spans[0];
234
+ return ((query.name === undefined || first.name === query.name) &&
235
+ (query.startMin === undefined || first.startedMs >= query.startMin) &&
236
+ (query.startMax === undefined || first.startedMs <= query.startMax) &&
237
+ (!after || first.startedMs < after[0] || (first.startedMs === after[0] && trace.traceId > after[1])) &&
238
+ (!query.errors || trace.spans.some((span) => span.status.status === "error")) &&
239
+ (!query.attributes ||
240
+ trace.spans.some((span) => Object.entries(query.attributes).every(([key, value]) => span.attributes[key] === value))));
241
+ })
242
+ .sort((a, b) => b.spans[0].startedMs - a.spans[0].startedMs ||
243
+ (a.traceId < b.traceId ? -1 : a.traceId > b.traceId ? 1 : 0));
244
+ const traces = matches.slice(0, limit);
245
+ const last = traces.at(-1);
246
+ return {
247
+ traces,
248
+ ...(matches.length > limit ? { cursor: JSON.stringify([last.spans[0].startedMs, last.traceId]) } : {}),
249
+ };
250
+ }
251
+ /** Read raw measurements as count-one rows, without changing getMetrics() snapshots. */
252
+ async findMetrics(query) {
253
+ return this.state.measurements
254
+ .filter(({ intervalMs, measurement }) => measurement.name === query.name &&
255
+ (query.startMin === undefined || intervalMs >= query.startMin) &&
256
+ (query.startMax === undefined || intervalMs <= query.startMax) &&
257
+ Object.entries(query.attributes ?? {}).every(([key, value]) => measurement.attributes[key] === value))
258
+ .map(({ intervalMs, measurement }) => ({
259
+ intervalMs,
260
+ name: measurement.name,
261
+ kind: measurement.kind,
262
+ ...(measurement.unit === undefined ? {} : { unit: measurement.unit }),
263
+ attributes: copyAttributes(measurement.attributes),
264
+ count: 1,
265
+ sum: measurement.value,
266
+ min: measurement.value,
267
+ max: measurement.value,
268
+ }));
269
+ }
270
+ /** Returns detached measurements in recording order, without aggregation. */
271
+ getMetrics() {
272
+ return this.state.measurements.map(({ measurement }) => ({
273
+ ...measurement,
274
+ ...(measurement.boundaries === undefined ? {} : { boundaries: [...measurement.boundaries] }),
275
+ attributes: copyAttributes(measurement.attributes),
276
+ context: measurement.context ? { ...measurement.context } : null,
277
+ }));
278
+ }
137
279
  /** Returns detached snapshots in span-start order. */
138
280
  getSpans() {
139
281
  return this.state.spans.map((span) => ({
140
282
  id: span.id,
141
283
  parentId: span.parentId,
284
+ context: { ...span.context },
285
+ parentContext: span.parentContext ? { ...span.parentContext } : null,
286
+ links: span.links.map((link) => ({
287
+ context: { ...link.context },
288
+ attributes: copyAttributes(link.attributes),
289
+ })),
142
290
  name: span.name,
143
291
  attributes: copyAttributes(span.attributes),
144
292
  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// 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: Date.now(),\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: 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 = 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"]}
@@ -0,0 +1,78 @@
1
+ import type { ExactTelemetryAttributes, InferRequiredAndOptionalAttributes, SpanAttributes, TelemetryContext, TelemetrySchemaDefinition, TelemetryStartAttributeDefinition } from "./index.ts";
2
+ export interface InstrumentOptions {
3
+ description?: string;
4
+ unit?: string;
5
+ }
6
+ export interface HistogramOptions extends InstrumentOptions {
7
+ /** Bucket hints; callers supply finite, strictly increasing values. */
8
+ boundaries?: readonly number[];
9
+ }
10
+ export interface TelemetryCounter {
11
+ add(value: number, attributes?: SpanAttributes): void;
12
+ }
13
+ export interface TelemetryUpDownCounter {
14
+ add(value: number, attributes?: SpanAttributes): void;
15
+ }
16
+ export interface TelemetryHistogram {
17
+ record(value: number, attributes?: SpanAttributes, context?: TelemetryContext): void;
18
+ }
19
+ /**
20
+ * Optional adapter capability with synchronous factories and recording methods.
21
+ * Typed inputs are trusted; callers supply finite measurements and nonnegative counter increments.
22
+ * Malformed input behavior is unspecified.
23
+ */
24
+ export interface TelemetryMetrics {
25
+ counter(name: string, options?: InstrumentOptions): TelemetryCounter;
26
+ upDownCounter(name: string, options?: InstrumentOptions): TelemetryUpDownCounter;
27
+ histogram(name: string, options?: HistogramOptions): TelemetryHistogram;
28
+ }
29
+ export type TelemetryMetricAttributeDefinition = TelemetryStartAttributeDefinition & {
30
+ cardinality?: "low";
31
+ };
32
+ export type TelemetryMetricDefinition = {
33
+ description: string;
34
+ unit?: string;
35
+ attributes: Record<string, TelemetryMetricAttributeDefinition>;
36
+ } & ({
37
+ kind: "counter" | "upDownCounter";
38
+ boundaries?: never;
39
+ } | {
40
+ kind: "histogram";
41
+ boundaries?: readonly number[];
42
+ });
43
+ type MetricKind = TelemetryMetricDefinition["kind"];
44
+ type MetricSchemas = readonly [TelemetrySchemaDefinition, ...TelemetrySchemaDefinition[]];
45
+ type MetricsOf<Schema extends TelemetrySchemaDefinition> = Schema extends {
46
+ metrics: infer Metrics extends Record<string, TelemetryMetricDefinition>;
47
+ } ? Metrics : Record<never, never>;
48
+ type MetricNames<Schema extends TelemetrySchemaDefinition, Kind extends MetricKind> = Schema extends TelemetrySchemaDefinition ? {
49
+ [Name in keyof MetricsOf<Schema>]: MetricsOf<Schema>[Name] extends {
50
+ kind: Kind;
51
+ } ? Name : never;
52
+ }[keyof MetricsOf<Schema>] & string : never;
53
+ type MetricByName<Schema extends TelemetrySchemaDefinition, Name extends string> = Schema extends TelemetrySchemaDefinition ? Name extends keyof MetricsOf<Schema> ? MetricsOf<Schema>[Name] : never : never;
54
+ type DuplicateMetricNames<Schemas extends readonly TelemetrySchemaDefinition[], Seen extends string = never> = Schemas extends readonly [
55
+ infer Schema extends TelemetrySchemaDefinition,
56
+ ...infer Rest extends readonly TelemetrySchemaDefinition[]
57
+ ] ? Extract<keyof MetricsOf<Schema>, Seen> | DuplicateMetricNames<Rest, Seen | (keyof MetricsOf<Schema> & string)> : never;
58
+ type MetricAttributes<Definition extends TelemetryMetricDefinition> = InferRequiredAndOptionalAttributes<Definition["attributes"]>;
59
+ type MeasurementArguments<Definition extends TelemetryMetricDefinition, Attributes extends MetricAttributes<Definition>> = {
60
+ [Name in keyof Definition["attributes"]]: Definition["attributes"][Name]["required"] extends true ? Name : never;
61
+ }[keyof Definition["attributes"]] extends never ? [attributes?: ExactTelemetryAttributes<MetricAttributes<Definition>, Attributes>] : [attributes: ExactTelemetryAttributes<MetricAttributes<Definition>, Attributes>];
62
+ export type SchemaTelemetryCounter<Definition extends TelemetryMetricDefinition> = {
63
+ add<const Attributes extends MetricAttributes<Definition> = MetricAttributes<Definition>>(value: number, ...args: MeasurementArguments<Definition, Attributes>): void;
64
+ };
65
+ export type SchemaTelemetryHistogram<Definition extends TelemetryMetricDefinition> = {
66
+ record<const Attributes extends MetricAttributes<Definition> = MetricAttributes<Definition>>(value: number, ...args: [...MeasurementArguments<Definition, Attributes>, context?: TelemetryContext]): void;
67
+ };
68
+ export interface TypedTelemetryMetrics<Schemas extends MetricSchemas> {
69
+ counter<Name extends MetricNames<Schemas[number], "counter">>(name: Name): SchemaTelemetryCounter<MetricByName<Schemas[number], Name>>;
70
+ upDownCounter<Name extends MetricNames<Schemas[number], "upDownCounter">>(name: Name): SchemaTelemetryCounter<MetricByName<Schemas[number], Name>>;
71
+ histogram<Name extends MetricNames<Schemas[number], "histogram">>(name: Name): SchemaTelemetryHistogram<MetricByName<Schemas[number], Name>>;
72
+ }
73
+ /** Bind instrument names, kinds, metadata, and exact measurement attributes to one or more schemas. */
74
+ export declare function createTypedMetrics<const Schemas extends MetricSchemas>(metrics: TelemetryMetrics, schemas: Schemas & ([DuplicateMetricNames<Schemas>] extends [never] ? unknown : {
75
+ readonly "duplicate telemetry metric names": DuplicateMetricNames<Schemas>;
76
+ })): TypedTelemetryMetrics<Schemas>;
77
+ export {};
78
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"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"}