@primo-ai/observability 0.1.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/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # @primo-ai/observability
2
+
3
+ Span, Tracer, and Metrics abstractions with an OpenTelemetry bridge.
4
+
5
+ ## Overview
6
+
7
+ Provides the observability layer for AgentForge. All pipeline stages emit spans with attributes, and the framework exposes metrics for token usage, tool calls, and gate decisions.
8
+
9
+ ## Quick Example
10
+
11
+ ```typescript
12
+ import { OTelBridge } from '@primo-ai/observability';
13
+ import { EventBus } from '@primo-ai/core';
14
+ import { BasicTracerProvider, InMemorySpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
15
+
16
+ const exporter = new InMemorySpanExporter();
17
+ const provider = new BasicTracerProvider({
18
+ spanProcessors: [new SimpleSpanProcessor(exporter)],
19
+ });
20
+
21
+ const bus = new EventBus();
22
+ const tracer = new OTelBridge({ tracerProvider: provider, eventBus: bus });
23
+
24
+ // Use with an Agent
25
+ const agent = new Agent({ model: 'deepseek/deepseek-v4-flash' }, { tracer });
26
+ ```
27
+
28
+ ## Key Exports
29
+
30
+ | Export | Description |
31
+ |--------|-------------|
32
+ | `TracerImpl` | Default tracer implementation with span lifecycle |
33
+ | `SpanImpl` | Span implementation with attributes and events |
34
+ | `NoOpTracer` | No-op tracer for when observability is disabled |
35
+ | `NoOpSpan` | No-op span that discards all data |
36
+ | `OTelBridge` | Bridge connecting AgentForge spans to OpenTelemetry |
37
+ | `InMemoryMetrics` | In-memory metrics collector (counter, gauge, histogram) |
38
+ | `NoOpMetrics` | No-op metrics implementation |
39
+ | `TestExporter` | Test utility for capturing spans |
40
+ | `TraceCollector` | Collects and formats traces as JSON, console, or OTLP |
41
+ | `formatTraceJson` | Formats traces as JSON |
42
+ | `formatTraceConsole` | Formats traces for console output |
43
+ | `formatTraceOtlp` | Formats traces as OTLP for export |
44
+
45
+ ## Span Types
46
+
47
+ The SDK defines standard span types via `SpanType`:
48
+
49
+ | Span Type | Description |
50
+ |-----------|-------------|
51
+ | `agent_run` | Full agent execution |
52
+ | `model_step` | Single LLM invocation |
53
+ | `tool_call` | Tool execution |
54
+ | `processor_run` | Pipeline processor execution |
55
+ | `llm.stream` | LLM streaming span |
56
+ | `tool.execute` | Tool execution with hooks |
57
+ | `harness.gate` | Gate decision (allow/deny) |
58
+ | `harness.cost-cap` | Cost cap check |
59
+ | `harness.token-budget` | Token budget check |
60
+ | `session.lifecycle` | Session state transitions |
61
+ | `context.build` | Context assembly |
62
+ | `loop.iteration` | Agentic loop iteration |
63
+
64
+ ## Metrics
65
+
66
+ ```typescript
67
+ import { InMemoryMetrics } from '@primo-ai/observability';
68
+
69
+ const metrics = new InMemoryMetrics();
70
+ metrics.increment('llm.calls', 1, { model: 'deepseek' });
71
+ metrics.gauge('tokens.used', 150, { type: 'input' });
72
+ metrics.histogram('tool.duration', 42, { tool: 'getWeather' });
73
+
74
+ const snapshot = metrics.snapshot();
75
+ ```
76
+
77
+ ## Dependencies
78
+
79
+ - `@primo-ai/sdk` -- Span, Tracer, Metrics interfaces
@@ -0,0 +1,9 @@
1
+ import type { Tracer } from '@primo-ai/sdk';
2
+ import { type SpanData } from './tracer.js';
3
+ export declare class TestExporter {
4
+ private spans;
5
+ createTracer(): Tracer;
6
+ getSpans(): SpanData[];
7
+ clear(): void;
8
+ }
9
+ //# sourceMappingURL=exporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exporter.d.ts","sourceRoot":"","sources":["../src/exporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,MAAM,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAuBtD,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAsB;IAEnC,YAAY,IAAI,MAAM;IAgBtB,QAAQ,IAAI,QAAQ,EAAE;IAItB,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,38 @@
1
+ import { SpanImpl } from './tracer.js';
2
+ class ExporterSpan extends SpanImpl {
3
+ exporter;
4
+ constructor(exporter, name, traceId, spanId, parentSpanId) {
5
+ super(name, traceId, spanId, parentSpanId);
6
+ this.exporter = exporter;
7
+ }
8
+ startChild(name) {
9
+ const child = new ExporterSpan(this.exporter, name, (this.spanContext().traceId), crypto.randomUUID(), this.spanContext().spanId);
10
+ this.exporter['spans'].push(child);
11
+ return child;
12
+ }
13
+ }
14
+ export class TestExporter {
15
+ spans = [];
16
+ createTracer() {
17
+ const exporter = this;
18
+ return {
19
+ startSpan(name) {
20
+ const traceId = crypto.randomUUID();
21
+ const spanId = crypto.randomUUID();
22
+ const span = new ExporterSpan(exporter, name, traceId, spanId);
23
+ exporter.spans.push(span);
24
+ return span;
25
+ },
26
+ getCurrentSpan() {
27
+ return undefined;
28
+ },
29
+ };
30
+ }
31
+ getSpans() {
32
+ return this.spans.map((s) => s.toData());
33
+ }
34
+ clear() {
35
+ this.spans = [];
36
+ }
37
+ }
38
+ //# sourceMappingURL=exporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exporter.js","sourceRoot":"","sources":["../src/exporter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAiB,MAAM,aAAa,CAAC;AAEtD,MAAM,YAAa,SAAQ,QAAQ;IAChB,QAAQ,CAAe;IAExC,YAAY,QAAsB,EAAE,IAAY,EAAE,OAAe,EAAE,MAAc,EAAE,YAAqB;QACtG,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAC3C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,UAAU,CAAC,IAAY;QACrB,MAAM,KAAK,GAAG,IAAI,YAAY,CAC5B,IAAI,CAAC,QAAQ,EACb,IAAI,EACJ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,EAC5B,MAAM,CAAC,UAAU,EAAE,EACnB,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,CAC1B,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAED,MAAM,OAAO,YAAY;IACf,KAAK,GAAmB,EAAE,CAAC;IAEnC,YAAY;QACV,MAAM,QAAQ,GAAG,IAAI,CAAC;QACtB,OAAO;YACL,SAAS,CAAC,IAAY;gBACpB,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;gBACpC,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;gBACnC,MAAM,IAAI,GAAG,IAAI,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;gBAC/D,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC1B,OAAO,IAAI,CAAC;YACd,CAAC;YACD,cAAc;gBACZ,OAAO,SAAS,CAAC;YACnB,CAAC;SACF,CAAC;IACJ,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ export { NoOpTracer, NoOpSpan } from './noop.js';
2
+ export { TracerImpl, SpanImpl, NoOpMetrics, type SpanData, type OnSpanEndCallback } from './tracer.js';
3
+ export { InMemoryMetrics, type HistogramStats, type MetricsSnapshot } from './metrics.js';
4
+ export { TestExporter } from './exporter.js';
5
+ export { OTelBridge, type OTelBridgeOptions, type EventBusLike } from './otel-bridge.js';
6
+ export { TraceCollector, formatTraceJson, formatTraceConsole, formatTraceOtlp, type Trace, type TraceNode, type OtlpOptions } from './trace-collector.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,QAAQ,EAAE,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACvG,OAAO,EAAE,eAAe,EAAE,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,kBAAkB,EAAE,eAAe,EAAE,KAAK,KAAK,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ // @primo-ai/observability — Span, Tracer, Metrics abstractions
2
+ export { NoOpTracer, NoOpSpan } from './noop.js';
3
+ export { TracerImpl, SpanImpl, NoOpMetrics } from './tracer.js';
4
+ export { InMemoryMetrics } from './metrics.js';
5
+ export { TestExporter } from './exporter.js';
6
+ export { OTelBridge } from './otel-bridge.js';
7
+ export { TraceCollector, formatTraceJson, formatTraceConsole, formatTraceOtlp } from './trace-collector.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAE/D,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAyC,MAAM,aAAa,CAAC;AACvG,OAAO,EAAE,eAAe,EAA6C,MAAM,cAAc,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,UAAU,EAA6C,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,kBAAkB,EAAE,eAAe,EAAgD,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { Metrics } from '@primo-ai/sdk';
2
+ export interface HistogramStats {
3
+ count: number;
4
+ sum: number;
5
+ min: number;
6
+ max: number;
7
+ avg: number;
8
+ }
9
+ export interface MetricsSnapshot {
10
+ counters: Record<string, number>;
11
+ gauges: Record<string, number>;
12
+ histograms: Record<string, HistogramStats>;
13
+ labeledCounters: Record<string, number>;
14
+ labeledGauges: Record<string, number>;
15
+ labeledHistograms: Record<string, HistogramStats>;
16
+ }
17
+ export declare class InMemoryMetrics implements Metrics {
18
+ private counters;
19
+ private gauges;
20
+ private histograms;
21
+ private labeledCounters;
22
+ private labeledGauges;
23
+ private labeledHistograms;
24
+ increment(name: string, delta?: number, labels?: Record<string, string>): void;
25
+ gauge(name: string, value: number, labels?: Record<string, string>): void;
26
+ histogram(name: string, value: number, labels?: Record<string, string>): void;
27
+ getCounter(name: string, labels?: Record<string, string>): number;
28
+ getGauge(name: string, labels?: Record<string, string>): number | undefined;
29
+ getHistogram(name: string, labels?: Record<string, string>): HistogramStats | undefined;
30
+ snapshot(): MetricsSnapshot;
31
+ reset(): void;
32
+ }
33
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC3C,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CACnD;AAaD,qBAAa,eAAgB,YAAW,OAAO;IAC7C,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,UAAU,CAAoC;IAGtD,OAAO,CAAC,eAAe,CAA6B;IACpD,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,iBAAiB,CAAoC;IAE7D,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAI,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IASzE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IASzE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAyB7E,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM;IAOjE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,GAAG,SAAS;IAO3E,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,cAAc,GAAG,SAAS;IAQvF,QAAQ,IAAI,eAAe;IAmB3B,KAAK,IAAI,IAAI;CAQd"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Build a stable serialization key from a metric name and its labels.
3
+ * Labels are sorted alphabetically to ensure deterministic keys.
4
+ */
5
+ function labelKey(name, labels) {
6
+ const parts = Object.keys(labels).sort().map((k) => `${k}=${labels[k]}`);
7
+ return `${name}|${parts.join(',')}`;
8
+ }
9
+ export class InMemoryMetrics {
10
+ counters = new Map();
11
+ gauges = new Map();
12
+ histograms = new Map();
13
+ // Labeled variants — keyed by `name|k1=v1,k2=v2`
14
+ labeledCounters = new Map();
15
+ labeledGauges = new Map();
16
+ labeledHistograms = new Map();
17
+ increment(name, delta = 1, labels) {
18
+ if (labels && Object.keys(labels).length > 0) {
19
+ const key = labelKey(name, labels);
20
+ this.labeledCounters.set(key, (this.labeledCounters.get(key) ?? 0) + delta);
21
+ }
22
+ else {
23
+ this.counters.set(name, (this.counters.get(name) ?? 0) + delta);
24
+ }
25
+ }
26
+ gauge(name, value, labels) {
27
+ if (labels && Object.keys(labels).length > 0) {
28
+ const key = labelKey(name, labels);
29
+ this.labeledGauges.set(key, value);
30
+ }
31
+ else {
32
+ this.gauges.set(name, value);
33
+ }
34
+ }
35
+ histogram(name, value, labels) {
36
+ if (labels && Object.keys(labels).length > 0) {
37
+ const key = labelKey(name, labels);
38
+ const existing = this.labeledHistograms.get(key);
39
+ if (existing) {
40
+ existing.count += 1;
41
+ existing.sum += value;
42
+ if (value < existing.min)
43
+ existing.min = value;
44
+ if (value > existing.max)
45
+ existing.max = value;
46
+ }
47
+ else {
48
+ this.labeledHistograms.set(key, { count: 1, sum: value, min: value, max: value });
49
+ }
50
+ }
51
+ else {
52
+ const existing = this.histograms.get(name);
53
+ if (existing) {
54
+ existing.count += 1;
55
+ existing.sum += value;
56
+ if (value < existing.min)
57
+ existing.min = value;
58
+ if (value > existing.max)
59
+ existing.max = value;
60
+ }
61
+ else {
62
+ this.histograms.set(name, { count: 1, sum: value, min: value, max: value });
63
+ }
64
+ }
65
+ }
66
+ getCounter(name, labels) {
67
+ if (labels && Object.keys(labels).length > 0) {
68
+ return this.labeledCounters.get(labelKey(name, labels)) ?? 0;
69
+ }
70
+ return this.counters.get(name) ?? 0;
71
+ }
72
+ getGauge(name, labels) {
73
+ if (labels && Object.keys(labels).length > 0) {
74
+ return this.labeledGauges.get(labelKey(name, labels));
75
+ }
76
+ return this.gauges.get(name);
77
+ }
78
+ getHistogram(name, labels) {
79
+ const map = (labels && Object.keys(labels).length > 0) ? this.labeledHistograms : this.histograms;
80
+ const key = (labels && Object.keys(labels).length > 0) ? labelKey(name, labels) : name;
81
+ const h = map.get(key);
82
+ if (!h)
83
+ return undefined;
84
+ return { ...h, avg: h.sum / h.count };
85
+ }
86
+ snapshot() {
87
+ const histograms = {};
88
+ for (const [name, h] of this.histograms) {
89
+ histograms[name] = { ...h, avg: h.sum / h.count };
90
+ }
91
+ const labeledHists = {};
92
+ for (const [key, h] of this.labeledHistograms) {
93
+ labeledHists[key] = { ...h, avg: h.sum / h.count };
94
+ }
95
+ return {
96
+ counters: Object.fromEntries(this.counters),
97
+ gauges: Object.fromEntries(this.gauges),
98
+ histograms,
99
+ labeledCounters: Object.fromEntries(this.labeledCounters),
100
+ labeledGauges: Object.fromEntries(this.labeledGauges),
101
+ labeledHistograms: labeledHists,
102
+ };
103
+ }
104
+ reset() {
105
+ this.counters.clear();
106
+ this.gauges.clear();
107
+ this.histograms.clear();
108
+ this.labeledCounters.clear();
109
+ this.labeledGauges.clear();
110
+ this.labeledHistograms.clear();
111
+ }
112
+ }
113
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"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"}
package/dist/noop.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import type { Span, SpanContext, Tracer } from '@primo-ai/sdk';
2
+ export declare class NoOpSpan implements Span {
3
+ readonly name: string;
4
+ constructor(name: string);
5
+ startChild(name: string): Span;
6
+ end(): void;
7
+ setAttribute(_key: string, _value: unknown): Span;
8
+ addEvent(_name: string, _attributes?: Record<string, unknown>): Span;
9
+ spanContext(): SpanContext;
10
+ }
11
+ export declare class NoOpTracer implements Tracer {
12
+ startSpan(name: string): Span;
13
+ getCurrentSpan(): Span | undefined;
14
+ }
15
+ //# sourceMappingURL=noop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noop.d.ts","sourceRoot":"","sources":["../src/noop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE/D,qBAAa,QAAS,YAAW,IAAI;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,IAAI,EAAE,MAAM;IAIxB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9B,GAAG,IAAI,IAAI;IAEX,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI;IAIjD,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIpE,WAAW,IAAI,WAAW;CAG3B;AAED,qBAAa,UAAW,YAAW,MAAM;IACvC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI7B,cAAc,IAAI,IAAI,GAAG,SAAS;CAGnC"}
package/dist/noop.js ADDED
@@ -0,0 +1,28 @@
1
+ export class NoOpSpan {
2
+ name;
3
+ constructor(name) {
4
+ this.name = name;
5
+ }
6
+ startChild(name) {
7
+ return new NoOpSpan(name);
8
+ }
9
+ end() { }
10
+ setAttribute(_key, _value) {
11
+ return this;
12
+ }
13
+ addEvent(_name, _attributes) {
14
+ return this;
15
+ }
16
+ spanContext() {
17
+ return { spanId: '', traceId: '' };
18
+ }
19
+ }
20
+ export class NoOpTracer {
21
+ startSpan(name) {
22
+ return new NoOpSpan(name);
23
+ }
24
+ getCurrentSpan() {
25
+ return undefined;
26
+ }
27
+ }
28
+ //# sourceMappingURL=noop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noop.js","sourceRoot":"","sources":["../src/noop.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,QAAQ;IACV,IAAI,CAAS;IAEtB,YAAY,IAAY;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,UAAU,CAAC,IAAY;QACrB,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,GAAG,KAAU,CAAC;IAEd,YAAY,CAAC,IAAY,EAAE,MAAe;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,QAAQ,CAAC,KAAa,EAAE,WAAqC;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,WAAW;QACT,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACrC,CAAC;CACF;AAED,MAAM,OAAO,UAAU;IACrB,SAAS,CAAC,IAAY;QACpB,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,cAAc;QACZ,OAAO,SAAS,CAAC;IACnB,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ import type { Span, Tracer } from '@primo-ai/sdk';
2
+ import type { Tracer as OTelTracerType } from '@opentelemetry/api';
3
+ export interface EventBusLike {
4
+ emit(eventType: string, data?: unknown): void;
5
+ }
6
+ export interface OTelBridgeOptions {
7
+ tracerProvider?: {
8
+ getTracer(name: string, version?: string): OTelTracerType;
9
+ };
10
+ tracerName?: string;
11
+ eventBus?: EventBusLike;
12
+ }
13
+ export declare class OTelBridge implements Tracer {
14
+ private readonly otelTracer;
15
+ private readonly eventBus?;
16
+ constructor(options?: OTelBridgeOptions);
17
+ startSpan(name: string): Span;
18
+ getCurrentSpan(): Span | undefined;
19
+ }
20
+ //# sourceMappingURL=otel-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otel-bridge.d.ts","sourceRoot":"","sources":["../src/otel-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAe,MAAM,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,KAAK,EAAwB,MAAM,IAAI,cAAc,EAAW,MAAM,oBAAoB,CAAC;AAIlG,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CAC/C;AAED,MAAM,WAAW,iBAAiB;IAChC,cAAc,CAAC,EAAE;QAAE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,cAAc,CAAA;KAAE,CAAC;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAwDD,qBAAa,UAAW,YAAW,MAAM;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;IACxD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAe;gBAE7B,OAAO,CAAC,EAAE,iBAAiB;IAOvC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM7B,cAAc,IAAI,IAAI,GAAG,SAAS;CAGnC"}
@@ -0,0 +1,61 @@
1
+ import { context, trace } from '@opentelemetry/api';
2
+ import { NoOpSpan } from './noop.js';
3
+ class OTelAdapterSpan {
4
+ name;
5
+ otelSpan;
6
+ otelTracer;
7
+ otelContext;
8
+ eventBus;
9
+ constructor(name, otelSpan, otelTracer, otelContext, eventBus) {
10
+ this.name = name;
11
+ this.otelSpan = otelSpan;
12
+ this.otelTracer = otelTracer;
13
+ this.otelContext = otelContext;
14
+ this.eventBus = eventBus;
15
+ }
16
+ startChild(childName) {
17
+ const childCtx = trace.setSpan(this.otelContext, this.otelSpan);
18
+ const childSpan = this.otelTracer.startSpan(childName, undefined, childCtx);
19
+ return new OTelAdapterSpan(childName, childSpan, this.otelTracer, childCtx, this.eventBus);
20
+ }
21
+ end() {
22
+ this.otelSpan.end();
23
+ if (this.eventBus) {
24
+ const ctx = this.otelSpan.spanContext();
25
+ this.eventBus.emit('span.end', {
26
+ name: this.name,
27
+ spanContext: { traceId: ctx.traceId, spanId: ctx.spanId },
28
+ });
29
+ }
30
+ }
31
+ setAttribute(key, value) {
32
+ this.otelSpan.setAttribute(key, value);
33
+ return this;
34
+ }
35
+ addEvent(name, attributes) {
36
+ this.otelSpan.addEvent(name, attributes);
37
+ return this;
38
+ }
39
+ spanContext() {
40
+ const ctx = this.otelSpan.spanContext();
41
+ return { spanId: ctx.spanId, traceId: ctx.traceId };
42
+ }
43
+ }
44
+ export class OTelBridge {
45
+ otelTracer;
46
+ eventBus;
47
+ constructor(options) {
48
+ this.otelTracer = options?.tracerProvider?.getTracer(options?.tracerName ?? '@primo-ai/observability');
49
+ this.eventBus = options?.eventBus;
50
+ }
51
+ startSpan(name) {
52
+ if (!this.otelTracer)
53
+ return new NoOpSpan(name);
54
+ const otelSpan = this.otelTracer.startSpan(name);
55
+ return new OTelAdapterSpan(name, otelSpan, this.otelTracer, context.active(), this.eventBus);
56
+ }
57
+ getCurrentSpan() {
58
+ return undefined;
59
+ }
60
+ }
61
+ //# sourceMappingURL=otel-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otel-bridge.js","sourceRoot":"","sources":["../src/otel-bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { Tracer } from '@primo-ai/sdk';
2
+ import { type SpanData } from './tracer.js';
3
+ export interface TraceNode {
4
+ span: SpanData;
5
+ children: TraceNode[];
6
+ }
7
+ export interface Trace {
8
+ traceId: string;
9
+ durationMs: number;
10
+ spans: SpanData[];
11
+ root?: TraceNode;
12
+ }
13
+ export declare class TraceCollector {
14
+ private _endedSpans;
15
+ private _traceId;
16
+ createTracer(): Tracer;
17
+ getTrace(): Trace;
18
+ clear(): void;
19
+ flush(): Trace;
20
+ /** Arrow field so CollectorSpan can reference it via closure without private-access issues. */
21
+ onSpanEnd: (data: SpanData) => void;
22
+ private buildTree;
23
+ }
24
+ export declare function formatTraceJson(trace: Trace): string;
25
+ export declare function formatTraceConsole(trace: Trace): string;
26
+ export interface OtlpOptions {
27
+ serviceName?: string;
28
+ }
29
+ export declare function formatTraceOtlp(trace: Trace, options?: OtlpOptions): string;
30
+ //# sourceMappingURL=trace-collector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace-collector.d.ts","sourceRoot":"","sources":["../src/trace-collector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,MAAM,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEtD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,SAAS,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AA4BD,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,QAAQ,CAAuB;IAEvC,YAAY,IAAI,MAAM;IAatB,QAAQ,IAAI,KAAK;IAWjB,KAAK,IAAI,IAAI;IAKb,KAAK,IAAI,KAAK;IAMd,+FAA+F;IAC/F,SAAS,GAAI,MAAM,QAAQ,KAAG,IAAI,CAGhC;IAEF,OAAO,CAAC,SAAS;CAoBlB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAGpD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAMvD;AAkBD,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAuBD,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CA0C3E"}
@@ -0,0 +1,156 @@
1
+ import { SpanImpl } from './tracer.js';
2
+ class CollectorSpan extends SpanImpl {
3
+ collector;
4
+ constructor(collector, name, traceId, spanId, parentSpanId) {
5
+ super(name, traceId, spanId, parentSpanId, (data) => collector.onSpanEnd(data));
6
+ this.collector = collector;
7
+ }
8
+ startChild(name) {
9
+ const child = new CollectorSpan(this.collector, name, this.spanContext().traceId, crypto.randomUUID(), this.spanContext().spanId);
10
+ return child;
11
+ }
12
+ }
13
+ export class TraceCollector {
14
+ _endedSpans = [];
15
+ _traceId = crypto.randomUUID();
16
+ createTracer() {
17
+ const collector = this;
18
+ const traceId = this._traceId;
19
+ return {
20
+ startSpan(name) {
21
+ return new CollectorSpan(collector, name, traceId, crypto.randomUUID());
22
+ },
23
+ getCurrentSpan() {
24
+ return undefined;
25
+ },
26
+ };
27
+ }
28
+ getTrace() {
29
+ const ended = this._endedSpans;
30
+ const root = this.buildTree(ended);
31
+ return {
32
+ traceId: this._traceId,
33
+ durationMs: root?.span.durationMs ?? 0,
34
+ spans: ended,
35
+ root,
36
+ };
37
+ }
38
+ clear() {
39
+ this._endedSpans = [];
40
+ this._traceId = crypto.randomUUID();
41
+ }
42
+ flush() {
43
+ const trace = this.getTrace();
44
+ this.clear();
45
+ return trace;
46
+ }
47
+ /** Arrow field so CollectorSpan can reference it via closure without private-access issues. */
48
+ onSpanEnd = (data) => {
49
+ if (!data.ended)
50
+ return;
51
+ this._endedSpans.push(data);
52
+ };
53
+ buildTree(spans) {
54
+ if (spans.length === 0)
55
+ return undefined;
56
+ const byId = new Map();
57
+ for (const span of spans) {
58
+ byId.set(span.spanId, { span, children: [] });
59
+ }
60
+ let root;
61
+ for (const node of byId.values()) {
62
+ if (node.span.parentSpanId) {
63
+ const parent = byId.get(node.span.parentSpanId);
64
+ parent?.children.push(node);
65
+ }
66
+ else {
67
+ root = node;
68
+ }
69
+ }
70
+ return root;
71
+ }
72
+ }
73
+ export function formatTraceJson(trace) {
74
+ if (!trace.root)
75
+ return 'null';
76
+ return JSON.stringify(trace, null, 2);
77
+ }
78
+ export function formatTraceConsole(trace) {
79
+ if (!trace.root)
80
+ return '(no trace)';
81
+ const lines = [];
82
+ renderNode(trace.root, 0, lines);
83
+ return lines.join('\n');
84
+ }
85
+ function renderNode(node, depth, lines) {
86
+ const indent = ' '.repeat(depth);
87
+ const attrs = Object.entries(node.span.attributes);
88
+ const attrStr = attrs.length > 0
89
+ ? ' ' + attrs.map(([k, v]) => `${k}=${v}`).join(' ')
90
+ : '';
91
+ lines.push(`${indent}${node.span.name} ${node.span.durationMs}ms${attrStr}`);
92
+ for (const child of node.children) {
93
+ renderNode(child, depth + 1, lines);
94
+ }
95
+ }
96
+ function toHex16(uuid) {
97
+ return uuid.replace(/-/g, '').slice(0, 16).toLowerCase();
98
+ }
99
+ function toHex32(uuid) {
100
+ return uuid.replace(/-/g, '').toLowerCase();
101
+ }
102
+ function msToNano(ms) {
103
+ return String(BigInt(ms) * 1000000n);
104
+ }
105
+ function toOtlpAttributes(attrs) {
106
+ return Object.entries(attrs).map(([key, value]) => {
107
+ if (typeof value === 'string')
108
+ return { key, value: { stringValue: value } };
109
+ if (typeof value === 'number')
110
+ return { key, value: { intValue: String(value) } };
111
+ if (typeof value === 'boolean')
112
+ return { key, value: { boolValue: value } };
113
+ return { key, value: { stringValue: String(value) } };
114
+ });
115
+ }
116
+ export function formatTraceOtlp(trace, options) {
117
+ if (!trace.root) {
118
+ return JSON.stringify({ resourceSpans: [] });
119
+ }
120
+ const serviceName = options?.serviceName ?? 'agentforge';
121
+ const otlpSpans = trace.spans.map((span) => {
122
+ const otlpSpan = {
123
+ traceId: toHex32(span.traceId),
124
+ spanId: toHex16(span.spanId),
125
+ name: span.name,
126
+ kind: 1,
127
+ startTimeUnixNano: msToNano(span.startTime),
128
+ endTimeUnixNano: msToNano(span.endTime),
129
+ attributes: toOtlpAttributes(span.attributes),
130
+ status: {},
131
+ };
132
+ if (span.parentSpanId) {
133
+ otlpSpan.parentSpanId = toHex16(span.parentSpanId);
134
+ }
135
+ if (span.events.length > 0) {
136
+ otlpSpan.events = span.events.map((ev) => ({
137
+ name: ev.name,
138
+ timeUnixNano: msToNano(span.startTime),
139
+ attributes: ev.attributes ? toOtlpAttributes(ev.attributes) : [],
140
+ }));
141
+ }
142
+ return otlpSpan;
143
+ });
144
+ return JSON.stringify({
145
+ resourceSpans: [{
146
+ resource: {
147
+ attributes: [{ key: 'service.name', value: { stringValue: serviceName } }],
148
+ },
149
+ scopeSpans: [{
150
+ scope: { name: '@primo-ai/observability' },
151
+ spans: otlpSpans,
152
+ }],
153
+ }],
154
+ });
155
+ }
156
+ //# sourceMappingURL=trace-collector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace-collector.js","sourceRoot":"","sources":["../src/trace-collector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import type { Metrics, Span, SpanContext, Tracer } from '@primo-ai/sdk';
2
+ export interface SpanData {
3
+ name: string;
4
+ spanId: string;
5
+ traceId: string;
6
+ parentSpanId?: string;
7
+ attributes: Record<string, unknown>;
8
+ events: Array<{
9
+ name: string;
10
+ attributes?: Record<string, unknown>;
11
+ }>;
12
+ ended: boolean;
13
+ startTime: number;
14
+ endTime: number;
15
+ durationMs: number;
16
+ }
17
+ export type OnSpanEndCallback = (span: SpanData) => void;
18
+ export declare class SpanImpl implements Span {
19
+ readonly name: string;
20
+ private readonly _traceId;
21
+ private readonly _spanId;
22
+ private readonly _parentSpanId?;
23
+ private readonly _onSpanEnd?;
24
+ private _ended;
25
+ private _attributes;
26
+ private _events;
27
+ private readonly _startTime;
28
+ constructor(name: string, traceId: string, spanId: string, parentSpanId?: string, onSpanEnd?: OnSpanEndCallback);
29
+ startChild(name: string): Span;
30
+ end(): void;
31
+ get startTime(): number;
32
+ setAttribute(key: string, value: unknown): Span;
33
+ addEvent(name: string, attributes?: Record<string, unknown>): Span;
34
+ spanContext(): SpanContext;
35
+ get parentSpanId(): string | undefined;
36
+ get ended(): boolean;
37
+ toData(): SpanData;
38
+ }
39
+ export declare class TracerImpl implements Tracer {
40
+ private readonly _traceId;
41
+ private readonly _onSpanEnd?;
42
+ private _currentSpan;
43
+ constructor(onSpanEnd?: OnSpanEndCallback);
44
+ startSpan(name: string): Span;
45
+ get traceId(): string;
46
+ getCurrentSpan(): Span | undefined;
47
+ withSpan<T>(span: Span, fn: () => T): T;
48
+ }
49
+ export declare class NoOpMetrics implements Metrics {
50
+ increment(_name: string, _delta?: number, _labels?: Record<string, string>): void;
51
+ gauge(_name: string, _value: number, _labels?: Record<string, string>): void;
52
+ histogram(_name: string, _value: number, _labels?: Record<string, string>): void;
53
+ }
54
+ //# sourceMappingURL=tracer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../src/tracer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAExE,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IACtE,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;AAEzD,qBAAa,QAAS,YAAW,IAAI;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAoB;IAChD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,OAAO,CAAqE;IACpF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,iBAAiB;IAS/G,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9B,GAAG,IAAI,IAAI;IAKX,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAK/C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAKlE,WAAW,IAAI,WAAW;IAI1B,IAAI,YAAY,IAAI,MAAM,GAAG,SAAS,CAErC;IAED,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED,MAAM,IAAI,QAAQ;CAenB;AAED,qBAAa,UAAW,YAAW,MAAM;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAoB;IAChD,OAAO,CAAC,YAAY,CAAmB;gBAE3B,SAAS,CAAC,EAAE,iBAAiB;IAKzC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK7B,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,cAAc,IAAI,IAAI,GAAG,SAAS;IAIlC,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;CASxC;AAED,qBAAa,WAAY,YAAW,OAAO;IACzC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IACjF,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAC5E,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;CACjF"}
package/dist/tracer.js ADDED
@@ -0,0 +1,96 @@
1
+ export class SpanImpl {
2
+ name;
3
+ _traceId;
4
+ _spanId;
5
+ _parentSpanId;
6
+ _onSpanEnd;
7
+ _ended = false;
8
+ _attributes = {};
9
+ _events = [];
10
+ _startTime;
11
+ constructor(name, traceId, spanId, parentSpanId, onSpanEnd) {
12
+ this.name = name;
13
+ this._traceId = traceId;
14
+ this._spanId = spanId;
15
+ this._parentSpanId = parentSpanId;
16
+ this._onSpanEnd = onSpanEnd;
17
+ this._startTime = Date.now();
18
+ }
19
+ startChild(name) {
20
+ return new SpanImpl(name, this._traceId, crypto.randomUUID(), this._spanId, this._onSpanEnd);
21
+ }
22
+ end() {
23
+ this._ended = true;
24
+ this._onSpanEnd?.(this.toData());
25
+ }
26
+ get startTime() {
27
+ return this._startTime;
28
+ }
29
+ setAttribute(key, value) {
30
+ this._attributes[key] = value;
31
+ return this;
32
+ }
33
+ addEvent(name, attributes) {
34
+ this._events.push({ name, attributes });
35
+ return this;
36
+ }
37
+ spanContext() {
38
+ return { spanId: this._spanId, traceId: this._traceId };
39
+ }
40
+ get parentSpanId() {
41
+ return this._parentSpanId;
42
+ }
43
+ get ended() {
44
+ return this._ended;
45
+ }
46
+ toData() {
47
+ const endTime = this._ended ? Date.now() : this._startTime;
48
+ return {
49
+ name: this.name,
50
+ spanId: this._spanId,
51
+ traceId: this._traceId,
52
+ parentSpanId: this._parentSpanId,
53
+ attributes: { ...this._attributes },
54
+ events: [...this._events],
55
+ ended: this._ended,
56
+ startTime: this._startTime,
57
+ endTime,
58
+ durationMs: endTime - this._startTime,
59
+ };
60
+ }
61
+ }
62
+ export class TracerImpl {
63
+ _traceId;
64
+ _onSpanEnd;
65
+ _currentSpan;
66
+ constructor(onSpanEnd) {
67
+ this._traceId = crypto.randomUUID();
68
+ this._onSpanEnd = onSpanEnd;
69
+ }
70
+ startSpan(name) {
71
+ const spanId = crypto.randomUUID();
72
+ return new SpanImpl(name, this._traceId, spanId, undefined, this._onSpanEnd);
73
+ }
74
+ get traceId() {
75
+ return this._traceId;
76
+ }
77
+ getCurrentSpan() {
78
+ return this._currentSpan;
79
+ }
80
+ withSpan(span, fn) {
81
+ const previous = this._currentSpan;
82
+ this._currentSpan = span;
83
+ try {
84
+ return fn();
85
+ }
86
+ finally {
87
+ this._currentSpan = previous;
88
+ }
89
+ }
90
+ }
91
+ export class NoOpMetrics {
92
+ increment(_name, _delta, _labels) { }
93
+ gauge(_name, _value, _labels) { }
94
+ histogram(_name, _value, _labels) { }
95
+ }
96
+ //# sourceMappingURL=tracer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracer.js","sourceRoot":"","sources":["../src/tracer.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@primo-ai/observability",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "files": ["dist"],
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "tsc -p tsconfig.build.json",
16
+ "test": "vitest run --passWithNoTests",
17
+ "check-types": "tsc --noEmit",
18
+ "lint": "eslint src __tests__"
19
+ },
20
+ "devDependencies": {
21
+ "@primo-ai/sdk": "workspace:*",
22
+ "@opentelemetry/resources": "^2.7.1",
23
+ "@opentelemetry/sdk-trace-base": "^2.7.1",
24
+ "typescript": "^5.7.3",
25
+ "vitest": "^3.0.5"
26
+ },
27
+ "dependencies": {
28
+ "@opentelemetry/api": "^1.9.1"
29
+ }
30
+ }