@compilr-dev/agents 0.0.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/README.md +1277 -0
- package/dist/agent.d.ts +1272 -0
- package/dist/agent.js +1912 -0
- package/dist/anchors/builtin.d.ts +24 -0
- package/dist/anchors/builtin.js +61 -0
- package/dist/anchors/index.d.ts +6 -0
- package/dist/anchors/index.js +5 -0
- package/dist/anchors/manager.d.ts +115 -0
- package/dist/anchors/manager.js +412 -0
- package/dist/anchors/types.d.ts +168 -0
- package/dist/anchors/types.js +10 -0
- package/dist/context/index.d.ts +12 -0
- package/dist/context/index.js +10 -0
- package/dist/context/manager.d.ts +224 -0
- package/dist/context/manager.js +770 -0
- package/dist/context/types.d.ts +377 -0
- package/dist/context/types.js +7 -0
- package/dist/costs/index.d.ts +8 -0
- package/dist/costs/index.js +7 -0
- package/dist/costs/tracker.d.ts +121 -0
- package/dist/costs/tracker.js +295 -0
- package/dist/costs/types.d.ts +157 -0
- package/dist/costs/types.js +8 -0
- package/dist/errors.d.ts +178 -0
- package/dist/errors.js +249 -0
- package/dist/guardrails/builtin.d.ts +27 -0
- package/dist/guardrails/builtin.js +223 -0
- package/dist/guardrails/index.d.ts +6 -0
- package/dist/guardrails/index.js +5 -0
- package/dist/guardrails/manager.d.ts +117 -0
- package/dist/guardrails/manager.js +288 -0
- package/dist/guardrails/types.d.ts +159 -0
- package/dist/guardrails/types.js +7 -0
- package/dist/hooks/index.d.ts +31 -0
- package/dist/hooks/index.js +29 -0
- package/dist/hooks/manager.d.ts +147 -0
- package/dist/hooks/manager.js +600 -0
- package/dist/hooks/types.d.ts +368 -0
- package/dist/hooks/types.js +12 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +73 -0
- package/dist/mcp/client.d.ts +93 -0
- package/dist/mcp/client.js +287 -0
- package/dist/mcp/errors.d.ts +60 -0
- package/dist/mcp/errors.js +78 -0
- package/dist/mcp/index.d.ts +43 -0
- package/dist/mcp/index.js +45 -0
- package/dist/mcp/manager.d.ts +120 -0
- package/dist/mcp/manager.js +276 -0
- package/dist/mcp/tools.d.ts +54 -0
- package/dist/mcp/tools.js +99 -0
- package/dist/mcp/types.d.ts +150 -0
- package/dist/mcp/types.js +40 -0
- package/dist/memory/index.d.ts +8 -0
- package/dist/memory/index.js +7 -0
- package/dist/memory/loader.d.ts +114 -0
- package/dist/memory/loader.js +463 -0
- package/dist/memory/types.d.ts +182 -0
- package/dist/memory/types.js +8 -0
- package/dist/messages/index.d.ts +82 -0
- package/dist/messages/index.js +155 -0
- package/dist/permissions/index.d.ts +5 -0
- package/dist/permissions/index.js +4 -0
- package/dist/permissions/manager.d.ts +125 -0
- package/dist/permissions/manager.js +379 -0
- package/dist/permissions/types.d.ts +162 -0
- package/dist/permissions/types.js +7 -0
- package/dist/providers/claude.d.ts +90 -0
- package/dist/providers/claude.js +348 -0
- package/dist/providers/index.d.ts +8 -0
- package/dist/providers/index.js +11 -0
- package/dist/providers/mock.d.ts +133 -0
- package/dist/providers/mock.js +204 -0
- package/dist/providers/types.d.ts +168 -0
- package/dist/providers/types.js +4 -0
- package/dist/rate-limit/index.d.ts +45 -0
- package/dist/rate-limit/index.js +47 -0
- package/dist/rate-limit/limiter.d.ts +104 -0
- package/dist/rate-limit/limiter.js +326 -0
- package/dist/rate-limit/provider-wrapper.d.ts +112 -0
- package/dist/rate-limit/provider-wrapper.js +201 -0
- package/dist/rate-limit/retry.d.ts +108 -0
- package/dist/rate-limit/retry.js +287 -0
- package/dist/rate-limit/types.d.ts +181 -0
- package/dist/rate-limit/types.js +22 -0
- package/dist/rehearsal/file-analyzer.d.ts +22 -0
- package/dist/rehearsal/file-analyzer.js +351 -0
- package/dist/rehearsal/git-analyzer.d.ts +22 -0
- package/dist/rehearsal/git-analyzer.js +472 -0
- package/dist/rehearsal/index.d.ts +35 -0
- package/dist/rehearsal/index.js +36 -0
- package/dist/rehearsal/manager.d.ts +100 -0
- package/dist/rehearsal/manager.js +290 -0
- package/dist/rehearsal/types.d.ts +235 -0
- package/dist/rehearsal/types.js +8 -0
- package/dist/skills/index.d.ts +160 -0
- package/dist/skills/index.js +282 -0
- package/dist/state/agent-state.d.ts +41 -0
- package/dist/state/agent-state.js +88 -0
- package/dist/state/checkpointer.d.ts +110 -0
- package/dist/state/checkpointer.js +362 -0
- package/dist/state/errors.d.ts +66 -0
- package/dist/state/errors.js +88 -0
- package/dist/state/index.d.ts +35 -0
- package/dist/state/index.js +37 -0
- package/dist/state/serializer.d.ts +55 -0
- package/dist/state/serializer.js +172 -0
- package/dist/state/types.d.ts +312 -0
- package/dist/state/types.js +14 -0
- package/dist/tools/builtin/bash-output.d.ts +61 -0
- package/dist/tools/builtin/bash-output.js +90 -0
- package/dist/tools/builtin/bash.d.ts +150 -0
- package/dist/tools/builtin/bash.js +354 -0
- package/dist/tools/builtin/edit.d.ts +50 -0
- package/dist/tools/builtin/edit.js +215 -0
- package/dist/tools/builtin/glob.d.ts +62 -0
- package/dist/tools/builtin/glob.js +244 -0
- package/dist/tools/builtin/grep.d.ts +74 -0
- package/dist/tools/builtin/grep.js +363 -0
- package/dist/tools/builtin/index.d.ts +44 -0
- package/dist/tools/builtin/index.js +69 -0
- package/dist/tools/builtin/kill-shell.d.ts +44 -0
- package/dist/tools/builtin/kill-shell.js +80 -0
- package/dist/tools/builtin/read-file.d.ts +57 -0
- package/dist/tools/builtin/read-file.js +184 -0
- package/dist/tools/builtin/shell-manager.d.ts +176 -0
- package/dist/tools/builtin/shell-manager.js +337 -0
- package/dist/tools/builtin/task.d.ts +202 -0
- package/dist/tools/builtin/task.js +350 -0
- package/dist/tools/builtin/todo.d.ts +207 -0
- package/dist/tools/builtin/todo.js +453 -0
- package/dist/tools/builtin/utils.d.ts +27 -0
- package/dist/tools/builtin/utils.js +70 -0
- package/dist/tools/builtin/web-fetch.d.ts +96 -0
- package/dist/tools/builtin/web-fetch.js +290 -0
- package/dist/tools/builtin/write-file.d.ts +54 -0
- package/dist/tools/builtin/write-file.js +147 -0
- package/dist/tools/define.d.ts +60 -0
- package/dist/tools/define.js +65 -0
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.js +37 -0
- package/dist/tools/registry.d.ts +79 -0
- package/dist/tools/registry.js +151 -0
- package/dist/tools/types.d.ts +59 -0
- package/dist/tools/types.js +4 -0
- package/dist/tracing/hooks.d.ts +58 -0
- package/dist/tracing/hooks.js +377 -0
- package/dist/tracing/index.d.ts +51 -0
- package/dist/tracing/index.js +55 -0
- package/dist/tracing/logging.d.ts +78 -0
- package/dist/tracing/logging.js +310 -0
- package/dist/tracing/manager.d.ts +160 -0
- package/dist/tracing/manager.js +468 -0
- package/dist/tracing/otel.d.ts +102 -0
- package/dist/tracing/otel.js +246 -0
- package/dist/tracing/types.d.ts +346 -0
- package/dist/tracing/types.js +38 -0
- package/dist/utils/index.d.ts +23 -0
- package/dist/utils/index.js +44 -0
- package/package.json +79 -0
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TracingManager - Manages distributed tracing for agent execution
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - Trace and span management with correlation IDs
|
|
6
|
+
* - OpenTelemetry-compatible span structure
|
|
7
|
+
* - Event emission for observability integrations
|
|
8
|
+
* - Optional export to OTel backends
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Default maximum spans per trace
|
|
12
|
+
*/
|
|
13
|
+
const DEFAULT_MAX_SPANS = 1000;
|
|
14
|
+
/**
|
|
15
|
+
* Manages distributed tracing for agent operations
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const tracing = new TracingManager({
|
|
20
|
+
* serviceName: 'my-agent',
|
|
21
|
+
* defaultAttributes: { environment: 'production' },
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* // Start a trace
|
|
25
|
+
* const traceId = tracing.startTrace();
|
|
26
|
+
*
|
|
27
|
+
* // Create spans
|
|
28
|
+
* const span = tracing.startSpan({ name: 'process-request' });
|
|
29
|
+
* span.attributes['request.id'] = '123';
|
|
30
|
+
*
|
|
31
|
+
* // End span and trace
|
|
32
|
+
* tracing.endSpan(span.spanId, { status: 'ok' });
|
|
33
|
+
* const trace = tracing.endTrace(traceId);
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export class TracingManager {
|
|
37
|
+
serviceName;
|
|
38
|
+
serviceVersion;
|
|
39
|
+
defaultAttributes;
|
|
40
|
+
maxSpansPerTrace;
|
|
41
|
+
autoGenerateTraceId;
|
|
42
|
+
// Storage
|
|
43
|
+
traces = new Map();
|
|
44
|
+
spans = new Map();
|
|
45
|
+
activeSpanStack = [];
|
|
46
|
+
// Event handling
|
|
47
|
+
eventHandlers = new Set();
|
|
48
|
+
// Optional OTel exporter
|
|
49
|
+
otelExporter;
|
|
50
|
+
// ID generation
|
|
51
|
+
spanIdCounter = 0;
|
|
52
|
+
traceIdCounter = 0;
|
|
53
|
+
constructor(options = {}) {
|
|
54
|
+
this.serviceName = options.serviceName ?? 'agent';
|
|
55
|
+
this.serviceVersion = options.serviceVersion ?? '1.0.0';
|
|
56
|
+
this.defaultAttributes = {
|
|
57
|
+
'service.name': this.serviceName,
|
|
58
|
+
'service.version': this.serviceVersion,
|
|
59
|
+
...options.defaultAttributes,
|
|
60
|
+
};
|
|
61
|
+
this.maxSpansPerTrace = options.maxSpansPerTrace ?? DEFAULT_MAX_SPANS;
|
|
62
|
+
this.autoGenerateTraceId = options.autoGenerateTraceId ?? true;
|
|
63
|
+
this.otelExporter = options.otelExporter;
|
|
64
|
+
if (options.onEvent) {
|
|
65
|
+
this.eventHandlers.add(options.onEvent);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// ============================================================================
|
|
69
|
+
// Trace Management
|
|
70
|
+
// ============================================================================
|
|
71
|
+
/**
|
|
72
|
+
* Start a new trace
|
|
73
|
+
*
|
|
74
|
+
* @param attributes - Additional trace-level attributes
|
|
75
|
+
* @returns Trace ID
|
|
76
|
+
*/
|
|
77
|
+
startTrace(attributes) {
|
|
78
|
+
const traceId = this.generateTraceId();
|
|
79
|
+
const now = Date.now();
|
|
80
|
+
const trace = {
|
|
81
|
+
traceId,
|
|
82
|
+
rootSpanId: '', // Will be set when first span is created
|
|
83
|
+
spans: [],
|
|
84
|
+
startTime: now,
|
|
85
|
+
attributes: {
|
|
86
|
+
...this.defaultAttributes,
|
|
87
|
+
...attributes,
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
this.traces.set(traceId, trace);
|
|
91
|
+
this.emit({ type: 'trace:started', traceId, timestamp: now });
|
|
92
|
+
return traceId;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* End a trace and optionally export it
|
|
96
|
+
*
|
|
97
|
+
* @param traceId - Trace ID to end
|
|
98
|
+
* @returns Completed trace or undefined if not found
|
|
99
|
+
*/
|
|
100
|
+
endTrace(traceId) {
|
|
101
|
+
const trace = this.traces.get(traceId);
|
|
102
|
+
if (!trace)
|
|
103
|
+
return undefined;
|
|
104
|
+
const now = Date.now();
|
|
105
|
+
trace.endTime = now;
|
|
106
|
+
trace.durationMs = now - trace.startTime;
|
|
107
|
+
// End any remaining active spans in this trace
|
|
108
|
+
for (const span of trace.spans) {
|
|
109
|
+
if (span.endTime === undefined) {
|
|
110
|
+
this.endSpan(span.spanId, { status: 'unset' });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
this.emit({
|
|
114
|
+
type: 'trace:ended',
|
|
115
|
+
traceId,
|
|
116
|
+
durationMs: trace.durationMs,
|
|
117
|
+
spanCount: trace.spans.length,
|
|
118
|
+
});
|
|
119
|
+
// Export if exporter is configured
|
|
120
|
+
if (this.otelExporter) {
|
|
121
|
+
void this.exportTrace(trace);
|
|
122
|
+
}
|
|
123
|
+
return trace;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Get a trace by ID
|
|
127
|
+
*/
|
|
128
|
+
getTrace(traceId) {
|
|
129
|
+
return this.traces.get(traceId);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Get all active traces
|
|
133
|
+
*/
|
|
134
|
+
getActiveTraces() {
|
|
135
|
+
return Array.from(this.traces.values()).filter((t) => t.endTime === undefined);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Clear a trace from memory
|
|
139
|
+
*/
|
|
140
|
+
clearTrace(traceId) {
|
|
141
|
+
const trace = this.traces.get(traceId);
|
|
142
|
+
if (!trace)
|
|
143
|
+
return false;
|
|
144
|
+
// Remove all spans
|
|
145
|
+
for (const span of trace.spans) {
|
|
146
|
+
this.spans.delete(span.spanId);
|
|
147
|
+
}
|
|
148
|
+
this.traces.delete(traceId);
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
// ============================================================================
|
|
152
|
+
// Span Management
|
|
153
|
+
// ============================================================================
|
|
154
|
+
/**
|
|
155
|
+
* Start a new span
|
|
156
|
+
*
|
|
157
|
+
* @param options - Span options
|
|
158
|
+
* @returns Created span
|
|
159
|
+
*/
|
|
160
|
+
startSpan(options) {
|
|
161
|
+
const spanId = this.generateSpanId();
|
|
162
|
+
const now = options.startTime ?? Date.now();
|
|
163
|
+
// Determine parent context
|
|
164
|
+
let traceId;
|
|
165
|
+
let parentSpanId;
|
|
166
|
+
if (options.parentContext) {
|
|
167
|
+
traceId = options.parentContext.traceId;
|
|
168
|
+
parentSpanId = options.parentContext.parentSpanId;
|
|
169
|
+
}
|
|
170
|
+
else if (this.activeSpanStack.length > 0) {
|
|
171
|
+
// Use current span as parent
|
|
172
|
+
const currentSpan = this.getCurrentSpan();
|
|
173
|
+
if (currentSpan) {
|
|
174
|
+
traceId = currentSpan.traceId;
|
|
175
|
+
parentSpanId = currentSpan.spanId;
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
// No active span, create new trace if auto-generate is on
|
|
179
|
+
traceId = this.autoGenerateTraceId ? this.startTrace() : this.generateTraceId();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
// No context, create new trace if auto-generate is on
|
|
184
|
+
traceId = this.autoGenerateTraceId ? this.startTrace() : this.generateTraceId();
|
|
185
|
+
}
|
|
186
|
+
const span = {
|
|
187
|
+
spanId,
|
|
188
|
+
traceId,
|
|
189
|
+
parentSpanId,
|
|
190
|
+
name: options.name,
|
|
191
|
+
kind: options.kind ?? 'internal',
|
|
192
|
+
startTime: now,
|
|
193
|
+
status: 'unset',
|
|
194
|
+
attributes: {
|
|
195
|
+
...this.defaultAttributes,
|
|
196
|
+
...options.attributes,
|
|
197
|
+
},
|
|
198
|
+
events: [],
|
|
199
|
+
};
|
|
200
|
+
// Store span
|
|
201
|
+
this.spans.set(spanId, span);
|
|
202
|
+
this.activeSpanStack.push(spanId);
|
|
203
|
+
// Add to trace
|
|
204
|
+
const trace = this.traces.get(traceId);
|
|
205
|
+
if (trace) {
|
|
206
|
+
// Check max spans limit
|
|
207
|
+
if (trace.spans.length >= this.maxSpansPerTrace) {
|
|
208
|
+
// Remove oldest span to make room
|
|
209
|
+
const oldest = trace.spans.shift();
|
|
210
|
+
if (oldest) {
|
|
211
|
+
this.spans.delete(oldest.spanId);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
trace.spans.push(span);
|
|
215
|
+
// Set root span if this is the first
|
|
216
|
+
if (!trace.rootSpanId) {
|
|
217
|
+
trace.rootSpanId = spanId;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
this.emit({
|
|
221
|
+
type: 'span:started',
|
|
222
|
+
spanId,
|
|
223
|
+
traceId,
|
|
224
|
+
name: span.name,
|
|
225
|
+
parentSpanId,
|
|
226
|
+
});
|
|
227
|
+
return span;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* End a span
|
|
231
|
+
*
|
|
232
|
+
* @param spanId - Span ID to end
|
|
233
|
+
* @param options - End options
|
|
234
|
+
* @returns Ended span or undefined if not found
|
|
235
|
+
*/
|
|
236
|
+
endSpan(spanId, options) {
|
|
237
|
+
const span = this.spans.get(spanId);
|
|
238
|
+
if (!span)
|
|
239
|
+
return undefined;
|
|
240
|
+
const now = options?.endTime ?? Date.now();
|
|
241
|
+
span.endTime = now;
|
|
242
|
+
span.durationMs = now - span.startTime;
|
|
243
|
+
if (options?.status) {
|
|
244
|
+
span.status = options.status;
|
|
245
|
+
}
|
|
246
|
+
if (options?.statusMessage) {
|
|
247
|
+
span.statusMessage = options.statusMessage;
|
|
248
|
+
}
|
|
249
|
+
if (options?.attributes) {
|
|
250
|
+
Object.assign(span.attributes, options.attributes);
|
|
251
|
+
}
|
|
252
|
+
// Remove from active stack
|
|
253
|
+
const stackIndex = this.activeSpanStack.indexOf(spanId);
|
|
254
|
+
if (stackIndex !== -1) {
|
|
255
|
+
this.activeSpanStack.splice(stackIndex, 1);
|
|
256
|
+
}
|
|
257
|
+
this.emit({
|
|
258
|
+
type: 'span:ended',
|
|
259
|
+
spanId,
|
|
260
|
+
traceId: span.traceId,
|
|
261
|
+
durationMs: span.durationMs,
|
|
262
|
+
status: span.status,
|
|
263
|
+
});
|
|
264
|
+
return span;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Get a span by ID
|
|
268
|
+
*/
|
|
269
|
+
getSpan(spanId) {
|
|
270
|
+
return this.spans.get(spanId);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Get the current active span
|
|
274
|
+
*/
|
|
275
|
+
getCurrentSpan() {
|
|
276
|
+
if (this.activeSpanStack.length === 0)
|
|
277
|
+
return undefined;
|
|
278
|
+
const currentId = this.activeSpanStack[this.activeSpanStack.length - 1];
|
|
279
|
+
return this.spans.get(currentId);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Get current span context for propagation
|
|
283
|
+
*/
|
|
284
|
+
getCurrentContext() {
|
|
285
|
+
const currentSpan = this.getCurrentSpan();
|
|
286
|
+
if (!currentSpan)
|
|
287
|
+
return undefined;
|
|
288
|
+
return {
|
|
289
|
+
traceId: currentSpan.traceId,
|
|
290
|
+
parentSpanId: currentSpan.spanId,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
// ============================================================================
|
|
294
|
+
// Span Modification
|
|
295
|
+
// ============================================================================
|
|
296
|
+
/**
|
|
297
|
+
* Add an event to a span
|
|
298
|
+
*
|
|
299
|
+
* @param spanId - Span ID
|
|
300
|
+
* @param name - Event name
|
|
301
|
+
* @param attributes - Event attributes
|
|
302
|
+
*/
|
|
303
|
+
addSpanEvent(spanId, name, attributes) {
|
|
304
|
+
const span = this.spans.get(spanId);
|
|
305
|
+
if (!span)
|
|
306
|
+
return;
|
|
307
|
+
const event = {
|
|
308
|
+
name,
|
|
309
|
+
timestamp: Date.now(),
|
|
310
|
+
attributes,
|
|
311
|
+
};
|
|
312
|
+
span.events.push(event);
|
|
313
|
+
this.emit({
|
|
314
|
+
type: 'span:event',
|
|
315
|
+
spanId,
|
|
316
|
+
traceId: span.traceId,
|
|
317
|
+
eventName: name,
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Set attributes on a span
|
|
322
|
+
*
|
|
323
|
+
* @param spanId - Span ID
|
|
324
|
+
* @param attributes - Attributes to set
|
|
325
|
+
*/
|
|
326
|
+
setSpanAttributes(spanId, attributes) {
|
|
327
|
+
const span = this.spans.get(spanId);
|
|
328
|
+
if (!span)
|
|
329
|
+
return;
|
|
330
|
+
Object.assign(span.attributes, attributes);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Set span status
|
|
334
|
+
*
|
|
335
|
+
* @param spanId - Span ID
|
|
336
|
+
* @param status - Status
|
|
337
|
+
* @param message - Optional status message
|
|
338
|
+
*/
|
|
339
|
+
setSpanStatus(spanId, status, message) {
|
|
340
|
+
const span = this.spans.get(spanId);
|
|
341
|
+
if (!span)
|
|
342
|
+
return;
|
|
343
|
+
span.status = status;
|
|
344
|
+
if (message) {
|
|
345
|
+
span.statusMessage = message;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Record an error on a span
|
|
350
|
+
*
|
|
351
|
+
* @param spanId - Span ID
|
|
352
|
+
* @param error - Error to record
|
|
353
|
+
*/
|
|
354
|
+
recordError(spanId, error) {
|
|
355
|
+
const span = this.spans.get(spanId);
|
|
356
|
+
if (!span)
|
|
357
|
+
return;
|
|
358
|
+
span.status = 'error';
|
|
359
|
+
span.statusMessage = error.message;
|
|
360
|
+
this.addSpanEvent(spanId, 'exception', {
|
|
361
|
+
'exception.type': error.name,
|
|
362
|
+
'exception.message': error.message,
|
|
363
|
+
'exception.stacktrace': error.stack ?? '',
|
|
364
|
+
});
|
|
365
|
+
this.emit({
|
|
366
|
+
type: 'span:error',
|
|
367
|
+
spanId,
|
|
368
|
+
traceId: span.traceId,
|
|
369
|
+
error,
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
// ============================================================================
|
|
373
|
+
// Event Handling
|
|
374
|
+
// ============================================================================
|
|
375
|
+
/**
|
|
376
|
+
* Subscribe to tracing events
|
|
377
|
+
*
|
|
378
|
+
* @param handler - Event handler
|
|
379
|
+
* @returns Unsubscribe function
|
|
380
|
+
*/
|
|
381
|
+
onEvent(handler) {
|
|
382
|
+
this.eventHandlers.add(handler);
|
|
383
|
+
return () => this.eventHandlers.delete(handler);
|
|
384
|
+
}
|
|
385
|
+
emit(event) {
|
|
386
|
+
for (const handler of this.eventHandlers) {
|
|
387
|
+
try {
|
|
388
|
+
handler(event);
|
|
389
|
+
}
|
|
390
|
+
catch {
|
|
391
|
+
// Silently ignore handler errors
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
// ============================================================================
|
|
396
|
+
// Export
|
|
397
|
+
// ============================================================================
|
|
398
|
+
/**
|
|
399
|
+
* Export a trace to configured exporter
|
|
400
|
+
*/
|
|
401
|
+
async exportTrace(trace) {
|
|
402
|
+
if (!this.otelExporter)
|
|
403
|
+
return;
|
|
404
|
+
try {
|
|
405
|
+
await this.otelExporter.export(trace.spans);
|
|
406
|
+
this.emit({
|
|
407
|
+
type: 'export:success',
|
|
408
|
+
traceId: trace.traceId,
|
|
409
|
+
exporter: this.otelExporter.name,
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
catch (error) {
|
|
413
|
+
this.emit({
|
|
414
|
+
type: 'export:error',
|
|
415
|
+
traceId: trace.traceId,
|
|
416
|
+
exporter: this.otelExporter.name,
|
|
417
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Manually export a trace
|
|
423
|
+
*/
|
|
424
|
+
async export(traceId) {
|
|
425
|
+
const trace = this.traces.get(traceId);
|
|
426
|
+
if (trace && this.otelExporter) {
|
|
427
|
+
await this.exportTrace(trace);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
// ============================================================================
|
|
431
|
+
// Utility Methods
|
|
432
|
+
// ============================================================================
|
|
433
|
+
generateTraceId() {
|
|
434
|
+
// Generate a 32-character hex string (128-bit) compatible with W3C Trace Context
|
|
435
|
+
const timestamp = Date.now().toString(16).padStart(12, '0');
|
|
436
|
+
const counter = (++this.traceIdCounter).toString(16).padStart(4, '0');
|
|
437
|
+
const random = Math.random().toString(16).slice(2, 18).padStart(16, '0');
|
|
438
|
+
return `${timestamp}${counter}${random}`.slice(0, 32);
|
|
439
|
+
}
|
|
440
|
+
generateSpanId() {
|
|
441
|
+
// Generate a 16-character hex string (64-bit) compatible with W3C Trace Context
|
|
442
|
+
const timestamp = Date.now().toString(16).padStart(8, '0');
|
|
443
|
+
const counter = (++this.spanIdCounter).toString(16).padStart(4, '0');
|
|
444
|
+
const random = Math.random().toString(16).slice(2, 6);
|
|
445
|
+
return `${timestamp}${counter}${random}`.slice(0, 16);
|
|
446
|
+
}
|
|
447
|
+
// ============================================================================
|
|
448
|
+
// Statistics
|
|
449
|
+
// ============================================================================
|
|
450
|
+
/**
|
|
451
|
+
* Get tracing statistics
|
|
452
|
+
*/
|
|
453
|
+
getStats() {
|
|
454
|
+
return {
|
|
455
|
+
activeTraces: this.getActiveTraces().length,
|
|
456
|
+
totalSpans: this.spans.size,
|
|
457
|
+
activeSpans: this.activeSpanStack.length,
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Clear all traces and spans
|
|
462
|
+
*/
|
|
463
|
+
clear() {
|
|
464
|
+
this.traces.clear();
|
|
465
|
+
this.spans.clear();
|
|
466
|
+
this.activeSpanStack.length = 0;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenTelemetry Integration
|
|
3
|
+
*
|
|
4
|
+
* Provides optional integration with OpenTelemetry for exporting traces
|
|
5
|
+
* to OTel-compatible backends (Jaeger, Zipkin, etc.)
|
|
6
|
+
*
|
|
7
|
+
* Requires optional peer dependency: @opentelemetry/api
|
|
8
|
+
*/
|
|
9
|
+
import type { OTelExporter } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Error thrown when OpenTelemetry SDK is not installed
|
|
12
|
+
*/
|
|
13
|
+
export declare class OTelNotInstalledError extends Error {
|
|
14
|
+
constructor();
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Check if a value is an OTelNotInstalledError
|
|
18
|
+
*/
|
|
19
|
+
export declare function isOTelNotInstalledError(error: unknown): error is OTelNotInstalledError;
|
|
20
|
+
/**
|
|
21
|
+
* Create an OpenTelemetry exporter that wraps OTel spans
|
|
22
|
+
*
|
|
23
|
+
* This exporter converts our internal Span format to OpenTelemetry spans
|
|
24
|
+
* and uses the configured OTel tracer to export them.
|
|
25
|
+
*
|
|
26
|
+
* @param tracerName - Name for the OTel tracer
|
|
27
|
+
* @param tracerVersion - Version for the OTel tracer
|
|
28
|
+
* @returns OTelExporter instance
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* // First, set up OpenTelemetry in your application:
|
|
33
|
+
* // import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
|
|
34
|
+
* // const provider = new NodeTracerProvider();
|
|
35
|
+
* // provider.register();
|
|
36
|
+
*
|
|
37
|
+
* // Then use with TracingManager:
|
|
38
|
+
* const exporter = await createOTelExporter('my-agent', '1.0.0');
|
|
39
|
+
* const tracingManager = new TracingManager({
|
|
40
|
+
* serviceName: 'my-agent',
|
|
41
|
+
* otelExporter: exporter,
|
|
42
|
+
* });
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function createOTelExporter(tracerName?: string, tracerVersion?: string): Promise<OTelExporter>;
|
|
46
|
+
/**
|
|
47
|
+
* Create a console exporter for debugging
|
|
48
|
+
*
|
|
49
|
+
* This exporter simply logs spans to the console in a readable format.
|
|
50
|
+
* Useful for development and debugging.
|
|
51
|
+
*
|
|
52
|
+
* @param options - Console exporter options
|
|
53
|
+
* @returns OTelExporter instance
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const exporter = createConsoleExporter({ prettyPrint: true });
|
|
58
|
+
* const tracingManager = new TracingManager({
|
|
59
|
+
* serviceName: 'my-agent',
|
|
60
|
+
* otelExporter: exporter,
|
|
61
|
+
* });
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare function createConsoleExporter(options?: {
|
|
65
|
+
prettyPrint?: boolean;
|
|
66
|
+
output?: (message: string) => void;
|
|
67
|
+
}): OTelExporter;
|
|
68
|
+
/**
|
|
69
|
+
* Create a batch exporter that buffers spans and exports in batches
|
|
70
|
+
*
|
|
71
|
+
* @param innerExporter - The actual exporter to use
|
|
72
|
+
* @param options - Batch options
|
|
73
|
+
* @returns OTelExporter instance
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* const otelExporter = await createOTelExporter();
|
|
78
|
+
* const batchExporter = createBatchExporter(otelExporter, {
|
|
79
|
+
* maxBatchSize: 100,
|
|
80
|
+
* flushIntervalMs: 5000,
|
|
81
|
+
* });
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare function createBatchExporter(innerExporter: OTelExporter, options?: {
|
|
85
|
+
maxBatchSize?: number;
|
|
86
|
+
flushIntervalMs?: number;
|
|
87
|
+
}): OTelExporter;
|
|
88
|
+
/**
|
|
89
|
+
* Create a multi-exporter that sends to multiple backends
|
|
90
|
+
*
|
|
91
|
+
* @param exporters - List of exporters to use
|
|
92
|
+
* @returns OTelExporter instance
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* const multiExporter = createMultiExporter([
|
|
97
|
+
* createConsoleExporter(),
|
|
98
|
+
* await createOTelExporter(),
|
|
99
|
+
* ]);
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export declare function createMultiExporter(exporters: OTelExporter[]): OTelExporter;
|