autotel-cloudflare 2.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.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +432 -0
  3. package/dist/actors.d.ts +248 -0
  4. package/dist/actors.js +1030 -0
  5. package/dist/actors.js.map +1 -0
  6. package/dist/agents.d.ts +219 -0
  7. package/dist/agents.js +276 -0
  8. package/dist/agents.js.map +1 -0
  9. package/dist/bindings.d.ts +40 -0
  10. package/dist/bindings.js +4 -0
  11. package/dist/bindings.js.map +1 -0
  12. package/dist/chunk-JDPN3HND.js +520 -0
  13. package/dist/chunk-JDPN3HND.js.map +1 -0
  14. package/dist/chunk-QXFYTHQF.js +298 -0
  15. package/dist/chunk-QXFYTHQF.js.map +1 -0
  16. package/dist/chunk-SKKRPS5K.js +50 -0
  17. package/dist/chunk-SKKRPS5K.js.map +1 -0
  18. package/dist/events.d.ts +1 -0
  19. package/dist/events.js +3 -0
  20. package/dist/events.js.map +1 -0
  21. package/dist/handlers.d.ts +121 -0
  22. package/dist/handlers.js +4 -0
  23. package/dist/handlers.js.map +1 -0
  24. package/dist/index.d.ts +144 -0
  25. package/dist/index.js +576 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/logger.d.ts +1 -0
  28. package/dist/logger.js +3 -0
  29. package/dist/logger.js.map +1 -0
  30. package/dist/sampling.d.ts +4 -0
  31. package/dist/sampling.js +3 -0
  32. package/dist/sampling.js.map +1 -0
  33. package/dist/testing.d.ts +1 -0
  34. package/dist/testing.js +3 -0
  35. package/dist/testing.js.map +1 -0
  36. package/package.json +107 -0
  37. package/src/actors/alarms.ts +225 -0
  38. package/src/actors/index.ts +36 -0
  39. package/src/actors/instrument-actor.test.ts +179 -0
  40. package/src/actors/instrument-actor.ts +574 -0
  41. package/src/actors/sockets.ts +217 -0
  42. package/src/actors/storage.ts +263 -0
  43. package/src/actors/traced-handler.ts +300 -0
  44. package/src/actors/types.ts +98 -0
  45. package/src/actors.ts +50 -0
  46. package/src/agents/index.ts +42 -0
  47. package/src/agents/otel-observability.test.ts +329 -0
  48. package/src/agents/otel-observability.ts +465 -0
  49. package/src/agents/types.ts +167 -0
  50. package/src/agents.ts +76 -0
  51. package/src/bindings/bindings.ts +621 -0
  52. package/src/bindings/common.ts +75 -0
  53. package/src/bindings/index.ts +12 -0
  54. package/src/bindings.ts +6 -0
  55. package/src/events.ts +6 -0
  56. package/src/global/cache.test.ts +292 -0
  57. package/src/global/cache.ts +164 -0
  58. package/src/global/fetch.test.ts +344 -0
  59. package/src/global/fetch.ts +134 -0
  60. package/src/global/index.ts +7 -0
  61. package/src/handlers/durable-objects.test.ts +524 -0
  62. package/src/handlers/durable-objects.ts +250 -0
  63. package/src/handlers/index.ts +6 -0
  64. package/src/handlers/workflows.ts +318 -0
  65. package/src/handlers.ts +6 -0
  66. package/src/index.ts +57 -0
  67. package/src/logger.ts +6 -0
  68. package/src/sampling.ts +6 -0
  69. package/src/testing.ts +6 -0
  70. package/src/wrappers/index.ts +8 -0
  71. package/src/wrappers/instrument.integration.test.ts +468 -0
  72. package/src/wrappers/instrument.ts +643 -0
  73. package/src/wrappers/wrap-do.ts +34 -0
  74. package/src/wrappers/wrap-module.ts +37 -0
@@ -0,0 +1,465 @@
1
+ /**
2
+ * OpenTelemetry-based Observability implementation for Cloudflare Agents SDK
3
+ *
4
+ * Converts Agent events into OpenTelemetry spans for distributed tracing.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { Agent } from 'agents'
9
+ * import { createOtelObservability } from 'autotel-cloudflare/agents'
10
+ *
11
+ * class MyAgent extends Agent<Env> {
12
+ * observability = createOtelObservability({
13
+ * service: { name: 'my-agent' },
14
+ * exporter: { url: env.OTLP_ENDPOINT }
15
+ * })
16
+ *
17
+ * @callable()
18
+ * async doSomething() {
19
+ * // This RPC call will be automatically traced
20
+ * return 'done'
21
+ * }
22
+ * }
23
+ * ```
24
+ */
25
+
26
+ import {
27
+ trace,
28
+ SpanStatusCode,
29
+ SpanKind,
30
+ type Span,
31
+ type Attributes,
32
+ } from '@opentelemetry/api';
33
+ import { resourceFromAttributes } from '@opentelemetry/resources';
34
+ import {
35
+ createInitialiser,
36
+ WorkerTracerProvider,
37
+ WorkerTracer,
38
+ type ResolvedEdgeConfig,
39
+ } from 'autotel-edge';
40
+ import type {
41
+ Observability,
42
+ ObservabilityEvent,
43
+ OtelObservabilityConfig,
44
+ AgentInstrumentationOptions,
45
+ } from './types';
46
+
47
+ /**
48
+ * Map of active spans keyed by event ID
49
+ * Used to correlate start/end events
50
+ */
51
+ const activeSpans = new Map<string, Span>();
52
+
53
+ /**
54
+ * Whether the provider has been initialized
55
+ */
56
+ let providerInitialized = false;
57
+
58
+ /**
59
+ * Initialize the tracer provider for Agents
60
+ */
61
+ function initProvider(config: ResolvedEdgeConfig): void {
62
+ if (providerInitialized) return;
63
+
64
+ // Create resource with agent-specific attributes
65
+ const resource = resourceFromAttributes({
66
+ 'service.name': config.service.name,
67
+ 'service.version': config.service.version,
68
+ 'service.namespace': config.service.namespace,
69
+ 'cloud.provider': 'cloudflare',
70
+ 'cloud.platform': 'cloudflare.workers',
71
+ 'telemetry.sdk.name': 'autotel-cloudflare',
72
+ 'telemetry.sdk.language': 'js',
73
+ 'agent.framework': 'cloudflare-agents',
74
+ });
75
+
76
+ // Create and register provider
77
+ const provider = new WorkerTracerProvider(config.spanProcessors, resource);
78
+ provider.register();
79
+
80
+ // Set head sampler on tracer
81
+ const tracer = trace.getTracer('autotel-cloudflare/agents') as WorkerTracer;
82
+ tracer.setHeadSampler(config.sampling.headSampler);
83
+
84
+ providerInitialized = true;
85
+ }
86
+
87
+ /**
88
+ * Get default span name for an event
89
+ */
90
+ function getDefaultSpanName(event: ObservabilityEvent): string {
91
+ switch (event.type) {
92
+ case 'rpc': {
93
+ return `agent.rpc ${event.payload.method}`;
94
+ }
95
+ case 'schedule:create': {
96
+ return `agent.schedule.create ${event.payload.callback}`;
97
+ }
98
+ case 'schedule:execute': {
99
+ return `agent.schedule.execute ${event.payload.callback}`;
100
+ }
101
+ case 'schedule:cancel': {
102
+ return `agent.schedule.cancel ${event.payload.callback}`;
103
+ }
104
+ case 'connect': {
105
+ return `agent.connect`;
106
+ }
107
+ case 'destroy': {
108
+ return `agent.destroy`;
109
+ }
110
+ case 'state:update': {
111
+ return `agent.state.update`;
112
+ }
113
+ case 'message:request': {
114
+ return `agent.message.request`;
115
+ }
116
+ case 'message:response': {
117
+ return `agent.message.response`;
118
+ }
119
+ case 'message:clear': {
120
+ return `agent.message.clear`;
121
+ }
122
+ case 'mcp:client:preconnect': {
123
+ return `mcp.preconnect ${event.payload.serverId}`;
124
+ }
125
+ case 'mcp:client:connect': {
126
+ return `mcp.connect ${event.payload.url}`;
127
+ }
128
+ case 'mcp:client:authorize': {
129
+ return `mcp.authorize ${event.payload.serverId}`;
130
+ }
131
+ case 'mcp:client:discover': {
132
+ return `mcp.discover`;
133
+ }
134
+ default: {
135
+ return `agent.${(event as ObservabilityEvent).type}`;
136
+ }
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Get default attributes for an event
142
+ */
143
+ function getDefaultAttributes(event: ObservabilityEvent): Attributes {
144
+ const attrs: Attributes = {
145
+ 'agent.event.type': event.type,
146
+ 'agent.event.id': event.id,
147
+ };
148
+
149
+ // Add type-specific attributes
150
+ switch (event.type) {
151
+ case 'rpc': {
152
+ attrs['agent.rpc.method'] = event.payload.method;
153
+ if (event.payload.streaming !== undefined) {
154
+ attrs['agent.rpc.streaming'] = event.payload.streaming;
155
+ }
156
+ break;
157
+ }
158
+
159
+ case 'schedule:create':
160
+ case 'schedule:execute':
161
+ case 'schedule:cancel': {
162
+ attrs['agent.schedule.callback'] = event.payload.callback;
163
+ attrs['agent.schedule.id'] = event.payload.id;
164
+ break;
165
+ }
166
+
167
+ case 'connect': {
168
+ attrs['agent.connection.id'] = event.payload.connectionId;
169
+ break;
170
+ }
171
+
172
+ case 'mcp:client:preconnect': {
173
+ attrs['agent.mcp.server_id'] = event.payload.serverId;
174
+ break;
175
+ }
176
+
177
+ case 'mcp:client:connect': {
178
+ attrs['agent.mcp.url'] = event.payload.url;
179
+ attrs['agent.mcp.transport'] = event.payload.transport;
180
+ attrs['agent.mcp.state'] = event.payload.state;
181
+ if (event.payload.error) {
182
+ attrs['agent.mcp.error'] = event.payload.error;
183
+ }
184
+ break;
185
+ }
186
+
187
+ case 'mcp:client:authorize': {
188
+ attrs['agent.mcp.server_id'] = event.payload.serverId;
189
+ attrs['agent.mcp.auth_url'] = event.payload.authUrl;
190
+ if (event.payload.clientId) {
191
+ attrs['agent.mcp.client_id'] = event.payload.clientId;
192
+ }
193
+ break;
194
+ }
195
+ }
196
+
197
+ // Add any additional payload properties as attributes
198
+ for (const [key, value] of Object.entries(event.payload)) {
199
+ if (
200
+ attrs[`agent.${key}`] === undefined &&
201
+ (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean')
202
+ ) {
203
+ attrs[`agent.payload.${key}`] = value;
204
+ }
205
+ }
206
+
207
+ return attrs;
208
+ }
209
+
210
+ /**
211
+ * Determine span kind based on event type
212
+ */
213
+ function getSpanKind(event: ObservabilityEvent): SpanKind {
214
+ switch (event.type) {
215
+ case 'rpc': {
216
+ return SpanKind.SERVER;
217
+ }
218
+ case 'connect': {
219
+ return SpanKind.SERVER;
220
+ }
221
+ case 'mcp:client:connect':
222
+ case 'mcp:client:preconnect':
223
+ case 'mcp:client:authorize':
224
+ case 'mcp:client:discover': {
225
+ return SpanKind.CLIENT;
226
+ }
227
+ default: {
228
+ return SpanKind.INTERNAL;
229
+ }
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Check if an event type should be traced based on options
235
+ */
236
+ function shouldTraceEvent(
237
+ event: ObservabilityEvent,
238
+ options: AgentInstrumentationOptions,
239
+ ): boolean {
240
+ const defaults: AgentInstrumentationOptions = {
241
+ traceRpc: true,
242
+ traceSchedule: true,
243
+ traceMcp: true,
244
+ traceStateUpdates: false,
245
+ traceMessages: true,
246
+ traceLifecycle: true,
247
+ };
248
+
249
+ const opts = { ...defaults, ...options };
250
+
251
+ switch (event.type) {
252
+ case 'rpc': {
253
+ return opts.traceRpc ?? true;
254
+ }
255
+
256
+ case 'schedule:create':
257
+ case 'schedule:execute':
258
+ case 'schedule:cancel': {
259
+ return opts.traceSchedule ?? true;
260
+ }
261
+
262
+ case 'mcp:client:preconnect':
263
+ case 'mcp:client:connect':
264
+ case 'mcp:client:authorize':
265
+ case 'mcp:client:discover': {
266
+ return opts.traceMcp ?? true;
267
+ }
268
+
269
+ case 'state:update': {
270
+ return opts.traceStateUpdates ?? false;
271
+ }
272
+
273
+ case 'message:request':
274
+ case 'message:response':
275
+ case 'message:clear': {
276
+ return opts.traceMessages ?? true;
277
+ }
278
+
279
+ case 'connect':
280
+ case 'destroy': {
281
+ return opts.traceLifecycle ?? true;
282
+ }
283
+
284
+ default: {
285
+ return true;
286
+ }
287
+ }
288
+ }
289
+
290
+ /**
291
+ * Export spans asynchronously
292
+ */
293
+ async function exportSpans(traceId: string, ctx?: DurableObjectState): Promise<void> {
294
+ const tracer = trace.getTracer('autotel-cloudflare/agents');
295
+ if (tracer instanceof WorkerTracer) {
296
+ try {
297
+ await scheduler.wait(1);
298
+ await tracer.forceFlush(traceId);
299
+ } catch (error) {
300
+ console.error('[autotel-cloudflare/agents] Failed to export spans:', error);
301
+ }
302
+ }
303
+
304
+ // If we have a DurableObject context, use waitUntil for export
305
+ if (ctx && 'waitUntil' in ctx) {
306
+ // Already exported above, but could defer more work here
307
+ }
308
+ }
309
+
310
+ /**
311
+ * OpenTelemetry-based Observability implementation
312
+ *
313
+ * Implements the Agents SDK Observability interface and converts
314
+ * events into OpenTelemetry spans.
315
+ */
316
+ export class OtelObservability implements Observability {
317
+ private config: ResolvedEdgeConfig;
318
+ private options: AgentInstrumentationOptions;
319
+ private initialized = false;
320
+
321
+ constructor(config: OtelObservabilityConfig) {
322
+ // Use createInitialiser to resolve the config
323
+ const initialiser = createInitialiser(config);
324
+ this.config = initialiser({}, undefined);
325
+ this.options = config.agents ?? {};
326
+ }
327
+
328
+ /**
329
+ * Initialize the tracer provider (called lazily on first emit)
330
+ */
331
+ private initialize(): void {
332
+ if (this.initialized) return;
333
+ initProvider(this.config);
334
+ this.initialized = true;
335
+ }
336
+
337
+ /**
338
+ * Emit an observability event
339
+ *
340
+ * Converts the event to an OpenTelemetry span based on the event type.
341
+ */
342
+ emit(event: ObservabilityEvent, ctx?: DurableObjectState): void {
343
+ // Initialize provider on first emit
344
+ this.initialize();
345
+
346
+ // Check if this event type should be traced
347
+ if (!shouldTraceEvent(event, this.options)) {
348
+ return;
349
+ }
350
+
351
+ const tracer = trace.getTracer('autotel-cloudflare/agents');
352
+
353
+ // Get span name (custom or default)
354
+ const spanName = this.options.spanNameFormatter
355
+ ? this.options.spanNameFormatter(event)
356
+ : getDefaultSpanName(event);
357
+
358
+ // Get attributes (custom + default)
359
+ const defaultAttrs = getDefaultAttributes(event);
360
+ const customAttrs = this.options.attributeExtractor
361
+ ? this.options.attributeExtractor(event)
362
+ : {};
363
+ const attributes = { ...defaultAttrs, ...customAttrs };
364
+
365
+ // Determine span kind
366
+ const kind = getSpanKind(event);
367
+
368
+ // Create span with event timestamp
369
+ const span = tracer.startSpan(spanName, {
370
+ kind,
371
+ attributes,
372
+ startTime: event.timestamp,
373
+ });
374
+
375
+ // For short-lived events, end immediately
376
+ // For events that have duration (like RPC), we would ideally track start/end
377
+ // But the Agents SDK emits single events, so we create point-in-time spans
378
+ span.setStatus({ code: SpanStatusCode.OK });
379
+ span.end(event.timestamp + 1); // End 1ms after start
380
+
381
+ // Store span for potential correlation
382
+ activeSpans.set(event.id, span);
383
+
384
+ // Schedule span export
385
+ const traceId = span.spanContext().traceId;
386
+ if (ctx && 'waitUntil' in ctx && typeof (ctx as any).waitUntil === 'function') {
387
+ (ctx as any).waitUntil(exportSpans(traceId, ctx));
388
+ } else {
389
+ // In environments without waitUntil, export synchronously-ish
390
+ void exportSpans(traceId, ctx);
391
+ }
392
+ }
393
+ }
394
+
395
+ /**
396
+ * Create an OtelObservability instance
397
+ *
398
+ * @example
399
+ * ```typescript
400
+ * import { Agent } from 'agents'
401
+ * import { createOtelObservability } from 'autotel-cloudflare/agents'
402
+ *
403
+ * class MyAgent extends Agent<Env> {
404
+ * observability = createOtelObservability({
405
+ * service: { name: 'my-agent' },
406
+ * exporter: { url: env.OTLP_ENDPOINT }
407
+ * })
408
+ * }
409
+ * ```
410
+ */
411
+ export function createOtelObservability(config: OtelObservabilityConfig): OtelObservability {
412
+ return new OtelObservability(config);
413
+ }
414
+
415
+ /**
416
+ * Create an OtelObservability instance with environment-based config
417
+ *
418
+ * Use this when you need to access environment variables for configuration.
419
+ *
420
+ * @example
421
+ * ```typescript
422
+ * import { Agent } from 'agents'
423
+ * import { createOtelObservabilityFromEnv } from 'autotel-cloudflare/agents'
424
+ *
425
+ * class MyAgent extends Agent<Env> {
426
+ * observability?: OtelObservability
427
+ *
428
+ * constructor(state: DurableObjectState, env: Env) {
429
+ * super(state, env)
430
+ * this.observability = createOtelObservabilityFromEnv(env)
431
+ * }
432
+ * }
433
+ * ```
434
+ */
435
+ export function createOtelObservabilityFromEnv(
436
+ env: Record<string, unknown>,
437
+ options?: AgentInstrumentationOptions,
438
+ ): OtelObservability {
439
+ // Extract standard OTLP env vars
440
+ const endpoint = (env.OTEL_EXPORTER_OTLP_ENDPOINT as string) || undefined;
441
+ const serviceName = (env.OTEL_SERVICE_NAME as string) || 'cloudflare-agent';
442
+
443
+ // Parse headers if present
444
+ let headers: Record<string, string> | undefined;
445
+ const headersStr = env.OTEL_EXPORTER_OTLP_HEADERS as string;
446
+ if (headersStr) {
447
+ headers = {};
448
+ for (const pair of headersStr.split(',')) {
449
+ const [key, value] = pair.split('=');
450
+ if (key && value) {
451
+ headers[key.trim()] = value.trim();
452
+ }
453
+ }
454
+ }
455
+
456
+ // If no endpoint is configured, use a default localhost endpoint
457
+ // In production, users should set OTEL_EXPORTER_OTLP_ENDPOINT
458
+ const exporterUrl = endpoint || 'http://localhost:4318/v1/traces';
459
+
460
+ return createOtelObservability({
461
+ service: { name: serviceName },
462
+ exporter: { url: exporterUrl, headers },
463
+ agents: options,
464
+ });
465
+ }
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Type definitions for Cloudflare Agents SDK observability integration
3
+ */
4
+
5
+ import type { ConfigurationOption } from 'autotel-edge';
6
+ import type { Attributes } from '@opentelemetry/api';
7
+
8
+ /**
9
+ * Base event structure from Agents SDK (mirrors agents/src/observability/base.ts)
10
+ */
11
+ export interface BaseAgentEvent<
12
+ T extends string,
13
+ Payload extends Record<string, unknown> = Record<string, unknown>
14
+ > {
15
+ type: T;
16
+ /** Unique identifier for the event */
17
+ id: string;
18
+ /** Human-readable message for logging */
19
+ displayMessage: string;
20
+ /** Event payload with type-specific data */
21
+ payload: Payload & Record<string, unknown>;
22
+ /** Timestamp in milliseconds since epoch */
23
+ timestamp: number;
24
+ }
25
+
26
+ /**
27
+ * Agent-specific observability events
28
+ */
29
+ export type AgentObservabilityEvent =
30
+ | BaseAgentEvent<'state:update', Record<string, unknown>>
31
+ | BaseAgentEvent<
32
+ 'rpc',
33
+ {
34
+ method: string;
35
+ streaming?: boolean;
36
+ }
37
+ >
38
+ | BaseAgentEvent<'message:request' | 'message:response', Record<string, unknown>>
39
+ | BaseAgentEvent<'message:clear'>
40
+ | BaseAgentEvent<
41
+ 'schedule:create' | 'schedule:execute' | 'schedule:cancel',
42
+ {
43
+ callback: string;
44
+ id: string;
45
+ }
46
+ >
47
+ | BaseAgentEvent<'destroy'>
48
+ | BaseAgentEvent<
49
+ 'connect',
50
+ {
51
+ connectionId: string;
52
+ }
53
+ >;
54
+
55
+ /**
56
+ * MCP-specific observability events
57
+ */
58
+ export type MCPObservabilityEvent =
59
+ | BaseAgentEvent<'mcp:client:preconnect', { serverId: string }>
60
+ | BaseAgentEvent<
61
+ 'mcp:client:connect',
62
+ { url: string; transport: string; state: string; error?: string }
63
+ >
64
+ | BaseAgentEvent<
65
+ 'mcp:client:authorize',
66
+ {
67
+ serverId: string;
68
+ authUrl: string;
69
+ clientId?: string;
70
+ }
71
+ >
72
+ | BaseAgentEvent<'mcp:client:discover', Record<string, unknown>>;
73
+
74
+ /**
75
+ * Union of all observability event types
76
+ */
77
+ export type ObservabilityEvent = AgentObservabilityEvent | MCPObservabilityEvent;
78
+
79
+ /**
80
+ * Observability interface from Agents SDK
81
+ */
82
+ export interface Observability {
83
+ /**
84
+ * Emit an event for the Agent's observability implementation to handle.
85
+ * @param event - The event to emit
86
+ * @param ctx - The execution context of the invocation (optional)
87
+ */
88
+ emit(event: ObservabilityEvent, ctx?: DurableObjectState): void;
89
+ }
90
+
91
+ /**
92
+ * Agent-specific instrumentation options
93
+ */
94
+ export interface AgentInstrumentationOptions {
95
+ /**
96
+ * Whether to create spans for RPC calls
97
+ * @default true
98
+ */
99
+ traceRpc?: boolean;
100
+
101
+ /**
102
+ * Whether to create spans for schedule operations
103
+ * @default true
104
+ */
105
+ traceSchedule?: boolean;
106
+
107
+ /**
108
+ * Whether to create spans for MCP operations
109
+ * @default true
110
+ */
111
+ traceMcp?: boolean;
112
+
113
+ /**
114
+ * Whether to create spans for state updates
115
+ * @default false (can be noisy)
116
+ */
117
+ traceStateUpdates?: boolean;
118
+
119
+ /**
120
+ * Whether to create spans for message events
121
+ * @default true
122
+ */
123
+ traceMessages?: boolean;
124
+
125
+ /**
126
+ * Whether to create spans for connect/destroy lifecycle events
127
+ * @default true
128
+ */
129
+ traceLifecycle?: boolean;
130
+
131
+ /**
132
+ * Custom attribute extractor for events
133
+ */
134
+ attributeExtractor?: (event: ObservabilityEvent) => Attributes;
135
+
136
+ /**
137
+ * Custom span name formatter
138
+ */
139
+ spanNameFormatter?: (event: ObservabilityEvent) => string;
140
+ }
141
+
142
+ /**
143
+ * Configuration for OtelObservability
144
+ */
145
+ export type OtelObservabilityConfig = ConfigurationOption & {
146
+ /**
147
+ * Agent-specific instrumentation options
148
+ */
149
+ agents?: AgentInstrumentationOptions;
150
+ };
151
+
152
+ /**
153
+ * Semantic attributes for Agent spans
154
+ */
155
+ export interface AgentSpanAttributes {
156
+ 'agent.event.type': string;
157
+ 'agent.event.id': string;
158
+ 'agent.rpc.method'?: string;
159
+ 'agent.rpc.streaming'?: boolean;
160
+ 'agent.schedule.callback'?: string;
161
+ 'agent.schedule.id'?: string;
162
+ 'agent.connection.id'?: string;
163
+ 'agent.mcp.server_id'?: string;
164
+ 'agent.mcp.url'?: string;
165
+ 'agent.mcp.transport'?: string;
166
+ 'agent.mcp.state'?: string;
167
+ }
package/src/agents.ts ADDED
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Cloudflare Agents SDK integration entry point
3
+ *
4
+ * Provides an OpenTelemetry-based Observability implementation for the
5
+ * Cloudflare Agents SDK (https://github.com/cloudflare/agents).
6
+ *
7
+ * @example Basic Usage
8
+ * ```typescript
9
+ * import { Agent } from 'agents'
10
+ * import { createOtelObservability } from 'autotel-cloudflare/agents'
11
+ *
12
+ * class MyAgent extends Agent<Env> {
13
+ * // Replace default observability with OpenTelemetry
14
+ * observability = createOtelObservability({
15
+ * service: { name: 'my-agent' },
16
+ * exporter: { url: env.OTLP_ENDPOINT }
17
+ * })
18
+ *
19
+ * @callable()
20
+ * async processTask(task: string) {
21
+ * // All RPC calls are automatically traced
22
+ * return { result: 'done' }
23
+ * }
24
+ * }
25
+ * ```
26
+ *
27
+ * @example Environment-Based Configuration
28
+ * ```typescript
29
+ * import { Agent } from 'agents'
30
+ * import { createOtelObservabilityFromEnv, OtelObservability } from 'autotel-cloudflare/agents'
31
+ *
32
+ * class MyAgent extends Agent<Env> {
33
+ * observability?: OtelObservability
34
+ *
35
+ * constructor(state: DurableObjectState, env: Env) {
36
+ * super(state, env)
37
+ * // Automatically reads OTEL_* environment variables
38
+ * this.observability = createOtelObservabilityFromEnv(env)
39
+ * }
40
+ * }
41
+ * ```
42
+ *
43
+ * @example Selective Tracing
44
+ * ```typescript
45
+ * import { createOtelObservability } from 'autotel-cloudflare/agents'
46
+ *
47
+ * const observability = createOtelObservability({
48
+ * service: { name: 'my-agent' },
49
+ * agents: {
50
+ * traceRpc: true, // Trace RPC calls (default: true)
51
+ * traceSchedule: true, // Trace scheduled tasks (default: true)
52
+ * traceMcp: true, // Trace MCP operations (default: true)
53
+ * traceStateUpdates: false, // Skip state updates (default: false, can be noisy)
54
+ * traceMessages: true, // Trace message events (default: true)
55
+ * traceLifecycle: true, // Trace connect/destroy (default: true)
56
+ * }
57
+ * })
58
+ * ```
59
+ *
60
+ * @packageDocumentation
61
+ */
62
+
63
+ export {
64
+ createOtelObservability,
65
+ createOtelObservabilityFromEnv,
66
+ OtelObservability,
67
+ } from './agents/otel-observability';
68
+ export type {
69
+ OtelObservabilityConfig,
70
+ AgentObservabilityEvent,
71
+ MCPObservabilityEvent,
72
+ ObservabilityEvent,
73
+ Observability,
74
+ AgentInstrumentationOptions,
75
+ AgentSpanAttributes,
76
+ } from './agents/types';